import dataclasses import textwrap from typing import Any, MutableMapping, Match, Optional, Sequence from agame.action import Action from agame.color import colorize from agame.item import Item, ItemInst from agame.room import Room from agame.trigger import * __all__ = ( "Database", "Game", ) @dataclasses.dataclass class Database: # All items available to the game. items: MutableMapping[str, Item] = dataclasses.field(default_factory=dict) # All rooms available to the game. rooms: MutableMapping[str, Room] = dataclasses.field(default_factory=dict) def add_item(self, item: Item): self.items[item.id] = item def add_items(self, *items: Item): for item in items: self.add_item(item) def add_room(self, room: Room): self.rooms[room.id] = room def add_rooms(self, *rooms: Room): for room in rooms: self.add_room(room) @dataclasses.dataclass class Game: # Game room/items database database: Database # Current room. room: Room # Player inventory. inventory: MutableMapping[str, ItemInst] = dataclasses.field(default_factory=dict) # Variables. vars: MutableMapping[str, Any] = dataclasses.field(default_factory=dict) def run_command(self, line: str): line = line.strip() if not line: return triggers: Sequence[Trigger] = [ GetTrigger(), UseTrigger(), PutTrigger(), LookTrigger(), OpenTrigger(), CloseTrigger(), GoTrigger(), ] trigger = None match: Optional[Match] = None for t in triggers: match = t.pattern().fullmatch(line) if match: trigger = t break if not trigger: self.say("I'm not sure what you mean.") return assert match, "why were no patterns matched?" trigger.trigger(self, match) def do_actions(self, actions: Sequence[Action]): "Executes the supplied actions." for action in actions: action.act(self) def print_room(self): "Prints this room's description." self.say(self.room.name) self.say() self.say(self.room.desc) # Look at revealed text for item in self.room.items.values(): if not item.revealed or item.room_desc is None: continue if item.room_desc == "": # TODO - pluralization, 'a' vs 'an' self.say(f"You see a (({item.name})).") else: self.say(item.room_desc) def say(self, message: Optional[str] = None): "Format, colorize, wrap, and print the message." message = message or "" message = textwrap.fill(message) print(colorize(message)) @property def rooms(self): "Shortcut property for `game.database.rooms`." return self.database.rooms @property def items(self): "Shortcut property for `game.database.items`." return self.database.items