Further work on stabilizing output across different situations.

This commit is contained in:
Griatch 2015-09-23 18:51:29 +02:00
parent bac8f51401
commit 23e63111cc
2 changed files with 89 additions and 70 deletions

View file

@ -108,6 +108,9 @@ _RE_REF = re.compile(r"\{+\#([0-9]+)\}+")
# This regex is used to quickly reference one self in an emote. # This regex is used to quickly reference one self in an emote.
_RE_SELF_REF = re.compile(r"/me|@", _RE_FLAGS) _RE_SELF_REF = re.compile(r"/me|@", _RE_FLAGS)
# regex for non-alphanumberic end of a string
_RE_CHAREND = re.compile(r"\W+$", _RE_FLAGS)
# reference markers for language # reference markers for language
_RE_REF_LANG = re.compile(r"\{+\##([0-9]+)\}+") _RE_REF_LANG = re.compile(r"\{+\##([0-9]+)\}+")
# language says in the emote are on the form "..." or langname"..." (no spaces). # language says in the emote are on the form "..." or langname"..." (no spaces).
@ -262,7 +265,6 @@ def parse_language(speaker, emote):
return emote, mapping return emote, mapping
def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False): def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False):
""" """
Read a textraw emote and parse it into an intermediary Read a textraw emote and parse it into an intermediary
@ -379,7 +381,9 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False):
mapping[key] = obj if search_mode else (obj.db.sdesc or obj.key) mapping[key] = obj if search_mode else (obj.db.sdesc or obj.key)
else: else:
refname = marker_match.group() refname = marker_match.group()
reflist = ["%s%s%s (%s)" % (inum+1, _NUM_SEP, _RE_PREFIX.sub("", refname), text) reflist = ["%s%s%s (%s%s)" % (inum+1, _NUM_SEP,
_RE_PREFIX.sub("", refname), text,
" (%s)" % sender.key if sender == obj else "")
for inum, (obj, text) in enumerate(bestmatches) if score == maxscore] for inum, (obj, text) in enumerate(bestmatches) if score == maxscore]
errors.append(_EMOTE_MULTIMATCH_ERROR.format( errors.append(_EMOTE_MULTIMATCH_ERROR.format(
ref=marker_match.group(), reflist="\n ".join(reflist))) ref=marker_match.group(), reflist="\n ".join(reflist)))
@ -401,50 +405,7 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False):
return string, mapping return string, mapping
def receive_emote(sender, receiver, emote, sdesc_mapping, language_mapping): def send_emote(sender, receivers, emote, anonymous_add="first"):
"""
Receive a pre-parsed emote.
Args:
sender (Object): The object sending the emote.
receiver (Object): The object receiving (seeing) the emote.
emote (str): A pre-parsed emote string created with
`parse_emote`, with {#dbref} and {##nn} references for
objects and languages respectively.
sdesc_mapping (dict): A mapping between "#dbref" keys and
objects.
language_mapping (dict): A mapping "##dbref" and (langname, saytext).
Returns:
finished_emote (str): The finished and ready-to-send emote
string, customized for receiver.
Notes:
This function will translage all text back based both on sdesc
and recog mappings, but will give presedence to recog mappings.
"""
# we make a local copy that we can modify
mapping = copy(sdesc_mapping)
# overload mapping with receiver's recogs (which is on the same form)
try:
mapping.update(receiver.recog.ref2recog)
except AttributeError:
pass
# handle the language mapping, which always produce different keys ##nn
for key, (langname, saytext) in language_mapping.iteritems():
# color say's white
mapping[key] = "{w%s{n" % _LANGUAGE_TRANSLATE(sender, receiver, langname, saytext)
# make sure receiver always sees their real name
rkey = "#%i" % receiver.id
if rkey in mapping:
mapping[rkey] = receiver.key
#TODO - color handling
mapping = dict((key, "{b%s{n" % val) for key, val in mapping.iteritems())
receiver.msg(emote.format(**mapping))
def send_emote(sender, receivers, emote, no_anonymous=True):
""" """
Main access function for distribute an emote. Main access function for distribute an emote.
@ -454,10 +415,12 @@ def send_emote(sender, receivers, emote, no_anonymous=True):
will also form the basis for which sdescs are will also form the basis for which sdescs are
'valid' to use in the emote. 'valid' to use in the emote.
emote (str): The raw emote string as input by emoter. emote (str): The raw emote string as input by emoter.
no_anonymous (bool, optional): Do not allow anonynous anonymous_add (str or None, optional): If `sender` is not
emotes, that is, emotes without sender self-referencing, self-referencing in the emote, this will auto-add
but add an extra reference to the end of the emote `sender`'s data to the emote. Possible values are
if so. - None: No auto-add at anonymous emote
- 'last': Add sender to the end of emote as [sender]
- 'first': Prepend sender to start of emote.
""" """
try: try:
@ -468,15 +431,39 @@ def send_emote(sender, receivers, emote, no_anonymous=True):
sender.msg(err.message) sender.msg(err.message)
return return
if no_anonymous and not "#%i" % sender.id in sdesc_mapping: if anonymous_add and not "#%i" % sender.id in sdesc_mapping:
# no self-reference in the emote - add to the end # no self-reference in the emote - add to the end
key = "#%i" % sender.id key = "#%i" % sender.id
emote = "%s [%s]" % (emote, "{%s}" % key)
sdesc_mapping[key] = sender.sdesc.get() or sender.key sdesc_mapping[key] = sender.sdesc.get() or sender.key
if anonymous_add == 'first':
possessive = "" if emote.startswith('\'') else " "
emote = "%s%s%s" % ("{%s}" % key, possessive, emote)
else:
emote = "%s [%s]" % (emote, "{%s}" % key)
# broadcast emote # broadcast emote to everyone
for receiver in receivers: for receiver in receivers:
receive_emote(sender, receiver, emote, sdesc_mapping, language_mapping) # we make a temporary copy that we can modify
mapping = copy(sdesc_mapping)
# overload mapping with receiver's recogs (which is on the same form)
try:
mapping.update(receiver.recog.ref2recog)
except AttributeError:
pass
# handle the language mapping, which always produce different keys ##nn
for key, (langname, saytext) in language_mapping.iteritems():
# color say's white
mapping[key] = "{w%s{n" % _LANGUAGE_TRANSLATE(sender, receiver, langname, saytext)
# make sure receiver always sees their real name
rkey = "#%i" % receiver.id
if rkey in mapping:
mapping[rkey] = receiver.key
#TODO - color handling
mapping = dict((key, "%s" % val) for key, val in mapping.iteritems())
# do the template replacement
receiver.msg(emote.format(**mapping))
#------------------------------------------------------------ #------------------------------------------------------------
@ -524,9 +511,9 @@ class CmdEmote(RPCommand): # replaces the main emote
# we also include ourselves here. # we also include ourselves here.
emote = self.args emote = self.args
targets = self.caller.location.contents targets = self.caller.location.contents
if not emote.endswith("."): if not emote.endswith((".", "!")):
emote = "%s." % emote emote = "%s." % emote
send_emote(self.caller, targets, emote, no_anonymous=True) send_emote(self.caller, targets, emote, anonymous_add='first')
class CmdSdesc(RPCommand): # set/look at own sdesc class CmdSdesc(RPCommand): # set/look at own sdesc
@ -549,7 +536,9 @@ class CmdSdesc(RPCommand): # set/look at own sdesc
caller.msg("Usage: sdesc <sdesc-text>") caller.msg("Usage: sdesc <sdesc-text>")
return return
else: else:
sdesc = caller.sdesc.add(self.args) # strip non-alfanum chars from end of sdesc
sdesc = _RE_CHAREND.sub("", self.args)
sdesc = caller.sdesc.add(sdesc)
caller.msg("Your sdesc was set to '%s'." % sdesc) caller.msg("Your sdesc was set to '%s'." % sdesc)
@ -562,6 +551,8 @@ class CmdPose(Command): # set current pose and default pose
pose default <pose> pose default <pose>
pose reset pose reset
pose obj = <pose> pose obj = <pose>
pose default obj = <pose>
pose reset obj =
Examples: Examples:
pose leans against the tree pose leans against the tree
@ -632,7 +623,7 @@ class CmdPose(Command): # set current pose and default pose
caller.msg("Default pose is now '%s %s'." % (target_name, pose)) caller.msg("Default pose is now '%s %s'." % (target_name, pose))
return return
else: else:
caller.db.pose = pose target.db.pose = pose
caller.msg("Pose will read '%s %s'." % (target_name, pose)) caller.msg("Pose will read '%s %s'." % (target_name, pose))
@ -675,13 +666,17 @@ class CmdRecog(Command): # assign personal alias to object in room
if nmatches == 0: if nmatches == 0:
caller.msg(_EMOTE_NOMATCH_ERROR.format(ref=sdesc)) caller.msg(_EMOTE_NOMATCH_ERROR.format(ref=sdesc))
elif nmatches > 1: elif nmatches > 1:
reflist = ["%s%s%s (%s)" % (inum+1, _NUM_SEP, _RE_PREFIX.sub("", sdesc), obj.sdesc.get()) reflist = ["%s%s%s (%s%s)" % (inum+1, _NUM_SEP,
_RE_PREFIX.sub("", sdesc), caller.recog.get(obj),
" (%s)" % caller.key if caller == obj else "")
for inum, obj in enumerate(matches)] for inum, obj in enumerate(matches)]
caller.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=sdesc,reflist="\n ".join(reflist))) caller.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=sdesc,reflist="\n ".join(reflist)))
else: else:
# we have all we need, add the recog alias # we have all we need, add the recog alias
obj = matches[0]
sdesc = obj.sdesc.get() if hasattr(obj, "sdesc") else obj.key
alias = caller.recog.add(obj, alias) alias = caller.recog.add(obj, alias)
caller.msg("You will now remember {w%s{n as {w%s{n." % (obj.db.sdesc, alias)) caller.msg("You will now remember {w%s{n as {w%s{n." % (sdesc, alias))
class CmdLanguage(Command): # list available languages class CmdLanguage(Command): # list available languages
@ -871,10 +866,11 @@ class RecogHandler(object):
# mapping #dbref:obj # mapping #dbref:obj
key = "#%i" % obj.id key = "#%i" % obj.id
self.db._ref2recog[key] = recog print "self.obj:", self.obj, self.obj.db._ref2recog
self.db._obj2recog[obj] = recog self.obj.db._recog_ref2recog[key] = recog
self.obj.db._recog_obj2recog[obj] = recog
regex = ordered_permutation_regex(cleaned_recog) regex = ordered_permutation_regex(cleaned_recog)
self.db._obj2regex[obj] = regex self.obj.db._recog_obj2regex[obj] = regex
# local caching # local caching
self.ref2recog[key] = recog self.ref2recog[key] = recog
self.obj2recog[obj] = recog self.obj2recog[obj] = recog
@ -883,14 +879,16 @@ class RecogHandler(object):
def get(self, obj): def get(self, obj):
""" """
Get recog replacement string, if one exists. Get recog replacement string, if one exists, otherwise
get sdesc and as a last resort, the object's key.
Args: Args:
obj (Object): The object, whose sdesc to replace obj (Object): The object, whose sdesc to replace
Returns: Returns:
recog (str): The replacement string to use. recog (str): The replacement string to use.
""" """
return self.obj2recog.get(obj) return self.obj2recog.get(obj, obj.sdesc.get()
if hasattr(obj, "sdesc") else obj.key)
def remove(self, obj): def remove(self, obj):
""" """
@ -900,9 +898,9 @@ class RecogHandler(object):
obj (Object): The object for which to remove recog. obj (Object): The object for which to remove recog.
""" """
if obj in self.db.obj2recog: if obj in self.db.obj2recog:
del self.db.obj2recog[obj] del self.db._recog_obj2recog[obj]
del self.db.obj2regex[obj] del self.db._recog_obj2regex[obj]
del self.db.ref2regex["#%i" % obj.id] del self.db._recog_ref2regex["#%i" % obj.id]
self._cache() self._cache()
def get_regex_tuple(self, obj): def get_regex_tuple(self, obj):
@ -953,17 +951,36 @@ class RPObject(DefaultObject):
if (isinstance(searchdata, basestring) and not if (isinstance(searchdata, basestring) and not
(kwargs.get("global_search") or (kwargs.get("global_search") or
kwargs.get("candidates"))): kwargs.get("candidates"))):
matches = parse_sdescs_and_recogs(self, self.location.contents, # searchdata is a string; common self-references
if searchdata.lower() in ("here", ):
return [self.location] if "quiet" in kwargs else self.location
if searchdata.lower() in ("me", "self",):
return [self] if "quiet" in kwargs else self
if searchdata.lower() == self.key.lower():
return [self] if "quiet" in kwargs else self
# sdesc/recog matching
candidates = self.location.contents
matches = parse_sdescs_and_recogs(self, candidates,
_PREFIX + searchdata, search_mode=True) _PREFIX + searchdata, search_mode=True)
nmatches = len(matches) nmatches = len(matches)
if nmatches == 1: if nmatches == 1:
return matches[0] return matches[0]
elif nmatches > 1: elif nmatches > 1:
# multimatch # multimatch
reflist = ["%s%s%s (%s)" % (inum+1, _NUM_SEP, searchdata, obj.sdesc.get()) reflist = ["%s%s%s (%s%s)" % (inum+1, _NUM_SEP, searchdata, self.recog.get(obj),
" (%s)" % self.key if self == obj else "")
for inum, obj in enumerate(matches)] for inum, obj in enumerate(matches)]
self.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=searchdata,reflist="\n ".join(reflist))) self.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=searchdata,reflist="\n ".join(reflist)))
return return
if not self.locks.check_lockstring(self, "perm(Builders)"):
# we block lookup unless we have access to continue
if "nofound_string" in kwargs:
self.msg(kwargs["nofound_string"])
else:
self.msg("There is nothing here called '%s'." % searchdata)
return
# fall back to normal search # fall back to normal search
return super(RPObject, self).search(searchdata, **kwargs) return super(RPObject, self).search(searchdata, **kwargs)

View file

@ -503,6 +503,8 @@ class LockHandler(object):
or (hasattr(accessing_obj, 'player') and hasattr(accessing_obj.player, 'is_superuser') and accessing_obj.player.is_superuser) or (hasattr(accessing_obj, 'player') and hasattr(accessing_obj.player, 'is_superuser') and accessing_obj.player.is_superuser)
or (hasattr(accessing_obj, 'get_player') and (not accessing_obj.get_player() or accessing_obj.get_player().is_superuser))): or (hasattr(accessing_obj, 'get_player') and (not accessing_obj.get_player() or accessing_obj.get_player().is_superuser))):
return True return True
if not ":" in lockstring:
lockstring = "%s:%s" % ("_dummy", lockstring)
locks = self._parse_lockstring(lockstring) locks = self._parse_lockstring(lockstring)