moss-n-puddles/typeclasses/pets.py
Howard Abrams 37f3e8d479 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.
2025-02-02 00:02:49 -08:00

209 lines
6.3 KiB
Python
Executable file

#!/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, LightSource
from commands.feedables import CmdFeed, CmdFeedSet
from utils.word_list import squish
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(70, 90)
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.location.msg_contents(f"Feeding a pet: {amount} {isinstance(amount, str)}-> {self.db.hunger_level} / {self.hungry_rate}")
self.db.hunger_level = self.db.hunger_level + amount
if self.db.hunger_level < 0:
self.db.hunger_level = 0
# if self.db.hunger_level < 5:
# self.db.is_giving_light = False
# else:
# self.db.is_giving_light = True
if self.hunger() != curr:
self.location.msg_contents("|w%s|n\n" % self.hunger_appearance())
if self.location.check_light_state:
self.location.check_light_state()
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()}"
# ------------------------------------------------------------
# Fireplace, both a pet that is hungry and consumes food,
# but also emits light when it isn't starving.
# ------------------------------------------------------------
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):
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
get_up = ""
gets_up = ""
if feeder.db.is_sitting:
get_up = "get up and"
gets_up = "gets up and"
if self.db.hunger_level < 5:
feeder.msg(squish(f"You {get_up} put some {adj} wood in the "
f"fireplace, and start a fire."))
self.location.msg_contents(squish(f"{feeder.name} {gets_up} starts a fire."),
exclude=feeder)
else:
feeder.msg(squish(f"You {get_up} put some {adj} wood on the "
f"fire in the fireplace."))
self.location.msg_contents(squish(f"{feeder.name} {gets_up} puts {adj} wood on the fire."),
exclude=feeder)
self.update_hunger(feeder=feeder, amount=300)