python-course.eu

18. Adventure Game with Structural Pattern Matching

By Bernd Klein. Last modified: 10 Nov 2023.

Introduction

Adventure Game image

In this section of our Python tutorial, we introduce structural pattern matching through an intriguing scenario—a hypothetical text-based adventure game.

Text adventure games, often referred to as interactive fiction, are a type of computer game that relies primarily on text-based descriptions and typed language commands for user input, rather than graphics and sound. Typical user input for most of these games look like:

A notable example of such a game is "Hack," a text-based role-playing game developed in the 1980s at the Massachusetts Institute of Technology (MIT) and more commonly recognized as "NetHack."

We will showcase Python code snippets that simulate scenarios within a text adventure game, while also elucidating significant aspects and features of structural pattern matching.

command = input("What are you doing next? ")
action, object = command.split()
print(f"{action=}, {object=}")

OUTPUT:

action='take', object='sword'

What if the user types less or more than 2 words?

command = input("What are you doing next? ")
words = command.split()
no_of_words = len(words)
if no_of_words == 1:
    print(f"action without object: {action=}")
elif no_of_words == 2:
    print(f"{action=}, {object=}")
else:
    print(words)

OUTPUT:

action='take', object='sword'

Now with structural pattern recognition. Matching multiple patterns:

command = input("What are you doing next? ")
match command.split():
    case [action]:
        print(f"action without object: {action=}")
    case [action, obj]:
        print(f"{action=}, {obj=}")

OUTPUT:

action without object: action='look'

Live Python training

instructor-led training course

Enjoying this page? We offer live Python training courses covering the content of this site.

See: Live Python courses overview

Enrol here

Matching specific patterns:

command = input("What are you doing next? ")
match command.split():
    case ["quit"]:
        print("Goodbye!")
        quit_game()
    case ["look"]:
        print("You are in cold and dark room ....")
    case ["get", obj]:
        print(f"You grab the {obj}")
    case ["go", direction]:
        print(f"You will go {direction} if possible")
    case _:
        print("Sorry, I do not understand!")

OUTPUT:

You grab the apple

Warrior in a Python adventure game

Matching Multiple Values:

command = "drop apple armour shield"

match command.split():
    case ["drop", *objects]:
        for obj in objects:
            print(f"You drop a{'n' if obj[0] in 'aeiou' else ''} {obj}")

OUTPUT:

You drop an apple
You drop an armour
You drop a shield

Live Python training

instructor-led training course

Enjoying this page? We offer live Python training courses covering the content of this site.

See: Live Python courses overview

Upcoming online Courses

Enrol here

Adding a wildcard

In the following code, if you use an input that doesn't match any of the defined patterns, Python doesn't raise an exception. Instead, the code will simply continue without entering any of the case blocks like in the following Python example:

command = 'fight monster'
match command.split():
    case ["help"]:
        print("""You can use the following commands:
        """)
    case ["go", direction]: 
        print('going', direction)
    case ["drop", "all", "weapons"]: 
        for weapon in weapons:
            inventory.remove(weapon)
    case ["drop", item]:
        print('dropping', item)
    

To handle unexpected or unmatched input gracefully, you can add a wildcard case using an underscore _ as a wildcard to catch any input that doesn't match the specific patterns.

commands = ['go north','go west', 'drop potion', 'drop all weapons', 'drop shield', 'fight monster']
weapons = ['axe','sword','dagger']
shield = True
inventory = ['apple','wood','potion'] + weapons + ['shield']
for command in commands: 
    match command.split():
        case ["help"]:
            print("""You can use the following commands:
            """)
        case ["go", direction]: 
            print('going', direction)
        case ["drop", "all", "weapons"]: 
            for weapon in weapons:
                inventory.remove(weapon)
        case ["drop", item]:
            print('dropping', item)
            inventory.remove(item)
        case ["drop shield"]:
            shield = False 
        case _:
            print(f"Sorry, I couldn't understand {command!r}")

OUTPUT:

going north
going west
dropping potion
dropping shield
Sorry, I couldn't understand 'fight monster'

Several Patterns Resulting in the Same Outcome

command = input("What are you doing next? ")

match command.split():
    # Other cases
    # .....
    case ["north"] | ["go", "north"]:
        print("Let's go north")
    case ["look"] | ["look", "around"]:
        print("You are in a cold and dark room ....")
    case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]:
        print(f"Picking up {obj}")

OUTPUT:

You are in a cold and dark room ....

Live Python training

instructor-led training course

Enjoying this page? We offer live Python training courses covering the content of this site.

See: Live Python courses overview

Enrol here

Capturing Matched Subpatterns

command = input("What are you doing next? ")
match command.split():
    case ["go", ("north" | "south" | "east" | "west") as direction]:
        print(f"You go {direction}")

OUTPUT:

You go north

Patterns mit Conditions

We can also add conditions to a branch of a structural pattern matching. So like checking if an exit exists in a certain direction of a room.

Condition: Two doors to choose from

command = input("What are you doing next? ")
possible_direction = ['north', 'south']
match command.split():
    case ["go", direction] if direction in possible_direction:
        print(f"So, let's go {direction}!")

OUTPUT:

So, let's go south!

Live Python training

instructor-led training course

Enjoying this page? We offer live Python training courses covering the content of this site.

See: Live Python courses overview

Upcoming online Courses

Enrol here