Format code with black. Add makefile to run fmt/tests
This commit is contained in:
parent
d00bce9288
commit
c2c7fa311a
299 changed files with 19037 additions and 11611 deletions
|
|
@ -35,7 +35,7 @@ from evennia import syscmdkeys
|
|||
from evennia.utils import variable_from_module
|
||||
from .utils import create_evscaperoom_object
|
||||
|
||||
_AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
|
||||
_AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit(".", 1))
|
||||
|
||||
_RE_ARGSPLIT = re.compile(r"\s(with|on|to|in|at)\s", re.I + re.U)
|
||||
_RE_EMOTE_SPEECH = re.compile(r"(\".*?\")|(\'.*?\')")
|
||||
|
|
@ -111,6 +111,7 @@ class CmdEvscapeRoom(Command):
|
|||
command [<obj1>|<arg1>] [<prep> <obj2>|<arg2>]
|
||||
|
||||
"""
|
||||
|
||||
# always separate the command from any args with a space
|
||||
arg_regex = r"(/\w+?(\s|$))|\s|$"
|
||||
help_category = "Evscaperoom"
|
||||
|
|
@ -210,6 +211,7 @@ class CmdGiveUp(CmdEvscapeRoom):
|
|||
Abandons your attempts at escaping and of ever winning the pie-eating contest.
|
||||
|
||||
"""
|
||||
|
||||
key = "give up"
|
||||
aliases = ("abort", "chicken out", "quit", "q")
|
||||
|
||||
|
|
@ -224,10 +226,10 @@ class CmdGiveUp(CmdEvscapeRoom):
|
|||
warning = _QUIT_WARNING_CAN_COME_BACK.format(roomname=self.room.name)
|
||||
warning = _QUIT_WARNING.format(warning=warning)
|
||||
|
||||
ret = yield(warning)
|
||||
ret = yield (warning)
|
||||
if ret.upper() == "QUIT":
|
||||
self.msg("|R ... Oh. Okay then. Off you go.|n\n")
|
||||
yield(1)
|
||||
yield (1)
|
||||
|
||||
self.room.log(f"QUIT: {self.caller.key} used the quit command")
|
||||
|
||||
|
|
@ -250,6 +252,7 @@ class CmdLook(CmdEvscapeRoom):
|
|||
look [obj]
|
||||
|
||||
"""
|
||||
|
||||
key = "look"
|
||||
aliases = ["l", "ls"]
|
||||
obj1_search = None
|
||||
|
|
@ -276,6 +279,7 @@ class CmdWho(CmdEvscapeRoom, default_cmds.CmdWho):
|
|||
server as a whole.
|
||||
|
||||
"""
|
||||
|
||||
key = "who"
|
||||
|
||||
obj1_search = False
|
||||
|
|
@ -285,7 +289,7 @@ class CmdWho(CmdEvscapeRoom, default_cmds.CmdWho):
|
|||
|
||||
caller = self.caller
|
||||
|
||||
if self.args == 'all':
|
||||
if self.args == "all":
|
||||
table = self.style_table("|wName", "|wRoom")
|
||||
sessions = SESSION_HANDLER.get_sessions()
|
||||
for session in sessions:
|
||||
|
|
@ -298,15 +302,19 @@ class CmdWho(CmdEvscapeRoom, default_cmds.CmdWho):
|
|||
account = session.get_account()
|
||||
table.add_row(account.get_display_name(caller), "(OOC)")
|
||||
|
||||
txt = (f"|cPlayers active on this server|n:\n{table}\n"
|
||||
"(use 'who' to see only those in your room)")
|
||||
txt = (
|
||||
f"|cPlayers active on this server|n:\n{table}\n"
|
||||
"(use 'who' to see only those in your room)"
|
||||
)
|
||||
|
||||
else:
|
||||
chars = [f"{obj.get_display_name(caller)} - {obj.db.desc.strip()}"
|
||||
for obj in self.room.get_all_characters()
|
||||
if obj != caller]
|
||||
chars = [
|
||||
f"{obj.get_display_name(caller)} - {obj.db.desc.strip()}"
|
||||
for obj in self.room.get_all_characters()
|
||||
if obj != caller
|
||||
]
|
||||
chars = "\n".join([f"{caller.key} - {caller.db.desc.strip()} (you)"] + chars)
|
||||
txt = (f"|cPlayers in this room (room-name '{self.room.name}')|n:\n {chars}")
|
||||
txt = f"|cPlayers in this room (room-name '{self.room.name}')|n:\n {chars}"
|
||||
caller.msg(txt)
|
||||
|
||||
|
||||
|
|
@ -320,6 +328,7 @@ class CmdSpeak(Command):
|
|||
shout
|
||||
|
||||
"""
|
||||
|
||||
key = "say"
|
||||
aliases = [";", "shout", "whisper"]
|
||||
arg_regex = r"\w|\s|$"
|
||||
|
|
@ -329,7 +338,7 @@ class CmdSpeak(Command):
|
|||
args = self.args.strip()
|
||||
caller = self.caller
|
||||
action = self.cmdname
|
||||
action = "say" if action == ';' else action
|
||||
action = "say" if action == ";" else action
|
||||
room = self.caller.location
|
||||
|
||||
if not self.args:
|
||||
|
|
@ -365,6 +374,7 @@ class CmdEmote(Command):
|
|||
emote /me points to /box and /lever.
|
||||
|
||||
"""
|
||||
|
||||
key = "emote"
|
||||
aliases = [":", "pose"]
|
||||
arg_regex = r"\w|\s|$"
|
||||
|
|
@ -379,7 +389,7 @@ class CmdEmote(Command):
|
|||
emote = self.args.strip()
|
||||
|
||||
if not emote:
|
||||
self.caller.msg("Usage: emote /me points to /door, saying \"look over there!\"")
|
||||
self.caller.msg('Usage: emote /me points to /door, saying "look over there!"')
|
||||
return
|
||||
|
||||
speech_clr = "|c"
|
||||
|
|
@ -438,6 +448,7 @@ class CmdFocus(CmdEvscapeRoom):
|
|||
looks and what actions is available.
|
||||
|
||||
"""
|
||||
|
||||
key = "focus"
|
||||
aliases = ["examine", "e", "ex", "unfocus"]
|
||||
|
||||
|
|
@ -454,7 +465,9 @@ class CmdFocus(CmdEvscapeRoom):
|
|||
return
|
||||
|
||||
if self.focus != self.obj1:
|
||||
self.room.msg_room(self.caller, f"~You ~examine *{self.obj1.key}.", skip_caller=True)
|
||||
self.room.msg_room(
|
||||
self.caller, f"~You ~examine *{self.obj1.key}.", skip_caller=True
|
||||
)
|
||||
self.focus = self.obj1
|
||||
self.obj1.at_focus(self.caller)
|
||||
elif not self.focus:
|
||||
|
|
@ -473,11 +486,13 @@ class CmdOptions(CmdEvscapeRoom):
|
|||
options
|
||||
|
||||
"""
|
||||
|
||||
key = "options"
|
||||
aliases = ["option"]
|
||||
|
||||
def func(self):
|
||||
from .menu import run_option_menu
|
||||
|
||||
run_option_menu(self.caller, self.session)
|
||||
|
||||
|
||||
|
|
@ -486,6 +501,7 @@ class CmdGet(CmdEvscapeRoom):
|
|||
Use focus / examine instead.
|
||||
|
||||
"""
|
||||
|
||||
key = "get"
|
||||
aliases = ["inventory", "i", "inv", "give"]
|
||||
|
||||
|
|
@ -501,6 +517,7 @@ class CmdRerouter(default_cmds.MuxCommand):
|
|||
<action> [arg]
|
||||
|
||||
"""
|
||||
|
||||
# reroute commands from the default cmdset to the catch-all
|
||||
# focus function where needed. This allows us to override
|
||||
# individual default commands without replacing the entire
|
||||
|
|
@ -512,9 +529,10 @@ class CmdRerouter(default_cmds.MuxCommand):
|
|||
def func(self):
|
||||
# reroute to another command
|
||||
from evennia.commands import cmdhandler
|
||||
cmdhandler.cmdhandler(self.session, self.raw_string,
|
||||
cmdobj=CmdFocusInteraction(),
|
||||
cmdobj_key=self.cmdname)
|
||||
|
||||
cmdhandler.cmdhandler(
|
||||
self.session, self.raw_string, cmdobj=CmdFocusInteraction(), cmdobj_key=self.cmdname
|
||||
)
|
||||
|
||||
|
||||
class CmdFocusInteraction(CmdEvscapeRoom):
|
||||
|
|
@ -532,6 +550,7 @@ class CmdFocusInteraction(CmdEvscapeRoom):
|
|||
as keys into the method.
|
||||
|
||||
"""
|
||||
|
||||
# all commands not matching something else goes here.
|
||||
key = syscmdkeys.CMD_NOMATCH
|
||||
|
||||
|
|
@ -571,19 +590,18 @@ class CmdStand(CmdEvscapeRoom):
|
|||
Stand up from whatever position you had.
|
||||
|
||||
"""
|
||||
|
||||
key = "stand"
|
||||
|
||||
def func(self):
|
||||
|
||||
# Positionable objects will set this flag on you.
|
||||
pos = self.caller.attributes.get(
|
||||
"position", category=self.room.tagcategory)
|
||||
pos = self.caller.attributes.get("position", category=self.room.tagcategory)
|
||||
|
||||
if pos:
|
||||
# we have a position, clean up.
|
||||
obj, position = pos
|
||||
self.caller.attributes.remove(
|
||||
"position", category=self.room.tagcategory)
|
||||
self.caller.attributes.remove("position", category=self.room.tagcategory)
|
||||
del obj.db.positions[self.caller]
|
||||
self.room.msg_room(self.caller, "~You ~are back standing on the floor again.")
|
||||
else:
|
||||
|
|
@ -598,8 +616,9 @@ class CmdHelp(CmdEvscapeRoom, default_cmds.CmdHelp):
|
|||
help <topic> or <command>
|
||||
|
||||
"""
|
||||
key = 'help'
|
||||
aliases = ['?']
|
||||
|
||||
key = "help"
|
||||
aliases = ["?"]
|
||||
|
||||
def func(self):
|
||||
if self.obj1:
|
||||
|
|
@ -608,8 +627,10 @@ class CmdHelp(CmdEvscapeRoom, default_cmds.CmdHelp):
|
|||
if not helptxt:
|
||||
helptxt = f"There is no help to be had about {self.obj1.get_display_name(self.caller)}."
|
||||
else:
|
||||
helptxt = (f"|y{self.obj1.get_display_name(self.caller)}|n is "
|
||||
"likely |rnot|n part of any of the Jester's trickery.")
|
||||
helptxt = (
|
||||
f"|y{self.obj1.get_display_name(self.caller)}|n is "
|
||||
"likely |rnot|n part of any of the Jester's trickery."
|
||||
)
|
||||
elif self.arg1:
|
||||
# fall back to the normal help command
|
||||
super().func()
|
||||
|
|
@ -621,6 +642,7 @@ class CmdHelp(CmdEvscapeRoom, default_cmds.CmdHelp):
|
|||
|
||||
# Debug/help command
|
||||
|
||||
|
||||
class CmdCreateObj(CmdEvscapeRoom):
|
||||
"""
|
||||
Create command, only for Admins during debugging.
|
||||
|
|
@ -631,6 +653,7 @@ class CmdCreateObj(CmdEvscapeRoom):
|
|||
Here, :typeclass is a class in evscaperoom.commands
|
||||
|
||||
"""
|
||||
|
||||
key = "createobj"
|
||||
aliases = ["cobj"]
|
||||
locks = "cmd:perm(Admin)"
|
||||
|
|
@ -668,6 +691,7 @@ class CmdSetFlag(CmdEvscapeRoom):
|
|||
flag <obj> with <flagname>
|
||||
|
||||
"""
|
||||
|
||||
key = "flag"
|
||||
aliases = ["setflag"]
|
||||
locks = "cmd:perm(Admin)"
|
||||
|
|
@ -700,6 +724,7 @@ class CmdJumpState(CmdEvscapeRoom):
|
|||
jumpstate <statename>
|
||||
|
||||
"""
|
||||
|
||||
key = "jumpstate"
|
||||
locks = "cmd:perm(Admin)"
|
||||
|
||||
|
|
@ -713,22 +738,26 @@ class CmdJumpState(CmdEvscapeRoom):
|
|||
|
||||
# Helper command to start the Evscaperoom menu
|
||||
|
||||
|
||||
class CmdEvscapeRoomStart(Command):
|
||||
"""
|
||||
Go to the Evscaperoom start menu
|
||||
|
||||
"""
|
||||
|
||||
key = "evscaperoom"
|
||||
help_category = "EvscapeRoom"
|
||||
|
||||
def func(self):
|
||||
# need to import here to break circular import
|
||||
from .menu import run_evscaperoom_menu
|
||||
|
||||
run_evscaperoom_menu(self.caller)
|
||||
|
||||
|
||||
# command sets
|
||||
|
||||
|
||||
class CmdSetEvScapeRoom(CmdSet):
|
||||
priority = 1
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ def _move_to_room(caller, raw_string, **kwargs):
|
|||
Helper to move a user to a room
|
||||
|
||||
"""
|
||||
room = kwargs['room']
|
||||
room = kwargs["room"]
|
||||
room.msg_char(caller, f"Entering room |c'{room.name}'|n ...")
|
||||
room.msg_room(caller, f"~You |c~were just tricked in here too!|n")
|
||||
# we do a manual move since we don't want all hooks to fire.
|
||||
|
|
@ -78,7 +78,9 @@ def _create_new_room(caller, raw_string, **kwargs):
|
|||
_move_to_room(caller, "", room=room)
|
||||
|
||||
nrooms = EvscapeRoom.objects.all().count()
|
||||
logger.log_info(f"Evscaperoom: {caller.key} created room '{key}' (#{room.id}). Now {nrooms} room(s) active.")
|
||||
logger.log_info(
|
||||
f"Evscaperoom: {caller.key} created room '{key}' (#{room.id}). Now {nrooms} room(s) active."
|
||||
)
|
||||
|
||||
room.log(f"JOIN: {caller.key} created and joined room")
|
||||
return "node_quit", {"quiet": True}
|
||||
|
|
@ -96,10 +98,12 @@ def _get_all_rooms(caller):
|
|||
if not room.pk or room.db.deleting:
|
||||
continue
|
||||
stats = room.db.stats or {"progress": 0}
|
||||
progress = int(stats['progress'])
|
||||
progress = int(stats["progress"])
|
||||
nplayers = len(room.get_all_characters())
|
||||
desc = (f"Join room |c'{room.get_display_name(caller)}'|n "
|
||||
f"(complete: {progress}%, players: {nplayers})")
|
||||
desc = (
|
||||
f"Join room |c'{room.get_display_name(caller)}'|n "
|
||||
f"(complete: {progress}%, players: {nplayers})"
|
||||
)
|
||||
room_map[desc] = room
|
||||
room_option_descs.append(desc)
|
||||
caller.ndb._menutree.room_map = room_map
|
||||
|
|
@ -121,24 +125,34 @@ def node_start(caller, raw_string, **kwargs):
|
|||
|
||||
# build a list of available rooms
|
||||
options = (
|
||||
{"key": ("|y[s]et your description|n", "set your description",
|
||||
"set", "desc", "description", "s"),
|
||||
"goto": "node_set_desc"},
|
||||
{"key": ("|y[c]reate/join a new room|n", "create a new room", "create", "c"),
|
||||
"goto": "node_create_room"},
|
||||
{"key": ("|r[q]uit the challenge", "quit", "q"),
|
||||
"goto": "node_quit"})
|
||||
{
|
||||
"key": (
|
||||
"|y[s]et your description|n",
|
||||
"set your description",
|
||||
"set",
|
||||
"desc",
|
||||
"description",
|
||||
"s",
|
||||
),
|
||||
"goto": "node_set_desc",
|
||||
},
|
||||
{
|
||||
"key": ("|y[c]reate/join a new room|n", "create a new room", "create", "c"),
|
||||
"goto": "node_create_room",
|
||||
},
|
||||
{"key": ("|r[q]uit the challenge", "quit", "q"), "goto": "node_quit"},
|
||||
)
|
||||
|
||||
return text, options
|
||||
|
||||
|
||||
def node_set_desc(caller, raw_string, **kwargs):
|
||||
|
||||
current_desc = kwargs.get('desc', caller.db.desc)
|
||||
current_desc = kwargs.get("desc", caller.db.desc)
|
||||
|
||||
text = ("Your current description is\n\n "
|
||||
f" \"{current_desc}\""
|
||||
"\n\nEnter your new description!")
|
||||
text = (
|
||||
"Your current description is\n\n " f' "{current_desc}"' "\n\nEnter your new description!"
|
||||
)
|
||||
|
||||
def _temp_description(caller, raw_string, **kwargs):
|
||||
desc = raw_string.strip()
|
||||
|
|
@ -154,12 +168,10 @@ def node_set_desc(caller, raw_string, **kwargs):
|
|||
return "node_start"
|
||||
|
||||
options = (
|
||||
{"key": "_default",
|
||||
"goto": _temp_description},
|
||||
{"key": ("|g[a]ccept", "a"),
|
||||
"goto": (_set_description, {"desc": current_desc})},
|
||||
{"key": ("|r[c]ancel", "c"),
|
||||
"goto": "node_start"})
|
||||
{"key": "_default", "goto": _temp_description},
|
||||
{"key": ("|g[a]ccept", "a"), "goto": (_set_description, {"desc": current_desc})},
|
||||
{"key": ("|r[c]ancel", "c"), "goto": "node_start"},
|
||||
)
|
||||
return text, options
|
||||
|
||||
|
||||
|
|
@ -168,34 +180,31 @@ def node_create_room(caller, raw_string, **kwargs):
|
|||
text = _CREATE_ROOM_TEXT
|
||||
|
||||
options = (
|
||||
{"key": ("|g[c]reate new room and start game|n", "c"),
|
||||
"goto": _create_new_room},
|
||||
{"key": ("|r[a]bort and go back|n", "a"),
|
||||
"goto": "node_start"})
|
||||
{"key": ("|g[c]reate new room and start game|n", "c"), "goto": _create_new_room},
|
||||
{"key": ("|r[a]bort and go back|n", "a"), "goto": "node_start"},
|
||||
)
|
||||
|
||||
return text, options
|
||||
|
||||
|
||||
def node_join_room(caller, raw_string, **kwargs):
|
||||
|
||||
room = kwargs['room']
|
||||
room = kwargs["room"]
|
||||
stats = room.db.stats or {"progress": 0}
|
||||
|
||||
players = [char.key for char in room.get_all_characters()]
|
||||
text = _JOIN_EXISTING_ROOM_TEXT.format(
|
||||
roomname=room.get_display_name(caller),
|
||||
percent=int(stats['progress']),
|
||||
percent=int(stats["progress"]),
|
||||
nplayers=len(players),
|
||||
players=list_to_string(players)
|
||||
players=list_to_string(players),
|
||||
)
|
||||
|
||||
options = (
|
||||
{"key": ("|g[a]ccept|n (default)", "a"),
|
||||
"goto": (_move_to_room, kwargs)},
|
||||
{"key": ("|r[c]ancel|n", "c"),
|
||||
"goto": "node_start"},
|
||||
{"key": "_default",
|
||||
"goto": (_move_to_room, kwargs)})
|
||||
{"key": ("|g[a]ccept|n (default)", "a"), "goto": (_move_to_room, kwargs)},
|
||||
{"key": ("|r[c]ancel|n", "c"), "goto": "node_start"},
|
||||
{"key": "_default", "goto": (_move_to_room, kwargs)},
|
||||
)
|
||||
|
||||
return text, options
|
||||
|
||||
|
|
@ -210,9 +219,10 @@ def node_quit(caller, raw_string, **kwargs):
|
|||
if caller.db.evscaperoom_standalone:
|
||||
from evennia.commands import cmdhandler
|
||||
from evennia import default_cmds
|
||||
cmdhandler.cmdhandler(caller.ndb._menutree._session, "",
|
||||
cmdobj=default_cmds.CmdQuit(),
|
||||
cmdobj_key="@quit")
|
||||
|
||||
cmdhandler.cmdhandler(
|
||||
caller.ndb._menutree._session, "", cmdobj=default_cmds.CmdQuit(), cmdobj_key="@quit"
|
||||
)
|
||||
|
||||
return text, None # empty options exit the menu
|
||||
|
||||
|
|
@ -222,10 +232,11 @@ class EvscaperoomMenu(EvMenu):
|
|||
Custom menu with a different formatting of options.
|
||||
|
||||
"""
|
||||
|
||||
node_border_char = "~"
|
||||
|
||||
def nodetext_formatter(self, text):
|
||||
return justify(text.strip("\n").rstrip(), align='c', indent=1)
|
||||
return justify(text.strip("\n").rstrip(), align="c", indent=1)
|
||||
|
||||
def options_formatter(self, optionlist):
|
||||
main_options = []
|
||||
|
|
@ -237,9 +248,7 @@ class EvscaperoomMenu(EvMenu):
|
|||
main_options.append(key)
|
||||
main_options = " | ".join(main_options)
|
||||
room_choices = super().options_formatter(room_choices)
|
||||
return "{}{}{}".format(main_options,
|
||||
"\n\n" if room_choices else "",
|
||||
room_choices)
|
||||
return "{}{}{}".format(main_options, "\n\n" if room_choices else "", room_choices)
|
||||
|
||||
|
||||
# access function
|
||||
|
|
@ -248,20 +257,22 @@ def run_evscaperoom_menu(caller):
|
|||
Run room selection menu
|
||||
|
||||
"""
|
||||
menutree = {"node_start": node_start,
|
||||
"node_quit": node_quit,
|
||||
"node_set_desc": node_set_desc,
|
||||
"node_create_room": node_create_room,
|
||||
"node_join_room": node_join_room}
|
||||
menutree = {
|
||||
"node_start": node_start,
|
||||
"node_quit": node_quit,
|
||||
"node_set_desc": node_set_desc,
|
||||
"node_create_room": node_create_room,
|
||||
"node_join_room": node_join_room,
|
||||
}
|
||||
|
||||
EvscaperoomMenu(caller, menutree, startnode="node_start",
|
||||
cmd_on_exit=None, auto_quit=True)
|
||||
EvscaperoomMenu(caller, menutree, startnode="node_start", cmd_on_exit=None, auto_quit=True)
|
||||
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# In-game Options menu
|
||||
# ------------------------------------------------------------
|
||||
|
||||
|
||||
def _set_thing_style(caller, raw_string, **kwargs):
|
||||
room = caller.location
|
||||
options = caller.attributes.get("options", category=room.tagcategory, default={})
|
||||
|
|
@ -272,7 +283,7 @@ def _set_thing_style(caller, raw_string, **kwargs):
|
|||
|
||||
def _toggle_screen_reader(caller, raw_string, **kwargs):
|
||||
|
||||
session = kwargs['session']
|
||||
session = kwargs["session"]
|
||||
# flip old setting
|
||||
session.protocol_flags["SCREENREADER"] = not session.protocol_flags.get("SCREENREADER", False)
|
||||
# sync setting with portal
|
||||
|
|
@ -287,22 +298,33 @@ def node_options(caller, raw_string, **kwargs):
|
|||
options = caller.attributes.get("options", category=room.tagcategory, default={})
|
||||
things_style = options.get("things_style", 2)
|
||||
|
||||
session = kwargs['session'] # we give this as startnode_input when starting menu
|
||||
session = kwargs["session"] # we give this as startnode_input when starting menu
|
||||
screenreader = session.protocol_flags.get("SCREENREADER", False)
|
||||
|
||||
options = (
|
||||
{"desc": "{}No item markings (hard mode)".format(
|
||||
"|g(*)|n " if things_style == 0 else "( ) "),
|
||||
"goto": (_set_thing_style, {"value": 0, 'session': session})},
|
||||
{"desc": "{}Items marked as |yitem|n (with color)".format(
|
||||
"|g(*)|n " if things_style == 1 else "( ) "),
|
||||
"goto": (_set_thing_style, {"value": 1, 'session': session})},
|
||||
{"desc": "{}Items are marked as |y[item]|n (screenreader friendly)".format(
|
||||
"|g(*)|n " if things_style == 2 else "( ) "),
|
||||
"goto": (_set_thing_style, {"value": 2, 'session': session})},
|
||||
{"desc": "{}Screenreader mode".format(
|
||||
"(*) " if screenreader else "( ) "),
|
||||
"goto": (_toggle_screen_reader, kwargs)})
|
||||
{
|
||||
"desc": "{}No item markings (hard mode)".format(
|
||||
"|g(*)|n " if things_style == 0 else "( ) "
|
||||
),
|
||||
"goto": (_set_thing_style, {"value": 0, "session": session}),
|
||||
},
|
||||
{
|
||||
"desc": "{}Items marked as |yitem|n (with color)".format(
|
||||
"|g(*)|n " if things_style == 1 else "( ) "
|
||||
),
|
||||
"goto": (_set_thing_style, {"value": 1, "session": session}),
|
||||
},
|
||||
{
|
||||
"desc": "{}Items are marked as |y[item]|n (screenreader friendly)".format(
|
||||
"|g(*)|n " if things_style == 2 else "( ) "
|
||||
),
|
||||
"goto": (_set_thing_style, {"value": 2, "session": session}),
|
||||
},
|
||||
{
|
||||
"desc": "{}Screenreader mode".format("(*) " if screenreader else "( ) "),
|
||||
"goto": (_toggle_screen_reader, kwargs),
|
||||
},
|
||||
)
|
||||
return text, options
|
||||
|
||||
|
||||
|
|
@ -310,6 +332,7 @@ class OptionsMenu(EvMenu):
|
|||
"""
|
||||
Custom display of Option menu
|
||||
"""
|
||||
|
||||
def node_formatter(self, nodetext, optionstext):
|
||||
return f"{nodetext}\n\n{optionstext}"
|
||||
|
||||
|
|
@ -321,5 +344,11 @@ def run_option_menu(caller, session):
|
|||
"""
|
||||
menutree = {"node_start": node_options}
|
||||
|
||||
OptionsMenu(caller, menutree, startnode="node_start",
|
||||
cmd_on_exit="look", auto_quit=True, startnode_input=("", {"session": session}))
|
||||
OptionsMenu(
|
||||
caller,
|
||||
menutree,
|
||||
startnode="node_start",
|
||||
cmd_on_exit="look",
|
||||
auto_quit=True,
|
||||
startnode_input=("", {"session": session}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class EvscaperoomObject(DefaultObject):
|
|||
Default object base for all objects related to the contrib.
|
||||
|
||||
"""
|
||||
|
||||
# these will be automatically filtered out by self.parse for
|
||||
# focus-commands using arguments like (`combine [with] object`)
|
||||
# override this per-class as necessary.
|
||||
|
|
@ -63,10 +64,7 @@ class EvscaperoomObject(DefaultObject):
|
|||
|
||||
# this mapping allows for prettier descriptions of our current
|
||||
# position
|
||||
position_prep_map = {"sit": "sitting",
|
||||
"kneel": "kneeling",
|
||||
"lie": "lying",
|
||||
"climb": "standing"}
|
||||
position_prep_map = {"sit": "sitting", "kneel": "kneeling", "lie": "lying", "climb": "standing"}
|
||||
|
||||
def at_object_creation(self):
|
||||
"""
|
||||
|
|
@ -86,8 +84,9 @@ class EvscaperoomObject(DefaultObject):
|
|||
@property
|
||||
def tagcategory(self):
|
||||
if not self._tagcategory:
|
||||
self._tagcategory = (self.location.db.tagcategory
|
||||
if self.location else self.db.tagcategory)
|
||||
self._tagcategory = (
|
||||
self.location.db.tagcategory if self.location else self.db.tagcategory
|
||||
)
|
||||
return self._tagcategory
|
||||
|
||||
@property
|
||||
|
|
@ -162,16 +161,15 @@ class EvscaperoomObject(DefaultObject):
|
|||
you = caller.key if caller else "they"
|
||||
first_person, third_person = parse_for_perspectives(string, you=you)
|
||||
for char in self.room.get_all_characters():
|
||||
options = char.attributes.get(
|
||||
"options", category=self.room.tagcategory, default={})
|
||||
options = char.attributes.get("options", category=self.room.tagcategory, default={})
|
||||
style = options.get("things_style", 2)
|
||||
if char == caller:
|
||||
if not skip_caller:
|
||||
txt = parse_for_things(first_person, things_style=style)
|
||||
char.msg((txt, {'type': 'your_action'}))
|
||||
char.msg((txt, {"type": "your_action"}))
|
||||
else:
|
||||
txt = parse_for_things(third_person, things_style=style)
|
||||
char.msg((txt, {'type': 'others_action'}))
|
||||
char.msg((txt, {"type": "others_action"}))
|
||||
|
||||
def msg_char(self, caller, string, client_type="your_action"):
|
||||
"""
|
||||
|
|
@ -180,8 +178,7 @@ class EvscaperoomObject(DefaultObject):
|
|||
"""
|
||||
# we must clean away markers
|
||||
first_person, _ = parse_for_perspectives(string)
|
||||
options = caller.attributes.get(
|
||||
"options", category=self.room.tagcategory, default={})
|
||||
options = caller.attributes.get("options", category=self.room.tagcategory, default={})
|
||||
style = options.get("things_style", 2)
|
||||
txt = parse_for_things(first_person, things_style=style)
|
||||
caller.msg((txt, {"type": client_type}))
|
||||
|
|
@ -227,8 +224,7 @@ class EvscaperoomObject(DefaultObject):
|
|||
"""
|
||||
if new_position is None:
|
||||
# reset position
|
||||
caller.attributes.remove(
|
||||
"position", category=self.tagcategory)
|
||||
caller.attributes.remove("position", category=self.tagcategory)
|
||||
if caller in self.db.positions:
|
||||
del self.db.positions[caller]
|
||||
else:
|
||||
|
|
@ -279,8 +275,9 @@ class EvscaperoomObject(DefaultObject):
|
|||
here.
|
||||
|
||||
"""
|
||||
args = re.sub(r"|".join(r"^{}\s".format(prep) for prep in self.action_prepositions),
|
||||
"", args)
|
||||
args = re.sub(
|
||||
r"|".join(r"^{}\s".format(prep) for prep in self.action_prepositions), "", args
|
||||
)
|
||||
return args
|
||||
|
||||
def get_cmd_signatures(self):
|
||||
|
|
@ -307,11 +304,11 @@ class EvscaperoomObject(DefaultObject):
|
|||
command_signatures = sorted(command_signatures)
|
||||
|
||||
if len(command_signatures) == 1:
|
||||
helpstr = (f"It looks like {self.key} may be "
|
||||
"suitable to {callsigns}.")
|
||||
helpstr = f"It looks like {self.key} may be " "suitable to {callsigns}."
|
||||
else:
|
||||
helpstr = (f"At first glance, it looks like {self.key} might be "
|
||||
"suitable to {callsigns}.")
|
||||
helpstr = (
|
||||
f"At first glance, it looks like {self.key} might be " "suitable to {callsigns}."
|
||||
)
|
||||
return command_signatures, helpstr
|
||||
|
||||
def get_short_desc(self, full_desc):
|
||||
|
|
@ -319,7 +316,7 @@ class EvscaperoomObject(DefaultObject):
|
|||
Extract the first sentence from the desc and use as the short desc.
|
||||
|
||||
"""
|
||||
mat = re.match(r"(^.*?[.?!])", full_desc.strip(), re.M+re.U+re.I+re.S)
|
||||
mat = re.match(r"(^.*?[.?!])", full_desc.strip(), re.M + re.U + re.I + re.S)
|
||||
if mat:
|
||||
return mat.group(0).strip()
|
||||
return full_desc
|
||||
|
|
@ -336,8 +333,7 @@ class EvscaperoomObject(DefaultObject):
|
|||
callsigns = list_to_string(["*" + sig for sig in command_signatures], endsep="or")
|
||||
|
||||
# parse for *thing markers (use these as items)
|
||||
options = caller.attributes.get(
|
||||
"options", category=self.room.tagcategory, default={})
|
||||
options = caller.attributes.get("options", category=self.room.tagcategory, default={})
|
||||
style = options.get("things_style", 2)
|
||||
|
||||
helpstr = helpstr.format(callsigns=callsigns)
|
||||
|
|
@ -354,7 +350,7 @@ class EvscaperoomObject(DefaultObject):
|
|||
# accept a custom desc
|
||||
desc = kwargs.get("desc", self.db.desc)
|
||||
|
||||
if kwargs.get('unfocused', False):
|
||||
if kwargs.get("unfocused", False):
|
||||
# use the shorter description
|
||||
focused = ""
|
||||
desc = self.get_short_desc(desc)
|
||||
|
|
@ -364,8 +360,11 @@ class EvscaperoomObject(DefaultObject):
|
|||
helptxt = kwargs.get("helptxt", f"\n\n({self.get_help(looker)})")
|
||||
|
||||
obj, pos = self.get_position(looker)
|
||||
pos = (f" |w({self.position_prep_map[pos]} on "
|
||||
f"{obj.get_display_name(looker)})" if obj else "")
|
||||
pos = (
|
||||
f" |w({self.position_prep_map[pos]} on " f"{obj.get_display_name(looker)})"
|
||||
if obj
|
||||
else ""
|
||||
)
|
||||
|
||||
return f" ~~ |y{self.get_display_name(looker)}|n{focused}{pos}|n ~~\n\n{desc}{helptxt}"
|
||||
|
||||
|
|
@ -375,6 +374,7 @@ class Feelable(EvscaperoomObject):
|
|||
Any object that you can feel the surface of.
|
||||
|
||||
"""
|
||||
|
||||
def at_focus_feel(self, caller, **kwargs):
|
||||
self.msg_char(caller, f"You feel *{self.key}.")
|
||||
|
||||
|
|
@ -384,6 +384,7 @@ class Listenable(EvscaperoomObject):
|
|||
Any object one can listen to.
|
||||
|
||||
"""
|
||||
|
||||
def at_focus_listen(self, caller, **kwargs):
|
||||
self.msg_char(caller, f"You listen to *{self.key}")
|
||||
|
||||
|
|
@ -393,6 +394,7 @@ class Smellable(EvscaperoomObject):
|
|||
Any object you can smell.
|
||||
|
||||
"""
|
||||
|
||||
def at_focus_smell(self, caller, **kwargs):
|
||||
self.msg_char(caller, f"You smell *{self.key}.")
|
||||
|
||||
|
|
@ -402,6 +404,7 @@ class Rotatable(EvscaperoomObject):
|
|||
Any object that you can lift up and look at from different angles
|
||||
|
||||
"""
|
||||
|
||||
rotate_flag = "rotatable"
|
||||
start_rotatable = True
|
||||
|
||||
|
|
@ -417,6 +420,7 @@ class Rotatable(EvscaperoomObject):
|
|||
self.at_rotate(caller)
|
||||
else:
|
||||
self.at_cannot_rotate(caller)
|
||||
|
||||
at_focus_turn = at_focus_rotate
|
||||
|
||||
def at_rotate(self, caller):
|
||||
|
|
@ -432,6 +436,7 @@ class Openable(EvscaperoomObject):
|
|||
a flag.
|
||||
|
||||
"""
|
||||
|
||||
# this flag must be set for item to open. None for unlocked.
|
||||
unlock_flag = "unlocked"
|
||||
open_flag = "open"
|
||||
|
|
@ -482,6 +487,7 @@ class Readable(EvscaperoomObject):
|
|||
from a flag.
|
||||
|
||||
"""
|
||||
|
||||
# this must be set to be able to read. None to
|
||||
# always be able to read.
|
||||
|
||||
|
|
@ -515,11 +521,7 @@ class IndexReadable(Readable):
|
|||
"""
|
||||
|
||||
# keys should be lower-key
|
||||
index = {
|
||||
"page1": "This is page1",
|
||||
"page2": "This is page2",
|
||||
"page two": "page2" # alias
|
||||
}
|
||||
index = {"page1": "This is page1", "page2": "This is page2", "page two": "page2"} # alias
|
||||
|
||||
def at_focus_read(self, caller, **kwargs):
|
||||
|
||||
|
|
@ -536,8 +538,10 @@ class IndexReadable(Readable):
|
|||
self.at_read(caller, topic, entry)
|
||||
|
||||
def get_cmd_signatures(self):
|
||||
txt = (f"You don't have the time to read this from beginning to end. "
|
||||
"Use *read <topic> to look up something in particular.")
|
||||
txt = (
|
||||
f"You don't have the time to read this from beginning to end. "
|
||||
"Use *read <topic> to look up something in particular."
|
||||
)
|
||||
return [], txt
|
||||
|
||||
def at_cannot_read(self, caller, topic, *args, **kwargs):
|
||||
|
|
@ -556,10 +560,10 @@ class Movable(EvscaperoomObject):
|
|||
change.
|
||||
|
||||
"""
|
||||
|
||||
# these are the possible locations (or directions) to move to
|
||||
# name: callable
|
||||
move_positions = {"left": "at_left",
|
||||
"right": "at_right"}
|
||||
move_positions = {"left": "at_left", "right": "at_right"}
|
||||
start_position = "left"
|
||||
|
||||
def at_object_creation(self):
|
||||
|
|
@ -571,7 +575,7 @@ class Movable(EvscaperoomObject):
|
|||
return ["move", "push", "shove left/right"], txt
|
||||
|
||||
def at_focus_move(self, caller, **kwargs):
|
||||
pos = self.parse(kwargs['args'])
|
||||
pos = self.parse(kwargs["args"])
|
||||
callfunc_name = self.move_positions.get(pos)
|
||||
|
||||
if callfunc_name:
|
||||
|
|
@ -610,6 +614,7 @@ class BaseConsumable(EvscaperoomObject):
|
|||
a custom object if needed).
|
||||
|
||||
"""
|
||||
|
||||
consume_flag = "consume"
|
||||
# may only consume once
|
||||
one_consume_only = True
|
||||
|
|
@ -647,6 +652,7 @@ class Edible(BaseConsumable):
|
|||
Any object specifically possible to eat.
|
||||
|
||||
"""
|
||||
|
||||
consume_flag = "eat"
|
||||
|
||||
def at_focus_eat(self, caller, **kwargs):
|
||||
|
|
@ -658,6 +664,7 @@ class Drinkable(BaseConsumable):
|
|||
Any object specifically possible to drink.
|
||||
|
||||
"""
|
||||
|
||||
consume_flag = "drink"
|
||||
|
||||
def at_focus_drink(self, caller, **kwargs):
|
||||
|
|
@ -679,6 +686,7 @@ class BaseApplicable(EvscaperoomObject):
|
|||
This acts an an abstract base class.
|
||||
|
||||
"""
|
||||
|
||||
# the target object this is to be used with must
|
||||
# have this flag. It'll likely be unique to this
|
||||
# object combination.
|
||||
|
|
@ -689,7 +697,7 @@ class BaseApplicable(EvscaperoomObject):
|
|||
Wrap this with the at_focus methods in the child classes
|
||||
|
||||
"""
|
||||
args = self.parse(kwargs['args'])
|
||||
args = self.parse(kwargs["args"])
|
||||
if not args:
|
||||
self.msg_char(caller, "You need to specify a target.")
|
||||
return
|
||||
|
|
@ -717,6 +725,7 @@ class Usable(BaseApplicable):
|
|||
Any object that can be used with another object.
|
||||
|
||||
"""
|
||||
|
||||
target_flag = "usable"
|
||||
|
||||
def at_focus_use(self, caller, **kwargs):
|
||||
|
|
@ -736,6 +745,7 @@ class Insertable(BaseApplicable):
|
|||
This would cover a key, for example.
|
||||
|
||||
"""
|
||||
|
||||
# this would likely be a custom name
|
||||
target_flag = "insertable"
|
||||
|
||||
|
|
@ -759,6 +769,7 @@ class Combinable(BaseApplicable):
|
|||
a new one.
|
||||
|
||||
"""
|
||||
|
||||
# the other object must have this flag to be able to be combined
|
||||
# (this is likely unique for a given combination)
|
||||
target_flag = "combinable"
|
||||
|
|
@ -767,7 +778,8 @@ class Combinable(BaseApplicable):
|
|||
new_create_dict = {
|
||||
"typeclass": "evscaperoom.objects.Combinable",
|
||||
"key": "sword",
|
||||
"aliases": ["combined"]}
|
||||
"aliases": ["combined"],
|
||||
}
|
||||
# if set, destroy the two components used to make the new one
|
||||
destroy_components = True
|
||||
|
||||
|
|
@ -784,11 +796,12 @@ class Combinable(BaseApplicable):
|
|||
def at_apply(self, caller, action, other_obj):
|
||||
create_dict = self.new_create_dict
|
||||
if "location" not in create_dict:
|
||||
create_dict['location'] = self.location
|
||||
create_dict["location"] = self.location
|
||||
new_obj = create_evscaperoom_object(**create_dict)
|
||||
if new_obj and self.destroy_components:
|
||||
self.msg_char(caller,
|
||||
f"You combine *{self.key} with {other_obj.key} to make {new_obj.key}!")
|
||||
self.msg_char(
|
||||
caller, f"You combine *{self.key} with {other_obj.key} to make {new_obj.key}!"
|
||||
)
|
||||
other_obj.delete()
|
||||
self.delete()
|
||||
|
||||
|
|
@ -800,14 +813,11 @@ class Mixable(EvscaperoomObject):
|
|||
the ingredients should be 'used' with this object in order
|
||||
mix, calling at_mix when they do.
|
||||
"""
|
||||
|
||||
# ingredients can check for this before they allow to mix at all
|
||||
mixer_flag = "mixer"
|
||||
# ingredients must have these flags and this order
|
||||
ingredient_recipe = [
|
||||
"ingredient1",
|
||||
"ingredient2",
|
||||
"ingredient3"
|
||||
]
|
||||
ingredient_recipe = ["ingredient1", "ingredient2", "ingredient3"]
|
||||
|
||||
def at_object_creation(self):
|
||||
super().at_object_creation()
|
||||
|
|
@ -847,7 +857,9 @@ class Mixable(EvscaperoomObject):
|
|||
if self.check_mixture():
|
||||
self.at_mix_success(caller, ingredient, **kwargs)
|
||||
else:
|
||||
self.room.log(f"{self.name} mix failure: Tried {' + '.join([ing.key for ing in self.db.ingredients if ing])}")
|
||||
self.room.log(
|
||||
f"{self.name} mix failure: Tried {' + '.join([ing.key for ing in self.db.ingredients if ing])}"
|
||||
)
|
||||
self.db.ingredients = []
|
||||
self.at_mix_failure(caller, ingredient, **kwargs)
|
||||
|
||||
|
|
@ -866,25 +878,31 @@ class HasButtons(EvscaperoomObject):
|
|||
Any object with buttons to push/press
|
||||
|
||||
"""
|
||||
|
||||
# mapping keys/aliases to calling method
|
||||
buttons = {'green button': "at_green_button",
|
||||
'green': "at_green_button",
|
||||
'red button': "at_red_button",
|
||||
'red': "at_red_button"}
|
||||
buttons = {
|
||||
"green button": "at_green_button",
|
||||
"green": "at_green_button",
|
||||
"red button": "at_red_button",
|
||||
"red": "at_red_button",
|
||||
}
|
||||
|
||||
def get_cmd_signatures(self):
|
||||
helptxt = ("It looks like you should be able to operate "
|
||||
f"*{self.key} by means of "
|
||||
"{callsigns}.")
|
||||
helptxt = (
|
||||
"It looks like you should be able to operate "
|
||||
f"*{self.key} by means of "
|
||||
"{callsigns}."
|
||||
)
|
||||
return ["push", "press red/green button"], helptxt
|
||||
|
||||
def at_focus_press(self, caller, **kwargs):
|
||||
arg = self.parse(kwargs['args'])
|
||||
arg = self.parse(kwargs["args"])
|
||||
callfunc_name = self.buttons.get(arg)
|
||||
if callfunc_name:
|
||||
getattr(self, callfunc_name)(caller)
|
||||
else:
|
||||
self.at_nomatch(caller)
|
||||
|
||||
at_focus_push = at_focus_press
|
||||
|
||||
def at_nomatch(self, caller):
|
||||
|
|
@ -903,6 +921,7 @@ class CodeInput(EvscaperoomObject):
|
|||
to have an effect happen.
|
||||
|
||||
"""
|
||||
|
||||
# the code of this
|
||||
code = "PASSWORD"
|
||||
code_hint = "eight letters A-Z"
|
||||
|
|
@ -912,7 +931,7 @@ class CodeInput(EvscaperoomObject):
|
|||
|
||||
def at_focus_code(self, caller, **kwargs):
|
||||
|
||||
args = self.parse(kwargs['args'].strip())
|
||||
args = self.parse(kwargs["args"].strip())
|
||||
|
||||
if not args:
|
||||
self.at_no_code(caller)
|
||||
|
|
@ -967,6 +986,7 @@ class BasePositionable(EvscaperoomObject):
|
|||
object or not.
|
||||
|
||||
"""
|
||||
|
||||
def at_object_creation(self):
|
||||
super().at_object_creation()
|
||||
# mapping {object: position}.
|
||||
|
|
@ -992,11 +1012,16 @@ class BasePositionable(EvscaperoomObject):
|
|||
self.at_position(caller, new_pos)
|
||||
|
||||
def at_cannot_position(self, caller, position, old_obj, old_pos):
|
||||
self.msg_char(caller, f"You can't; you are currently {self.position_prep_map[old_pos]} on *{old_obj.key} "
|
||||
"(better |wstand|n first).")
|
||||
self.msg_char(
|
||||
caller,
|
||||
f"You can't; you are currently {self.position_prep_map[old_pos]} on *{old_obj.key} "
|
||||
"(better |wstand|n first).",
|
||||
)
|
||||
|
||||
def at_again_position(self, caller, position):
|
||||
self.msg_char(caller, f"But you are already {self.position_prep_map[position]} on *{self.key}?")
|
||||
self.msg_char(
|
||||
caller, f"But you are already {self.position_prep_map[position]} on *{self.key}?"
|
||||
)
|
||||
|
||||
def at_position(self, caller, position):
|
||||
self.msg_room(caller, f"~You ~{position} on *{self.key}.")
|
||||
|
|
@ -1017,6 +1042,7 @@ class Liable(BasePositionable):
|
|||
Any object you can lie down on.
|
||||
|
||||
"""
|
||||
|
||||
def at_focus_lie(self, caller, **kwargs):
|
||||
super().handle_position(caller, "lie", **kwargs)
|
||||
|
||||
|
|
@ -1026,6 +1052,7 @@ class Kneelable(BasePositionable):
|
|||
Any object you can kneel on.
|
||||
|
||||
"""
|
||||
|
||||
def at_focus_kneel(self, caller, **kwargs):
|
||||
super().handle_position(caller, "kneel", **kwargs)
|
||||
|
||||
|
|
@ -1037,6 +1064,7 @@ class Climbable(BasePositionable):
|
|||
command, which resets your position.
|
||||
|
||||
"""
|
||||
|
||||
def at_focus_climb(self, caller, **kwargs):
|
||||
super().handle_position(caller, "climb", **kwargs)
|
||||
|
||||
|
|
@ -1047,6 +1075,7 @@ class Positionable(Sittable, Liable, Kneelable, Climbable):
|
|||
supported ways (sit, lie, kneel or climb)
|
||||
|
||||
"""
|
||||
|
||||
def get_cmd_signatures(self):
|
||||
txt = "It looks like you can {callsigns} on it."
|
||||
return ["sit", "lie", "kneel", "climb"], txt
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
|
|||
super().at_object_creation()
|
||||
|
||||
# starting state
|
||||
self.db.state = None # name
|
||||
self.db.state = None # name
|
||||
self.db.prev_state = None
|
||||
|
||||
# this is used for tagging of all objects belonging to this
|
||||
|
|
@ -43,11 +43,11 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
|
|||
# room progress statistics
|
||||
self.db.stats = {
|
||||
"progress": 0, # in percent
|
||||
"score": {}, # reason: score
|
||||
"score": {}, # reason: score
|
||||
"max_score": 100,
|
||||
"hints_used": 0, # total across all states
|
||||
"hints_total": 41,
|
||||
"total_achievements": 14
|
||||
"total_achievements": 14,
|
||||
}
|
||||
|
||||
self.cmdset.add(CmdSetEvScapeRoom, permanent=True)
|
||||
|
|
@ -69,21 +69,21 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
|
|||
caller = f"[caller.key]: " if caller else ""
|
||||
|
||||
logger.log_file(
|
||||
strip_ansi(f"{caller}{message.strip()}"),
|
||||
filename=self.tagcategory + ".log")
|
||||
strip_ansi(f"{caller}{message.strip()}"), filename=self.tagcategory + ".log"
|
||||
)
|
||||
|
||||
def score(self, new_score, reason):
|
||||
"""
|
||||
We don't score individually but for everyone in room together.
|
||||
You can only be scored for a given reason once."""
|
||||
if reason not in self.db.stats['score']:
|
||||
if reason not in self.db.stats["score"]:
|
||||
self.log(f"score: {reason} ({new_score}pts)")
|
||||
self.db.stats['score'][reason] = new_score
|
||||
self.db.stats["score"][reason] = new_score
|
||||
|
||||
def progress(self, new_progress):
|
||||
"Progress is what we set it to be (0-100%)"
|
||||
self.log(f"progress: {new_progress}%")
|
||||
self.db.stats['progress'] = new_progress
|
||||
self.db.stats["progress"] = new_progress
|
||||
|
||||
def achievement(self, caller, achievement, subtext=""):
|
||||
"""
|
||||
|
|
@ -96,8 +96,7 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
|
|||
subtext (str, optional): Eventual subtext/explanation
|
||||
of the achievement.
|
||||
"""
|
||||
achievements = caller.attributes.get(
|
||||
"achievements", category=self.tagcategory)
|
||||
achievements = caller.attributes.get("achievements", category=self.tagcategory)
|
||||
if not achievements:
|
||||
achievements = {}
|
||||
if achievement not in achievements:
|
||||
|
|
@ -173,6 +172,7 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
|
|||
"""
|
||||
self.log(f"EXIT: {char} left room")
|
||||
from .menu import run_evscaperoom_menu
|
||||
|
||||
self.character_cleanup(char)
|
||||
char.location = char.home
|
||||
|
||||
|
|
@ -223,15 +223,18 @@ class EvscapeRoom(EvscaperoomObject, DefaultRoom):
|
|||
|
||||
def return_appearance(self, looker, **kwargs):
|
||||
obj, pos = self.get_position(looker)
|
||||
pos = (f"\n|x[{self.position_prep_map[pos]} on "
|
||||
f"{obj.get_display_name(looker)}]|n" if obj else "")
|
||||
pos = (
|
||||
f"\n|x[{self.position_prep_map[pos]} on " f"{obj.get_display_name(looker)}]|n"
|
||||
if obj
|
||||
else ""
|
||||
)
|
||||
|
||||
admin_only = ""
|
||||
if self.check_perm(looker, "Admin"):
|
||||
# only for admins
|
||||
objs = DefaultObject.objects.filter_family(
|
||||
db_location=self).exclude(id=looker.id)
|
||||
admin_only = "\n|xAdmin only: " + \
|
||||
list_to_string([obj.get_display_name(looker) for obj in objs])
|
||||
objs = DefaultObject.objects.filter_family(db_location=self).exclude(id=looker.id)
|
||||
admin_only = "\n|xAdmin only: " + list_to_string(
|
||||
[obj.get_display_name(looker) for obj in objs]
|
||||
)
|
||||
|
||||
return f"{self.db.desc}{pos}{admin_only}"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ from evscaperoom.room import EvscapeRoom
|
|||
|
||||
|
||||
class CleanupScript(DefaultScript):
|
||||
|
||||
def at_script_creation(self):
|
||||
|
||||
self.key = "evscaperoom_cleanup"
|
||||
|
|
|
|||
|
|
@ -35,11 +35,13 @@ _GA = object.__getattribute__
|
|||
|
||||
# handler for managing states on room
|
||||
|
||||
|
||||
class StateHandler(object):
|
||||
"""
|
||||
This sits on the room and is used to progress through the states.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, room):
|
||||
self.room = room
|
||||
self.current_state_name = room.db.state or _FIRST_STATE
|
||||
|
|
@ -109,12 +111,14 @@ class StateHandler(object):
|
|||
|
||||
# base state class
|
||||
|
||||
|
||||
class BaseState(object):
|
||||
"""
|
||||
Base object holding all callables for a state. This is here to
|
||||
allow easy overriding for child states.
|
||||
|
||||
"""
|
||||
|
||||
next_state = "unset"
|
||||
# a sequence of hints to describe this state.
|
||||
hints = []
|
||||
|
|
@ -144,15 +148,20 @@ class BaseState(object):
|
|||
Wrapper handling state method errors.
|
||||
|
||||
"""
|
||||
|
||||
@wraps(method)
|
||||
def decorator(*args, **kwargs):
|
||||
try:
|
||||
return method(*args, **kwargs)
|
||||
except Exception:
|
||||
logger.log_trace(f"Error in State {__name__}")
|
||||
self.room.msg_room(None, f"|rThere was an unexpected error in State {__name__}. "
|
||||
"Please |wreport|r this as an issue.|n")
|
||||
self.room.msg_room(
|
||||
None,
|
||||
f"|rThere was an unexpected error in State {__name__}. "
|
||||
"Please |wreport|r this as an issue.|n",
|
||||
)
|
||||
raise # TODO
|
||||
|
||||
return decorator
|
||||
|
||||
def __getattribute__(self, key):
|
||||
|
|
@ -176,8 +185,10 @@ class BaseState(object):
|
|||
# return the next hint in the sequence.
|
||||
self.room.db.state_hint_level = next_level
|
||||
self.room.db.stats["hints_used"] += 1
|
||||
self.room.log(f"HINT: {self.name.split('.')[-1]}, level {next_level + 1} "
|
||||
f"(total used: {self.room.db.stats['hints_used']})")
|
||||
self.room.log(
|
||||
f"HINT: {self.name.split('.')[-1]}, level {next_level + 1} "
|
||||
f"(total used: {self.room.db.stats['hints_used']})"
|
||||
)
|
||||
return self.hints[next_level]
|
||||
else:
|
||||
# no more hints for this state
|
||||
|
|
@ -191,8 +202,7 @@ class BaseState(object):
|
|||
if cinematic:
|
||||
message = msg_cinematic(message, borders=borders)
|
||||
if target:
|
||||
options = target.attributes.get(
|
||||
"options", category=self.room.tagcategory, default={})
|
||||
options = target.attributes.get("options", category=self.room.tagcategory, default={})
|
||||
style = options.get("things_style", 2)
|
||||
# we assume this is a char
|
||||
target.msg(parse_for_things(message, things_style=style))
|
||||
|
|
@ -205,7 +215,7 @@ class BaseState(object):
|
|||
"""
|
||||
self.msg(message, target=target, borders=True, cinematic=True)
|
||||
|
||||
def create_object(self, typeclass=None, key='testobj', location=None, **kwargs):
|
||||
def create_object(self, typeclass=None, key="testobj", location=None, **kwargs):
|
||||
"""
|
||||
This is a convenience-wrapper for quickly building EvscapeRoom objects.
|
||||
|
||||
|
|
@ -223,8 +233,12 @@ class BaseState(object):
|
|||
if not location:
|
||||
location = self.room
|
||||
return create_evscaperoom_object(
|
||||
typeclass=typeclass, key=key, location=location,
|
||||
tags=[("room", self.room.tagcategory.lower())], **kwargs)
|
||||
typeclass=typeclass,
|
||||
key=key,
|
||||
location=location,
|
||||
tags=[("room", self.room.tagcategory.lower())],
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def get_object(self, key):
|
||||
"""
|
||||
|
|
@ -237,7 +251,8 @@ class BaseState(object):
|
|||
|
||||
"""
|
||||
match = EvscaperoomObject.objects.filter_family(
|
||||
db_key__iexact=key, db_tags__db_category=self.room.tagcategory.lower())
|
||||
db_key__iexact=key, db_tags__db_category=self.room.tagcategory.lower()
|
||||
)
|
||||
if not match:
|
||||
logger.log_err(f"get_object: No match for '{key}' in state ")
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class Door(objects.Openable):
|
|||
The door leads out of the room.
|
||||
|
||||
"""
|
||||
|
||||
start_open = False
|
||||
|
||||
def at_object_creation(self):
|
||||
|
|
@ -108,7 +109,6 @@ On the wall is a button marked
|
|||
|
||||
|
||||
class HelpButton(objects.EvscaperoomObject):
|
||||
|
||||
def at_focus_push(self, caller, **kwargs):
|
||||
"this adds the 'push' action to the button"
|
||||
|
||||
|
|
@ -116,8 +116,9 @@ class HelpButton(objects.EvscaperoomObject):
|
|||
if hint is None:
|
||||
self.msg_char(caller, "There are no more hints to be had.")
|
||||
else:
|
||||
self.msg_room(caller, f"{caller.key} pushes *button and gets the "
|
||||
f"hint:\n \"{hint.strip()}\"|n")
|
||||
self.msg_room(
|
||||
caller, f"{caller.key} pushes *button and gets the " f'hint:\n "{hint.strip()}"|n'
|
||||
)
|
||||
|
||||
|
||||
# state
|
||||
|
|
@ -144,9 +145,7 @@ class State(BaseState):
|
|||
"""
|
||||
|
||||
# this makes these hints available to the .get_hint method.
|
||||
hints = [STATE_HINT_LVL1,
|
||||
STATE_HINT_LVL2,
|
||||
STATE_HINT_LVL3]
|
||||
hints = [STATE_HINT_LVL1, STATE_HINT_LVL2, STATE_HINT_LVL3]
|
||||
|
||||
def character_enters(self, char):
|
||||
"Called when char enters room at this state"
|
||||
|
|
@ -159,16 +158,13 @@ class State(BaseState):
|
|||
self.room.db.desc = ROOM_DESC
|
||||
|
||||
# create the room objects
|
||||
door = self.create_object(
|
||||
Door, key="door to the cabin", aliases=["door"])
|
||||
door = self.create_object(Door, key="door to the cabin", aliases=["door"])
|
||||
door.db.desc = DOOR_DESC.strip()
|
||||
|
||||
key = self.create_object(
|
||||
Key, key="key", aliases=["room key"])
|
||||
key = self.create_object(Key, key="key", aliases=["room key"])
|
||||
key.db.desc = KEY_DESC.strip()
|
||||
|
||||
button = self.create_object(
|
||||
HelpButton, key="button", aliases=["help button"])
|
||||
button = self.create_object(HelpButton, key="button", aliases=["help button"])
|
||||
button.db.desc = BUTTON_DESC.strip()
|
||||
|
||||
def clean(self):
|
||||
|
|
|
|||
|
|
@ -16,11 +16,9 @@ from . import utils
|
|||
|
||||
|
||||
class TestEvscaperoomCommands(CommandTest):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.room1 = utils.create_evscaperoom_object(
|
||||
"evscaperoom.room.EvscapeRoom", key='Testroom')
|
||||
self.room1 = utils.create_evscaperoom_object("evscaperoom.room.EvscapeRoom", key="Testroom")
|
||||
self.char1.location = self.room1
|
||||
self.obj1.location = self.room1
|
||||
|
||||
|
|
@ -114,7 +112,7 @@ class TestEvscaperoomCommands(CommandTest):
|
|||
|
||||
self.assertEqual(cmd.obj1, None)
|
||||
self.assertEqual(cmd.obj2, self.obj1)
|
||||
self.assertEqual(cmd.arg1, 'foo')
|
||||
self.assertEqual(cmd.arg1, "foo")
|
||||
self.assertEqual(cmd.arg2, None)
|
||||
|
||||
cmd = commands.CmdEvscapeRoom()
|
||||
|
|
@ -127,7 +125,7 @@ class TestEvscaperoomCommands(CommandTest):
|
|||
self.assertEqual(cmd.obj1, self.obj1)
|
||||
self.assertEqual(cmd.obj2, None)
|
||||
self.assertEqual(cmd.arg1, None)
|
||||
self.assertEqual(cmd.arg2, 'foo')
|
||||
self.assertEqual(cmd.arg2, "foo")
|
||||
|
||||
cmd = commands.CmdEvscapeRoom()
|
||||
cmd.caller = self.char1
|
||||
|
|
@ -152,21 +150,20 @@ class TestEvscaperoomCommands(CommandTest):
|
|||
cmd.caller = self.char1
|
||||
cmd.room = self.room1
|
||||
cmd.focus = self.obj1
|
||||
self.assertEqual(self.char1.attributes.get(
|
||||
"focus", category=self.room1.tagcategory), self.obj1)
|
||||
self.assertEqual(
|
||||
self.char1.attributes.get("focus", category=self.room1.tagcategory), self.obj1
|
||||
)
|
||||
|
||||
def test_focus(self):
|
||||
# don't focus on a non-room object
|
||||
self.call(commands.CmdFocus(), "obj")
|
||||
self.assertEqual(self.char1.attributes.get(
|
||||
"focus", category=self.room1.tagcategory), None)
|
||||
self.assertEqual(self.char1.attributes.get("focus", category=self.room1.tagcategory), None)
|
||||
# should focus correctly
|
||||
myobj = utils.create_evscaperoom_object(
|
||||
objects.EvscaperoomObject, "mytestobj", location=self.room1)
|
||||
objects.EvscaperoomObject, "mytestobj", location=self.room1
|
||||
)
|
||||
self.call(commands.CmdFocus(), "mytestobj")
|
||||
self.assertEqual(self.char1.attributes.get(
|
||||
"focus", category=self.room1.tagcategory), myobj)
|
||||
|
||||
self.assertEqual(self.char1.attributes.get("focus", category=self.room1.tagcategory), myobj)
|
||||
|
||||
def test_look(self):
|
||||
self.call(commands.CmdLook(), "at obj", "Obj")
|
||||
|
|
@ -181,31 +178,31 @@ class TestEvscaperoomCommands(CommandTest):
|
|||
self.call(commands.CmdSpeak(), "Hi.", "You whisper: Hi.", cmdstring="whisper")
|
||||
self.call(commands.CmdSpeak(), "HELLO!", "You shout: HELLO!", cmdstring="shout")
|
||||
|
||||
self.call(commands.CmdSpeak(), "Hello to obj",
|
||||
"You say: Hello", cmdstring="say")
|
||||
self.call(commands.CmdSpeak(), "Hello to obj",
|
||||
"You shout: Hello", cmdstring="shout")
|
||||
self.call(commands.CmdSpeak(), "Hello to obj", "You say: Hello", cmdstring="say")
|
||||
self.call(commands.CmdSpeak(), "Hello to obj", "You shout: Hello", cmdstring="shout")
|
||||
|
||||
def test_emote(self):
|
||||
self.call(commands.CmdEmote(),
|
||||
"/me smiles to /obj",
|
||||
f"Char(#{self.char1.id}) smiles to Obj(#{self.obj1.id})")
|
||||
self.call(
|
||||
commands.CmdEmote(),
|
||||
"/me smiles to /obj",
|
||||
f"Char(#{self.char1.id}) smiles to Obj(#{self.obj1.id})",
|
||||
)
|
||||
|
||||
def test_focus_interaction(self):
|
||||
self.call(commands.CmdFocusInteraction(), "", "Hm?")
|
||||
|
||||
|
||||
class TestUtils(EvenniaTest):
|
||||
|
||||
def test_overwrite(self):
|
||||
room = utils.create_evscaperoom_object(
|
||||
"evscaperoom.room.EvscapeRoom", key='Testroom')
|
||||
room = utils.create_evscaperoom_object("evscaperoom.room.EvscapeRoom", key="Testroom")
|
||||
obj1 = utils.create_evscaperoom_object(
|
||||
objects.EvscaperoomObject, key="testobj", location=room)
|
||||
objects.EvscaperoomObject, key="testobj", location=room
|
||||
)
|
||||
id1 = obj1.id
|
||||
|
||||
obj2 = utils.create_evscaperoom_object(
|
||||
objects.EvscaperoomObject, key="testobj", location=room)
|
||||
objects.EvscaperoomObject, key="testobj", location=room
|
||||
)
|
||||
id2 = obj2.id
|
||||
|
||||
# we should have created a new object, deleting the old same-named one
|
||||
|
|
@ -231,14 +228,12 @@ class TestUtils(EvenniaTest):
|
|||
self.assertEqual(utils.parse_for_things(string, 2), "Looking at |y[book]|n and |y[key]|n.")
|
||||
|
||||
|
||||
|
||||
class TestEvScapeRoom(EvenniaTest):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.room = utils.create_evscaperoom_object(
|
||||
"evscaperoom.room.EvscapeRoom", key='Testroom',
|
||||
home=self.room1)
|
||||
"evscaperoom.room.EvscapeRoom", key="Testroom", home=self.room1
|
||||
)
|
||||
self.roomtag = "evscaperoom_{}".format(self.room.key)
|
||||
|
||||
def tearDown(self):
|
||||
|
|
@ -253,24 +248,21 @@ class TestEvScapeRoom(EvenniaTest):
|
|||
self.assertEqual(list(room.get_all_characters()), [self.char1])
|
||||
|
||||
room.tag_character(self.char1, "opened_door")
|
||||
self.assertEqual(self.char1.tags.get(
|
||||
"opened_door", category=self.roomtag), "opened_door")
|
||||
self.assertEqual(self.char1.tags.get("opened_door", category=self.roomtag), "opened_door")
|
||||
|
||||
room.tag_all_characters("tagged_all")
|
||||
self.assertEqual(self.char1.tags.get(
|
||||
"tagged_all", category=self.roomtag), "tagged_all")
|
||||
self.assertEqual(self.char1.tags.get("tagged_all", category=self.roomtag), "tagged_all")
|
||||
|
||||
room.character_cleanup(self.char1)
|
||||
self.assertEqual(self.char1.tags.get(category=self.roomtag), None)
|
||||
|
||||
|
||||
class TestStates(EvenniaTest):
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.room = utils.create_evscaperoom_object(
|
||||
"evscaperoom.room.EvscapeRoom", key='Testroom',
|
||||
home=self.room1)
|
||||
"evscaperoom.room.EvscapeRoom", key="Testroom", home=self.room1
|
||||
)
|
||||
self.roomtag = "evscaperoom_#{}".format(self.room.id)
|
||||
|
||||
def tearDown(self):
|
||||
|
|
@ -280,7 +272,8 @@ class TestStates(EvenniaTest):
|
|||
dirname = path.join(path.dirname(__file__), "states")
|
||||
states = []
|
||||
for imp, module, ispackage in pkgutil.walk_packages(
|
||||
path=[dirname], prefix="evscaperoom.states."):
|
||||
path=[dirname], prefix="evscaperoom.states."
|
||||
):
|
||||
mod = mod_import(module)
|
||||
states.append(mod)
|
||||
return states
|
||||
|
|
|
|||
|
|
@ -12,12 +12,13 @@ from evennia import create_object, search_object
|
|||
from evennia.utils import justify, inherits_from
|
||||
|
||||
_BASE_TYPECLASS_PATH = "evscaperoom.objects."
|
||||
_RE_PERSPECTIVE = re.compile(r"~(\w+)", re.I+re.U+re.M)
|
||||
_RE_THING = re.compile(r"\*(\w+)", re.I+re.U+re.M)
|
||||
_RE_PERSPECTIVE = re.compile(r"~(\w+)", re.I + re.U + re.M)
|
||||
_RE_THING = re.compile(r"\*(\w+)", re.I + re.U + re.M)
|
||||
|
||||
|
||||
def create_evscaperoom_object(typeclass=None, key="testobj", location=None,
|
||||
delete_duplicates=True, **kwargs):
|
||||
def create_evscaperoom_object(
|
||||
typeclass=None, key="testobj", location=None, delete_duplicates=True, **kwargs
|
||||
):
|
||||
"""
|
||||
This is a convenience-wrapper for quickly building EvscapeRoom objects. This
|
||||
is called from the helper-method create_object on states, but is also useful
|
||||
|
|
@ -38,25 +39,29 @@ def create_evscaperoom_object(typeclass=None, key="testobj", location=None,
|
|||
|
||||
|
||||
"""
|
||||
if not (callable(typeclass) or
|
||||
typeclass.startswith("evennia") or
|
||||
typeclass.startswith("typeclasses") or
|
||||
typeclass.startswith("evscaperoom")):
|
||||
if not (
|
||||
callable(typeclass)
|
||||
or typeclass.startswith("evennia")
|
||||
or typeclass.startswith("typeclasses")
|
||||
or typeclass.startswith("evscaperoom")
|
||||
):
|
||||
# unless we specify a full typeclass path or the class itself,
|
||||
# auto-complete it
|
||||
typeclass = _BASE_TYPECLASS_PATH + typeclass
|
||||
|
||||
if delete_duplicates:
|
||||
old_objs = [obj for obj in search_object(key)
|
||||
if not inherits_from(obj, "evennia.objects.objects.DefaultCharacter")]
|
||||
old_objs = [
|
||||
obj
|
||||
for obj in search_object(key)
|
||||
if not inherits_from(obj, "evennia.objects.objects.DefaultCharacter")
|
||||
]
|
||||
if location:
|
||||
# delete only matching objects in the given location
|
||||
[obj.delete() for obj in old_objs if obj.location == location]
|
||||
else:
|
||||
[obj.delete() for obj in old_objs]
|
||||
|
||||
new_obj = create_object(typeclass=typeclass, key=key,
|
||||
location=location, **kwargs)
|
||||
new_obj = create_object(typeclass=typeclass, key=key, location=location, **kwargs)
|
||||
return new_obj
|
||||
|
||||
|
||||
|
|
@ -74,9 +79,11 @@ def create_fantasy_word(length=5, capitalize=True):
|
|||
if not length:
|
||||
return ""
|
||||
|
||||
phonemes = ("ea oh ae aa eh ah ao aw ai er ey ow ia ih iy oy ua "
|
||||
"uh uw a e i u y p b t d f v t dh "
|
||||
"s z sh zh ch jh k ng g m n l r w").split()
|
||||
phonemes = (
|
||||
"ea oh ae aa eh ah ao aw ai er ey ow ia ih iy oy ua "
|
||||
"uh uw a e i u y p b t d f v t dh "
|
||||
"s z sh zh ch jh k ng g m n l r w"
|
||||
).split()
|
||||
word = [choice(phonemes)]
|
||||
while len(word) < length:
|
||||
word.append(choice(phonemes))
|
||||
|
|
@ -113,6 +120,7 @@ def parse_for_perspectives(string, you=None):
|
|||
"~You ~open"
|
||||
-> "You open", "Bob opens"
|
||||
"""
|
||||
|
||||
def _replace_third_person(match):
|
||||
match = match.group(1)
|
||||
lmatch = match.lower()
|
||||
|
|
@ -122,7 +130,7 @@ def parse_for_perspectives(string, you=None):
|
|||
if match[0].isupper():
|
||||
return irregulars[lmatch].capitalize()
|
||||
return irregulars[lmatch]
|
||||
elif lmatch[-1] == 's':
|
||||
elif lmatch[-1] == "s":
|
||||
return match + "es"
|
||||
else:
|
||||
return match + "s" # simple, most normal form
|
||||
|
|
@ -181,7 +189,7 @@ def msg_cinematic(text, borders=True):
|
|||
|
||||
"""
|
||||
text = text.strip()
|
||||
text = justify(text, align='c', indent=1)
|
||||
text = justify(text, align="c", indent=1)
|
||||
if borders:
|
||||
text = add_msg_borders(text)
|
||||
return text
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue