diff --git a/commands/default_cmdsets.py b/commands/default_cmdsets.py index 54d163e..f17f3be 100644 --- a/commands/default_cmdsets.py +++ b/commands/default_cmdsets.py @@ -15,7 +15,7 @@ own cmdsets by inheriting from them or directly from `evennia.CmdSet`. """ from evennia import default_cmds - +from evennia.contrib.grid import extended_room from commands.sittables import CmdNoSitStand class CharacterCmdSet(default_cmds.CharacterCmdSet): @@ -33,6 +33,7 @@ class CharacterCmdSet(default_cmds.CharacterCmdSet): """ super().at_cmdset_creation() self.add(CmdNoSitStand) + self.add(extended_room.ExtendedRoomCmdSet) # # any commands you add below will overload the default ones. # diff --git a/commands/drinkables.py b/commands/drinkables.py new file mode 100755 index 0000000..bc91784 --- /dev/null +++ b/commands/drinkables.py @@ -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) diff --git a/typeclasses/drinkables.py b/typeclasses/drinkables.py new file mode 100755 index 0000000..2ed6320 --- /dev/null +++ b/typeclasses/drinkables.py @@ -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]) diff --git a/typeclasses/pets.py b/typeclasses/pets.py index ac14492..6dcaa63 100755 --- a/typeclasses/pets.py +++ b/typeclasses/pets.py @@ -133,7 +133,8 @@ class Pet(Object): if self.hunger() != curr: 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): """ diff --git a/typeclasses/rooms.py b/typeclasses/rooms.py index 77226be..e4443c5 100644 --- a/typeclasses/rooms.py +++ b/typeclasses/rooms.py @@ -6,8 +6,13 @@ Rooms are simple containers that has no location of their own. """ 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 .drinkables import TEACUP_DESCS +from commands.drinkables import CmdSetTrolley +from utils.word_list import routput, character_has, Token import random @@ -35,7 +40,7 @@ _SEARCH_AT_RESULT = utils.object_from_module(settings.SEARCH_AT_RESULT) from .objects import ObjectParent -class Room(ObjectParent, DefaultRoom): +class Room(ObjectParent, ExtendedRoom): """ Rooms are like any Object, except their location is None (which is default). They also use basetype_setup() to @@ -292,4 +297,25 @@ class DarkRoom(Room): self.check_light_state(exclude=obj) 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.") diff --git a/utils/word_list.py b/utils/word_list.py index db11027..2195da2 100755 --- a/utils/word_list.py +++ b/utils/word_list.py @@ -6,13 +6,34 @@ import string class Token(): 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): if len(self.words) > 0: - return [True for w in self.words if w == word][0] - else: - return False + result = [True for w in self.words if w == word] + if len(result) > 0: + 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): "Remove series of spaces from the text."