Did some polishing

This commit is contained in:
Enrico Ludwig 2024-08-15 15:15:13 +02:00
parent 5052fb4f46
commit d7060768d2
7 changed files with 181 additions and 74 deletions

View File

@ -4,7 +4,7 @@
"name": "Streichholzpackung", "name": "Streichholzpackung",
"description": "Eine Packung mit Streichhoelzern, leider ist aber nur noch ein einziges uebrig." "description": "Eine Packung mit Streichhoelzern, leider ist aber nur noch ein einziges uebrig."
}, },
"key": { "laundry_key": {
"name": "Ein rostiger, alter Schluessel", "name": "Ein rostiger, alter Schluessel",
"description": "Wo der wohl passen koennte?" "description": "Wo der wohl passen koennte?"
} }
@ -12,7 +12,9 @@
"rooms": { "rooms": {
"entrance": { "entrance": {
"name": "Haupthalle", "name": "Haupthalle",
"identifier": [ "haupthalle", "eingang", "eingangsbereich" ],
"is_start": true, "is_start": true,
"requires_key": false,
"enter_text": "Du betrittst die Haupthalle. Nebst Spinnenweben und Staub findet sich jede Menge kaputter Moebel.", "enter_text": "Du betrittst die Haupthalle. Nebst Spinnenweben und Staub findet sich jede Menge kaputter Moebel.",
"interactables": [ "interactables": [
{ {
@ -26,7 +28,7 @@
{ {
"failed": "failed":
{ {
"action": null, "actions": null,
"text": "Vielleicht sollte ich sie erstmal mitnehmen, bevor ich versuche damit irgendwas zu tun?" "text": "Vielleicht sollte ich sie erstmal mitnehmen, bevor ich versuche damit irgendwas zu tun?"
} }
}, },
@ -34,7 +36,7 @@
{ {
"success": "success":
{ {
"action": "add_item matches", "actions": "add_item matches",
"text": "Die nehme ich mal mit ... vielleicht will ich ja spontan was abfackeln" "text": "Die nehme ich mal mit ... vielleicht will ich ja spontan was abfackeln"
} }
}, },
@ -42,7 +44,7 @@
{ {
"success": "success":
{ {
"action": null, "actions": null,
"text": "Streichhoelzer. Man streicht sie und sie sind aus Holz. Macht Sinn, oder?" "text": "Streichhoelzer. Man streicht sie und sie sind aus Holz. Macht Sinn, oder?"
} }
} }
@ -62,24 +64,27 @@
"interactions": { "interactions": {
"use": { "use": {
"success": { "success": {
"action": "set_room_flag entrance lit_up", "actions": [
"set_room_flag entrance lit_up",
"remove_item matches"
],
"text": "Du hast die Kerze mit einem Streichholz entzuendet, es ist nun ein wenig heller im Raum" "text": "Du hast die Kerze mit einem Streichholz entzuendet, es ist nun ein wenig heller im Raum"
}, },
"failed": { "failed": {
"action": null, "actions": null,
"text": "Du kannst die Kerze nicht einfach mit deinen Haenden anzuenden." "text": "Du kannst die Kerze nicht einfach mit deinen Haenden anzuenden."
} }
}, },
"take": { "take": {
"failed": { "failed": {
"action": null, "actions": null,
"text": "DU NICHT NEHMEN KERZE!" "text": "DU NICHT NEHMEN KERZE!"
} }
}, },
"look": "look":
{ {
"success": { "success": {
"action": null, "actions": null,
"text": "Eine dicke Kerze, wie man sie in einer Kirche findet." "text": "Eine dicke Kerze, wie man sie in einer Kirche findet."
} }
} }
@ -93,20 +98,20 @@
"interactions": { "interactions": {
"use": { "use": {
"failed": { "failed": {
"action": null, "actions": null,
"text": "Vielleicht sollte ich diesen eventuell wichtigen Gegenstand ja erstmal mitnehmen ..." "text": "Vielleicht sollte ich diesen eventuell wichtigen Gegenstand ja erstmal mitnehmen ..."
} }
}, },
"take": { "take": {
"success": { "success": {
"action": "add_item key", "actions": "add_item laundry_key",
"text": "Den nehme ich mal lieber mit ..." "text": "Den nehme ich mal lieber mit ..."
} }
}, },
"look": "look":
{ {
"success": { "success": {
"action": null, "actions": null,
"text": "Ein rostiger, alter Schluessel - wo der wohl passt?" "text": "Ein rostiger, alter Schluessel - wo der wohl passt?"
} }
} }
@ -119,6 +124,8 @@
}, },
"laundry": { "laundry": {
"name": "Waschkueche", "name": "Waschkueche",
"identifier": [ "waschkueche", "waschraum" ],
"requires_key": "laundry_key",
"enter_text": "Dies hier scheint die Waschkueche zu sein ... zumindest deutet die uralte, benutzte Unterwaesche darauf hin.", "enter_text": "Dies hier scheint die Waschkueche zu sein ... zumindest deutet die uralte, benutzte Unterwaesche darauf hin.",
"interactables": [], "interactables": [],
"doors": [ "doors": [

View File

@ -13,6 +13,9 @@ class Game:
self.rooms : list[Room] = [] self.rooms : list[Room] = []
self.current_room : Room = None self.current_room : Room = None
def tiges(mett):
pass
def load_game(self, file: str) -> None: def load_game(self, file: str) -> None:
try: try:
with open(file, 'r') as f: with open(file, 'r') as f:
@ -27,9 +30,12 @@ class Game:
room = self.game_data['rooms'][room_id] room = self.game_data['rooms'][room_id]
g_room = Room(room_id, room['name']) g_room = Room(room_id, room['name'])
g_room.identifier = room['identifier']
g_room.enter_text = room['enter_text'] g_room.enter_text = room['enter_text']
g_room.doors = room['doors'] g_room.doors = room['doors']
g_room.interactables = [] g_room.interactables = []
g_room.requires_key = room['requires_key'] if 'requires_key' in room else False
g_room.unlocked = g_room.requires_key == False
g_room.is_start = room['is_start'] if 'is_start' in room else False g_room.is_start = room['is_start'] if 'is_start' in room else False
# Check if we had a starting room already # Check if we had a starting room already
@ -63,6 +69,26 @@ class Game:
return None return None
def get_matching_rooms(self, query : str) -> list[Room]:
rooms : list[Room] = []
query : str = query.lower().strip()
for room in self.rooms:
if room.id == id:
rooms.append(room)
else:
for identifier in room.identifier:
if identifier.lower().strip().startswith(query):
already_there = False
for r in rooms:
if r.id == room.id:
already_there = True
if not already_there:
rooms.append(room)
return rooms
def get_start_room(self) -> Room | None: def get_start_room(self) -> Room | None:
for room in self.rooms: for room in self.rooms:
if room.is_start: if room.is_start:
@ -70,12 +96,16 @@ class Game:
return None return None
def run_action(self, action : str) -> bool: def run_actions(self, actions : str|list[str]) -> bool:
if isinstance(actions, list) == False:
actions = [ actions ]
for action in actions:
print(f"[DEBUG] run_action('{action}')") print(f"[DEBUG] run_action('{action}')")
action_parts = action.split(' ') action_parts = action.lower().split(' ')
action_cmd = action_parts[0] action_cmd = action_parts[0]
action_args = action_parts[1:] if len(action_parts) >= 2 else [] action_args = list(filter(None, action_parts[1:] if len(action_parts) >= 2 else []))
if action_cmd == "set_room_flag": if action_cmd == "set_room_flag":
room = self.get_room(action_args[0]) room = self.get_room(action_args[0])
@ -87,5 +117,8 @@ class Game:
elif action_cmd == "add_item": elif action_cmd == "add_item":
self.inventory.add_item(action_args[0]) self.inventory.add_item(action_args[0])
elif action_cmd == "remove_item":
self.inventory.remove_item(action_args[0])
else: else:
return False return False

View File

@ -45,7 +45,7 @@ class Interactable:
continue continue
if requirement.type == "item": if requirement.type == "item":
if requirement.id not in self.game.inventory.get_items(): if self.game.inventory.has_item(requirement.id) == False:
all_met = False all_met = False
return all_met return all_met
@ -53,8 +53,8 @@ class Interactable:
def can_see(self): def can_see(self):
return self.visible == True or self.room.has_flag(self.visible) return self.visible == True or self.room.has_flag(self.visible)
def run(self, action : str): def run(self, action : str) -> bool:
if not self.can_see(): if self.can_see() == False:
print(f"[{self.room.name}] Du kannst nicht genug sehen, um damit etwas zu tun") print(f"[{self.room.name}] Du kannst nicht genug sehen, um damit etwas zu tun")
return return
@ -64,36 +64,42 @@ class Interactable:
if "success" in self.data["interactions"][action]: if "success" in self.data["interactions"][action]:
print(f"[{self.room.name}] {self.data['interactions'][action]['success']['text']}") print(f"[{self.room.name}] {self.data['interactions'][action]['success']['text']}")
if "action" in self.data["interactions"][action]["success"] and self.data["interactions"][action]["success"]["action"] != None: if "actions" in self.data["interactions"][action]["success"] and self.data["interactions"][action]["success"]["actions"] != None:
self.game.run_action(self.data["interactions"][action]["success"]["action"]) self.game.run_actions(self.data["interactions"][action]["success"]["actions"])
pass return True
elif "failed" in self.data["interactions"][action]: elif "failed" in self.data["interactions"][action]:
print(f"[{self.room.name}] {self.data['interactions'][action]['failed']['text']}") print(f"[{self.room.name}] {self.data['interactions'][action]['failed']['text']}")
if "action" in self.data["interactions"][action]["failed"] and self.data["interactions"][action]["failed"]["action"] != None: if "actions" in self.data["interactions"][action]["failed"] and self.data["interactions"][action]["failed"]["actions"] != None:
self.game.run_action(self.data["interactions"][action]["failed"]["action"]) self.game.run_actions(self.data["interactions"][action]["failed"]["actions"])
pass return False
else:
return False
else: else:
all_met = self.check_action_requirements(action, requirements) all_met = self.check_action_requirements(action, requirements)
if not all_met: if not all_met:
print(f"[{self.room.name}] {self.data['interactions'][action]['failed']['text']}") print(f"[{self.room.name}] {self.data['interactions'][action]['failed']['text']}")
if self.data["interactions"][action]["failed"]["action"] is not None: if self.data["interactions"][action]["failed"]["actions"] is not None:
self.game.run_action(self.data["interactions"][action]["failed"]["action"]) self.game.run_actions(self.data["interactions"][action]["failed"]["actions"])
return False
else: else:
print(f"[{self.room.name}] {self.data['interactions'][action]['success']['text']}") print(f"[{self.room.name}] {self.data['interactions'][action]['success']['text']}")
if self.data["interactions"][action]["success"]["action"] is not None: if self.data["interactions"][action]["success"]["actions"] is not None:
self.game.run_action(self.data["interactions"][action]["success"]["action"]) self.game.run_actions(self.data["interactions"][action]["success"]["actions"])
return True
def use(self): def use(self):
self.run("use") self.run("use")
def take(self): def take(self):
self.run("take") if self.run("take"):
self.room.interactables.remove(self)
def look(self): def look(self):
self.run("look") self.run("look")

View File

@ -1,17 +1,41 @@
from item import Item
class Inventory: class Inventory:
def __init__(self, item_db : dict): def __init__(self, item_db : dict):
self.items = [] self.items : list[str] = []
self.item_db = item_db self.item_db : dict[str,Item] = {}
for id in item_db:
item = item_db[id]
self.item_db[id] = Item(id, item['name'], item['description'])
def add_item(self, item): def add_item(self, item):
self.items.append(item) self.items.append(item)
def get_items(self): def has_item(self, id: str) -> bool:
return self.items return id in self.items
def get_item(self, name : str) -> None|dict: def get_items(self) -> list[Item]:
lname = name.lower().strip() items = []
if lname in self.item_db and lname in self.items: for id in self.items:
return self.item_db[lname] items.append(self.item_db[id])
return items
def remove_item(self, item : str):
if item.lower().strip() in self.items:
self.items.remove(item.lower().strip())
def get_item(self, id : str) -> None|Item:
if id in self.item_db and id in self.items:
return self.item_db[id]
else: else:
return None return None
def get_item_by_name(self, name : str) -> Item|None:
for id in self.item_db:
item = self.item_db[id]
if name.lower().strip() in item.name.lower().strip():
return item
return None

View File

@ -1,8 +1,8 @@
class Item: class Item:
def __init__(self, name, description): def __init__(self, id : str, name : str, description : str):
self.name = name self.id : str = id
self.description = description self.name : str = name
self.is_key = False self.description : str = description
def __str__(self): def __str__(self):
return f"Item: {self.name}" return f"Item: {self.name}"

View File

@ -3,15 +3,19 @@ from game import Game
def main(): def main():
game = Game() game = Game()
game.load_game('data.json') game.load_game('data.json')
print()
has_changed_room = True
while game.is_running: while game.is_running:
if has_changed_room:
print(f"[{game.current_room.name}] {game.current_room.enter_text}") print(f"[{game.current_room.name}] {game.current_room.enter_text}")
has_changed_room = False
cmd = input("[Player] ") cmd = input("[Player] ")
cmd_parts = cmd.split(' ') cmd_parts = cmd.split(' ')
cmd_name = cmd_parts[0] cmd_name = cmd_parts[0]
cmd_args = cmd_parts[1:] if len(cmd_parts) >= 2 else [] cmd_args = list(filter(None, cmd_parts[1:] if len(cmd_parts) >= 2 else []))
if cmd_name.lower().strip() == "quit": if cmd_name.lower().strip() == "quit":
game.is_running = False game.is_running = False
@ -28,8 +32,8 @@ def main():
print(f"[Player] In diesem Raum befindet sich eine Tuer zu {room.name}.") print(f"[Player] In diesem Raum befindet sich eine Tuer zu {room.name}.")
else: else:
rooms = [] rooms = []
for room_id in game.current_room.doors: for query in game.current_room.doors:
rooms.append(game.get_room(room_id).name) rooms.append(game.get_room(query).name)
print(f"[Player] In diesem Raum befinden sich {door_count} Tueren zu {', '.join(rooms)}.") print(f"[Player] In diesem Raum befinden sich {door_count} Tueren zu {', '.join(rooms)}.")
@ -66,7 +70,7 @@ def main():
what = cmd_args[0] what = cmd_args[0]
interactable = game.current_room.get_interactable(what) interactable = game.current_room.get_interactable(what)
if what is None: if what is None or interactable is None:
print(f"[Player] Ich kann {what} nicht nehmen, da es nicht da ist!") print(f"[Player] Ich kann {what} nicht nehmen, da es nicht da ist!")
else: else:
interactable.take() interactable.take()
@ -78,7 +82,7 @@ def main():
what = cmd_args[0] what = cmd_args[0]
interactable = game.current_room.get_interactable(what) interactable = game.current_room.get_interactable(what)
if what is None: if what is None or interactable is None:
print(f"[Player] Ich kann {what} nicht benutzen, da es nicht da ist!") print(f"[Player] Ich kann {what} nicht benutzen, da es nicht da ist!")
else: else:
interactable.use() interactable.use()
@ -88,27 +92,50 @@ def main():
if cmd_name.lower().strip() == "inspect": if cmd_name.lower().strip() == "inspect":
if len(cmd_args) == 1: if len(cmd_args) == 1:
item_name = cmd_args[0].lower().strip() item_name = cmd_args[0].lower().strip()
item = game.inventory.get_item(item_name) item = game.inventory.get_item_by_name(item_name)
if item is not None: if item is not None:
print(f"[Player] {item['name']}: {item['description']}") print(f"[Player] {item.name}: {item.description}")
else: else:
print(f"[Player] {item_name} habe ich nicht bei mir") print(f"[Player] {item_name} habe ich nicht bei mir")
elif len(cmd_args) == 0:
item_count = len(game.inventory.get_items())
if item_count == 0:
print("[Player] Ich habe nichts bei mir.")
elif item_count == 1:
item = game.inventory.get_items()[0]
print(f"[Player] Ich habe gerade nur {item.name}")
else: else:
print(f"[Player] Was soll ich mir denn anschauen?") print("[Player] Ein paar Sachen habe ich schon dabei ...")
for item in game.inventory.get_items():
print(f"[Player] {item.name}")
else:
print("[Player] Was soll ich mir denn anschauen?")
if cmd_name.lower().strip() == "enter": if cmd_name.lower().strip() == "enter":
if len(cmd_args) == 1: if len(cmd_args) == 1:
room_id = cmd_args[0].lower().strip() query = cmd_args[0].lower().strip()
room = game.get_room(room_id) rooms = game.get_matching_rooms(query)
if room is not None and room_id in game.current_room.doors: if len(rooms) == 0:
print(f"[Player] Wenn ich nicht weiss, wo ich rein soll, dann bleibe ich lieber einfach, wo ich bin.")
elif len(rooms) == 1:
room = rooms[0]
if game.current_room.is_adjacent(room):
if room.unlocked or (type(room.requires_key) is str and game.inventory.has_item(room.requires_key)):
print(f"[{game.current_room.name}] Du gehst durch die Tuer zum {room.name}") print(f"[{game.current_room.name}] Du gehst durch die Tuer zum {room.name}")
game.current_room = room game.current_room = room
room.unlocked = True
has_changed_room = True
if type(room.requires_key) is str and game.inventory.has_item(room.requires_key):
game.inventory.remove_item(room.requires_key)
else:
print("[Player] Es scheint so, als brauche ich hier einen passenden Schluessel ...")
else: else:
print(f"[Player] Hier gibt es keine Tuer dort hin ... vielleicht sollte ich ja einfach mit dem Kopf durch die Wand?") print(f"[Player] Hier gibt es keine Tuer dort hin ... vielleicht sollte ich ja einfach mit dem Kopf durch die Wand?")
else: else:
print(f"[Player] Wenn ich nicht weiss, wo ich rein soll, dann bleibe ich lieber einfach, wo ich bin.") print("[Player] Ich bin mir nicht ganz sicher, in welchen Raum ich denn nun gehen soll ...")
print() print()

View File

@ -4,11 +4,14 @@ class Room:
def __init__(self, id : str, name : str): def __init__(self, id : str, name : str):
self.id : str = id self.id : str = id
self.name : str = name self.name : str = name
self.identifier : list[str] = []
self.enter_text : str = "" self.enter_text : str = ""
self.is_start : bool = False self.is_start : bool = False
self.doors : list[str] = [] self.doors : list[str] = []
self.interactables : list[Interactable] = [] self.interactables : list[Interactable] = []
self.flags : list = [] self.flags : list = []
self.requires_key : str|bool = False
self.unlocked : bool = True
def set_flag(self, flag : str) -> None: def set_flag(self, flag : str) -> None:
if flag not in self.flags: if flag not in self.flags:
@ -25,6 +28,13 @@ class Room:
return None return None
def is_adjacent(self, room) -> bool:
if type(room) is not Room:
print("[WARN] room is not of type Room")
return False
return room.id in self.doors
def __str__(self): def __str__(self):
r = f"[Room] ID: {self.id} | Name: {self.name} | IsStart: {self.is_start}" r = f"[Room] ID: {self.id} | Name: {self.name} | IsStart: {self.is_start}"