Tea and teacups.

Dabbler's room will produce a tea cup for each person.

A teapot can make different types of teas, or even just a random one.
This commit is contained in:
Howard Abrams 2025-02-02 00:02:49 -08:00
parent cec2de230d
commit 37f3e8d479
6 changed files with 227 additions and 8 deletions

View file

@ -15,7 +15,7 @@ own cmdsets by inheriting from them or directly from `evennia.CmdSet`.
""" """
from evennia import default_cmds from evennia import default_cmds
from evennia.contrib.grid import extended_room
from commands.sittables import CmdNoSitStand from commands.sittables import CmdNoSitStand
class CharacterCmdSet(default_cmds.CharacterCmdSet): class CharacterCmdSet(default_cmds.CharacterCmdSet):
@ -33,6 +33,7 @@ class CharacterCmdSet(default_cmds.CharacterCmdSet):
""" """
super().at_cmdset_creation() super().at_cmdset_creation()
self.add(CmdNoSitStand) self.add(CmdNoSitStand)
self.add(extended_room.ExtendedRoomCmdSet)
# #
# any commands you add below will overload the default ones. # any commands you add below will overload the default ones.
# #

67
commands/drinkables.py Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/env python
from evennia import Command, CmdSet
import random
class CmdDrinkTea(Command):
"""
Drink tea.
"""
key = "drink"
aliases = "sip"
def func(self):
self.obj.do_drink(self.caller)
class CmdMakeTea(Command):
"""
Make a pot of magical tea.
"""
key = "make"
aliases = ["make tea"]
locks = "cmd:all()"
def func(self):
"""
Make a pot of tea. Optional accept the type of tea.
"""
self.obj.do_make_tea(self.caller, self.args.strip())
class CmdFillTeacup(Command):
"""
Fill the teacup with whatever is in the teapot.
"""
key = "fill"
aliases = "pour"
def func(self):
self.obj.do_fill(self.caller)
class CmdGetTeacup(Command):
"""
Get a teacup.
"""
key = "get teacup"
aliases = ["get cup", "pickup cup", "pickup teacup", "take cup", "take teacup"]
locks = "cmd:all()"
def func(self):
"""
Get a teacup from the container. It will
itself handle all messages.
"""
self.obj.produce_teacup(self.caller)
class CmdSetTeacup(CmdSet):
def at_cmdset_creation(self):
self.add(CmdDrinkTea)
class CmdSetTeapot(CmdSet):
def at_cmdset_creation(self):
self.add(CmdMakeTea)
self.add(CmdFillTeacup)
class CmdSetTrolley(CmdSet):
def at_cmdset_creation(self):
self.add(CmdGetTeacup)

103
typeclasses/drinkables.py Executable file
View file

@ -0,0 +1,103 @@
#!/usr/bin/env python
from typeclasses.objects import Object
from commands.drinkables import CmdSetTeapot, CmdSetTeacup
from utils.word_list import routput, character_has, Token
import random
TEACUP_DESCS = [
"A rustic, clay teacup carefully crafted on a wheel. Beautiful [dark red|olive green|navy blue] glaze.",
"A fine example of Royal Albert teacup, sporting a design of violet azaleas. Perfect for a black tea.",
"A Wings of Grace style teacup with blue butterflies. Perfect for some Earl Grey.",
"A dark brown Yixing clay teacup. Perfect for an Oolong tea.",
"A light jade green handle-less teacup. A good choice for a green tea.",
]
FILL_MSGS = [
"You fill your [teacup|cup] with {1}.",
"You pour [some|] {0} tea into your [teacup|cup].",
]
DRINK_MSGS = [
"You take a sip of {0} tea.",
"You take a sip of {0} tea [in|from] your [teacup|cup].",
"You [sip|sample|drink] from your [teacup|cup].",
"You savor {1} in your [teacup|cup].",
]
EMPTY_MSGS = [
"Your [teacup|cup] is empty. Perhaps you can |bmake|n some |btea|n?",
"Your cup certainly doesn't runneth over, as it be quite empty.",
"Alas, you find your cup devoid of any sort of watery infusion.",
"You notice your cup is empty.",
"It appears that you need to refill your tea cup."
]
TEA_TYPES = {
"black": "a rich and fragrant black tea",
"green": "a subtle green tea",
"oolong": "a complex and earthy oolong",
"macha": "a frothy macha",
"herbal": "an herbal infusion",
"earl": "a flowery Earl Gray",
"unknown": "tea",
}
class TeaCup(Object):
fill_amount = 4
sip_amount = 1
def at_object_creation(self):
self.cmdset.add_default(CmdSetTeacup)
def do_drink(self, drinker):
amount = self.db.amount or 0
tea_type = self.db.tea_type or "tea"
tea_details = self.db.tea_details
if amount > 0:
self.db.amount = self.db.amount - self.sip_amount
drinker.msg(routput(random.choice(DRINK_MSGS).format(tea_type, tea_details)))
else:
drinker.msg(routput(random.choice(EMPTY_MSGS).format(tea_type, tea_details)))
def do_fill(self, drinker, tea_type, tea_details):
self.db.tea_type = tea_type
self.db.tea_details = tea_details
self.db.amount = self.fill_amount
drinker.msg(routput(random.choice(FILL_MSGS).format(tea_type, tea_details)))
# Spam the room? Maybe not.
# self.location.msg_contents(f"{drinker.name} refills a {self.key}.",
# exclude=drinker)
class Teapot(Object):
def at_object_creation(self):
"""
called at creation
"""
self.cmdset.add_default(CmdSetTeapot, persistent=True)
def do_make_tea(self, drinker, args):
words = Token(args)
tea_choice = [tea for tea in TEA_TYPES.keys() if words.contains(tea)][0]
if tea_choice:
self.db.tea_type = tea_choice
elif words.empty():
self.db.tea_type = random.choice(TEA_TYPES.keys())
else:
self.db.tea_type = "unknown"
desc = TEA_TYPES[self.db.tea_type]
self.db.desc = f"A large, brown teapot full of {desc}."
drinker.msg(f"You make a teapot of {desc}.")
self.location.msg_contents(f"{drinker.name} makes a pot of tea.", exclude=drinker)
def do_fill(self, drinker):
teacup = character_has(drinker, "teacup")
if teacup:
teacup.do_fill(drinker, self.db.tea_type, TEA_TYPES[self.db.tea_type])

