Learn How to Build a Text-Based Adventure Game in Python: Absolute Beginners Tutorial

Building a game is one of the most effective ways to learn Python. In this tutorial you will build a fully playable text-based adventure game from scratch — no libraries, no frameworks, just the Python you learn along the way.

Text-based adventure games have been teaching programmers the fundamentals for decades. Every room you walk into is a function call. Every choice the player makes is a conditional branch. Every item in the inventory is a data structure. By the time you finish this tutorial, you will have written real, working Python and understood exactly why each piece behaves the way it does.

What You Will Build

The finished game will have five rooms connected by directional exits (north, south, east, west). The player can pick up items, check their inventory, and reach a win condition by arriving at the correct room while carrying a specific item. The entire game runs in a terminal and requires nothing beyond a standard Python 3 installation.

Here is the complete game in one file so you can see where you are headed before you start building it piece by piece:

python
# adventure.py — complete text adventure game

rooms = {
    "entrance": {
        "description": "You stand at the entrance to a crumbling fortress.",
        "exits": {"north": "courtyard"},
        "items": ["torch"]
    },
    "courtyard": {
        "description": "A wide courtyard, open to the grey sky. Passages lead in three directions.",
        "exits": {"south": "entrance", "east": "armory", "west": "garden"},
        "items": []
    },
    "armory": {
        "description": "Racks of rusted weapons line the walls. One blade still gleams.",
        "exits": {"west": "courtyard"},
        "items": ["sword"]
    },
    "garden": {
        "description": "An overgrown garden. Vines cover a locked iron door to the north.",
        "exits": {"east": "courtyard", "north": "vault"},
        "items": ["key"]
    },
    "vault": {
        "description": "The vault. This is where the treasure is kept.",
        "exits": {"south": "garden"},
        "items": ["treasure"]
    }
}

current_room = "entrance"
inventory = []


def display_room(rooms, room_name):
    room = rooms[room_name]
    print("\n---")
    print(room["description"])
    if room["items"]:
        print(f"You see: {', '.join(room['items'])}")
    exits = ", ".join(room["exits"].keys())
    print(f"Exits: {exits}")


print("Welcome to the Fortress. Type a direction to move, 'take [item]' to pick something up,")
print("'inventory' to check your bag, or 'quit' to exit.\n")

while True:
    display_room(rooms, current_room)

    # Win condition
    if current_room == "vault" and "key" in inventory:
        print("\nYou unlock the vault with the key. The treasure is yours. You win!")
        break

    command = input("\n> ").strip().lower()

    if command == "quit":
        print("Farewell.")
        break

    elif command in rooms[current_room]["exits"]:
        current_room = rooms[current_room]["exits"][command]

    elif command.startswith("take "):
        item = command[5:]
        if item in rooms[current_room]["items"]:
            inventory.append(item)
            rooms[current_room]["items"].remove(item)
            print(f"You pick up the {item}.")
        else:
            print(f"There is no {item} here.")

    elif command == "inventory":
        if inventory:
            print(f"You are carrying: {', '.join(inventory)}")
        else:
            print("Your inventory is empty.")

    else:
        print("That direction is not available. Check your exits.")
How to run the game

Save the code above as adventure.py, open a terminal, navigate to the folder, and run python adventure.py. You need Python 3.6 or later. On some systems the command is python3 adventure.py.

Variables, input(), and Player Interaction

Two lines near the top of the game set up the player's starting state:

python
current_room = "entrance"
inventory = []

current_room is a string variable that holds the name of the room the player is currently in. inventory is a list variable that starts empty and grows when the player picks up items. Both of these values change as the game runs — that is exactly what variables are for.

Player input arrives through the built-in input() function. When Python reaches that line, execution pauses and waits for the user to type something and press Enter. Whatever the user typed is returned as a string.

python
command = input("\n> ").strip().lower()

Two string methods are chained after input(). The .strip() call removes any whitespace that accidentally crept in at the start or end of what the user typed. The .lower() call converts everything to lowercase so that typing "North", "NORTH", or "north" all produce the same string: "north". Without these two calls, players would need to type commands in exactly the right case every time.

Dictionaries as room data

The rooms are stored in a dictionary named rooms. A Python dictionary is a collection of key-value pairs wrapped in curly braces. Each room name is a key, and its value is another dictionary containing that room's description, exits, and items. This nested structure means you can look up any room by name and immediately access all of its data.

python
# Accessing nested dictionary values
room = rooms["courtyard"]
print(room["description"])   # A wide courtyard, open to the grey sky...
print(room["exits"])         # {'south': 'entrance', 'east': 'armory', 'west': 'garden'}
Pro Tip

Adding a room is as simple as adding a new key-value pair to the rooms dictionary and making sure at least one existing room has an exit pointing to it. The rest of the code adapts automatically.

code builder click a token to place it

Build the correct Python line to read player input, strip whitespace, and convert to lowercase:

your code will appear here...
.strip() print( input( command "> " .lower() = ) .upper()
Why: The assignment starts with command =. Then input("> ") captures the user's text. .strip() must come before .lower() since both are chained left to right. .upper() is a distractor — it converts to uppercase, which is the opposite of what you want. print( is also a distractor — it outputs text, it does not read input.

Conditional Logic with if, elif, and else

Once the player's command is a clean lowercase string, the game needs to decide what to do with it. That decision-making is handled by a chain of if, elif, and else statements.

python
if command == "quit":
    print("Farewell.")
    break

elif command in rooms[current_room]["exits"]:
    current_room = rooms[current_room]["exits"][command]

elif command.startswith("take "):
    item = command[5:]
    if item in rooms[current_room]["items"]:
        inventory.append(item)
        rooms[current_room]["items"].remove(item)
        print(f"You pick up the {item}.")
    else:
        print(f"There is no {item} here.")

elif command == "inventory":
    if inventory:
        print(f"You are carrying: {', '.join(inventory)}")
    else:
        print("Your inventory is empty.")

else:
    print("That direction is not available. Check your exits.")

Python evaluates each condition top to bottom and runs the first block whose condition is True. Once a block runs, all the remaining elif and else branches are skipped. The final else acts as a catch-all — it runs only when none of the above conditions matched, giving the player a helpful error message instead of silent failure.

Notice the movement branch: command in rooms[current_room]["exits"]. The in keyword checks whether a value exists inside a collection. Here it checks whether the player's typed direction is a key in the current room's exits dictionary. If it is, the game updates current_room to the destination room name — one dictionary lookup moves the player to a new location.

What happens
Python raises a SyntaxError because a single = is the assignment operator, not a comparison. You cannot assign inside an if condition this way.
The fix
Use == to compare two values: if command == "quit":
What happens
Python raises a SyntaxError immediately. Every if, elif, and else header must end with a colon.
The fix
Always end the header line with : — for example, elif command == "inventory":
What happens
Python uses indentation to define blocks. Code that should be inside the if statement runs unconditionally if it is not indented.
The fix
Indent every line that belongs inside the block by exactly four spaces (or one tab — but be consistent throughout the file).
What happens
Python raises a SyntaxError. The else block must always come last. You cannot add elif branches after it.
The fix
Put all elif clauses before the final else. else is the catch-all that only runs when nothing above matched.
spot the bug click the line that contains the bug

The movement handler below has one bug that prevents the player from moving to a new room. Click the line you think is wrong, then hit check.

1 elif command in rooms[current_room]["exits"]:
2 destination = rooms[current_room]["exits"][command]
3 current_room == destination
4 print(f"You move {command}.")
The fix: Change current_room == destination to current_room = destination. A double equals sign (==) is a comparison — it checks whether the two values are equal and returns True or False, but changes nothing. A single equals sign (=) is assignment — it stores the new value into the variable. Without the fix, the player's location never actually updates.

How to Build a Text-Based Adventure Game in Python

The game is built in five distinct steps. Each step introduces one new concept. Follow them in order and you will have a working game by the end of step five.

  1. Define the rooms dictionary

    Create a Python dictionary called rooms. Each top-level key is a room name string such as "entrance". Its value is a nested dictionary with three keys: "description" (a string), "exits" (a dictionary mapping direction strings to destination room names), and "items" (a list of item name strings). Start with two or three rooms and connect them by setting matching exit entries on each side.

  2. Set up the player state

    Below the rooms dictionary, declare two variables: current_room = "entrance" and inventory = []. These two variables represent the complete state of the player at any point in the game. Everything the game loop does will read or modify one of these two values.

  3. Write the display_room function

    Define a function called display_room(rooms, room_name). Inside the function, look up the room using rooms[room_name] and print its description. If the room's items list is not empty, print those too. Finally, join the exit keys into a comma-separated string and print them. Putting this logic in a function means you call it once per loop iteration rather than repeating the same print statements every time.

  4. Build the main game loop

    Write while True: to start an infinite loop. On each iteration: call display_room, read input with input("\n> ").strip().lower(), then branch with if/elif/else to handle the "quit" command (which breaks the loop), movement (updating current_room), item pickup (appending to inventory and removing from the room), and the inventory command.

  5. Add a win condition

    Inside the loop, just after the display_room call, add an if statement that checks two things at once using and: whether current_room equals the win room name, and whether the required item is in the inventory list. When both are true, print a victory message and break out of the loop. The game ends cleanly and does not prompt for another command.

"Programs must be written for people to read, and only incidentally for machines to execute." — Abelson and Sussman, Structure and Interpretation of Computer Programs

Python Learning Summary Points

  1. A dictionary is the natural data structure for a game world. Each room is a key, and its associated description, exits, and items are the value — stored as a nested dictionary. Looking up any piece of room data takes a single expression.
  2. The input() function always returns a string. Chaining .strip().lower() immediately after the call normalises player input so your conditions work regardless of how the player capitalises or spaces their commands.
  3. The while True loop combined with strategic break statements is the standard pattern for a terminal game loop. The loop runs indefinitely until a win condition or quit command triggers a break.
  4. Every conditional branch in the game loop corresponds to a real gameplay action. Keeping each action in its own elif block makes the code readable and easy to extend without breaking existing behaviour.
  5. Extracting repeated logic into a named function — such as display_room — eliminates duplication and gives a meaningful name to a chunk of behaviour, which makes the main loop far easier to follow.

The game you have built is intentionally simple, but it already demonstrates every foundational concept Python beginners need: variables, strings, lists, dictionaries, functions, loops, and conditional logic. From here you can extend it with a combat system, locked doors, saving and loading state to a file, or even a simple parser that understands multi-word commands. Every extension will use the same core concepts you just practised.

check your understanding question 1 of 5

Frequently Asked Questions

You do not need much prior knowledge. This tutorial is designed for absolute beginners and teaches all the concepts you need — variables, input(), if/elif/else, functions, loops, and dictionaries — as you build the game.

The input() function pauses the program and waits for the user to type something and press Enter. It always returns the entered text as a string. You can pass a prompt string to input() that is displayed to the user before they type.

if evaluates a condition and runs its block only when the condition is True. elif (short for else if) checks an additional condition when the previous if was False. else runs its block when none of the preceding if or elif conditions matched.

A dictionary groups related data together under a single name. Instead of separate variables for each room's description, exits, and items, you can store all of it in one dictionary keyed by room name. This makes the code easier to read, extend, and loop over.

A while loop keeps running its body as long as a condition stays True. In a text adventure, a while True loop runs the game indefinitely — showing the current room, accepting input, and updating game state — until the player wins, dies, or types a quit command that triggers a break.

Add a new key-value pair to the rooms dictionary for each new room. Give it a description, an exits dictionary mapping direction strings to room names, and an optional items list. Then make sure an existing room has a matching direction that points to the new room's key.

.strip() removes any leading or trailing whitespace from the string, including newlines. .lower() converts all characters to lowercase. Chaining them together normalises user input so that "North", "north", and " NORTH " all match the same condition in your if statement.

Yes. The code in this tutorial uses only Python's standard library with no third-party packages, so it runs on Windows, macOS, and Linux. You need Python 3.6 or later installed. Run the script from a terminal with: python adventure.py