Moved 'eat' command from food to people

This handles better error messages.

Also, cleaned up code warnings.
This commit is contained in:
Howard Abrams 2025-05-31 08:47:56 -07:00
parent ddcb0f0306
commit 167e8f356f
5 changed files with 106 additions and 49 deletions

View file

@ -20,22 +20,6 @@ class CmdSetMakeConsumable(CmdSet):
self.add(CmdMakeConsumable) self.add(CmdMakeConsumable)
class CmdEat(Command):
"""
Eat something
"""
key = "eat"
aliases = "bite"
def func(self):
self.obj.do_eat(self.caller)
class CmdSetEat(CmdSet):
def at_cmdset_creation(self):
self.add(CmdEat)
class CmdMakeTea(Command): class CmdMakeTea(Command):
""" """
make [tea-type] make [tea-type]

View file

@ -20,7 +20,7 @@ from evennia.contrib.game_systems.gendersub import SetGender
from evennia.contrib.rpg.rpsystem import RPSystemCmdSet from evennia.contrib.rpg.rpsystem import RPSystemCmdSet
from evennia.contrib.rpg.character_creator.character_creator import ContribChargenCmdSet from evennia.contrib.rpg.character_creator.character_creator import ContribChargenCmdSet
from commands.sittables import CmdNoSitStand from commands.sittables import CmdNoSitStand
from commands.everyone import CmdTake, CmdThink, CmdSay, CmdWhisper, CmdRead, CmdDrink from commands.everyone import CmdTake, CmdThink, CmdSay, CmdWhisper, CmdRead, CmdEat, CmdDrink
from commands.wizards import CmdGM, CmdSpell, CmdGMTrigger, CmdMakeCocktail from commands.wizards import CmdGM, CmdSpell, CmdGMTrigger, CmdMakeCocktail
class CharacterCmdSet(default_cmds.CharacterCmdSet): class CharacterCmdSet(default_cmds.CharacterCmdSet):
@ -38,6 +38,7 @@ class CharacterCmdSet(default_cmds.CharacterCmdSet):
""" """
super().at_cmdset_creation() super().at_cmdset_creation()
self.add(CmdNoSitStand) self.add(CmdNoSitStand)
self.add(CmdEat)
self.add(CmdDrink) self.add(CmdDrink)
self.add(CmdTake) self.add(CmdTake)
self.add(CmdThink) self.add(CmdThink)

View file

