From 132682f01522ab3374f7d3dad8caf5f96383f358 Mon Sep 17 00:00:00 2001 From: Sean Sube Date: Sun, 19 May 2024 16:49:02 -0500 Subject: [PATCH] refactor logic labels to use matching --- adventure/logic.py | 66 ++++++++------- adventure/systems/sim/environment_logic.yaml | 9 ++- adventure/systems/sim/hunger_logic.yaml | 85 ++++++++++++-------- adventure/systems/sim/hygiene_logic.yaml | 25 +++--- adventure/systems/sim/mood_logic.yaml | 27 ++++--- adventure/systems/sim/sleeping_logic.yaml | 17 ++-- 6 files changed, 131 insertions(+), 98 deletions(-) diff --git a/adventure/logic.py b/adventure/logic.py index 9807a31..4936b5a 100644 --- a/adventure/logic.py +++ b/adventure/logic.py @@ -8,13 +8,7 @@ from rule_engine import Rule from yaml import Loader, load from adventure.game_system import FormatPerspective, GameSystem -from adventure.models.entity import ( - Attributes, - AttributeValue, - World, - WorldEntity, - dataclass, -) +from adventure.models.entity import Attributes, World, WorldEntity, dataclass from adventure.plugins import get_plugin_function logger = getLogger(__name__) @@ -24,6 +18,8 @@ logger = getLogger(__name__) class LogicLabel: backstory: str description: str | None = None + match: Optional[Attributes] = None + rule: Optional[str] = None @dataclass @@ -39,20 +35,46 @@ class LogicRule: @dataclass class LogicTable: - rules: List[LogicRule] - labels: Dict[str, Dict[AttributeValue, LogicLabel]] = Field(default_factory=dict) + rules: List[LogicRule] = Field(default_factory=list) + labels: List[LogicLabel] = Field(default_factory=list) LogicTrigger = Callable[[WorldEntity], None] TriggerTable = Dict[str, LogicTrigger] +def match_logic( + entity: WorldEntity, + matcher: LogicLabel | LogicRule, +) -> bool: + typed_attributes = { + **entity.attributes, + "type": entity.type, + } + + if matcher.rule: + # TODO: pre-compile rules + rule_impl = Rule(matcher.rule) + if not rule_impl.matches( + { + "attributes": typed_attributes, + } + ): + logger.debug("logic rule did not match attributes: %s", matcher.rule) + return False + + if matcher.match and not (matcher.match.items() <= typed_attributes.items()): + logger.debug("logic did not match attributes: %s", matcher.match) + return False + + return True + + def update_attributes( entity: WorldEntity, rules: LogicTable, triggers: TriggerTable, ) -> None: - entity_type = entity.__class__.__name__.lower() skip_groups = set() for rule in rules.rules: @@ -61,24 +83,7 @@ def update_attributes( logger.debug("already ran a rule from group %s, skipping", rule.group) continue - typed_attributes = { - **entity.attributes, - "type": entity_type, - } - - if rule.rule: - # TODO: pre-compile rules - rule_impl = Rule(rule.rule) - if not rule_impl.matches( - { - "attributes": typed_attributes, - } - ): - logger.debug("logic rule did not match attributes: %s", rule.rule) - continue - - if rule.match and not (rule.match.items() <= typed_attributes.items()): - logger.debug("logic did not match attributes: %s", rule.match) + if not match_logic(entity, rule): continue logger.info("matched logic: %s", rule.match) @@ -125,9 +130,8 @@ def format_logic( ) -> str: labels = [] - for attribute, value in entity.attributes.items(): - if attribute in rules.labels and value in rules.labels[attribute]: - label = rules.labels[attribute][value] + for label in rules.labels: + if match_logic(entity, label): if perspective == FormatPerspective.SECOND_PERSON: labels.append(label.backstory) elif perspective == FormatPerspective.THIRD_PERSON and label.description: diff --git a/adventure/systems/sim/environment_logic.yaml b/adventure/systems/sim/environment_logic.yaml index 41ef136..4e2c661 100644 --- a/adventure/systems/sim/environment_logic.yaml +++ b/adventure/systems/sim/environment_logic.yaml @@ -32,8 +32,9 @@ rules: trigger: [adventure.sim_systems.environment_triggers:cold_room] labels: - wet: - true: - backstory: You are soaking wet. - description: They are soaking wet and dripping water. + - match: + type: actor + wet: true + backstory: You are soaking wet. + description: They are soaking wet and dripping water. # false intentionally omitted \ No newline at end of file diff --git a/adventure/systems/sim/hunger_logic.yaml b/adventure/systems/sim/hunger_logic.yaml index bc1f6af..c50e43b 100644 --- a/adventure/systems/sim/hunger_logic.yaml +++ b/adventure/systems/sim/hunger_logic.yaml @@ -51,38 +51,53 @@ rules: 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 + - match: + type: item + edible: true + backstory: You are edible. + description: This item is edible. + - match: + type: item + edible: false + backstory: You are not edible. + description: This item is not edible. + - match: + type: item + cooked: true + backstory: You are cooked. + description: This item is cooked. + - match: + type: item + cooked: false + backstory: You are raw. + description: This item is raw. + - match: + type: item + spoiled: true + backstory: You are rotten and inedible. + description: This item is rotten and inedible. + - match: + type: actor + spoiled: false + backstory: You are fresh and edible. + description: This item is fresh and edible. + - match: + type: actor + hunger: full + backstory: You are have eaten recently and are full. + description: ~ + - match: + type: actor + hunger: hungry + backstory: You are hungry and need to eat. + description: They look hungry. + - match: + type: actor + thirst: hydrated + backstory: You are hydrated. + description: ~ + - match: + type: actor + thirst: thirsty + backstory: You are thirsty and need to drink. + description: They look thirsty. \ No newline at end of file diff --git a/adventure/systems/sim/hygiene_logic.yaml b/adventure/systems/sim/hygiene_logic.yaml index 6444dce..4ba9949 100644 --- a/adventure/systems/sim/hygiene_logic.yaml +++ b/adventure/systems/sim/hygiene_logic.yaml @@ -20,13 +20,18 @@ rules: hygiene: clean 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. + - match: + type: actor + hygiene: clean + backstory: You are clean and smell fresh. + description: They look freshly washed and smell clean. + - match: + type: actor + hygiene: dirty + backstory: You are dirty and smell bad. + description: They look dirty and smell bad. + - match: + type: actor + hygiene: filthy + backstory: You are filthy and smell terrible. + description: They look filthy and smell terrible. diff --git a/adventure/systems/sim/mood_logic.yaml b/adventure/systems/sim/mood_logic.yaml index d680540..807dd8b 100644 --- a/adventure/systems/sim/mood_logic.yaml +++ b/adventure/systems/sim/mood_logic.yaml @@ -118,14 +118,19 @@ rules: 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. + - match: + type: actor + mood: happy + backstory: You are feeling happy. + description: They look happy. + - match: + type: actor + mood: sad + backstory: You are feeling sad. + description: They look sad. + - match: + type: actor + mood: angry + backstory: You are feeling angry. + description: They look angry. + # neutral intentionally omitted \ No newline at end of file diff --git a/adventure/systems/sim/sleeping_logic.yaml b/adventure/systems/sim/sleeping_logic.yaml index cb755b5..c99357d 100644 --- a/adventure/systems/sim/sleeping_logic.yaml +++ b/adventure/systems/sim/sleeping_logic.yaml @@ -14,10 +14,13 @@ rules: sleep: tired labels: - sleep: - rested: - backstory: You are well-rested. - description: They look well-rested. - tired: - backstory: You are tired. - description: They look tired. + - match: + type: actor + sleep: rested + backstory: You are well-rested. + description: They look well-rested. + - match: + type: actor + sleep: tired + backstory: You are tired. + description: They look tired.