Better 'say' command

That is easier to use.
This commit is contained in:
Howard Abrams 2025-11-03 22:08:07 -08:00
parent d28b993e71
commit 6cea0e122a

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from random import random from random import random
from re import split, sub, MULTILINE from re import match, split, sub, MULTILINE
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from evennia.commands.default.general import CmdGet, NumberedTargetCommand from evennia.commands.default.general import CmdGet, NumberedTargetCommand
@ -251,160 +251,191 @@ class CmdWhisper(MuxCommand):
self.caller.msg(full_speech, from_obj=self.caller) self.caller.msg(full_speech, from_obj=self.caller)
class CmdSay(MuxCommand): class CmdSay(Command):
""" """Say something to the characters in the same area.
Say something to the characters in the same area.
For instance: Usage:
|gsay Good evening!|n |gsay [[<adverb>] [to] [<character>],] <message>|n
However, you can use an alias and simply type: This command has many optional strings. You see, the text within
brackets, [...] are optional, while text in <...> are to be
replaced, and this technical jargon probably means little, so
perhaps examples would be better:
|g"Good evening! |gsay Good evening.|n
|wYou say, "Good evening."|n
Or: Or:
|g'Good evening! |gsay loudly, Good evening!|n
|wYou loudly exclaim, "Good evening!"|n
Creatures and objects in this game can sometimes respond to what you say. In the second example, the exclamation point changes the 'say' to
an 'exclaim'. A question mark changes 'say' to 'ask'.
Usage: Also, you gave an |wadverb|n that ends in -ly, as well as a comma.
say phrase The comma is important, as it triggers |wprocessing|n. Without
say/to char1 [, char2 ...] = phrase the comma, you would see:
say[/switches] phrase
Where switches can be any of the following: |gs loudly Good evening!
|wYou exclaim, "loudly Good evening!"|n
- exclaim : To replace 'says' with 'exclaims' You can also direct your message to a particular person (or thing),
- yell : To replace 'says' with 'yells' as in:
- scream : To replace 'says' with 'screams'
- ask : To replace 'says' with 'asks'
- to : Directs phrase to one or more characters
in the same area. Note others can still hear
the statement (see the 'whisper' command).
- adverb : Any adverb-like word that ends in '-ly'
is added to the say command, for instance:
say/quietly Hi there. |gsay to heron, How do you do?
|wYou ask the purple heron, "How do you do?"|n
"What can I do for you?" asks the purple heron.
Shows as: Again, the comma is important, otherwise, you will see:
|gsay to heron How do you do?
|wYou ask, "to heron How do you do?"|n
The purple heron questions, "Uhm. I'm not sure how to respond."
You can replace the 'say' command with any of the following:
- shout
- scream
- respond
- reply
- yell
- ask
Because this command is so common, you can also use ", as in:
|g"What's going on?|n
You quietly say, "Hi there."
""" """
key = "say" key = "say"
verb = "say"
aliases = ["says", "speak", "shout", "yell", "exclaim", "scream", "ask", aliases = ["says", "speak", "shout", "yell", "exclaim", "scream", "ask",
"reply", "respond", "\"", "'"] "reply", "respond", '"', "'"]
priority = 0
locks = "cmd:all()" locks = "cmd:all()"
rhs_split = ("=") # don't require a space after `say/'/"`
arg_regex = None arg_regex = None
adverb = None
target = None
def parse(self):
"""Parse the input into speech parts."""
self.phrase = self.args.strip()
m = match(r".+\?.*", self.phrase)
if m:
self.verb = "ask"
m = match(r".+!.*", self.phrase)
if m:
self.verb = "exclaim"
# Final quotes can be trimmed:
self.phrase = self.phrase.strip('"').strip("'")
m = match(r"(.*) *, *(.+)", self.phrase)
if m:
self.phrase = m.group(2)
for word in split(r" +", m.group(1)):
if word.endswith("ly") and not self.adverb:
self.adverb = word
elif word == "to":
pass
else:
self.target = self.caller.search(word)
def func(self): def func(self):
"""Implement the new 'say' command with switches.""" """Implement the new 'say' command with switches."""
speaker = self.caller speaker = self.caller
if not self.phrase or self.phrase == "":
if not self.args:
speaker.msg("Say what?") speaker.msg("Say what?")
return return
if 'to' in self.switches and not self.rhs:
speaker.msg(paragraph("""
When attempting to say something to one or more
characters, use the '=' character to identify what you
want to say.
For instance, |gsay/to elf = Hi there.|n """))
return
if self.rhs:
speech = self.rhs
else:
speech = self.args
# If speech is empty, stop here # If speech is empty, stop here
if not speaker.at_pre_say(speech): if not speaker.at_pre_say(self.phrase):
return return
adverb = '' if self.cmdstring == 'scream':
for switch in self.switches: self.verb = 'scream'
if switch.endswith('ly'): elif self.cmdstring == 'shout':
adverb = switch + ' ' self.verb = 'shout'
elif self.cmdstring == 'respond':
if 'scream' in self.switches or self.cmdstring == 'scream': self.verb = 'respond'
verb = 'scream' elif self.cmdstring == 'reply':
elif 'shout' in self.switches or self.cmdstring == 'shout': self.verb = 'reply'
verb = 'shout' elif self.cmdstring == 'yell':
elif 'respond' in self.switches or self.cmdstring == 'respond': self.verb = 'yell'
verb = 'respond' elif self.cmdstring == 'ask':
elif 'reply' in self.switches or self.cmdstring == 'reply': self.verb = 'ask'
verb = 'reply'
elif 'yell' in self.switches or self.cmdstring == 'yell':
verb = 'yell'
elif 'exclaim' in self.switches or self.cmdstring == 'exclaim' or speech.endswith('!'):
verb = 'exclaim'
elif 'ask' in self.switches or self.cmdstring == 'ask' or speech.endswith('?'):
verb = 'ask'
else:
verb = "say"
for_me, for_others, verb = \ for_me, for_others, verb = \
speech_effect(speech, verb, speech_effect(self.phrase, self.verb, speaker,
speaker,
speaker.attributes.get(category="effect", speaker.attributes.get(category="effect",
return_obj=True, return_obj=True,
return_list=True)) return_list=True))
self.to_puppets(speaker, for_others, self.target)
self.to_you(speaker, verb, for_me)
self.to_others(speaker, verb, for_others)
to_who = to_whom = '' def to_you(self, speaker, verb, phrase):
"""Send 'say' message to the speaker.
if 'to' not in self.switches:
for char in speaker.location.contents:
if hasattr(char, 'other_say') and callable(char.other_say):
char.other_say(speaker, for_others)
else:
# Send the message to 'puppets' that have the special 'other_sayto'
# method (if they are the object of the message):
targets = split(r" *, *", self.lhs)
to_chars = [speaker.search(c, quiet=True) for c in targets]
to_chars = [c[0] for c in to_chars if len(c) > 0]
if to_chars == []:
speaker.msg(f"No match for {', '.join(targets)}")
return
for char in to_chars:
if hasattr(char, 'other_sayto') and callable(char.other_sayto):
logger.info(f"Found {char.key}: {for_others}")
char.other_sayto(speaker, for_others)
who = iter_to_str([c.get_display_name(speaker)
if isinstance(c, Character) else c
for c in to_chars])
whom = iter_to_str([f"/{c}" for c in targets])
The `send_emote` is _global_, so if we want to say to 'Bob',
'You say ...', we have to both send him a message with the
'You' as well as everyone else with the 'send_emote'.
"""
to_who = ""
if self.target:
who = self.target.get_display_name(speaker)
if verb == "ask": if verb == "ask":
to_who = " " + who to_who = " " + who
to_whom = " " + whom
else: else:
to_who = " to " + who to_who = " to " + who
to_whom = " to " + whom
# The `send_emote` is _global_, so if we want to say to 'Bob', adverb = self.adverb + " " if self.adverb else ""
# 'You say ...', we have to both send him a message with the
# 'You' as well as everyone else with the 'send_emote'. full_speech = f"You {adverb}{verb}{to_who}, \"{phrase}\""
full_speech = f"You {adverb}{verb}{to_who}, \"{for_me}\""
speaker.msg(full_speech, from_obj=speaker) speaker.msg(full_speech, from_obj=speaker)
# English is weird... def to_others(self, speaker, verb, phrase):
if verb == 'reply': """Use the 'send_emote' to have speaker 'say' something to others.
verb = 'replie'
We use /me to be replaced by the user's appearance to others.
We also need to deal with weird English usage.
"""
to_whom = ""
if self.target:
whom = f"/{self.target.key}"
if verb == "ask":
to_whom = " " + whom
else:
to_whom = " to " + whom
adverb = self.adverb + " " if self.adverb else ""
# English is weird...
verb = 'replie' if verb == 'reply' else verb
targets = [item for item in speaker.location.contents targets = [item for item in speaker.location.contents
if item != speaker] if item != speaker]
full_speech = f"/me {adverb}{verb}s{to_whom}, \"{for_others}\""
full_speech = f"/me {adverb}{verb}s{to_whom}, \"{phrase}\""
send_emote(speaker, targets, full_speech, msg_type="say", send_emote(speaker, targets, full_speech, msg_type="say",
anonymous_add=None) anonymous_add=None)
def to_puppets(self, speaker, phrase, target=None):
"""Send phrase to puppet, target.
If target is None, then send to all puppets.
"""
# Speak to everyone in the room:
if not target:
for char in speaker.location.contents:
if hasattr(char, 'other_say') and callable(char.other_say):
char.other_say(speaker, phrase)
else:
if hasattr(target, 'other_sayto') and callable(target.other_sayto):
logger.info(f"Found {target.key}: {phrase}")
target.other_sayto(speaker, phrase)
class CmdThink(Command): class CmdThink(Command):
"""Think a thought out loud. """Think a thought out loud.