Files
fedora_openclaw d4fd5561c2 Fix keycard mismatch and typo in locked-door message
Inventory stored keycards under their full item_id (keycard_red) while
Room.locked_by/has_keycard checked against the plain color (red), so
the Waffentresor always reported itself as locked even with the
keycard in hand. Also fixes "rede Keycard" -> "rote Keycard".
2026-07-05 20:22:00 +02:00

113 lines
4.1 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Room-Klasse und Hub-Navigation: verbundene Raeume statt linearer Szenen."""
from doom_matrix.engine.ui import Colors, slow_print, menu, section_title
from doom_matrix.engine import cheats
KEYCARD_COLOR_DE = {"red": "rote", "blue": "blaue", "yellow": "gelbe"}
class Room:
def __init__(self, room_id, name, description, exits=None, item_ids=None,
locked_by=None, on_enter=None, one_time_event=True):
self.room_id = room_id
self.name = name
self.description = description
self.exits = exits or {} # direction_label -> room_id
self.item_ids = item_ids or [] # Item-IDs, die hier liegen
self.locked_by = locked_by # Keycard-Farbe oder None
self.on_enter = on_enter # Funktion(player, game_ctx) -> optionales Signal ("leave", room_id) oder None
self.one_time_event = one_time_event
self._event_triggered = False
self.visited = False
class Hub:
"""Eine Sammlung verbundener Raeume fuer einen Layer."""
def __init__(self, rooms, start_room_id):
self.rooms = {r.room_id: r for r in rooms}
self.current_id = start_room_id
def current(self):
return self.rooms[self.current_id]
def explore(self, player, item_registry, game_ctx=None):
"""
Haupt-Loop fuer die Raum-Navigation.
item_registry: dict item_id -> Item-Objekt (aus data/items.json geladen)
game_ctx: beliebiges Kontext-Objekt, das an on_enter-Callbacks weitergereicht wird.
Gibt zurueck, sobald ein on_enter-Callback ein Signal-Tuple ("leave", next_scene) liefert.
"""
while True:
room = self.current()
self._describe(room)
if not room.visited:
room.visited = True
self._collect_items(room, player, item_registry)
if room.on_enter and (not room.one_time_event or not room._event_triggered):
room._event_triggered = True
result = room.on_enter(player, game_ctx)
if result is not None:
return result
signal = self._prompt(player, room)
if signal is not None:
return signal
def _describe(self, room):
section_title(room.name, Colors.CYAN)
slow_print(room.description)
def _collect_items(self, room, player, item_registry):
for item_id in room.item_ids:
item = item_registry.get(item_id)
if item:
player.inventory.add(item)
slow_print(f"{Colors.GREEN}Gefunden: {item.name}{Colors.END} - {item.description}")
def _prompt(self, player, room):
options = []
exit_keys = list(room.exits.items())
for i, (label, _) in enumerate(exit_keys):
options.append((str(i + 1), label))
options.append(("s", "Status anzeigen"))
options.append(("i", "Inventar anzeigen"))
choice = menu(options, "Wohin")
if cheats.try_cheat(choice, player):
return None
if choice == "s":
player.show_status()
return None
if choice == "i":
lines = player.inventory.list_display()
if lines:
for line in lines:
print(f" {Colors.YELLOW}{line}{Colors.END}")
else:
print(f" {Colors.DIM}Inventar leer.{Colors.END}")
return None
try:
idx = int(choice) - 1
if 0 <= idx < len(exit_keys):
_, target_id = exit_keys[idx]
target = self.rooms.get(target_id)
if target and target.locked_by and not player.inventory.has_keycard(target.locked_by):
color_de = KEYCARD_COLOR_DE.get(target.locked_by, target.locked_by)
slow_print(f"\n{Colors.RED}Diese Tuer benoetigt eine {color_de} Keycard.{Colors.END}")
return None
self.current_id = target_id
return None
except ValueError:
pass
slow_print(f"{Colors.YELLOW}Das geht hier nicht.{Colors.END}")
return None