199 lines
6.3 KiB
Python
199 lines
6.3 KiB
Python
"""
|
|
Room
|
|
|
|
Rooms are simple containers that has no location of their own.
|
|
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from re import match
|
|
|
|
from evennia import utils
|
|
from evennia.utils import gametime, logger, delay
|
|
from evennia.contrib.grid.extended_room import ExtendedRoom
|
|
from evennia.contrib.rpg.rpsystem import ContribRPRoom
|
|
|
|
from django.conf import settings
|
|
|
|
from typeclasses.pets import Hunger
|
|
from typeclasses.objects import ObjectParent, Listener
|
|
from utils.word_list import fix_msg
|
|
|
|
_SEARCH_AT_RESULT = utils.object_from_module(settings.SEARCH_AT_RESULT)
|
|
|
|
|
|
def articlize_character(character, capitalize=False):
|
|
"""
|
|
Return a simple character with article prefix.
|
|
"""
|
|
if capitalize:
|
|
article = "A"
|
|
else:
|
|
article = "a"
|
|
|
|
logger.info(f"rooms: articlize_character({character})")
|
|
if character == "" or match(r"^\|[A-z][A-Z]", character):
|
|
return character
|
|
elif match(r"^\|[A-z][aeiou]", character):
|
|
return f"{article}n " + character
|
|
else:
|
|
return f"{article} " + character
|
|
|
|
def captialize_characters(characters):
|
|
"""
|
|
Capitalizes and prefixes an article on string of characters.
|
|
Assuming one per line.
|
|
"""
|
|
char_list = characters.split("\n")
|
|
updated = [articlize_character(ch, True) for ch in char_list]
|
|
return "\n".join(updated)
|
|
|
|
|
|
class Room(ObjectParent, ExtendedRoom, ContribRPRoom, Listener):
|
|
"""
|
|
Rooms are like any Object, except their location is None
|
|
(which is default). They also use basetype_setup() to
|
|
add locks so they cannot be puppeted or picked up.
|
|
(to change that, use at_object_creation instead)
|
|
|
|
See mygame/typeclasses/objects.py for a list of
|
|
properties and methods available on all Objects.
|
|
"""
|
|
is_dark = False
|
|
has_weather = False
|
|
appearance_template = """
|
|
|
|
{header}
|
|
|c{name}{extra_name_info}|n
|
|
{desc}
|
|
{exits}
|
|
{things}
|
|
{characters}
|
|
{footer}
|
|
"""
|
|
|
|
def get_time(self):
|
|
"""
|
|
Return tuple of current time of this location.
|
|
(Minute, Hour, Time of Day, Season)
|
|
"""
|
|
timestamp = gametime.gametime(absolute=True)
|
|
datestamp = datetime.fromtimestamp(timestamp)
|
|
return (datestamp.minute, datestamp.hour,
|
|
self.get_time_of_day(), self.get_season())
|
|
|
|
def get_display_header(self, looker, **kwargs):
|
|
return "|n"
|
|
|
|
def get_display_footer(self, looker, **kwargs):
|
|
return "|n"
|
|
|
|
def get_display_characters(self, looker, *args, **kwargs):
|
|
chars = self.contents_get(content_type="character")
|
|
vchars = self.filter_visible(chars, looker, **kwargs)
|
|
num_chars = len(vchars)
|
|
|
|
char_list = super().get_display_characters(looker, pose=True)
|
|
|
|
# We add the word 'also' in case we showed there were objects:
|
|
objs = self.contents_get(content_type="object")
|
|
if len(objs) > 0:
|
|
also = 'also '
|
|
else:
|
|
also = ''
|
|
|
|
if num_chars > 1:
|
|
return f"You {also}see the following characters:" + \
|
|
captialize_characters(char_list)
|
|
|
|
if num_chars > 0:
|
|
character = char_list.strip()
|
|
if character.startswith('|'):
|
|
comp_char = character[2:].lower()
|
|
else:
|
|
comp_char = character.lower()
|
|
|
|
if match(r"an? |the ", comp_char):
|
|
return f"You {also}see {character}."
|
|
elif match(r"[aeiou]", comp_char):
|
|
return f"You {also}see an {character}."
|
|
else:
|
|
return f"You {also}see a {character}."
|
|
return ''
|
|
|
|
def get_display_things(self, looker, *args, **kwargs):
|
|
std_msg = super().get_display_things(looker, pose=False)
|
|
if std_msg:
|
|
return std_msg.replace('|wYou see:|n', 'You notice') + '.'
|
|
else:
|
|
return ''
|
|
|
|
def msg_contents(self, message, exclude=None, from_obj=None, mapping=None,
|
|
raise_funcparse_errors=False, **kwargs):
|
|
message = fix_msg(message)
|
|
super().msg_contents(message, exclude, from_obj, mapping,
|
|
raise_funcparse_errors)
|
|
|
|
|
|
class DabblersRoom(Room):
|
|
def get_display_desc(self, looker):
|
|
fire = self.search("fire")
|
|
full_desc = self.db.initial_desc
|
|
if fire.hunger() == Hunger.RAVENOUS:
|
|
full_desc += " " + self.db.fire_out
|
|
elif fire.hunger() == Hunger.HUNGRY:
|
|
full_desc += " " + self.db.fire_dim
|
|
elif fire.hunger() == Hunger.FULL:
|
|
full_desc += " " + self.db.fire_full
|
|
else:
|
|
full_desc += " " + self.db.fire_on
|
|
full_desc += " " + self.db.final_desc
|
|
|
|
return full_desc
|
|
|
|
|
|
class OpenableRoom(Room):
|
|
"""
|
|
Rooms that accept the "open" and "close" command.
|
|
|
|
This will move an exit in and out of this location.
|
|
Set the follow properties:
|
|
|
|
@set here/open_exit = $search(red door)
|
|
@set here/open_exit_msg = "$You() $conj(open) the door!"
|
|
@set here/close_exit_msg = "$You() $conj(close) the door!"
|
|
@set here/close_automatic = 240
|
|
"""
|
|
def do_open(self, opener, item):
|
|
"""
|
|
Move the 'open_exit' to this location.
|
|
"""
|
|
the_exit = self.db.open_exit
|
|
if the_exit and the_exit.key.endswith(item):
|
|
if the_exit.location == self:
|
|
opener.msg(f"The {item} is already open.")
|
|
return True
|
|
the_exit.location = self
|
|
opener.announce_action(self.db.open_exit_msg or
|
|
f"$You() $conj(open) the {the_exit.name}")
|
|
if self.db.close_automatic:
|
|
delay(self.db.close_automatic, self.do_close)
|
|
return True
|
|
|
|
def do_close(self, closer=None, item=None):
|
|
"""
|
|
Move the 'open_exit' exit to Limbo.
|
|
"""
|
|
the_exit = self.db.open_exit
|
|
if the_exit and (not item or the_exit.key.endswith(item)):
|
|
if the_exit.location == self: # It is opened and can be closed:
|
|
the_exit.location = None
|
|
if closer:
|
|
closer.announce_action(self.db.close_exit_msg or
|
|
f"$You() $conj(close) the {the_exit.name}")
|
|
else:
|
|
self.msg_contents(self.db.close_exit_msg)
|
|
elif closer:
|
|
closer.msg(f"The {item} is already closed.")
|
|
return True
|