Start Free Now
Limited Time Offer: Get 50% OFF Starter & Basic Yearly Plans 🎉

How to Build a Text Adventure Game in the Command Prompt

Oct 3, 2026

Why the Command Prompt Is Still a Serious Place to Learn Game Design

Most beginners assume that making a game begins with an engine. It does not. The first honest lessons in game development are loops, state, branching, and persistence, and every one of them can be learned inside a plain text file with a .bat extension on hardware you already own.

When you build a game with batch scripting, there is no scene editor to drag sprites into, no physics engine to absorb your mistakes, and no automatic stack trace to rescue you at two in the morning. Every room description, every point of health, every item, and every ending exists because you typed it. That constraint is precisely what makes the exercise valuable. You cannot hide a broken game loop behind attractive art, so you are forced to understand the loop.

Batch also teaches persistence in the least abstract way possible. A save file in a console game is usually a plain text file containing lines such as health=7. Writing that file, reading it back, handling a file that does not exist yet, and surviving a file that someone edited by hand are the same problems real save systems solve, just smaller. Once you have solved them here, engine save systems stop feeling like magic.

Speed matters as well. The Command Prompt ships with Windows. No download, no account, no driver update. You can open a terminal, type the name of your script, and watch your own game run three minutes after you had the idea. For a beginner, that short distance between idea and playable result is worth more than any feature list on a product page.

Name the limits early, because they shape everything you build. Batch has no real arrays, weak arithmetic, no graphics beyond console text, and a syntax that punishes one missing quote. Treat those as part of the curriculum rather than obstacles. Designing around constraints is a skill every working developer uses daily, and a console game is a low-stakes place to practice it.

Setting Up a Workspace That Will Not Fight You

Start with a dedicated folder so your project never disappears among downloads. Something like C:\Games\TextQuest is enough. In File Explorer, turn on file name extensions so you can see whether a file is genuinely named game.bat or quietly named game.bat.txt. That single checkbox prevents one of the most common beginner frustrations.

For an editor, choose anything that shows line numbers and does not argue with you about encoding. Notepad++ and Visual Studio Code both highlight batch syntax and make mismatched labels easier to spot. Plain Notepad works too, but when you save, switch the file type to All files and type the .bat extension yourself.

Here is the smallest useful starting point. Create a new file and type:

@echo off
title Dark Cave
color 0A
echo Welcome to Dark Cave.
echo.
echo You wake on cold stone. Somewhere ahead, water drips.
echo.
pause

Save it, then double-click it or open a Command Prompt in that folder and type game.bat. Four things happen, and each matters. The @echo off line stops the console from printing every command before it runs, which keeps the screen readable. The title command sets the window caption. The color 0A command gives you a black background with light green text, an instant retro mood for free. The pause command holds the window open so you can read the output instead of watching it vanish in a blink.

A quick word on encoding. If you plan to use accented letters or non-Latin scripts, place chcp 65001 at the top of the file and save as UTF-8 without a byte order mark, or save as ANSI and stay consistent. Mixing these up produces garbled characters that look like a logic bug when they are really a text-file bug. Test with one accented line before you write three hundred lines of dialogue.

Finally, create a folder structure you can grow into. Keep game.bat at the root, a saves folder for save files, and an assets folder for any sound files you add later. When your script reaches several hundred lines, you will thank yourself for not scattering everything across the desktop.

The Core Batch Commands You Actually Need

You do not need a large vocabulary to build a complete text game. This short list covers nearly everything:

  • echo prints text; echo. prints a blank line.
  • set name=value stores a variable. Never put spaces around the equals sign.
  • set /p choice=What do you do? reads input from the player.
  • set /a health=health-3 performs integer arithmetic.
  • if tests a condition, and if /i makes text comparison case-insensitive.
  • goto :label jumps to a label, and :label marks the destination.
  • call :routine runs a subroutine, which must end with exit /b.
  • cls clears the screen, which is useful between scenes.
  • timeout /t 2 /nobreak discards keypresses for two seconds and paces your text.
  • choice /c 123 /n /m "Pick: " builds a menu and sets an exit code.
  • del file.txt and type file.txt manage save data.
  • for /f reads lines from a file, which is how you load a saved game.

Two syntax rules save beginners hours of pain. First, always wrap variable comparisons in quotes: if "%choice%"=="1". Without quotes, an empty variable produces a syntax error that looks far more mysterious than it is. Second, remember that batch expands variables when a block is parsed, not when each line executes. If a variable changes inside a parenthesized block and you read it in the same block, you will see the old value unless you enable delayed expansion with setlocal enabledelayedexpansion and reference the variable with exclamation marks.

One more habit worth forming now: never use the same label name as a variable, and never jump backwards without a way out. Infinite loops in batch look like a frozen window and cost you ten minutes of confusion every time.

Planning the Loop Before You Type a Single Command

Open a text file and sketch the game before you write any script. A working text adventure is almost always one small, slightly boring loop repeated with different content: describe the scene, list the options, read the player input, validate it, update the world, then jump to the next scene. Everything else is decoration.

Define your minimum viable game. Three rooms, one item, one win condition, one lose condition. For example: a cave entrance, a flooded tunnel, and a locked door; a rusty key; escape through the door to win; enter the flooded tunnel twice without the key and drown. That is a complete, shippable game, and it fits in one evening.

Next, build a variable table. List every number and flag you need: health, torch, gold, has_key, tunnel_count, current_room, and a language or difficulty setting if you want one. Name them in lowercase with underscores so they are easy to search later. Then list your labels, one per scene plus a handful of utility labels: :menu, :scene_entrance, :scene_tunnel, :scene_door, :win, :lose, :showstats, :quit.

Finally, write the flow as arrows on paper. Entrance leads to tunnel or door; tunnel leads back or to drowning; door leads to the win if has_key equals 1 and to a locked message otherwise. Draw it, and the script becomes transcription rather than invention. When something breaks, you check one scene instead of questioning the whole design. This planning step is where most beginner projects are won or lost, and it costs twenty minutes.

Branching: Turning Story Into Decisions

Branching is the backbone of any text game. In batch, the workhorse is the if statement combined with goto. Here is a complete, working scene:

:scene_entrance
cls
echo --- CAVE ENTRANCE ---
echo.
echo The tunnel mouth is dark and wet. A rusted door sits to your right.
echo.
echo 1) Enter the tunnel
echo 2) Try the door
echo 3) Check your pockets
set /p choice=Choose: 
if "%choice%"=="1" goto :scene_tunnel
if "%choice%"=="2" goto :scene_door
if "%choice%"=="3" goto :check_pockets
echo.
echo That is not an option.
timeout /t 2 /nobreak
goto :scene_entrance

Notice the pattern. Each valid input gets its own single-line if with a quote-wrapped comparison, and anything unrecognized falls through to a friendly message and returns to the same scene. That fall-through is the simplest reliable validation you can write, and it never crashes on empty input. It also handles the player who types a word instead of a number, which happens more often than you would expect.

The choice command produces cleaner menus when your options are single characters:

choice /c 123 /n /m "Choose: "
if errorlevel 3 goto :check_pockets
if errorlevel 2 goto :scene_door
goto :scene_tunnel

Be careful with the order. The errorlevel test means if the exit code is that value or higher, so you must always test the highest value first. Reverse the order and every choice routes to the same scene. This trips up nearly everyone the first time, and it is worth writing a note in your script so future-you remembers.

Branching scales further than you might think. Global commands belong above local choices: intercept quit, help, and stats before scene logic runs, usually by calling a shared :parse_input routine at the top of every scene. A short help text that lists valid commands reduces player frustration dramatically, and it costs you five lines.

State: Health, Flags, and Counters That Behave

A game where nothing changes is a slideshow. State is what turns a branching script into a game. Use set /a for numbers and plain set for booleans, keeping booleans as 0 or 1 so they can be tested numerically:

set /a torch=torch-1
if %torch% LEQ 0 (
  echo Your torch sputters and dies. The dark closes in.
  goto :lose
)

Flags remember what the player has already done. The classic use is preventing an event from firing twice:

if "%took_key%"=="1" (
  echo The hook on the wall is empty now.
  goto :scene_door
)
set took_key=1
set /a items=items+1
echo You lift the rusty key from its hook.

Watch out for delayed expansion inside those parentheses. If you both change and read a variable within the same block, add setlocal enabledelayedexpansion near the top of the script and reference it with exclamation marks instead of percent signs. This is the single most confusing batch behavior for newcomers, and knowing it in advance prevents a whole category of silent bugs.

Randomness adds variety with almost no effort. The %random% variable returns a large number, and you can reduce it to a range with the modulo operator written as two percent signs inside a script:

set /a damage=%random% %% 6 + 1
echo A falling rock hits you for %damage% damage.
set /a health=health-damage

That gives you a number from one to six. Use the same trick for enemy choices, loot tables, and flavor text variation.

Two more habits separate a finished game from a fragile one. Clamp your numbers, so health never drops below zero and counters have a ceiling that stops the game from running forever. And print state regularly with a small status line. Players tolerate difficulty; they do not tolerate not knowing why they died.

Inventories and Save Files Without Arrays

Batch has no arrays, so beginners usually reach for one of two patterns: a delimited string variable, or an external text file. The string version is fast to write and trivial to display:

set inventory=
set inventory=%inventory%rusty key, 
set inventory=%inventory%damp rope, 
echo You are carrying: %inventory%

For anything larger, a file is cleaner and gives you persistence almost for free. Keep one item per line in inventory.txt, append new items, and check for an existing item with findstr:

findstr /i "rusty key" inventory.txt >nul
if not errorlevel 1 (
  echo You already have the key.
  goto :scene_door
)
echo rusty key>>inventory.txt

Saving a game follows the same idea, but write structured lines so you can read them back later:

(
echo version=1
echo health=%health%
echo torch=%torch%
echo gold=%gold%
echo has_key=%has_key%
echo current_room=%current_room%
) > saves\slot1.txt

Loading uses a for loop that splits each line at the equals sign:

if exist saves\slot1.txt (
  for /f "tokens=1,2 delims==" %%a in (saves\slot1.txt) do set %%a=%%b
) else (
  echo No saved game found.
  timeout /t 2 /nobreak
)

Three gotchas deserve attention. First, writing a line as echo %gold% with a single output redirect inserts a trailing space into the file, and that space will break the next load; always write gold=%gold% inside a parenthesized block instead. Second, in a batch file you use double percent signs in the for loop, while at the interactive prompt you use single ones, which is a frequent source of confusion when copying snippets from a terminal. Third, if the save file is missing or truncated, the loop simply does nothing, leaving your variables at whatever value they already held. Initialize every default at the top of the script before you attempt a load.

Add a version line to the save file. When you later change the format, you can detect an old save and either upgrade it or refuse it with a clear message instead of loading nonsense numbers into your health variable.

Subroutines, Menus, and Presentation Polish

Once a script passes a few hundred lines, repeated blocks become a maintenance problem. Subroutines solve this. Create a status routine and call it whenever the player needs a readout:

:showstats
echo ---------------------------------
echo HP: %health%   Torch: %torch%   Gold: %gold%
echo ---------------------------------
exit /b

Then use call :showstats from any scene. The exit /b is essential. Without it, execution falls through into the next label and produces some genuinely baffling behavior that looks like a random jump. Utility routines for clearing the screen, printing a menu header, and pausing between text blocks will shrink your script substantially and make each scene easier to read.

Polish is where a school project starts to feel like a game. A title screen built from echo lines costs nothing and sets the mood immediately. A short timeout between paragraphs creates a typewriter rhythm that makes text feel paced rather than dumped. A color change during a damage event makes the screen react to the player's decisions, which is a surprisingly strong feedback signal in a text-only environment. If you want sound, you can borrow a Windows capability without installing anything:

powershell -c (New-Object Media.SoundPlayer 'assets\ding.wav').PlaySync()

Keep polish proportionate to your core loop. A beautiful title screen in front of a boring choice structure is still a boring game. Improve the loop first, then the surface.

Menus deserve one more thought. Keep them to five options or fewer, put the most likely action first, and always include an exit. A player who cannot leave a menu will close the window, and closed windows are the hardest bug to diagnose.

Testing, Debugging, and the Mistakes That Cost Beginners Hours

Debugging batch is easiest with a trace. Remove @echo off temporarily so every command prints before it runs, or scatter your own markers such as echo DEBUG health=%health% room=%current_room%. Watching which lines execute tells you immediately whether your goto landed where you expected, which is usually the fastest way to find a broken branch.

The most common mistakes, roughly in order of frequency:

  • Saving the file as game.txt or game.bat.txt and wondering why nothing happens when you double-click.
  • Comparing variables without quotes, which throws a syntax error the moment the input is empty.
  • Forgetting exit /b at the end of a subroutine, so execution bleeds into unrelated code.
  • Reading a variable inside the same parenthesized block where it changed, without delayed expansion.
  • Adding spaces around the equals sign in a set command, which silently includes them in the value.
  • Treating the errorlevel test as an equality check instead of a threshold, which collapses every menu option into one destination.
  • Escaping special characters incorrectly. An ampersand inside echoed text needs a caret, as in echoing Salt ^& iron.
  • Leaving a scene without a timeout, so a fast double keypress spins the screen and skips dialogue.

Test deliberately rather than randomly. Type letters where numbers are expected. Press Enter with no input at all. Enter a huge number or a negative one. Delete the save file mid-session. Hand-edit a save file to contain words instead of numbers. Each of those is a real player behavior, and each should produce a readable message rather than a crash or an endless loop. A short test checklist you run before sharing your game will catch more bugs than an hour of casual clicking.

Finally, keep a working copy. Before a big refactor, duplicate your script with a dated name. Batch has no undo history inside the console, and a broken script that worked yesterday is a demoralizing way to spend an evening.

FAQ and Where to Go Next

Can I make a graphical game with batch? Not really. The Command Prompt is a text surface. You can fake simple animation by clearing the screen and redrawing character frames, but real graphics mean moving to another tool. PowerShell with WinForms, Python with Pygame, or a small engine like Godot are all sensible next steps.

Is batch scripting worth learning if it is old? Yes, for the concepts. Variables, conditionals, loops, subroutines, file input and output, and state machines are identical ideas in every language you will use afterward. Batch is simply a particularly honest teacher because it hides nothing from you.

Do I need administrator rights? No. A game folder inside your user directory and a .bat file are enough. If Windows shows a security prompt the first time you run a downloaded script, that is a general warning about unknown files rather than a problem with batch itself.

How do I share my game with someone else? Send the .bat file and any save or asset folders it depends on, and tell the player to keep the folder structure intact. Relative paths break the moment someone moves only the script.

How long should the game be? Three to five rooms with two endings is a satisfying first release. More content makes the code harder to debug before you have learned the patterns that keep it manageable.

Can I use text from a story I wrote elsewhere? Absolutely. Keep dialogue in a separate text file and read it with a for loop, or paste it into echo lines. Separating story text from logic makes both easier to edit.

Where should I go after finishing one game? Add a mechanic, not a new project. A locked door that needs two items, a shop where gold buys torch refills, a combat round driven by random numbers, an ending counter that tracks how many times the player escaped. Each addition is small and each one teaches something transferable to larger engines and to modern video tooling alike.

If you want a structured path, try this order: build a three-room game with one item, add save and load, add a combat round or a timed hazard, then rebuild the same game in Python. The second version will take a fraction of the time, and you will see exactly how much of your knowledge was about batch syntax and how much was about designing a game. That distinction is the real takeaway from building something with nothing but a Command Prompt, and it is the part that keeps paying off long after your first .bat file is retired.

Alexander

Alexander