View file

@ -133,7 +133,8 @@ class Pet(Object):
if self.hunger() != curr: if self.hunger() != curr:
self.location.msg_contents("|w%s|n\n" % self.hunger_appearance()) self.location.msg_contents("|w%s|n\n" % self.hunger_appearance())
self.location.check_light_state() if self.location.check_light_state:
self.location.check_light_state()
def return_appearance(self, looker, **kwargs): def return_appearance(self, looker, **kwargs):
""" """

View file

@ -6,8 +6,13 @@ Rooms are simple containers that has no location of their own.
""" """
from evennia.objects.objects import DefaultRoom from evennia.objects.objects import DefaultRoom
from evennia.contrib.grid.extended_room import ExtendedRoom
from evennia.prototypes.spawner import spawn
from .objects import LightSource from .objects import LightSource
from .drinkables import TEACUP_DESCS
from commands.drinkables import CmdSetTrolley
from utils.word_list import routput, character_has, Token
import random import random
@ -35,7 +40,7 @@ _SEARCH_AT_RESULT = utils.object_from_module(settings.SEARCH_AT_RESULT)
from .objects import ObjectParent from .objects import ObjectParent
class Room(ObjectParent, DefaultRoom): class Room(ObjectParent, ExtendedRoom):
""" """
Rooms are like any Object, except their location is None Rooms are like any Object, except their location is None
(which is default). They also use basetype_setup() to (which is default). They also use basetype_setup() to
@ -292,4 +297,25 @@ class DarkRoom(Room):
self.check_light_state(exclude=obj) self.check_light_state(exclude=obj)
class DabblersRoom(Room): class DabblersRoom(Room):
pass teacup_prototype = {
"typeclass": "typeclasses.drinkables.TeaCup",
"key": "teacup",
"desc": "A nice teacup.",
}
def at_object_creation(self):
"""
called at creation
"""
self.cmdset.add_default(CmdSetTrolley, persistent=True)
def produce_teacup(self, caller):
if character_has(caller, "teacup"):
caller.msg("You already have a teacup.")
else:
cuptype = self.teacup_prototype
cuptype['desc'] = routput(random.choice(TEACUP_DESCS))
cup = spawn(cuptype)[0]
cup.location = caller
caller.msg("You pick up a teacup.")

View file

@ -6,13 +6,34 @@ import string
class Token(): class Token():
def __init__(self, string): def __init__(self, string):
self.words = ''.join(ch for ch in string if ch not in string.punctuation).split() cleaned_words = re.sub(r"[\.,\?!'\"=:;#\&\*\(\)\[\]\{\}]*", "", string)
self.words = cleaned_words.split()
def empty(self):
if len(self.words) == 0:
return True
def contains(self, word): def contains(self, word):
if len(self.words) > 0: if len(self.words) > 0:
return [True for w in self.words if w == word][0] result = [True for w in self.words if w == word]
else: if len(result) > 0:
return False return result[0]
def character_has(holder, item):
"""
Return true if character, holder, has an item.
Where item is probably a string name to match an item's key.
It can also be a type, for instance:
character_has(character, typeclasses.drinkables.TeaCup)
"""
for i in holder.contents:
if isinstance(item, str) and i.key == item:
return i
elif type(i) == item:
return i
elif i == item:
return i
def squish(text): def squish(text):
"Remove series of spaces from the text." "Remove series of spaces from the text."