diff --git a/.gitignore b/.gitignore index add8d97..b2f70c8 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,4 @@ nosetests.xml # VSCode config .vscode +/.venv/ diff --git a/commands/feedables.py b/commands/feedables.py new file mode 100755 index 0000000..d986690 --- /dev/null +++ b/commands/feedables.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + + +from commands.command import Command +from evennia import CmdSet + +class CmdFeed(Command): + """ + Feed or give. + """ + key = "feed" + aliases = ["give"] + + def func(self): + args = self.args.strip() + if not args: + self.caller.msg("Feed what?") + return + + self.obj.feed(self.caller, self.args) + +class CmdFeedSet(CmdSet): + def at_cmdset_creation(self): + self.add(CmdFeed) diff --git a/typeclasses/objects.py b/typeclasses/objects.py index d3f94c8..9734c2f 100644 --- a/typeclasses/objects.py +++ b/typeclasses/objects.py @@ -9,7 +9,6 @@ with a location in the game world (like Characters, Rooms, Exits). """ from evennia.objects.objects import DefaultObject -from commands.sittables import CmdSetSit class ObjectParent: diff --git a/typeclasses/pets.py b/typeclasses/pets.py new file mode 100755 index 0000000..d341355 --- /dev/null +++ b/typeclasses/pets.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python +""" +Pets + +Create interactive 'pets' that consume some sort of food, and need to be 'fed'. +Each level of pet requires more aspects for interaction. + +""" + +from typeclasses.objects import Object +from commands.feedables import CmdFeed, CmdFeedSet + +from evennia import ( + TICKER_HANDLER, + CmdSet, + Command, + create_object, + default_cmds, + search_object, + syscmdkeys, + utils, +) + +from enum import Enum +from time import time + +import random + + +class Hunger(Enum): + RAVENOUS = 100 + HUNGRY = 300 + FED = 850 + FULL = 1000 + + +class Pet(Object): + """ + This is a base class for Pets. + """ + fullname = None + pers_pronoun = "it" # or he/she/they + poss_pronoun = "its" # or his/her/them + + # Feed about once a day: + hungry_rate = -.7 + + hunger_states = { + Hunger.RAVENOUS: [ + "looks crazy with hunger", + ], + Hunger.HUNGRY: [ + "looks hungry", + "seems hungry", + ], + Hunger.FED: "looks well", + Hunger.FULL: [ + "looks content", + "looks sated", + ] + } + + + hungry_rate = -1 + hunger_states = { + Hunger.RAVENOUS: [ + "looks crazy with hunger", + ], + Hunger.HUNGRY: [ + "looks hungry", + "seems hungry", + ], + Hunger.FED: "looks well", + Hunger.FULL: [ + "looks content", + "looks sated", + ] + } + + def hunger(self): + if self.db.hunger_level < Hunger.RAVENOUS.value: + return Hunger.RAVENOUS + if self.db.hunger_level < Hunger.HUNGRY.value: + return Hunger.HUNGRY + if self.db.hunger_level < Hunger.FED.value: + return Hunger.FED + return Hunger.FULL + + def hunger_appearance(self): + msgs = self.hunger_states.get(self.hunger()) + if isinstance(msgs, str): + return f"{self.fullname or self.pers_pronoun} {msgs}" + else: + return f"{self.fullname or self.pers_pronoun} {random.choice(msgs)}" + + def at_object_creation(self): + """ + Called when object is first created. + We set up a ticker to update hunger levels regularly. + """ + super().at_object_creation() + self.db.hunger_level = Hunger.FULL.value + + self.cmdset.add_default(CmdFeedSet) + + # subscribe ourselves to a ticker to repeatedly call the hook + # "update_weather" on this object. The interval is randomized + # so as to not have all weather rooms update at the same time. + self.db.interval = random.randint(50, 70) + TICKER_HANDLER.add(interval=self.db.interval, callback=self.update_hunger) + + def update_hunger(self, *args, **kwargs): + """ + Called by the tickerhandler at regular intervals. Even so, we + only update at a hungry_rate of the time, picking a random weather message + when we do. The tickerhandler requires that this hook accepts + any arguments and keyword arguments (hence the *args, **kwargs + even though we don't actually use them in this example) + """ + curr = self.hunger() + amount = kwargs.get('amount', self.hungry_rate) + + self.db.hunger_level = self.db.hunger_level + amount + if self.hunger() != curr: + self.location.msg_contents("|w%s|n\n" % self.hunger_appearance()) + + def return_appearance(self, looker, **kwargs): + """ + This formats the description of this object based on 'hunger'. + Called by the 'look' command. + + Args: + looker (Object): Object doing the looking. + **kwargs (dict): Arbitrary, optional arguments for users + overriding the call (unused by default). + """ + return f"{self.db.desc} {self.hunger_appearance()}" + +class Fire(Pet): + """ + Fire in this world, is a cute fireplace pet. + + """ + fullname = "The fire in the fireplace" + hungry_rate = -5 + hunger_states = { + Hunger.RAVENOUS: [ + "is out. It is dark.", + ], + Hunger.HUNGRY: [ + "shows glowing red embers that seems breathe in a memorizing way.", + "is little more than glowing embers casting shadows on the wall.", + ], + Hunger.FED: [ + "dances and shimmies with warmth and light.", + "crackles and pops with warmth and light." + ], + Hunger.FULL: [ + "roars to life, casting a bright light around the room.", + "burns brightly and is very hot. You feel the need to move back a bit.", + ] + } + + def feed(self, feeder, args): + super().update_hunger(feeder, amount=300) + + now = time() + last_fed = feeder.ndb.fire_last_fed # could be None + if last_fed and (now - last_fed < 30): + adj = "some more" + else: + adj = "some" + + feeder.ndb.fire_last_fed = now + + feeder.msg(f"You put some {adj} wood on the fire in the fireplace.") + self.location.msg_contents(f"{feeder.name} gets up and puts {adj} wood on the fire.", + exclude=feeder) diff --git a/typeclasses/rooms_weather.py b/typeclasses/rooms_weather.py index 36f48aa..f40518c 100755 --- a/typeclasses/rooms_weather.py +++ b/typeclasses/rooms_weather.py @@ -66,7 +66,9 @@ TIMEBASE_WEATHER_MSGS = [ ], # Afternoon [ - "A lazy afternoon filled with the sound of bees and other insects." + "A lazy afternoon filled with the sound of bees and other insects.", + "A gentle breeze wafts the scent of distant flowers.", + "A low breeze fills the air with the earthy scent of mushrooms.", ], # Evening [