Ein Text-basiertes Abenteuerspiel

Einführung

Abenteuerspiel Höhle

Ein Text-Abenteuerspiel

Einführung

In diesem Abschnitt unseres Python-Kurses führen wir strukturelles Muster-Matching anhand eines faszinierenden Szenarios ein - eines hypothetischen textbasierten Abenteuerspiels.

Text-Abenteuerspiele, oft als interaktive Fiktion bezeichnet, sind eine Art von Computerspiel, das hauptsächlich auf textbasierten Beschreibungen und typisierten Sprachbefehlen für die Benutzereingabe basiert, anstatt auf Grafiken und Sound. Typische Benutzereingaben für die meisten dieser Spiele sehen so aus:

  • 'help'
  • 'show inventory'
  • 'go north'
  • 'go south'
  • 'drop shield'
  • 'drop all weapons'

Ein bemerkenswertes Beispiel für ein solches Spiel ist "Hack", ein textbasiertes Rollenspiel, das in den 1980er Jahren am Massachusetts Institute of Technology (MIT) entwickelt wurde und allgemein als "NetHack" bekannt ist.

Wir werden Python-Code-Schnipsel präsentieren, die Szenarien innerhalb eines textbasierten Abenteuerspiels simulieren, während wir auch bedeutende Aspekte und Merkmale des strukturellen Muster-Matchings erläutern.

In [3]:
command = input("What are you doing next? ")
action, object = command.split()
print(f"{action=}, {object=}")
action='take', object='sword'

Was passiert, wenn der Benutzer weniger oder mehr als 2 Wörter eingibt?

In [4]:
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)
action='take', object='sword'

Jetzt mit struktureller Mustererkennung. Übereinstimmung mehrerer Muster:

In [5]:
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=}")
action without object: action='look'

Übereinstimmung spezifischer Muster:

In [7]:
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!")
You grab the apple

Krieger in einem Python-Abenteuerspiel

Übereinstimmung mehrerer Werte:

In [1]:
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}")
You drop an apple
You drop an armour
You drop a shield

Hinzufügen eines Platzhalters

Wenn man im folgenden Code eine Eingabe verwendet, die keinem der definierten Muster entspricht, wirft Python keine Ausnahme. Stattdessen wird der Code einfach fortgesetzt, ohne in einen der Fallblöcke einzutreten, wie im folgenden Python-Beispiel:

In [2]:
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)
    

Um unerwartete oder nicht übereinstimmende Eingaben angemessen zu behandeln, kann man einen Platzhalterfall hinzufügen und einen Unterstrich (_) als Platzhalter verwenden, um alle Eingaben abzufangen, die nicht zu den spezifischen Mustern passen.

In [3]:
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}")
going north
going west
dropping potion
dropping shield
Sorry, I couldn't understand 'fight monster'

Verschiedene Muster mit gleichem Ergebnis

In [4]:
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}")
Let's go north

Erfassen übereinstimmender Teilmuster

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

Patterns mit Bedingungen

Wir können auch Bedingungen zu einem Zweig einer strukturellen Mustererkennung hinzufügen. Zum Beispiel überprüfen, ob ein Ausgang in eine bestimmte Richtung eines Raums existiert.

Condition: Two doors to choose from

In [1]:
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}!")