pub struct GameLoop {
pub mana_pools: Vec<ManaPool>,
pub combat: CombatState,
pub trigger_handler: TriggerHandler,
pub game_log: GameLog,
pub token_templates: HashMap<String, Card>,
pub token_art_variants: HashMap<(String, String), usize>,
pub token_fallback: HashMap<String, String>,
pub edition_dates: HashMap<String, String>,
pub game_rng: Box<dyn GameRng>,
pub experimental_restore_snapshot: bool,
pub abort_signal: Option<Arc<AtomicBool>>,
pub provide_priority_action_space: bool,
/* private fields */
}Expand description
Drives a complete game from setup through game over.
Fields§
§mana_pools: Vec<ManaPool>§combat: CombatState§trigger_handler: TriggerHandler§game_log: GameLog§token_templates: HashMap<String, Card>Token templates keyed by their script filename stem (e.g. “r_1_1_goblin”). Populated at game start by the Tauri layer; used by the Token effect handler.
token_art_variants: HashMap<(String, String), usize>Token art variant counts: (token_script, edition_code) → count.
Used for game-RNG parity with Java. When Java creates a token, it calls
Aggregates.random(collection) on a Set of art variants, which consumes
nextInt() once per element. Rust needs to consume the same number of
RNG calls to keep the game RNG in sync.
token_fallback: HashMap<String, String>Token fallback codes: edition_code → fallback_edition_code.
edition_dates: HashMap<String, String>Edition release dates: edition_code → “YYYY-MM-DD”.
game_rng: Box<dyn GameRng>Pluggable RNG for game effects (shuffles, coin flips, dice rolls). Default: ThreadRngAdapter (non-deterministic). For parity testing, replace with a JavaRandom-backed implementation.
experimental_restore_snapshot: boolEnables Java-parity snapshot rollback support (stash_game_state / restore_game_state).
abort_signal: Option<Arc<AtomicBool>>Cooperative shutdown signal. When the host (e.g. Tauri’s
GameManager::end_game) flips this flag we short-circuit the
outer run() loop and bail out. Prevents the engine from
continuing to tick after the user has conceded or returned to
the main menu — the previous behavior kept the game running
silently and drove a visible log/prompt loop on the frontend.
provide_priority_action_space: boolWhether the engine precomputes priority action space before calling
PlayerAgent::choose_action. UI agents use the default true; parity
disables it and requests action space explicitly only when needed.
Implementations§
Source§impl GameLoop
impl GameLoop
pub fn step_combat( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], )
Source§impl GameLoop
impl GameLoop
pub fn step_untap( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], )
pub fn step_draw( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], )
pub fn step_with_priority( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], is_main_phase: bool, )
pub fn step_main_phase( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], )
pub fn step_cleanup( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], )
Source§impl GameLoop
impl GameLoop
pub fn priority_round( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], is_main_phase: bool, )
Source§impl GameLoop
impl GameLoop
pub fn resolve_stack( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], )
Source§impl GameLoop
impl GameLoop
pub fn new(num_players: usize) -> Self
pub fn set_provide_priority_action_space(&mut self, provide: bool)
Sourcepub fn set_abort_signal(&mut self, signal: Arc<AtomicBool>)
pub fn set_abort_signal(&mut self, signal: Arc<AtomicBool>)
Install a cooperative abort signal. When the host flips the flag
the outer run() loop exits before the next turn so the game
thread can wind down cleanly instead of continuing to drive
prompts at a frontend that has already unmounted.
Sourcepub fn register_token(&mut self, script_name: impl Into<String>, template: Card)
pub fn register_token(&mut self, script_name: impl Into<String>, template: Card)
Register a token template by its script filename stem (e.g. “r_1_1_goblin”). Called at game start by the Tauri layer for every token script in the token DB.
Sourcepub fn token_art_variant_count(
&self,
token_script: &str,
edition_code: &str,
) -> usize
pub fn token_art_variant_count( &self, token_script: &str, edition_code: &str, ) -> usize
Get the number of art variants for a token in a given edition. Follows TokenFallbackCode chains. Returns 1 if not found.
pub fn pool(&self, pid: PlayerId) -> &ManaPool
pub fn pool_mut(&mut self, pid: PlayerId) -> &mut ManaPool
Sourcepub fn make_snapshot(
&self,
game: &GameState,
include_stack: bool,
) -> GameSnapshot
pub fn make_snapshot( &self, game: &GameState, include_stack: bool, ) -> GameSnapshot
Create a game snapshot. Set include_stack false for copy-without-stack flows.
Sourcepub fn restore_snapshot(
&mut self,
game: &mut GameState,
snapshot: &GameSnapshot,
)
pub fn restore_snapshot( &mut self, game: &mut GameState, snapshot: &GameSnapshot, )
Restore a previously captured snapshot.
Sourcepub fn stash_game_state(&mut self, game: &GameState)
pub fn stash_game_state(&mut self, game: &GameState)
Stash the current state if snapshot rollback is enabled.
Sourcepub fn restore_game_state(&mut self, game: &mut GameState) -> bool
pub fn restore_game_state(&mut self, game: &mut GameState) -> bool
Restore from the previously stashed state if available and enabled.
pub fn restore_checkpoint( &mut self, game: &mut GameState, checkpoint_id: u64, ) -> bool
Sourcepub fn get_tappable_lands(
&self,
game: &GameState,
player: PlayerId,
) -> Vec<CardId>
pub fn get_tappable_lands( &self, game: &GameState, player: PlayerId, ) -> Vec<CardId>
Get untapped lands on the battlefield for a player.
Sourcepub fn get_untappable_lands(
&self,
_game: &GameState,
player: PlayerId,
_pool_snapshot: &ManaPool,
) -> Vec<CardId>
pub fn get_untappable_lands( &self, _game: &GameState, player: PlayerId, _pool_snapshot: &ManaPool, ) -> Vec<CardId>
Get the top reversible mana source for a player, if any.
Sourcepub fn setup(
&mut self,
game: &mut GameState,
agents: &mut [Box<dyn PlayerAgent>],
rng: &mut impl Rng,
)
pub fn setup( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], rng: &mut impl Rng, )
Set up the game: roll for first player, shuffle libraries, draw opening hands, run mulligans.
Sourcepub fn roll_for_first_player(
&mut self,
game: &mut GameState,
agents: &mut [Box<dyn PlayerAgent>],
rng: &mut impl Rng,
)
pub fn roll_for_first_player( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], rng: &mut impl Rng, )
Each player rolls a d20; the highest roller goes first. Ties are broken by rerolling among the tied players (resolved internally — only the final round is surfaced to the UI).
Emits a single FirstPlayerRoll notification so the frontend can
animate every player’s die side-by-side. Mutates
game.turn.active_player and priority_player to the winner.
Sourcepub fn run_opening_hand_actions(
&mut self,
game: &mut GameState,
agents: &mut [Box<dyn PlayerAgent>],
)
pub fn run_opening_hand_actions( &mut self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], )
Run generic “opening hand” actions before the game begins.
Mirrors Java’s GameAction.runOpeningHandActions(): gather every
MayEffectFromOpeningHand keyword in hand, ask the controller whether
to use it, and resolve the referenced SVar immediately.