diff --git a/agame/__main__.py b/agame/__main__.py index 991c508..3f94116 100644 --- a/agame/__main__.py +++ b/agame/__main__.py @@ -2,6 +2,7 @@ import argparse import importlib.util from pathlib import Path import sys +from agame.color import colorize # Parse args @@ -21,11 +22,18 @@ game_module = importlib.import_module(package) game = game_module.game # type: ignore # Run -game.print_room() +game.say("=" * 70) +game.say("Type ((help)) for help, or ((quit)) to exit.") +game.say("=" * 70) +game.say() + +game.do_teleport_actions() while True: try: game.say() - line = input("> ") + line = input(colorize("{{>}} ")) + if line.lower() == "quit": + break game.say() game.run_command(line) except (KeyboardInterrupt, EOFError): diff --git a/agame/action.py b/agame/action.py index 80b8619..be20a0a 100644 --- a/agame/action.py +++ b/agame/action.py @@ -11,8 +11,9 @@ __all__ = ( "Action", "SleepAction", "PrintAction", - "TeleportAction", "PrintRoomAction", + "PlayerInputAction", + "TeleportAction", "GetAction", "CheckInvItemsAction", "CheckRoomItemsAction", @@ -73,6 +74,35 @@ class PrintAction(Action): game.say(line) +@dataclasses.dataclass +class PrintRoomAction(Action): + """ + Prints the current room. + """ + + def act(self, game: "Game"): + game.say("", "." * 70, "") + game.print_room() + + +@dataclasses.dataclass +class PlayerInputAction(Action): + """ + Waits for a user to press a key, or press enter, or whatever. + """ + + prompt: str = "Press enter to continue..." + store_var_id: Optional[str] = None + + def act(self, game: "Game"): + line = input(self.prompt) + if self.store_var_id: + assert ( + self.store_var_id in game.vars + ), f"could not find var with id {self.store_var_id}" + game.vars[self.store_var_id] = line + + @dataclasses.dataclass class TeleportAction(Action): """ @@ -90,22 +120,12 @@ class TeleportAction(Action): assert ( self.room_id in game.database.rooms ), f"could not find room with id {self.room_id}" - game.room = game.database.rooms[self.room_id] + game.teleport(game.database.rooms[self.room_id]) if self.announce: game.say("", "." * 70, "") game.print_room() -class PrintRoomAction(Action): - """ - Prints the current room. - """ - - def act(self, game: "Game"): - game.say("", "." * 70, "") - game.print_room() - - @dataclasses.dataclass class GetAction(Action): """ diff --git a/agame/game.py b/agame/game.py index a77161c..880314d 100644 --- a/agame/game.py +++ b/agame/game.py @@ -1,6 +1,6 @@ import dataclasses import textwrap -from typing import Any, MutableMapping, List, Match, Optional, Sequence +from typing import Any, MutableMapping, List, Match, Optional, Sequence, Union from agame.action import Action from agame.color import colorize from agame.item import Item, ItemInst @@ -98,6 +98,17 @@ class Game: for action in actions: action.act(self) + def do_teleport_actions(self): + "Executes the teleport actions for the current room." + self.do_actions(self.room.teleport_actions) + + def teleport(self, room: Union[str, Room]): + if isinstance(room, str): + assert room in self.database.rooms, f"could not find room with id {room}" + room = self.database.rooms[room] + self.room = room + self.do_teleport_actions() + def print_room(self): "Prints this room's description." self.say(f"(({self.room.name}))") diff --git a/agame/room.py b/agame/room.py index bd5031a..822116c 100644 --- a/agame/room.py +++ b/agame/room.py @@ -3,6 +3,9 @@ from typing import MutableMapping, Optional, Sequence, Union, TYPE_CHECKING from agame.item import ItemInst from agame.util import search_item_name +if TYPE_CHECKING: + from agame.action import Action + __all__ = ("Room",) @@ -13,6 +16,8 @@ class Room: name: str desc: Union[str, Sequence[str]] items: MutableMapping[str, ItemInst] + # Actions that are executed upon teleport or entrance to this room. + teleport_actions: Sequence["Action"] def __init__( self, @@ -20,6 +25,7 @@ class Room: name: str, desc: Union[str, Sequence[str]], items: Union[Sequence[ItemInst], MutableMapping[str, ItemInst]], + teleport_actions: Sequence["Action"] = [], ): self.id = id self.name = name @@ -28,6 +34,7 @@ class Room: self.items = items else: self.items = {item.id: item for item in items} + self.teleport_actions = teleport_actions def search_item_name(self, item_name: str) -> Optional[ItemInst]: """ diff --git a/agame/trigger.py b/agame/trigger.py index 62af989..87a5a9d 100644 --- a/agame/trigger.py +++ b/agame/trigger.py @@ -84,6 +84,7 @@ class HelpTrigger(Trigger): game.say() for trigger in game.database.triggers: game.say(trigger.help()) + game.say("To quit the game, type ((quit)).") class GetTrigger(Trigger): diff --git a/examplegame/__init__.py b/examplegame/__init__.py index 20a8c08..4e15984 100644 --- a/examplegame/__init__.py +++ b/examplegame/__init__.py @@ -13,5 +13,5 @@ from . import vars # Build the game state game = Game( database=database, - room=database.rooms["cabin_inside"], + room=database.rooms["prelude"], ) diff --git a/examplegame/rooms.py b/examplegame/rooms.py index 4d95518..adaff2a 100644 --- a/examplegame/rooms.py +++ b/examplegame/rooms.py @@ -4,6 +4,61 @@ from agame.room import Room from agame.trigger import * from . import database +################################################################################ +# Game intro +################################################################################ +database.add_room( + Room( + id="prelude", + name="Prelude", + desc="", + items={}, + teleport_actions=[ + PrintAction( + "." * 70, + "Many stories have been told about this place. Some are tall " + "tales and mostly contradictory. Some others, however, are true.", + # + "This is one of those stories.", + "." * 70, + ), + PlayerInputAction(), + PrintAction( + "." * 70, + # + "There used to be trees here. Fifteen years ago, we were sitting " + "in the shade, telling stories about last summer and what we hope " + "would happen next, our laughter unable to break past the leaves " + "and branches around us.", + # + "It is now desolate. Only the wind shakes the dry branches of the " + "remaining trees. They chitter and clack; any other noise is a " + "long echo. Nothing else stands tall enough to block the sound.", + # + "No animals patrol the sky nor ground. Life has left this place.", + "." * 70, + ), + PlayerInputAction(), + PrintAction( + "." * 70, + "It is because of the ((machine)).", + "." * 70, + ), + PlayerInputAction(), + SleepAction(1), + PrintAction("."), + SleepAction(1), + PrintAction(".."), + SleepAction(1), + PrintAction("..."), + SleepAction(1), + PrintAction("You awaken from a fitful sleep. Where are you again?"), + PlayerInputAction(), + TeleportAction("cabin_inside"), + ], + ) +) + ################################################################################ # Inside the cabin ################################################################################ @@ -200,6 +255,7 @@ database.add_items( id="cabin_outside_west_path", name="Western path", synonyms=( + "path", "path to west", "path to the west", "path leading west",