Source code for yasuki_core.engine.rules.work

from dataclasses import dataclass

from yasuki_core.engine.players import PlayerId
from yasuki_core.engine.rules.events import GameEvent


[docs] @dataclass(frozen=True, slots=True) class ResolveRecruit: """Finish a Recruit once its cost is paid: bring the card from its province into play (bowed for a Holding) and refill the vacated province. Attributes ---------- seat : PlayerId The recruiting seat. card_id : str The card leaving its province for play. invest_amount : int The gold Invested while recruiting, driving the card's one-time Invest effect on entry, or 0 when not Invested. Default 0. renew : bool Whether to refill the vacated province face-up (a granted Renew), on top of the card's own Renew keyword. Default False. proclaim : bool Whether the recruit is Proclaimed, claiming the seat's once-per-turn Proclaim and adding the Personality's Personal Honor to its Family Honor after entry. Default False. """ seat: PlayerId card_id: str invest_amount: int = 0 renew: bool = False proclaim: bool = False
[docs] @dataclass(frozen=True, slots=True) class ResumeCascade: """The exact remainder of an effect-and-trigger cascade a choice paused: the effects still to apply, then the ``(card_id, trigger)`` pairs still to fire for ``event``, then the events still queued behind them. The answered choice's own effects splice in ahead of these. Ephemeral like the rest of the stack — its effects and triggers are value-equal and stable module-level functions, so it rebuilds and compares equal under replay. Attributes ---------- effects : tuple of Effect The effects still to apply for the paused trigger, after the one that raised the choice. firing : tuple of (str, callable) The card id and trigger of each subscriber still to fire for ``event``. event : GameEvent or None The event those triggers are firing for, or None when the pause held only loose effects. queue : tuple of GameEvent The events still waiting behind ``event`` in the paused worklist. """ effects: tuple[object, ...] firing: tuple[tuple[str, object], ...] event: GameEvent | None queue: tuple[GameEvent, ...]
[docs] @dataclass(frozen=True, slots=True) class SelectAbilityTarget: """Raise an activated ability's target choice once its cost has been paid. Deferred so a cost whose own cascade pauses for a decision resolves fully before the target is chosen. Attributes ---------- card_id : str The card whose ability is resolving. candidates : tuple of str The ids the ability may target, fixed before paying so the choice is never left empty. """ card_id: str candidates: tuple[str, ...]
[docs] @dataclass(frozen=True, slots=True) class FinishRecruit: """The recruit steps that follow a card entering play — clearing its Sincerity tokens, resolving a Proclaim's honor gain, and applying any Invest effect. Deferred behind the ``EnteredPlay`` cascade so a trait that pauses on entry (a Sincerity seed choice) resolves before them. Attributes ---------- card_id : str The card that entered play. invest_amount : int The gold Invested while recruiting, driving the Invest effect, or 0 when not Invested. proclaim : bool Whether the recruit was Proclaimed, so entry claims the once-per-turn Proclaim and adds the Personality's Personal Honor to its seat's Family Honor. Default False. """ card_id: str invest_amount: int proclaim: bool = False
[docs] @dataclass(frozen=True, slots=True) class ApplyAbilityEffects: """Resolve an untargeted ability's effects against every card it hits, once its cost has been paid. The all-target counterpart of :class:`SelectAbilityTarget`, deferred for the same reason. Attributes ---------- card_id : str The card whose ability is resolving. target_ids : tuple of str The cards the ability affects, fixed before paying. """ card_id: str target_ids: tuple[str, ...]
[docs] @dataclass(frozen=True, slots=True) class ModestFarmStraighten: """Offer Modest Farm's optional sacrifice once its targeted recruit has resolved: the controller may destroy Modest Farm to straighten the freshly recruited card. Deferred so it runs after the recruit's payment and entry. Attributes ---------- modest_farm_id : str The Modest Farm that may be destroyed. target_id : str The recruited card that would be straightened. """ modest_farm_id: str target_id: str
# A unit of deferred engine work, run off GameState.stack once the current decision (if any) clears. # The action sequence pushes its later steps here while a step pauses for a decision; the union # grows as those steps do. Work items are ephemeral — replay rebuilds the stack by re-running. WorkItem = ( ResolveRecruit | ResumeCascade | SelectAbilityTarget | ApplyAbilityEffects | FinishRecruit | ModestFarmStraighten )