Create a friendly pet
This commit is contained in:
parent
c731383915
commit
43956fa818
1 changed files with 240 additions and 1 deletions
|
|
@ -1,4 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
# Emacs environement
|
||||||
|
# (setq python-shell-interpreter "/Users/howard/src/moss-n-puddles/.venv/bin/ipython")
|
||||||
"""
|
"""
|
||||||
Pets
|
Pets
|
||||||
|
|
||||||
|
|
@ -194,5 +196,242 @@ class Fire(Pet):
|
||||||
|
|
||||||
# def at_post_move(self, source_location, move_type, **kwargs):
|
# def at_post_move(self, source_location, move_type, **kwargs):
|
||||||
|
|
||||||
self.update_hunger(feeder=feeder, amount=300)
|
# ----------------------------------------------------------------------
|
||||||
|
# Friendly
|
||||||
|
|
||||||
|
|
||||||
|
class Reaction(Enum):
|
||||||
|
SCARED = 1
|
||||||
|
CONCERNED = 100
|
||||||
|
INTERESTED = 300
|
||||||
|
FRIENDLY = 850
|
||||||
|
ECSTATIC = 1000
|
||||||
|
|
||||||
|
|
||||||
|
class Friendly(Pet):
|
||||||
|
"""
|
||||||
|
This pet keeps track of the characters in the game.
|
||||||
|
It has different reactions based on the characters in the room.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def at_object_creation(self):
|
||||||
|
"""
|
||||||
|
Called when object is first created.
|
||||||
|
"""
|
||||||
|
super().at_object_creation()
|
||||||
|
|
||||||
|
# The higher this value the more "spammy" a pet is in making
|
||||||
|
# comments in the room:
|
||||||
|
self.db.active_amount = 3
|
||||||
|
|
||||||
|
# If set to 'ignores', the pet is more concerned about the
|
||||||
|
# 'friendliest' character in Room, otherwise, it is more
|
||||||
|
# scared at the stranger:
|
||||||
|
self.db.new_character_reaction = "ignores"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def friendly_var(self):
|
||||||
|
"""
|
||||||
|
Return variable name on character types use to gauge the
|
||||||
|
reaction of this pet towards that character.
|
||||||
|
"""
|
||||||
|
key = self.key.replace(" ", "_")
|
||||||
|
return f"{key}_friendly_level"
|
||||||
|
|
||||||
|
def friendly_level(self, character):
|
||||||
|
"""
|
||||||
|
Return reaction level of this pet towards a character.
|
||||||
|
"""
|
||||||
|
varname = self.friendly_var
|
||||||
|
return character.attributes.get(varname) or 0
|
||||||
|
|
||||||
|
def friendly_reaction(self, character=None):
|
||||||
|
"""
|
||||||
|
Return reaction enum of this pet towards a character.
|
||||||
|
If character not given, then looks at all characters in the room
|
||||||
|
"""
|
||||||
|
if character:
|
||||||
|
level = self.friendly_level(character)
|
||||||
|
if level < Reaction.SCARED.value:
|
||||||
|
return Reaction.SCARED
|
||||||
|
if level < Reaction.CONCERNED.value:
|
||||||
|
return Reaction.CONCERNED
|
||||||
|
if level < Reaction.INTERESTED.value:
|
||||||
|
return Reaction.INTERESTED
|
||||||
|
if level < Reaction.FRIENDLY.value:
|
||||||
|
return Reaction.FRIENDLY
|
||||||
|
return Reaction.ECSTATIC
|
||||||
|
else:
|
||||||
|
if self.db.new_character_reaction == "ignores":
|
||||||
|
return self.highest_friendly_reaction()
|
||||||
|
return self.lowest_friendly_reaction()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def local_characters(self):
|
||||||
|
"""
|
||||||
|
Return a list of all Characters in the room with the Pet.
|
||||||
|
"""
|
||||||
|
return [c for c in self.location.contents
|
||||||
|
if c.is_typeclass("typeclasses.characters.Character")]
|
||||||
|
|
||||||
|
def lowest_friendly_reaction(self):
|
||||||
|
"""
|
||||||
|
Return reaction of this pet to the least friendliest
|
||||||
|
character(s) in the area (room) that this pet resides.
|
||||||
|
Returns a tuple, Reaction and a list of characters.
|
||||||
|
"""
|
||||||
|
# State is a tuple of the level and the character:
|
||||||
|
level = Reaction.ECSTATIC
|
||||||
|
characters = []
|
||||||
|
|
||||||
|
for c in self.local_characters:
|
||||||
|
this_level = self.friendly_reaction(c)
|
||||||
|
if this_level.value < level.value:
|
||||||
|
level = this_level
|
||||||
|
characters = [c]
|
||||||
|
if this_level.value == level.value:
|
||||||
|
characters += [c]
|
||||||
|
return (level, characters)
|
||||||
|
|
||||||
|
def highest_friendly_reaction(self):
|
||||||
|
"""
|
||||||
|
Return reaction of this pet to the friendliest
|
||||||
|
character(s) in the area (room) that this pet resides.
|
||||||
|
Returns a tuple, Reaction and a list of characters.
|
||||||
|
"""
|
||||||
|
# State is a tuple of the level and the character:
|
||||||
|
level = Reaction.SCARED
|
||||||
|
characters = []
|
||||||
|
|
||||||
|
for c in self.local_characters:
|
||||||
|
this_level = self.friendly_reaction(c)
|
||||||
|
if this_level.value > level.value:
|
||||||
|
level = this_level
|
||||||
|
characters = [c]
|
||||||
|
if this_level.value == level.value:
|
||||||
|
characters += [c]
|
||||||
|
return (level, characters)
|
||||||
|
|
||||||
|
def adjust_all(self, amount):
|
||||||
|
"""
|
||||||
|
Adjusts reaction level to all characters that have
|
||||||
|
interacted with this pet, whether they are near it or not.
|
||||||
|
This is essentially a loneliness measure, for out-of-sight,
|
||||||
|
out-of-mind.
|
||||||
|
"""
|
||||||
|
for c in Character.objects.get_objs_with_attr(self.friendly_var):
|
||||||
|
self.adjust_character(c, amount)
|
||||||
|
|
||||||
|
def adjust_all_locally(self, amount):
|
||||||
|
"""
|
||||||
|
Adjusts reaction level to all characters in the room
|
||||||
|
with this pet. Hanging out with the pet should be helpful.
|
||||||
|
"""
|
||||||
|
for c in self.local_characters:
|
||||||
|
self.adjust_character(c, amount)
|
||||||
|
|
||||||
|
def adjust_character(self, character, amount):
|
||||||
|
"""
|
||||||
|
Adjusts the reaction to 'character' by an 'amount.
|
||||||
|
Note that this should never go below zero.
|
||||||
|
"""
|
||||||
|
new_val = self.friendly_level(character) + amount
|
||||||
|
if new_val < 0:
|
||||||
|
new_val = 0
|
||||||
|
character.attributes.add(self.friendly_var, new_val)
|
||||||
|
|
||||||
|
def return_appearance(self, looker, **kwargs):
|
||||||
|
"""
|
||||||
|
Called by the 'look' command. This formats the description
|
||||||
|
of this object based on 'reaction', and the character's
|
||||||
|
_friendly_ level.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
looker (Object): Object doing the looking.
|
||||||
|
"""
|
||||||
|
level = self.friendly_reaction(looker)
|
||||||
|
# looking at the friendly pets makes them nervous... just a little:
|
||||||
|
self.adjust_character(looker, -1)
|
||||||
|
|
||||||
|
if level == Reaction.SCARED:
|
||||||
|
return self.db.desc + " " + choices(self.db.scared_msg or "It seems scared of you.")
|
||||||
|
elif level == Reaction.CONCERNED:
|
||||||
|
return self.db.desc + " " + choices(self.db.concerned_msg or "It seems concerned you are here.")
|
||||||
|
elif level == Reaction.INTERESTED:
|
||||||
|
return self.db.desc + " " + choices(self.db.interested_msg or "It seems interested in you.")
|
||||||
|
elif level == Reaction.FRIENDLY:
|
||||||
|
return self.db.desc + " " + choices(self.db.friendly_msg or "It seems happy to see you.")
|
||||||
|
else:
|
||||||
|
# If we have an ecstatic message, use it otherwise, grab the friendly:
|
||||||
|
return self.db.desc + " " + choices(self.db.ecstatic_msg or self.db.friendly_msg or
|
||||||
|
"It seems ecstatic to see you.")
|
||||||
|
|
||||||
|
def update_state(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Hrm.
|
||||||
|
"""
|
||||||
|
super().update_state(*args, **kwargs)
|
||||||
|
self.adjust_all(self.db.loneliness_amount or -1)
|
||||||
|
self.adjust_all_locally(self.db.shyness_amount or 5)
|
||||||
|
|
||||||
|
# How spammy do we want the pet to be?
|
||||||
|
if random.randint(0, 100) < self.db.active_amount:
|
||||||
|
self.do_action()
|
||||||
|
else:
|
||||||
|
print("Nope")
|
||||||
|
|
||||||
|
def do_action(self):
|
||||||
|
# Do something based on the highest friendly level is the same area!
|
||||||
|
(level, chars) = self.friendly_reaction()
|
||||||
|
focus = random.choice(chars)
|
||||||
|
|
||||||
|
if level == Reaction.SCARED:
|
||||||
|
msg = choices(self.db.scared_actions)
|
||||||
|
elif level == Reaction.CONCERNED:
|
||||||
|
msg = choices(self.db.concerned_actions)
|
||||||
|
elif level == Reaction.INTERESTED:
|
||||||
|
msg = choices(self.db.interested_actions)
|
||||||
|
elif level == Reaction.FRIENDLY:
|
||||||
|
msg = choices(self.db.friendly_actions)
|
||||||
|
else:
|
||||||
|
# If we have an ecstatic message, use it otherwise, grab the friendly:
|
||||||
|
msg = choices(self.db.ecstatic_actions or self.db.friendly_actions)
|
||||||
|
|
||||||
|
focus.msg(
|
||||||
|
sub("<You>", "You", sub("<you>", "you", msg))
|
||||||
|
)
|
||||||
|
self.location.msg_contents(sub("<[Yy]ou>", focus.name.title(), msg),
|
||||||
|
exclude=focus)
|
||||||
|
|
||||||
|
|
||||||
|
class Imp(Friendly):
|
||||||
|
def action(self):
|
||||||
|
# Do something based on the highest friendly level is the same area!
|
||||||
|
# Need a ticker ..
|
||||||
|
# (state, chars) = self.highest_friendly_level()
|
||||||
|
pass
|
||||||
|
|
||||||
|
def update_state(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BHB(Friendly):
|
||||||
|
"The Big Hairy Beast object."
|
||||||
|
def action(self):
|
||||||
|
# Do something based on the highest friendly level is the same area!
|
||||||
|
# Need a ticker ..
|
||||||
|
# (state, chars) = self.highest_friendly_level()
|
||||||
|
pass
|
||||||
|
# - < 10 : Attempts to hide
|
||||||
|
# - < 20 : Steers clear but doesn’t hide
|
||||||
|
# - < 50 : Wags it tail/butt
|
||||||
|
# - > 50 : Follows you
|
||||||
|
# level = self.friendly_level(looker)
|
||||||
|
# if level == 0:
|
||||||
|
# return f"You see a massive shadow lurking "
|
||||||
|
# if level < 10:
|
||||||
|
# return f"{self.db.desc} {self.hunger_appearance()}"
|
||||||
|
|
||||||
|
def given(self, giver, thing):
|
||||||
|
# if obj.is_typeclass("typeclasses.things.Wood"):
|
||||||
|
return True
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue