1
0
Fork 0

refactor logic labels to use matching

This commit is contained in:
Sean Sube 2024-05-19 16:49:02 -05:00
parent 18c56f9cf3
commit 132682f015
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
6 changed files with 131 additions and 98 deletions

View File

@ -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:

View File

@ -32,8 +32,9 @@ rules:
trigger: [adventure.sim_systems.environment_triggers:cold_room]
labels:
wet:
true:
- match:
type: actor
wet: true
backstory: You are soaking wet.
description: They are soaking wet and dripping water.
# false intentionally omitted

View File

@ -51,38 +51,53 @@ rules:
thirst: hydrated
labels:
edible:
true:
- match:
type: item
edible: true
backstory: You are edible.
description: This item is edible.
false:
- match:
type: item
edible: false
backstory: You are not edible.
description: This item is not edible.
cooked:
true:
- match:
type: item
cooked: true
backstory: You are cooked.
description: This item is cooked.
false:
- match:
type: item
cooked: false
backstory: You are raw.
description: This item is raw.
spoiled:
true:
- match:
type: item
spoiled: true
backstory: You are rotten and inedible.
description: This item is rotten and inedible.
false:
- match:
type: actor
spoiled: false
backstory: You are fresh and edible.
description: This item is fresh and edible.
hunger:
full:
- match:
type: actor
hunger: full
backstory: You are have eaten recently and are full.
description: ~
hungry:
- match:
type: actor
hunger: hungry
backstory: You are hungry and need to eat.
description: They look hungry.
thirst:
hydrated:
- match:
type: actor
thirst: hydrated
backstory: You are hydrated.
description: ~
thirsty:
- match:
type: actor
thirst: thirsty
backstory: You are thirsty and need to drink.
description: They look thirsty.

View File

@ -20,13 +20,18 @@ rules:
hygiene: clean
labels:
hygiene:
clean:
- match:
type: actor
hygiene: clean
backstory: You are clean and smell fresh.
description: They look freshly washed and smell clean.
dirty:
- match:
type: actor
hygiene: dirty
backstory: You are dirty and smell bad.
description: They look dirty and smell bad.
filthy:
- match:
type: actor
hygiene: filthy
backstory: You are filthy and smell terrible.
description: They look filthy and smell terrible.

View File

@ -118,14 +118,19 @@ rules:
mood: happy
labels:
mood:
happy:
- match:
type: actor
mood: happy
backstory: You are feeling happy.
description: They look happy.
# neutral intentionally left out
sad:
- match:
type: actor
mood: sad
backstory: You are feeling sad.
description: They look sad.
angry:
- match:
type: actor
mood: angry
backstory: You are feeling angry.
description: They look angry.
# neutral intentionally omitted

View File

@ -14,10 +14,13 @@ rules:
sleep: tired
labels:
sleep:
rested:
- match:
type: actor
sleep: rested
backstory: You are well-rested.
description: They look well-rested.
tired:
- match:
type: actor
sleep: tired
backstory: You are tired.
description: They look tired.