@ -13,9 +13,12 @@ from typeclasses.readables import find_book
from typeclasses.characters import Character from typeclasses.characters import Character
from utils.word_list import routput, paragraph, choices from utils.word_list import routput, paragraph, choices
def speech_effect(speech, verb, target, effects): def speech_effect(speech, verb, target, effects):
""" """
Returns a tuple for what a user thinks he said, and what Return speech after applying 'effects'.
Return a tuple for what a user thinks he said, and what
others actually here. If no effect, just return speech twice. others actually here. If no effect, just return speech twice.
Effects: Effects:
@ -38,7 +41,7 @@ def speech_effect(speech, verb, target, effects):
class CmdWhisper(MuxCommand): class CmdWhisper(MuxCommand):
""" """
Speak privately as your character to another Speak privately as your character to another.
Usage: Usage:
whisper <character> = <message> whisper <character> = <message>
@ -47,15 +50,14 @@ class CmdWhisper(MuxCommand):
Talk privately to one or more characters in your current location, without Talk privately to one or more characters in your current location, without
others in the room being informed. others in the room being informed.
""" """
key = "whisper" key = "whisper"
priority = 0 priority = 0
locks = "cmd:all()" locks = "cmd:all()"
rhs_split = ("=") rhs_split = ("=")
def func(self): def func(self):
""" """Implement the new 'whisper' command."""
Implements the new 'whisper' command.
"""
if not self.args: if not self.args:
self.caller.msg("What are you whispering?") self.caller.msg("What are you whispering?")
return return
@ -75,7 +77,9 @@ class CmdWhisper(MuxCommand):
class CmdSay(MuxCommand): class CmdSay(MuxCommand):
""" """
Say something to the characters in the same area. For instance: Say something to the characters in the same area.
For instance:
|gsay Good evening!|n |gsay Good evening!|n
@ -114,16 +118,15 @@ class CmdSay(MuxCommand):
""" """
key = "say" key = "say"
aliases = ["says", "speak", "shout", "yell", "exclaim", "scream", "ask", "reply", "respond", "\"", "'"] aliases = ["says", "speak", "shout", "yell", "exclaim", "scream", "ask",
"reply", "respond", "\"", "'"]
priority = 0 priority = 0
locks = "cmd:all()" locks = "cmd:all()"
rhs_split = ("=") rhs_split = ("=")
arg_regex = None arg_regex = None
def func(self): def func(self):
""" """Implement the new 'say' command with switches."""
Implements the new 'say' command with switches.
"""
speaker = self.caller speaker = self.caller
if not self.args: if not self.args:
@ -220,9 +223,11 @@ class CmdSay(MuxCommand):
if verb == 'reply': if verb == 'reply':
verb = 'replie' verb = 'replie'
targets = [item for item in speaker.location.contents if item != speaker] targets = [item for item in speaker.location.contents
if item != speaker]
full_speech = f"/me {adverb}{verb}s{to_whom}, \"{for_others}\"" full_speech = f"/me {adverb}{verb}s{to_whom}, \"{for_others}\""
send_emote(speaker, targets, full_speech, msg_type="say", anonymous_add=None) send_emote(speaker, targets, full_speech, msg_type="say",
anonymous_add=None)
class CmdThink(Command): class CmdThink(Command):
@ -234,21 +239,21 @@ class CmdThink(Command):
Similar to the 'say' or 'pose' commands, this communicates an Similar to the 'say' or 'pose' commands, this communicates an
inner monologue to other players on the 'public' channel. inner monologue to other players on the 'public' channel.
""" """
key = "think" key = "think"
aliases = ["thinks", "("] aliases = ["thinks", "("]
arg_regex = None arg_regex = None
def func(self): def func(self):
""" """Implement the think out loud command."""
Implements the think out loud command.
"""
if not self.args: if not self.args:
self.caller.msg("What do you want to think out loud?") self.caller.msg("What do you want to think out loud?")
else: else:
thought = self.args.strip() thought = self.args.strip()
if (self.caller.db.thinking_count or 0) < 3 or random() < 0.4: if (self.caller.db.thinking_count or 0) < 3 or random() < 0.4:
msg = routput( msg = routput(
f"<< thinks ^ wonders >> << out loud ^ aloud >> ... o O ( {thought} )" f"<< thinks ^ wonders >> << out loud ^ aloud >> "
f"... o O ( {thought} )"
) )
else: else:
msg = f". o O ( {thought} )" msg = f". o O ( {thought} )"
@ -269,11 +274,11 @@ class CmdRead(Command):
@set <target>/inside = 'This is the text to read.' @set <target>/inside = 'This is the text to read.'
""" """
key = "read" key = "read"
def func(self): def func(self):
"""Return the 'inside' attribute.""" """Return the 'inside' attribute."""
target_str = self.args.strip() target_str = self.args.strip()
if target_str == "": if target_str == "":
self.caller.msg("Usage: |gread <object>|n") self.caller.msg("Usage: |gread <object>|n")
@ -294,14 +299,17 @@ class CmdTake(Command, NumberedTargetCommand):
Note that only some things can be stolen. Note that only some things can be stolen.
For instance, the brass ring from the door knocker. For instance, the brass ring from the door knocker.
""" """
key = "take" key = "take"
aliases = ["steal"] aliases = ["steal"]
rhs_split = ("=", " from ") rhs_split = ("=", " from ")
def func(self): def func(self):
""" """
Implements the take command. Since this command is designed Implement the take command.
to work on the object, we operate only on self.obj.
Since this command is designed to work on the object, we
operate only on self.obj.
""" """
if not self.args: if not self.args:
self.caller.msg("What do you want to take?") self.caller.msg("What do you want to take?")
@ -324,37 +332,99 @@ class CmdDrink(Command):
This doesn't tell others of this particular activity. This doesn't tell others of this particular activity.
""" """
key = "drink" key = "drink"
aliases = ["sip", "quaff"] aliases = ["sip", "quaff"]
def drinkable(self, item):
return hasattr(item, 'do_drink') and callable(item.do_drink)
def not_empty(self, item): def not_empty(self, item):
"""Return true is the cup has some drink left in it."""
return (item.db.amount or 0) > 0 return (item.db.amount or 0) > 0
def drink_item(self, name): def drink_item(self, name):
"""Find item in inventory, name, and call 'do_drink' on it."""
notfound = f"You don't have {name} in your inventory."
item = self.caller.search(name, location=self.caller, item = self.caller.search(name, location=self.caller,
nofound_string=f"You don't have {name} in your inventory.") nofound_string=notfound)
if item: if item:
if self.drinkable(item): if item.has_method('do_drink'):
item.do_drink(self.caller) item.do_drink(self.caller)
else: else:
self.caller.msg(f"The {item.name} is not drinkable.") self.caller.msg(f"The {item.name} is not drinkable.")
def drink_anything(self): def drink_anything(self):
"""Drink anything in your inventory, but only if you have one thing."""
containers = [item for item in self.caller.contents containers = [item for item in self.caller.contents
if self.drinkable(item) and self.not_empty(item)] if item.has_method('do_drink') and self.not_empty(item)]
if len(containers) == 1: if len(containers) == 1:
containers[0].do_drink(self.caller) containers[0].do_drink(self.caller)
elif len(containers) > 1: elif len(containers) > 1:
self.caller.msg("You have two many things you can drink. Which one do you want?") self.caller.msg("You have two many things you can drink. "
"Which one do you want?")
else: else:
self.caller.msg("You have nothing to drink.") self.caller.msg("You have nothing to drink.")
def func(self): def func(self):
"""
If given the name of something to drink, find and drink it.
Otherwise, drink the first item you find in your inventory.
"""
goal = self.args.strip() goal = self.args.strip()
if goal and goal != "": if goal and goal != "":
self.drink_item(goal) self.drink_item(goal)
else: else:
self.drink_anything() self.drink_anything()
class CmdEat(Command):
"""
Eat something edible in your inventory.
Usage:
eat [ food-item ]
This doesn't tell others of this particular activity.
"""
key = "eat"
aliases = ["consume", "bite"]
def not_gone(self, item):
"""Return true is the cup has some eat left in it."""
return (item.db.amount or 0) > 0
def eat_item(self, name):
"""Find item in inventory, name, and call 'do_eat' on it."""
notfound = f"You don't have {name} in your inventory."
item = self.caller.search(name, location=self.caller,
nofound_string=notfound)
if item:
if item.has_method('do_eat'):
item.do_eat(self.caller)
else:
self.caller.msg(f"The {item.name} is not edible.")
def eat_anything(self):
"""Eat something in your inventory, but only if you have one thing."""
items = [item for item in self.caller.contents
if item.has_method('do_eat') and self.not_gone(item)]
if len(items) == 1:
items[0].do_eat(self.caller)
elif len(items) > 1:
self.caller.msg("You have too many things to eat. "
"Which one do you want?")
else:
self.caller.msg("You have nothing to eat.")
def func(self):
"""
If given the name of something to eat, find and eat it.
Otherwise, eat the first item you find in your inventory.
"""
goal = self.args.strip()
if goal and goal != "":
self.eat_item(goal)
else:
self.eat_anything()

View file

@ -6,9 +6,8 @@ import random
from evennia import TICKER_HANDLER from evennia import TICKER_HANDLER
from evennia.prototypes.spawner import spawn from evennia.prototypes.spawner import spawn
from commands.consumables import ( from commands.consumables import CmdSetTrolley, CmdSetMakeConsumable
CmdSetEat, CmdSetTrolley, CmdSetMakeConsumable
)
from typeclasses.objects import Object from typeclasses.objects import Object
from utils.word_list import routput # , choices from utils.word_list import routput # , choices
@ -30,7 +29,6 @@ class Consumable(Object):
eat_amount = 1 eat_amount = 1
def at_object_creation(self): def at_object_creation(self):
self.cmdset.add_default(CmdSetEat)
self.db.amount = self.amount self.db.amount = self.amount
self.db.eat_amount = self.eat_amount self.db.eat_amount = self.eat_amount

View file

@ -250,6 +250,10 @@ class Object(ObjectParent, ContribRPObject):
return None return None
def has_method(self, method_name):
"""True if this object has a method of a particular name."""
return hasattr(self, method_name) and callable(getattr(self, method_name))
def delay_sequence(self, sequence_str, time_delay=1, *args): def delay_sequence(self, sequence_str, time_delay=1, *args):
"""Run a sequence of messages or commands with a delay. """Run a sequence of messages or commands with a delay.