| 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", |
| } |
|
|
| |
| _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 |
|
|