* Add RevealAction/UnrevealAction for revealing/hiding items in a room * Add a lot of checks for items being revealed when it's attempted to be triggered * Implement TeleportAction (mostly) * For all Check* family of actions, the `yes` and `no` values may be just be a single action instead of an array of actions * Change up how room descriptions and stuff work, mostly so that you can specify multiple lines in an array so you can preserve paragraph breaks when displayed. * Example game has some more content Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
132 lines
3.7 KiB
Python
132 lines
3.7 KiB
Python
import dataclasses
|
|
from typing import Mapping, Optional, Sequence, Union
|
|
from agame.action import Action
|
|
|
|
|
|
__all__ = (
|
|
"ItemInst",
|
|
"Item",
|
|
)
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class ItemInst:
|
|
"""
|
|
An instance of an item in the game.
|
|
"""
|
|
|
|
# Reference to the global item that this is an instance of.
|
|
item: "Item"
|
|
|
|
# Gets whether this item can be taken.
|
|
fixed: bool = False
|
|
|
|
# Gets how many of this item instance are present in this stack.
|
|
count: int = 1
|
|
|
|
# Gets whether this item is revealed or not.
|
|
revealed: bool = True
|
|
|
|
@property
|
|
def id(self) -> str:
|
|
return self.item.id
|
|
|
|
@property
|
|
def name(self) -> str:
|
|
return self.item.name
|
|
|
|
@property
|
|
def desc(self) -> Optional[str]:
|
|
return self.item.desc
|
|
|
|
@property
|
|
def synonyms(self) -> Sequence[str]:
|
|
return self.item.synonyms
|
|
|
|
@property
|
|
def room_desc(self) -> Optional[Union[str, Sequence[str]]]:
|
|
return self.item.room_desc
|
|
|
|
@property
|
|
def triggers(self) -> Mapping[str, Sequence[Action]]:
|
|
return self.item.triggers
|
|
|
|
@property
|
|
def use_actions(self) -> Mapping[str, Sequence[Action]]:
|
|
return self.item.use_actions
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class Item:
|
|
"""
|
|
A game item.
|
|
"""
|
|
|
|
# The ID of this item. This is how items are looked up in the game.
|
|
id: str
|
|
|
|
# The printable name of this item.
|
|
name: str
|
|
|
|
# A long description for this item.
|
|
desc: Optional[str] = None
|
|
|
|
# A list of all synonyms for this item.
|
|
synonyms: Sequence[str] = dataclasses.field(default_factory=list)
|
|
|
|
# The description that is used in the context of a room's `look` command.
|
|
#
|
|
# When someone wants to look at the entire room, all items that have been
|
|
# revealed will also be displayed.
|
|
#
|
|
# If you want to disable this behavior entirely, `room_desc` should be set
|
|
# to `None`.
|
|
#
|
|
# If you want to use the default text, "You see a (({item.name}))",
|
|
# `room_desc` should be set to the blank string, `""`.
|
|
#
|
|
# Otherwise, the `room_desc` string will be colorized and printed as
|
|
# written.
|
|
room_desc: Optional[Union[str, Sequence[str]]] = None
|
|
|
|
# A list of triggers that a game may use. Since this is just a mapping of
|
|
# strings to action sequences, only one set of actions is allowed per
|
|
# trigger.
|
|
#
|
|
# Valid triggers include:
|
|
# * get
|
|
# * use
|
|
# * put
|
|
# * look
|
|
# * open
|
|
# * close
|
|
# ...more to come
|
|
triggers: Mapping[str, Sequence[Action]] = dataclasses.field(default_factory=dict)
|
|
|
|
# A mapping of other items that this item may be used with, specifically on
|
|
# the USE command.
|
|
#
|
|
# USE is a strange beast, because instead of just one implicit target (which
|
|
# is verified to exist by the trigger, of all things) we have *two* targets:
|
|
# the subject and the direct object. And not always!
|
|
#
|
|
# For example, we have an item, paintbrush. These are some options:
|
|
# use paintbrush # <- on what?
|
|
# use paintbrush on canvas # <- you paint a beautiful masterpiece.
|
|
# use paintbrush on car # <- that's not allowed (custom text)
|
|
# use paintbrush on fake item # <- that item doesn't exist
|
|
#
|
|
# We can't really represent this with the current str -> sequence[action]
|
|
# stuff we have in place right now, so a special field will be good enough
|
|
# until a more insane/robust solution is implemented.
|
|
use_actions: Mapping[str, Sequence[Action]] = dataclasses.field(
|
|
default_factory=dict
|
|
)
|
|
|
|
def create_inst(self, *args, **kwargs):
|
|
"""
|
|
Creates a new item instance, passing the supplied args and kwargs to the
|
|
ItemInst constructor.
|
|
"""
|
|
return ItemInst(item=self, *args, **kwargs)
|