18. Adventure Game with Structural Pattern Matching
By Bernd Klein. Last modified: 10 Nov 2023.
Introduction
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:
- 'help'
- 'show inventory'
- 'go north'
- 'go south'
- 'drop shield'
- 'drop all weapons'
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
Enjoying this page? We offer live Python training courses covering the content of this site.
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
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
Enjoying this page? We offer live Python training courses covering the content of this site.
Upcoming online Courses
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
Enjoying this page? We offer live Python training courses covering the content of this site.
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.
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
Enjoying this page? We offer live Python training courses covering the content of this site.
Upcoming online Courses