refactor logic labels to use matching
This commit is contained in:
parent
18c56f9cf3
commit
132682f015
|
@ -8,13 +8,7 @@ from rule_engine import Rule
|
||||||
from yaml import Loader, load
|
from yaml import Loader, load
|
||||||
|
|
||||||
from adventure.game_system import FormatPerspective, GameSystem
|
from adventure.game_system import FormatPerspective, GameSystem
|
||||||
from adventure.models.entity import (
|
from adventure.models.entity import Attributes, World, WorldEntity, dataclass
|
||||||
Attributes,
|
|
||||||
AttributeValue,
|
|
||||||
World,
|
|
||||||
WorldEntity,
|
|
||||||
dataclass,
|
|
||||||
)
|
|
||||||
from adventure.plugins import get_plugin_function
|
from adventure.plugins import get_plugin_function
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
|
@ -24,6 +18,8 @@ logger = getLogger(__name__)
|
||||||
class LogicLabel:
|
class LogicLabel:
|
||||||
backstory: str
|
backstory: str
|
||||||
description: str | None = None
|
description: str | None = None
|
||||||
|
match: Optional[Attributes] = None
|
||||||
|
rule: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -39,20 +35,46 @@ class LogicRule:
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class LogicTable:
|
class LogicTable:
|
||||||
rules: List[LogicRule]
|
rules: List[LogicRule] = Field(default_factory=list)
|
||||||
labels: Dict[str, Dict[AttributeValue, LogicLabel]] = Field(default_factory=dict)
|
labels: List[LogicLabel] = Field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
LogicTrigger = Callable[[WorldEntity], None]
|
LogicTrigger = Callable[[WorldEntity], None]
|
||||||
TriggerTable = Dict[str, LogicTrigger]
|
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(
|
def update_attributes(
|
||||||
entity: WorldEntity,
|
entity: WorldEntity,
|
||||||
rules: LogicTable,
|
rules: LogicTable,
|
||||||
triggers: TriggerTable,
|
triggers: TriggerTable,
|
||||||
) -> None:
|
) -> None:
|
||||||
entity_type = entity.__class__.__name__.lower()
|
|
||||||
skip_groups = set()
|
skip_groups = set()
|
||||||
|
|
||||||
for rule in rules.rules:
|
for rule in rules.rules:
|
||||||
|
@ -61,24 +83,7 @@ def update_attributes(
|
||||||
logger.debug("already ran a rule from group %s, skipping", rule.group)
|
logger.debug("already ran a rule from group %s, skipping", rule.group)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
typed_attributes = {
|
if not match_logic(entity, rule):
|
||||||
**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)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logger.info("matched logic: %s", rule.match)
|
logger.info("matched logic: %s", rule.match)
|
||||||
|
@ -125,9 +130,8 @@ def format_logic(
|
||||||
) -> str:
|
) -> str:
|
||||||
labels = []
|
labels = []
|
||||||
|
|
||||||
for attribute, value in entity.attributes.items():
|
for label in rules.labels:
|
||||||
if attribute in rules.labels and value in rules.labels[attribute]:
|
if match_logic(entity, label):
|
||||||
label = rules.labels[attribute][value]
|
|
||||||
if perspective == FormatPerspective.SECOND_PERSON:
|
if perspective == FormatPerspective.SECOND_PERSON:
|
||||||
labels.append(label.backstory)
|
labels.append(label.backstory)
|
||||||
elif perspective == FormatPerspective.THIRD_PERSON and label.description:
|
elif perspective == FormatPerspective.THIRD_PERSON and label.description:
|
||||||
|
|
|
@ -32,8 +32,9 @@ rules:
|
||||||
trigger: [adventure.sim_systems.environment_triggers:cold_room]
|
trigger: [adventure.sim_systems.environment_triggers:cold_room]
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
wet:
|
- match:
|
||||||
true:
|
type: actor
|
||||||
|
wet: true
|
||||||
backstory: You are soaking wet.
|
backstory: You are soaking wet.
|
||||||
description: They are soaking wet and dripping water.
|
description: They are soaking wet and dripping water.
|
||||||
# false intentionally omitted
|
# false intentionally omitted
|
|
@ -51,38 +51,53 @@ rules:
|
||||||
thirst: hydrated
|
thirst: hydrated
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
edible:
|
- match:
|
||||||
true:
|
type: item
|
||||||
|
edible: true
|
||||||
backstory: You are edible.
|
backstory: You are edible.
|
||||||
description: This item is edible.
|
description: This item is edible.
|
||||||
false:
|
- match:
|
||||||
|
type: item
|
||||||
|
edible: false
|
||||||
backstory: You are not edible.
|
backstory: You are not edible.
|
||||||
description: This item is not edible.
|
description: This item is not edible.
|
||||||
cooked:
|
- match:
|
||||||
true:
|
type: item
|
||||||
|
cooked: true
|
||||||
backstory: You are cooked.
|
backstory: You are cooked.
|
||||||
description: This item is cooked.
|
description: This item is cooked.
|
||||||
false:
|
- match:
|
||||||
|
type: item
|
||||||
|
cooked: false
|
||||||
backstory: You are raw.
|
backstory: You are raw.
|
||||||
description: This item is raw.
|
description: This item is raw.
|
||||||
spoiled:
|
- match:
|
||||||
true:
|
type: item
|
||||||
|
spoiled: true
|
||||||
backstory: You are rotten and inedible.
|
backstory: You are rotten and inedible.
|
||||||
description: This item is rotten and inedible.
|
description: This item is rotten and inedible.
|
||||||
false:
|
- match:
|
||||||
|
type: actor
|
||||||
|
spoiled: false
|
||||||
backstory: You are fresh and edible.
|
backstory: You are fresh and edible.
|
||||||
description: This item is fresh and edible.
|
description: This item is fresh and edible.
|
||||||
hunger:
|
- match:
|
||||||
full:
|
type: actor
|
||||||
|
hunger: full
|
||||||
backstory: You are have eaten recently and are full.
|
backstory: You are have eaten recently and are full.
|
||||||
description: ~
|
description: ~
|
||||||
hungry:
|
- match:
|
||||||
|
type: actor
|
||||||
|
hunger: hungry
|
||||||
backstory: You are hungry and need to eat.
|
backstory: You are hungry and need to eat.
|
||||||
description: They look hungry.
|
description: They look hungry.
|
||||||
thirst:
|
- match:
|
||||||
hydrated:
|
type: actor
|
||||||
|
thirst: hydrated
|
||||||
backstory: You are hydrated.
|
backstory: You are hydrated.
|
||||||
description: ~
|
description: ~
|
||||||
thirsty:
|
- match:
|
||||||
|
type: actor
|
||||||
|
thirst: thirsty
|
||||||
backstory: You are thirsty and need to drink.
|
backstory: You are thirsty and need to drink.
|
||||||
description: They look thirsty.
|
description: They look thirsty.
|
|
@ -20,13 +20,18 @@ rules:
|
||||||
hygiene: clean
|
hygiene: clean
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
hygiene:
|
- match:
|
||||||
clean:
|
type: actor
|
||||||
|
hygiene: clean
|
||||||
backstory: You are clean and smell fresh.
|
backstory: You are clean and smell fresh.
|
||||||
description: They look freshly washed and smell clean.
|
description: They look freshly washed and smell clean.
|
||||||
dirty:
|
- match:
|
||||||
|
type: actor
|
||||||
|
hygiene: dirty
|
||||||
backstory: You are dirty and smell bad.
|
backstory: You are dirty and smell bad.
|
||||||
description: They look dirty and smell bad.
|
description: They look dirty and smell bad.
|
||||||
filthy:
|
- match:
|
||||||
|
type: actor
|
||||||
|
hygiene: filthy
|
||||||
backstory: You are filthy and smell terrible.
|
backstory: You are filthy and smell terrible.
|
||||||
description: They look filthy and smell terrible.
|
description: They look filthy and smell terrible.
|
||||||
|
|
|
@ -118,14 +118,19 @@ rules:
|
||||||
mood: happy
|
mood: happy
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
mood:
|
- match:
|
||||||
happy:
|
type: actor
|
||||||
|
mood: happy
|
||||||
backstory: You are feeling happy.
|
backstory: You are feeling happy.
|
||||||
description: They look happy.
|
description: They look happy.
|
||||||
# neutral intentionally left out
|
- match:
|
||||||
sad:
|
type: actor
|
||||||
|
mood: sad
|
||||||
backstory: You are feeling sad.
|
backstory: You are feeling sad.
|
||||||
description: They look sad.
|
description: They look sad.
|
||||||
angry:
|
- match:
|
||||||
|
type: actor
|
||||||
|
mood: angry
|
||||||
backstory: You are feeling angry.
|
backstory: You are feeling angry.
|
||||||
description: They look angry.
|
description: They look angry.
|
||||||
|
# neutral intentionally omitted
|
|
@ -14,10 +14,13 @@ rules:
|
||||||
sleep: tired
|
sleep: tired
|
||||||
|
|
||||||
labels:
|
labels:
|
||||||
sleep:
|
- match:
|
||||||
rested:
|
type: actor
|
||||||
|
sleep: rested
|
||||||
backstory: You are well-rested.
|
backstory: You are well-rested.
|
||||||
description: They look well-rested.
|
description: They look well-rested.
|
||||||
tired:
|
- match:
|
||||||
|
type: actor
|
||||||
|
sleep: tired
|
||||||
backstory: You are tired.
|
backstory: You are tired.
|
||||||
description: They look tired.
|
description: They look tired.
|
||||||
|
|
Loading…
Reference in New Issue