diff --git a/adventure/sim_systems/__init__.py b/adventure/sim_systems/__init__.py new file mode 100644 index 0000000..8befb3a --- /dev/null +++ b/adventure/sim_systems/__init__.py @@ -0,0 +1,28 @@ +from .hunger_actions import action_cook, action_eat +from .hygiene_actions import action_wash +from .sleeping_actions import action_sleep + +from adventure.logic import init_from_file + +LOGIC_FILES = [ + "./adventure/sim_systems/hunger_logic.yaml", + "./adventure/sim_systems/hygiene_logic.yaml", + "./adventure/sim_systems/mood_logic.yaml", + "./adventure/sim_systems/sleeping_logic.yaml", +] + + +def init_actions(): + return [ + # hunger + action_cook, + action_eat, + # hygiene + action_wash, + # sleeping + action_sleep, + ] + + +def init_logic(): + return [init_from_file(filename) for filename in LOGIC_FILES] diff --git a/adventure/sim_systems/hunger_actions.py b/adventure/sim_systems/hunger_actions.py index 7c10b7e..e7034f1 100644 --- a/adventure/sim_systems/hunger_actions.py +++ b/adventure/sim_systems/hunger_actions.py @@ -15,16 +15,17 @@ def action_cook(item: str) -> str: return "You don't have the item to cook." # Check if the item is edible - edible = target_item.attributes.get("edible", None) + edible = target_item.attributes.get("edible", False) if not edible: return "You can't cook that." # Check if the item is raw - if edible == "cooked": + cooked = target_item.attributes.get("cooked", False) + if cooked: return "That item is already cooked." # Cook the item - target_item.attributes["edible"] = "cooked" + target_item.attributes["cooked"] = True return f"You cook the {item}." @@ -42,16 +43,19 @@ def action_eat(item: str) -> str: return "You don't have the item to eat." # Check if the item is edible - edible = target_item.attributes.get("edible", None) + edible = target_item.attributes.get("edible", False) if not edible: return "You can't eat that." # Check if the item is cooked - if edible == "raw": + cooked = target_item.attributes.get("cooked", False) + if not cooked: return "You can't eat that raw." - if edible == "rotten": - return "That item is rotten." + # Check if the item is rotten + spoiled = target_item.attributes.get("spoiled", False) + if spoiled: + return "You can't eat that item, it is rotten." # Check if the actor is hungry hunger = action_actor.attributes.get("hunger", None) diff --git a/adventure/sim_systems/hunger_logic.yaml b/adventure/sim_systems/hunger_logic.yaml index cf895a4..c312f57 100644 --- a/adventure/sim_systems/hunger_logic.yaml +++ b/adventure/sim_systems/hunger_logic.yaml @@ -1,4 +1,21 @@ rules: + # cooking logic + - match: + type: item + edible: true + cooked: false + chance: 0.2 + set: + spoiled: true + + - match: + type: item + edible: true + cooked: true + chance: 0.1 + set: + spoiled: true + # hunger logic - match: type: actor @@ -13,16 +30,53 @@ rules: set: hunger: hungry - # cooking logic + # thirst logic - match: - type: item - edible: raw - chance: 0.1 + type: actor + thirst: hydrated + chance: 0.2 set: - edible: cooked - - match: - type: item - edible: cooked - chance: 0.1 + thirst: thirsty + + # thirst initialization + - rule: | + "thirst" not in attributes set: - edible: rotten + thirst: hydrated + +labels: + edible: + true: + backstory: You are edible. + description: This item is edible. + false: + backstory: You are not edible. + description: This item is not edible. + cooked: + true: + backstory: You are cooked. + description: This item is cooked. + false: + backstory: You are raw. + description: This item is raw. + spoiled: + true: + backstory: You are rotten and inedible. + description: This item is rotten and inedible. + false: + backstory: You are fresh and edible. + description: This item is fresh and edible. + hunger: + full: + backstory: You are have eaten recently and are full. + description: ~ + hungry: + backstory: You are hungry and need to eat. + description: They look hungry. + thirst: + hydrated: + backstory: You are hydrated. + description: ~ + thirsty: + backstory: You are thirsty and need to drink. + description: They look thirsty. \ No newline at end of file diff --git a/adventure/sim_systems/hygiene_actions.py b/adventure/sim_systems/hygiene_actions.py new file mode 100644 index 0000000..e17dcf8 --- /dev/null +++ b/adventure/sim_systems/hygiene_actions.py @@ -0,0 +1,20 @@ +from adventure.context import get_current_context, get_dungeon_master + + +def action_wash() -> str: + """ + Wash yourself. + """ + + _, action_room, action_actor = get_current_context() + hygiene = action_actor.attributes.get("hygiene", "clean") + + dungeon_master = get_dungeon_master() + outcome = dungeon_master( + f"{action_actor.name} washes themselves in the {action_room.name}. {action_room.description}. {action_actor.description}" + f"{action_actor.name} was {hygiene} to start with. How clean are they after washing? Respond with 'clean' or 'dirty'." + "If the room has a shower or running water, they should be cleaner. If the room is dirty, they should end up dirtier." + ) + + action_actor.attributes["clean"] = outcome.strip().lower() + return f"You wash yourself in the {action_room.name} and feel {outcome}" diff --git a/adventure/sim_systems/hygiene_logic.yaml b/adventure/sim_systems/hygiene_logic.yaml new file mode 100644 index 0000000..ce506ed --- /dev/null +++ b/adventure/sim_systems/hygiene_logic.yaml @@ -0,0 +1,26 @@ +rules: + - match: + type: actor + hygiene: clean + chance: 0.2 + set: + hygiene: dirty + + - match: + type: actor + hygiene: dirty + chance: 0.2 + set: + hygiene: filthy + +labels: + hygiene: + clean: + backstory: You are clean and smell fresh. + description: They look freshly washed and smell clean. + dirty: + backstory: You are dirty and smell bad. + description: They look dirty and smell bad. + filthy: + backstory: You are filthy and smell terrible. + description: They look filthy and smell terrible. diff --git a/adventure/sim_systems/mood_logic.yaml b/adventure/sim_systems/mood_logic.yaml new file mode 100644 index 0000000..0b63d9e --- /dev/null +++ b/adventure/sim_systems/mood_logic.yaml @@ -0,0 +1,131 @@ +rules: + # mood logic + - group: mood + match: + type: actor + mood: happy + chance: 0.2 + set: + mood: sad + + - group: mood + match: + type: actor + mood: happy + chance: 0.2 + set: + mood: neutral + + - group: mood + match: + type: actor + mood: angry + chance: 0.2 + set: + mood: neutral + + - group: mood + match: + type: actor + mood: neutral + chance: 0.2 + set: + mood: happy + + - group: mood + match: + type: actor + mood: neutral + chance: 0.2 + set: + mood: sad + + - group: mood + match: + type: actor + mood: sad + chance: 0.2 + set: + mood: angry + + - group: mood + match: + type: actor + mood: sad + chance: 0.2 + set: + mood: neutral + + # mood interactions with other systems + - group: mood + match: + type: actor + mood: sad + sleep: rested + chance: 0.5 + set: + sleep: tired + + - group: mood + match: + type: actor + hunger: hungry + chance: 0.5 + set: + mood: angry + + - group: mood + match: + type: actor + mood: angry + hunger: full + chance: 0.5 + set: + mood: neutral + + - group: mood + match: + type: actor + mood: neutral + hunger: full + chance: 0.5 + set: + mood: happy + + - group: mood + match: + type: actor + mood: happy + hunger: hungry + chance: 0.5 + set: + mood: neutral + + - group: mood + match: + type: actor + mood: neutral + sleep: tired + chance: 0.5 + set: + mood: sad + + # mood initialization + - group: mood + rule: | + "mood" not in attributes + set: + mood: happy + +labels: + mood: + happy: + backstory: You are feeling happy. + description: They look happy. + # neutral intentionally left out + sad: + backstory: You are feeling sad. + description: They look sad. + angry: + backstory: You are feeling angry. + description: They look angry. diff --git a/adventure/sim_systems/sleeping_actions.py b/adventure/sim_systems/sleeping_actions.py new file mode 100644 index 0000000..dc78b4a --- /dev/null +++ b/adventure/sim_systems/sleeping_actions.py @@ -0,0 +1,18 @@ +from adventure.context import get_current_context, get_dungeon_master + + +def action_sleep() -> str: + """ + Sleep until you are rested. + """ + + _, action_room, action_actor = get_current_context() + + dungeon_master = get_dungeon_master() + outcome = dungeon_master( + f"{action_actor.name} sleeps in the {action_room.name}. {action_room.description}. {action_actor.description}" + "How rested are they? Respond with 'rested' or 'tired'." + ) + + action_actor.attributes["rested"] = outcome + return f"You sleep in the {action_room.name} and wake up feeling {outcome}" diff --git a/adventure/sim_systems/sleeping_logic.yaml b/adventure/sim_systems/sleeping_logic.yaml new file mode 100644 index 0000000..3fd050a --- /dev/null +++ b/adventure/sim_systems/sleeping_logic.yaml @@ -0,0 +1,23 @@ +rules: + # sleeping logic + - match: + type: actor + sleep: rested + chance: 0.2 + set: + sleep: tired + + # sleeping initialization + - rule: | + "sleep" not in attributes + set: + sleep: tired + +labels: + sleep: + rested: + backstory: You are well-rested. + description: They look well-rested. + tired: + backstory: You are tired. + description: They look tired.