Files
ages/agame/game.py

131 lines
3.6 KiB
Python
Raw Normal View History

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(),
ReadTrigger(),
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(f"(({self.room.name}))")
if isinstance(self.room.desc, str):
self.say(self.room.desc)
else:
assert isinstance(
self.room.desc, Sequence
), f"room.desc is not a list or a string from room id {room.id}"
self.say(*self.room.desc)
# Look at revealed text
for (index, item) in enumerate(self.room.items.values()):
if not item.revealed or item.room_desc is None or item.room_desc == []:
continue
if index != 0:
# Space this out with blank lines
self.say()
if isinstance(item.room_desc, str):
self.say(item.room_desc)
else:
assert isinstance(item.room_desc, Sequence)
self.say(*item.room_desc)
def say(self, *lines: str):
"Format, colorize, wrap, and print the message."
if lines:
head = textwrap.fill(lines[0])
print(colorize(head))
for line in lines[1:]:
message = textwrap.fill(line)
print()
print(colorize(message))
else:
print()
@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