from __future__ import annotations from collections.abc import Iterable VALID_ROLES = ("citizen", "gatherer", "guard", "builder") _ROLE_ALIASES = { "farmer": "gatherer", "forager": "gatherer", "scribe": "gatherer", } _ACTION_ALIASES = { "eat": "consume", "talk": "communicate", "call_for_help": "communicate", "request_trade": "communicate", "trade": "transfer", "wander": "move_to", } _ACTION_ORDER = [ "move_to_resource", "gather", "transfer", "consume", "heal", "flee", "communicate", "go_home", "move_to", "steal", "attack", "defend", "patrol", "build", "idle", ] _SHARED_ACTIONS = { "move_to_resource", "consume", "heal", "flee", "communicate", "transfer", "go_home", "move_to", "idle", } # A citizen has no fixed job: it can do everything (gather, build, fight, steal). _CITIZEN_ACTIONS = _SHARED_ACTIONS | { "gather", "steal", "attack", "defend", "patrol", "build", } _ROLE_ACTIONS = { "citizen": _CITIZEN_ACTIONS, "gatherer": _SHARED_ACTIONS | {"gather", "steal"}, "guard": (_SHARED_ACTIONS | {"attack", "defend", "patrol"}) - {"move_to_resource"}, "builder": _SHARED_ACTIONS | {"build", "gather"}, } def normalize_role(role: str) -> str: normalized = _ROLE_ALIASES.get(role, role) return normalized if normalized in VALID_ROLES else "citizen" def canonical_action(action: str) -> str: return _ACTION_ALIASES.get(action, action) def actions_for_role(role: str) -> list[str]: normalized = normalize_role(role) allowed = _ROLE_ACTIONS[normalized] return [action for action in _ACTION_ORDER if action in allowed] def filter_actions_for_role(actions: Iterable[str], role: str) -> list[str]: role_actions = set(actions_for_role(role)) filtered: list[str] = [] for action in actions: canonical = canonical_action(action) if canonical in role_actions and canonical not in filtered: filtered.append(canonical) return filtered def action_allowed_for_role( role: str, action: str, *, resource_type: str | None = None, self_defense: bool = False, ) -> bool: normalized_role = normalize_role(role) canonical = canonical_action(action) if canonical == "attack" and normalized_role == "gatherer" and self_defense: return True if canonical not in _ROLE_ACTIONS[normalized_role]: return False if canonical == "gather" and normalized_role == "builder": return resource_type in (None, "wood") return True