Initial commit with a mostly working engine.
Basic commands are being parsed. I think the only weird part is the 'use' command because it needs to possibly target two things. A tiny test example is provided in __main__, this will probably be broken out later. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
113
agame/game.py
Normal file
113
agame/game.py
Normal file
@@ -0,0 +1,113 @@
|
||||
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
|
||||
Reference in New Issue
Block a user