pub trait PlayerAgent {
Show 83 methods
// Required methods
fn mulligan_decision(
&mut self,
player: PlayerId,
hand: &[CardId],
mulligan_count: u32,
) -> bool;
fn choose_action(
&mut self,
player: PlayerId,
action_space: Option<&PriorityActionSpace>,
request_action_space: &mut dyn FnMut() -> PriorityActionSpace,
) -> PlayerAction;
fn choose_attackers(
&mut self,
player: PlayerId,
available: &[CardId],
possible_defenders: &[DefenderId],
) -> Vec<(CardId, DefenderId)>;
fn choose_blockers(
&mut self,
player: PlayerId,
attackers: &[CardId],
available_blockers: &[CardId],
max_blockers: Option<usize>,
) -> Vec<(CardId, CardId)>;
fn choose_targets_for(
&mut self,
sa: &mut SpellAbility,
game: &GameState,
mana_pools: &[ManaPool],
) -> bool;
fn choose_target_player(
&mut self,
player: PlayerId,
valid: &[PlayerId],
sa: Option<&SpellAbility>,
) -> Option<PlayerId>;
fn choose_target_card(
&mut self,
player: PlayerId,
valid: &[CardId],
sa: Option<&SpellAbility>,
) -> Option<CardId>;
fn choose_target_any(
&mut self,
player: PlayerId,
valid_players: &[PlayerId],
valid_cards: &[CardId],
sa: Option<&SpellAbility>,
) -> TargetChoice;
fn choose_land_or_spell(&mut self, player: PlayerId) -> Option<bool>;
// Provided methods
fn snapshot_state(&mut self, _game: &GameState, _mana_pools: &[ManaPool]) { ... }
fn take_restore_request(&mut self) -> Option<u64> { ... }
fn reveal_cards(
&mut self,
_game: &GameState,
_player: PlayerId,
_cards: &[CardId],
_zone: ZoneType,
_owner: PlayerId,
_message_prefix: Option<&str>,
) { ... }
fn get_pass_until(&self) -> Option<PassUntilTarget> { ... }
fn clear_pass_until(&mut self) { ... }
fn mulligan_decision_send(
&mut self,
_player: PlayerId,
_hand: &[CardId],
_mulligan_count: u32,
) { ... }
fn mulligan_decision_recv(
&mut self,
player: PlayerId,
hand: &[CardId],
mulligan_count: u32,
) -> bool { ... }
fn choose_cards_to_bottom(
&mut self,
_player: PlayerId,
hand: &[CardId],
count: usize,
) -> Vec<CardId> { ... }
fn choose_cards_to_bottom_send(
&mut self,
_player: PlayerId,
_hand: &[CardId],
_count: usize,
) { ... }
fn choose_cards_to_bottom_recv(
&mut self,
player: PlayerId,
hand: &[CardId],
count: usize,
) -> Vec<CardId> { ... }
fn exert_attackers(
&mut self,
_player: PlayerId,
_attackers: &[CardId],
) -> Vec<CardId> { ... }
fn enlist_attackers(
&mut self,
_player: PlayerId,
_attackers: &[CardId],
) -> Vec<CardId> { ... }
fn choose_blocker_for(
&mut self,
player: PlayerId,
attackers: &[CardId],
blocker: CardId,
) -> Option<CardId> { ... }
fn choose_damage_assignment_order(
&mut self,
_player: PlayerId,
_attacker: CardId,
blockers: &[CardId],
) -> Vec<CardId> { ... }
fn assign_combat_damage(
&mut self,
game: &GameState,
_player: PlayerId,
attacker: CardId,
blockers_in_order: &[CardId],
defender_id: Option<DefenderId>,
damage_to_assign: i32,
) -> Vec<(Option<CardId>, i32)> { ... }
fn set_targeting_cancellable(&mut self, _cancellable: bool) { ... }
fn choose_target_card_from_zone(
&mut self,
player: PlayerId,
_zone: ZoneType,
valid: &[CardId],
sa: Option<&SpellAbility>,
) -> Option<CardId> { ... }
fn choose_sacrifice(
&mut self,
_player: PlayerId,
valid: &[CardId],
_source: Option<CardId>,
) -> Option<CardId> { ... }
fn choose_scry(
&mut self,
_game: &GameState,
_player: PlayerId,
_source: Option<CardId>,
cards: &[CardId],
) -> Vec<Vec<CardId>> { ... }
fn choose_surveil(
&mut self,
_game: &GameState,
_player: PlayerId,
_source: Option<CardId>,
cards: &[CardId],
) -> Vec<Vec<CardId>> { ... }
fn choose_dig(
&mut self,
_game: &GameState,
_player: PlayerId,
valid: &[CardId],
max: usize,
_optional: bool,
) -> Vec<CardId> { ... }
fn choose_reorder_library(
&mut self,
_game: &GameState,
_player: PlayerId,
cards: &[CardId],
) -> Vec<CardId> { ... }
fn choose_discard(
&mut self,
_player: PlayerId,
hand: &[CardId],
num: usize,
) -> Vec<CardId> { ... }
fn choose_discard_any_number(
&mut self,
_player: PlayerId,
hand: &[CardId],
min: usize,
max: usize,
) -> Vec<CardId> { ... }
fn choose_random_discard(
&mut self,
_player: PlayerId,
hand: &[CardId],
num: usize,
) -> Vec<CardId> { ... }
fn choose_target_spell(
&mut self,
_player: PlayerId,
valid: &[u32],
_source: Option<CardId>,
) -> Option<u32> { ... }
fn choose_mode(
&mut self,
_player: PlayerId,
descriptions: &[String],
min: usize,
_max: usize,
_source_card_id: Option<CardId>,
) -> Vec<usize> { ... }
fn choose_spell_abilities_for_effect(
&mut self,
_player: PlayerId,
abilities: &[SpellAbility],
num: usize,
) -> Vec<usize> { ... }
fn choose_single_entity_for_effect(
&mut self,
_player: PlayerId,
valid: &[GameEntity],
_is_optional: bool,
) -> Option<GameEntity> { ... }
fn get_ability_to_play(
&mut self,
_player: PlayerId,
abilities: &[SpellAbility],
) -> Option<usize> { ... }
fn choose_legend_keep(
&mut self,
_player: PlayerId,
duplicates: &[CardId],
) -> CardId { ... }
fn choose_optional_trigger(
&mut self,
_player: PlayerId,
_description: &str,
_source: Option<CardId>,
_api: Option<ApiType>,
) -> bool { ... }
fn confirm_replacement_effect(
&mut self,
_player: PlayerId,
_question: &str,
_effect_description: &str,
_source: Option<CardId>,
) -> bool { ... }
fn confirm_action(
&mut self,
_player: PlayerId,
_mode: Option<&str>,
_message: &str,
_options: &[String],
_source: Option<CardId>,
_api: Option<ApiType>,
) -> bool { ... }
fn confirm_payment(
&mut self,
player: PlayerId,
cost_kind: &str,
message: &str,
source: Option<CardId>,
api: Option<ApiType>,
) -> bool { ... }
fn pay_cost_to_prevent_effect(
&mut self,
player: PlayerId,
cost_kind: &str,
message: &str,
source: Option<CardId>,
api: Option<ApiType>,
can_pay: bool,
targets: &[GameEntity],
effect_text: &str,
) -> bool { ... }
fn choose_binary(
&mut self,
player: PlayerId,
question: &str,
kind: BinaryChoiceKind,
_default_choice: Option<bool>,
source: Option<CardId>,
api: Option<ApiType>,
) -> bool { ... }
fn choose_kicker(
&mut self,
_player: PlayerId,
_kicker_cost: &str,
_source: Option<CardId>,
) -> bool { ... }
fn help_pay_assist(
&mut self,
_player: PlayerId,
_card_name: &str,
_max_generic: u32,
) -> u32 { ... }
fn choose_buyback(
&mut self,
_player: PlayerId,
_buyback_cost: &str,
_source: Option<CardId>,
) -> bool { ... }
fn choose_multikicker(
&mut self,
_player: PlayerId,
_cost: &str,
_max_kicks: u32,
_source: Option<CardId>,
) -> u32 { ... }
fn choose_replicate(
&mut self,
_player: PlayerId,
_cost: &str,
_max_replicates: u32,
_source: Option<CardId>,
) -> u32 { ... }
fn choose_color(
&mut self,
_player: PlayerId,
valid_colors: &[String],
) -> Option<String> { ... }
fn choose_colors(
&mut self,
_player: PlayerId,
valid_colors: &[String],
min: usize,
max: usize,
) -> Vec<String> { ... }
fn choose_cards_for_effect(
&mut self,
_player: PlayerId,
valid: &[CardId],
_min: usize,
max: usize,
) -> Vec<CardId> { ... }
fn choose_tap_type_for_cost(
&mut self,
player: PlayerId,
valid: &[CardId],
_min_total_power: i32,
_card_powers: &[(CardId, i32)],
_card_sort_powers: &[(CardId, i32)],
_sa: Option<&SpellAbility>,
) -> Vec<CardId> { ... }
fn choose_entities_for_effect(
&mut self,
_player: PlayerId,
candidates: &[GameEntity],
_min: usize,
max: usize,
) -> Vec<GameEntity> { ... }
fn choose_single_card_for_zone_change(
&mut self,
_game: &GameState,
player: PlayerId,
valid: &[CardId],
_select_prompt: &str,
_is_optional: bool,
) -> Option<CardId> { ... }
fn choose_cards_for_zone_change(
&mut self,
_game: &GameState,
player: PlayerId,
valid: &[CardId],
min: usize,
max: usize,
_select_prompt: &str,
) -> Vec<CardId> { ... }
fn choose_type(
&mut self,
_player: PlayerId,
_type_category: &str,
valid_types: &[String],
) -> Option<String> { ... }
fn choose_counter_type(
&mut self,
_player: PlayerId,
options: &[CounterType],
_prompt: &str,
) -> Option<CounterType> { ... }
fn choose_card_name(
&mut self,
_player: PlayerId,
valid_names: &[String],
) -> Option<String> { ... }
fn choose_number(
&mut self,
_player: PlayerId,
_source: Option<CardId>,
_title: &str,
_description: Option<&str>,
min: i32,
_max: i32,
) -> Option<i32> { ... }
fn choose_number_for_keyword_cost(
&mut self,
_player: PlayerId,
_max: i32,
_prompt: &str,
_source: Option<CardId>,
) -> i32 { ... }
fn choose_number_from_list(
&mut self,
_player: PlayerId,
choices: &[i32],
_message: &str,
_source_card_id: Option<CardId>,
) -> Option<i32> { ... }
fn choose_roll_to_ignore(
&mut self,
_player: PlayerId,
rolls: &[i32],
_source: Option<CardId>,
) -> Option<i32> { ... }
fn choose_roll_to_swap(
&mut self,
_player: PlayerId,
rolls: &[i32],
_source: Option<CardId>,
) -> Option<i32> { ... }
fn choose_dice_to_reroll(
&mut self,
_player: PlayerId,
_rolls: &[i32],
_source: Option<CardId>,
) -> Vec<i32> { ... }
fn choose_roll_to_modify(
&mut self,
_player: PlayerId,
rolls: &[i32],
_source: Option<CardId>,
) -> Option<i32> { ... }
fn choose_roll_swap_value(
&mut self,
_player: PlayerId,
_current_result: i32,
_power: i32,
_toughness: i32,
_source: Option<CardId>,
) -> Option<RollSwapChoice> { ... }
fn flip_coin_call(&mut self, _player: PlayerId) -> bool { ... }
fn choose_phyrexian_pay_life(
&mut self,
_player: PlayerId,
_color: &str,
_source: Option<CardId>,
) -> bool { ... }
fn pay_combat_cost(
&mut self,
_player: PlayerId,
_attacker: CardId,
_cost: i32,
_description: &str,
_mana_ability_options: &[ManaAbilityOption],
_tappable_lands: &[CardId],
_untappable_lands: &[CardId],
_mana_pool_total: i32,
) -> CombatCostAction { ... }
fn choose_delve(
&mut self,
_player: PlayerId,
valid: &[CardId],
max: usize,
_source: Option<CardId>,
) -> Vec<CardId> { ... }
fn choose_improvise(
&mut self,
_player: PlayerId,
_untapped_artifacts: &[CardId],
_remaining_cost: &ManaCost,
_source: Option<CardId>,
) -> Vec<CardId> { ... }
fn choose_convoke(
&mut self,
_player: PlayerId,
_untapped_creatures: &[CardId],
_remaining_cost: &ManaCost,
_source: Option<CardId>,
) -> Vec<CardId> { ... }
fn pay_mana_cost(
&mut self,
_player: PlayerId,
_card_id: CardId,
_card_name: &str,
_mana_cost: &str,
_mana_cost_display: &str,
_mana_cost_checkpoint: &str,
_can_confirm_from_pool: bool,
_allow_reserved_source_reuse: bool,
_reserved_sacrifices: &[CardId],
_mana_ability_options: &[ManaAbilityOption],
_tappable_lands: &[CardId],
_untappable_lands: &[CardId],
_mana_pool: &ManaPool,
) -> ManaCostAction { ... }
fn await_display_ack(&mut self) { ... }
fn decide_cost_part(
&mut self,
_player: PlayerId,
_source: CardId,
_cost_part: &CostPart,
_game: &GameState,
) -> Option<PaymentDecision> { ... }
fn pays_right_after_decision(&self) -> bool { ... }
fn order_cost_parts(&mut self, parts: Vec<CostPart>) -> Vec<CostPart> { ... }
fn specify_mana_combo(
&mut self,
_player: PlayerId,
available_colors: &[String],
amount: usize,
_source: Option<CardId>,
_express_choice: Option<u16>,
) -> Vec<String> { ... }
fn notify(&mut self, _event: GameNotification) { ... }
fn choose_single_replacement_effect(
&mut self,
_player: PlayerId,
_descriptions: &[String],
) -> usize { ... }
}Expand description
Trait for player decision-making. Decouples the engine from UI/AI. Implementations can be interactive (prompt user), AI, or network-driven.
Required Methods§
Sourcefn mulligan_decision(
&mut self,
player: PlayerId,
hand: &[CardId],
mulligan_count: u32,
) -> bool
fn mulligan_decision( &mut self, player: PlayerId, hand: &[CardId], mulligan_count: u32, ) -> bool
Choose whether to keep the current opening hand or mulligan.
mulligan_count is the number of mulligans already taken this game.
Returns true to keep, false to mulligan.
Sourcefn choose_action(
&mut self,
player: PlayerId,
action_space: Option<&PriorityActionSpace>,
request_action_space: &mut dyn FnMut() -> PriorityActionSpace,
) -> PlayerAction
fn choose_action( &mut self, player: PlayerId, action_space: Option<&PriorityActionSpace>, request_action_space: &mut dyn FnMut() -> PriorityActionSpace, ) -> PlayerAction
Choose a main-phase action: play a card from hand, tap a land for mana, untap a land,
activate an ability, or pass.
tappable_lands lists untapped lands available for tapping.
untappable_lands lists source IDs whose most recent mana action can be undone.
activatable lists (card_id, ability_index) pairs for activated abilities that can be used.
Sourcefn choose_attackers(
&mut self,
player: PlayerId,
available: &[CardId],
possible_defenders: &[DefenderId],
) -> Vec<(CardId, DefenderId)>
fn choose_attackers( &mut self, player: PlayerId, available: &[CardId], possible_defenders: &[DefenderId], ) -> Vec<(CardId, DefenderId)>
Choose attackers from available creatures, assigning each to a defender.
possible_defenders lists valid attack targets (opponent players + their planeswalkers).
Returns (attacker, defender) pairs.
Sourcefn choose_blockers(
&mut self,
player: PlayerId,
attackers: &[CardId],
available_blockers: &[CardId],
max_blockers: Option<usize>,
) -> Vec<(CardId, CardId)>
fn choose_blockers( &mut self, player: PlayerId, attackers: &[CardId], available_blockers: &[CardId], max_blockers: Option<usize>, ) -> Vec<(CardId, CardId)>
Choose blockers. Returns pairs of (blocker, attacker).
max_blockers is the BlockRestrict limit (if any) — agent should stop after this many.
fn choose_targets_for( &mut self, sa: &mut SpellAbility, game: &GameState, mana_pools: &[ManaPool], ) -> bool
Sourcefn choose_target_player(
&mut self,
player: PlayerId,
valid: &[PlayerId],
sa: Option<&SpellAbility>,
) -> Option<PlayerId>
fn choose_target_player( &mut self, player: PlayerId, valid: &[PlayerId], sa: Option<&SpellAbility>, ) -> Option<PlayerId>
Choose a target player (e.g. for Lightning Bolt targeting a player).
sa is the active spell ability context (source card, API type, etc.) for UI display.
Sourcefn choose_target_card(
&mut self,
player: PlayerId,
valid: &[CardId],
sa: Option<&SpellAbility>,
) -> Option<CardId>
fn choose_target_card( &mut self, player: PlayerId, valid: &[CardId], sa: Option<&SpellAbility>, ) -> Option<CardId>
Choose a target card (e.g. for Lightning Bolt targeting a creature).
Sourcefn choose_target_any(
&mut self,
player: PlayerId,
valid_players: &[PlayerId],
valid_cards: &[CardId],
sa: Option<&SpellAbility>,
) -> TargetChoice
fn choose_target_any( &mut self, player: PlayerId, valid_players: &[PlayerId], valid_cards: &[CardId], sa: Option<&SpellAbility>, ) -> TargetChoice
Choose a target that can be a player or a card (e.g. “any target”).
Sourcefn choose_land_or_spell(&mut self, player: PlayerId) -> Option<bool>
fn choose_land_or_spell(&mut self, player: PlayerId) -> Option<bool>
Choose whether to play a land or cast a spell when both are possible. Returns true for land, false for spell, None to pass.
Provided Methods§
Sourcefn snapshot_state(&mut self, _game: &GameState, _mana_pools: &[ManaPool])
fn snapshot_state(&mut self, _game: &GameState, _mana_pools: &[ManaPool])
Called before each agent decision point with the current game state. Override this to capture snapshots for a UI or network layer.
Sourcefn take_restore_request(&mut self) -> Option<u64>
fn take_restore_request(&mut self) -> Option<u64>
Poll and clear any pending snapshot-restore request from this agent.
fn reveal_cards( &mut self, _game: &GameState, _player: PlayerId, _cards: &[CardId], _zone: ZoneType, _owner: PlayerId, _message_prefix: Option<&str>, )
Sourcefn get_pass_until(&self) -> Option<PassUntilTarget>
fn get_pass_until(&self) -> Option<PassUntilTarget>
Returns the (player, phase) slot this player auto-passes until.
A stop is genuinely (player, phase): “pass until Player2’s end” is
distinct from “pass until my end”. The declaration is HELD across
priority windows — the engine does not consume it each pass — and is
cleared only when the target is reached or a meaningful event occurs.
None = no standing pass-until (prompt normally).
Sourcefn clear_pass_until(&mut self)
fn clear_pass_until(&mut self)
Clear the pass-until declaration (target reached, cast, attackers declared, …).
Sourcefn mulligan_decision_send(
&mut self,
_player: PlayerId,
_hand: &[CardId],
_mulligan_count: u32,
)
fn mulligan_decision_send( &mut self, _player: PlayerId, _hand: &[CardId], _mulligan_count: u32, )
Fire the mulligan prompt without blocking for a response. Default: no-op. UI agents override to decouple prompt dispatch from response collection so multiple players can be prompted in parallel.
Sourcefn mulligan_decision_recv(
&mut self,
player: PlayerId,
hand: &[CardId],
mulligan_count: u32,
) -> bool
fn mulligan_decision_recv( &mut self, player: PlayerId, hand: &[CardId], mulligan_count: u32, ) -> bool
Block waiting for the mulligan response previously sent via
mulligan_decision_send. Default falls back to the blocking
mulligan_decision so agents that don’t split send/recv still work.
Sourcefn choose_cards_to_bottom(
&mut self,
_player: PlayerId,
hand: &[CardId],
count: usize,
) -> Vec<CardId>
fn choose_cards_to_bottom( &mut self, _player: PlayerId, hand: &[CardId], count: usize, ) -> Vec<CardId>
London Mulligan: after keeping, choose count cards from hand to put
on the bottom of the library. Returns exactly count card IDs.
Default: picks the first count cards (suitable for simple AI agents).
Sourcefn choose_cards_to_bottom_send(
&mut self,
_player: PlayerId,
_hand: &[CardId],
_count: usize,
)
fn choose_cards_to_bottom_send( &mut self, _player: PlayerId, _hand: &[CardId], _count: usize, )
Fire the put-back prompt without blocking. Default: no-op.
Sourcefn choose_cards_to_bottom_recv(
&mut self,
player: PlayerId,
hand: &[CardId],
count: usize,
) -> Vec<CardId>
fn choose_cards_to_bottom_recv( &mut self, player: PlayerId, hand: &[CardId], count: usize, ) -> Vec<CardId>
Block waiting for the put-back response. Default falls back to the
blocking choose_cards_to_bottom.
Sourcefn exert_attackers(
&mut self,
_player: PlayerId,
_attackers: &[CardId],
) -> Vec<CardId>
fn exert_attackers( &mut self, _player: PlayerId, _attackers: &[CardId], ) -> Vec<CardId>
Choose which attackers to exert.
Input is the subset of already-declared attackers that can pay an Exert
optional attack cost. Return a subset of attackers.
Default: choose none.
Sourcefn enlist_attackers(
&mut self,
_player: PlayerId,
_attackers: &[CardId],
) -> Vec<CardId>
fn enlist_attackers( &mut self, _player: PlayerId, _attackers: &[CardId], ) -> Vec<CardId>
Choose which attackers to enlist.
Input is the subset of already-declared attackers that can pay an Enlist
optional attack cost. Return a subset of attackers.
Default: choose none.
Sourcefn choose_blocker_for(
&mut self,
player: PlayerId,
attackers: &[CardId],
blocker: CardId,
) -> Option<CardId>
fn choose_blocker_for( &mut self, player: PlayerId, attackers: &[CardId], blocker: CardId, ) -> Option<CardId>
Choose one attacker for a specific blocker during sequential declaration.
Return Some(attacker_id) to assign this blocker, or None to leave it
unassigned. Default behavior maps through choose_blockers for the single
blocker, preserving existing agent behavior when not overridden.
Sourcefn choose_damage_assignment_order(
&mut self,
_player: PlayerId,
_attacker: CardId,
blockers: &[CardId],
) -> Vec<CardId>
fn choose_damage_assignment_order( &mut self, _player: PlayerId, _attacker: CardId, blockers: &[CardId], ) -> Vec<CardId>
Choose the order in which an attacker assigns damage to its blockers.
The attacker must assign lethal damage to each blocker in order before
assigning damage to the next one.
Returns a permutation of blockers in the desired assignment order.
Default: return blockers as-is (no reordering).
Sourcefn assign_combat_damage(
&mut self,
game: &GameState,
_player: PlayerId,
attacker: CardId,
blockers_in_order: &[CardId],
defender_id: Option<DefenderId>,
damage_to_assign: i32,
) -> Vec<(Option<CardId>, i32)>
fn assign_combat_damage( &mut self, game: &GameState, _player: PlayerId, attacker: CardId, blockers_in_order: &[CardId], defender_id: Option<DefenderId>, damage_to_assign: i32, ) -> Vec<(Option<CardId>, i32)>
Choose exact combat damage assignment for one blocked attacker.
blockers_in_order are in assignment order. defender_id is provided
only when damage can legally be assigned to the defender (e.g. trample).
Return pairs of (assignee, damage) where:
Some(card_id)assigns to a blockerNoneassigns to defender
fn set_targeting_cancellable(&mut self, _cancellable: bool)
Sourcefn choose_target_card_from_zone(
&mut self,
player: PlayerId,
_zone: ZoneType,
valid: &[CardId],
sa: Option<&SpellAbility>,
) -> Option<CardId>
fn choose_target_card_from_zone( &mut self, player: PlayerId, _zone: ZoneType, valid: &[CardId], sa: Option<&SpellAbility>, ) -> Option<CardId>
Choose a target card from a specific zone (e.g. Raise Dead from graveyard).
Sourcefn choose_sacrifice(
&mut self,
_player: PlayerId,
valid: &[CardId],
_source: Option<CardId>,
) -> Option<CardId>
fn choose_sacrifice( &mut self, _player: PlayerId, valid: &[CardId], _source: Option<CardId>, ) -> Option<CardId>
Choose one permanent to sacrifice/select from the valid options.
sa is the active spell ability context for UI display.
Default picks the first (used by AI agents).
Sourcefn choose_scry(
&mut self,
_game: &GameState,
_player: PlayerId,
_source: Option<CardId>,
cards: &[CardId],
) -> Vec<Vec<CardId>>
fn choose_scry( &mut self, _game: &GameState, _player: PlayerId, _source: Option<CardId>, cards: &[CardId], ) -> Vec<Vec<CardId>>
Distribute the looked-at Scry cards across the zones. Returns one ordered
pile per zone — [top, bottom] — where the last id in each pile is placed
on top of that pile. Default: keep everything on top, nothing to bottom.
Sourcefn choose_surveil(
&mut self,
_game: &GameState,
_player: PlayerId,
_source: Option<CardId>,
cards: &[CardId],
) -> Vec<Vec<CardId>>
fn choose_surveil( &mut self, _game: &GameState, _player: PlayerId, _source: Option<CardId>, cards: &[CardId], ) -> Vec<Vec<CardId>>
Distribute the looked-at Surveil cards: [top, graveyard] ordered piles.
Default: keep everything on top, nothing milled.
Sourcefn choose_dig(
&mut self,
_game: &GameState,
_player: PlayerId,
valid: &[CardId],
max: usize,
_optional: bool,
) -> Vec<CardId>
fn choose_dig( &mut self, _game: &GameState, _player: PlayerId, valid: &[CardId], max: usize, _optional: bool, ) -> Vec<CardId>
Choose up to max cards from valid to move to the destination zone (Dig effect).
optional means the player is not required to choose any.
Default: take first max cards.
Sourcefn choose_reorder_library(
&mut self,
_game: &GameState,
_player: PlayerId,
cards: &[CardId],
) -> Vec<CardId>
fn choose_reorder_library( &mut self, _game: &GameState, _player: PlayerId, cards: &[CardId], ) -> Vec<CardId>
Choose an ordering for the top N cards being put back on the library (Ponder/Reorder). Returns the cards in desired order: index 0 will be placed deepest, last will be on top. Default: keep original order.
Sourcefn choose_discard(
&mut self,
_player: PlayerId,
hand: &[CardId],
num: usize,
) -> Vec<CardId>
fn choose_discard( &mut self, _player: PlayerId, hand: &[CardId], num: usize, ) -> Vec<CardId>
Choose which cards to discard from hand (for SP$ Discard effects).
hand is the full hand, num is how many must be discarded.
Default: discard the first num cards.
Sourcefn choose_discard_any_number(
&mut self,
_player: PlayerId,
hand: &[CardId],
min: usize,
max: usize,
) -> Vec<CardId>
fn choose_discard_any_number( &mut self, _player: PlayerId, hand: &[CardId], min: usize, max: usize, ) -> Vec<CardId>
Choose any number of cards to discard (for AnyNumber$ True on
SP$/DB$ Discard). The agent may pick 0..=hand.len() cards.
Default: discard min cards (the minimum forced amount).
Sourcefn choose_random_discard(
&mut self,
_player: PlayerId,
hand: &[CardId],
num: usize,
) -> Vec<CardId>
fn choose_random_discard( &mut self, _player: PlayerId, hand: &[CardId], num: usize, ) -> Vec<CardId>
Choose cards to discard at random (for Mode$ Random discard, e.g. Hypnotic Specter).
The engine calls this instead of choose_discard when the discard is random.
Default: discard the first num cards (same as choose_discard).
Deterministic agents should override this to use their seeded RNG.
Sourcefn choose_target_spell(
&mut self,
_player: PlayerId,
valid: &[u32],
_source: Option<CardId>,
) -> Option<u32>
fn choose_target_spell( &mut self, _player: PlayerId, valid: &[u32], _source: Option<CardId>, ) -> Option<u32>
Choose a target spell on the stack (for SP$ Counter effects).
valid is a slice of stack entry IDs.
Default: target the first (topmost) spell.
Sourcefn choose_mode(
&mut self,
_player: PlayerId,
descriptions: &[String],
min: usize,
_max: usize,
_source_card_id: Option<CardId>,
) -> Vec<usize>
fn choose_mode( &mut self, _player: PlayerId, descriptions: &[String], min: usize, _max: usize, _source_card_id: Option<CardId>, ) -> Vec<usize>
Choose N modes for a modal spell (SP$ Charm / Commands).
descriptions — human-readable description of each mode.
min — minimum number of modes to choose.
max — maximum number of modes to choose.
Returns indices into descriptions of the chosen modes, in order.
Default: choose the first min modes (index 0, 1, …).
fn choose_spell_abilities_for_effect( &mut self, _player: PlayerId, abilities: &[SpellAbility], num: usize, ) -> Vec<usize>
Sourcefn choose_single_entity_for_effect(
&mut self,
_player: PlayerId,
valid: &[GameEntity],
_is_optional: bool,
) -> Option<GameEntity>
fn choose_single_entity_for_effect( &mut self, _player: PlayerId, valid: &[GameEntity], _is_optional: bool, ) -> Option<GameEntity>
Choose exactly one entity (Card or Player) from a candidate list.
fn get_ability_to_play( &mut self, _player: PlayerId, abilities: &[SpellAbility], ) -> Option<usize>
Sourcefn choose_legend_keep(
&mut self,
_player: PlayerId,
duplicates: &[CardId],
) -> CardId
fn choose_legend_keep( &mut self, _player: PlayerId, duplicates: &[CardId], ) -> CardId
Choose which legendary permanent to keep when the legend rule applies.
duplicates contains all legendaries with the same name controlled by this player.
Returns the CardId of the one to keep; the rest are sacrificed.
Sourcefn choose_optional_trigger(
&mut self,
_player: PlayerId,
_description: &str,
_source: Option<CardId>,
_api: Option<ApiType>,
) -> bool
fn choose_optional_trigger( &mut self, _player: PlayerId, _description: &str, _source: Option<CardId>, _api: Option<ApiType>, ) -> bool
Choose whether an optional triggered ability fires.
description is the trigger text shown to the player.
source is the engine card id of the source card (for UI display).
api is the spell ability API type.
Returns true to allow the trigger, false to decline.
Default: always allow (non-interactive agents accept all optional triggers).
fn confirm_replacement_effect( &mut self, _player: PlayerId, _question: &str, _effect_description: &str, _source: Option<CardId>, ) -> bool
Sourcefn confirm_action(
&mut self,
_player: PlayerId,
_mode: Option<&str>,
_message: &str,
_options: &[String],
_source: Option<CardId>,
_api: Option<ApiType>,
) -> bool
fn confirm_action( &mut self, _player: PlayerId, _mode: Option<&str>, _message: &str, _options: &[String], _source: Option<CardId>, _api: Option<ApiType>, ) -> bool
Generic confirmation hook for optional effect prompts that don’t yet have a dedicated typed callback in the Rust agent interface.
Returns true to accept/confirm, false to decline.
fn confirm_payment( &mut self, player: PlayerId, cost_kind: &str, message: &str, source: Option<CardId>, api: Option<ApiType>, ) -> bool
fn pay_cost_to_prevent_effect( &mut self, player: PlayerId, cost_kind: &str, message: &str, source: Option<CardId>, api: Option<ApiType>, can_pay: bool, targets: &[GameEntity], effect_text: &str, ) -> bool
fn choose_binary( &mut self, player: PlayerId, question: &str, kind: BinaryChoiceKind, _default_choice: Option<bool>, source: Option<CardId>, api: Option<ApiType>, ) -> bool
Sourcefn choose_kicker(
&mut self,
_player: PlayerId,
_kicker_cost: &str,
_source: Option<CardId>,
) -> bool
fn choose_kicker( &mut self, _player: PlayerId, _kicker_cost: &str, _source: Option<CardId>, ) -> bool
Choose whether to pay the kicker cost for a spell.
kicker_cost is the mana cost string (e.g. “W”, “2 R”).
source is the name of the spell being cast (for UI display).
Returns true to kick, false to cast without kicker.
Default: don’t kick (AI default).
Sourcefn help_pay_assist(
&mut self,
_player: PlayerId,
_card_name: &str,
_max_generic: u32,
) -> u32
fn help_pay_assist( &mut self, _player: PlayerId, _card_name: &str, _max_generic: u32, ) -> u32
Assist: another player asks if we’ll help pay generic mana. Returns how much generic mana to pay (0 = decline). Default: decline.
Sourcefn choose_buyback(
&mut self,
_player: PlayerId,
_buyback_cost: &str,
_source: Option<CardId>,
) -> bool
fn choose_buyback( &mut self, _player: PlayerId, _buyback_cost: &str, _source: Option<CardId>, ) -> bool
Choose whether to pay the buyback cost for a spell. Returns true to pay buyback, false to cast normally. Default: don’t pay buyback.
Sourcefn choose_multikicker(
&mut self,
_player: PlayerId,
_cost: &str,
_max_kicks: u32,
_source: Option<CardId>,
) -> u32
fn choose_multikicker( &mut self, _player: PlayerId, _cost: &str, _max_kicks: u32, _source: Option<CardId>, ) -> u32
Choose how many times to pay the multikicker cost.
max_kicks is the maximum affordable.
Returns the number of times to kick (0 to max_kicks).
Default: 0 (don’t multikick).
Sourcefn choose_replicate(
&mut self,
_player: PlayerId,
_cost: &str,
_max_replicates: u32,
_source: Option<CardId>,
) -> u32
fn choose_replicate( &mut self, _player: PlayerId, _cost: &str, _max_replicates: u32, _source: Option<CardId>, ) -> u32
Choose how many times to pay the replicate cost.
max_replicates is the maximum affordable.
Returns the number of replicates.
Default: 0.
Sourcefn choose_color(
&mut self,
_player: PlayerId,
valid_colors: &[String],
) -> Option<String>
fn choose_color( &mut self, _player: PlayerId, valid_colors: &[String], ) -> Option<String>
Choose a color (for ChooseColorEffect).
valid_colors lists the legal color choices (e.g. [“White”,“Blue”,“Black”,“Red”,“Green”]).
Default: pick the first valid color.
Sourcefn choose_colors(
&mut self,
_player: PlayerId,
valid_colors: &[String],
min: usize,
max: usize,
) -> Vec<String>
fn choose_colors( &mut self, _player: PlayerId, valid_colors: &[String], min: usize, max: usize, ) -> Vec<String>
Choose one or more colors.
Sourcefn choose_cards_for_effect(
&mut self,
_player: PlayerId,
valid: &[CardId],
_min: usize,
max: usize,
) -> Vec<CardId>
fn choose_cards_for_effect( &mut self, _player: PlayerId, valid: &[CardId], _min: usize, max: usize, ) -> Vec<CardId>
Choose cards for an effect (ChooseCardEffect, CloneEffect, etc.).
valid lists eligible card IDs, min/max are the selection bounds.
Default: pick up to max from the front of valid.
Sourcefn choose_tap_type_for_cost(
&mut self,
player: PlayerId,
valid: &[CardId],
_min_total_power: i32,
_card_powers: &[(CardId, i32)],
_card_sort_powers: &[(CardId, i32)],
_sa: Option<&SpellAbility>,
) -> Vec<CardId>
fn choose_tap_type_for_cost( &mut self, player: PlayerId, valid: &[CardId], _min_total_power: i32, _card_powers: &[(CardId, i32)], _card_sort_powers: &[(CardId, i32)], _sa: Option<&SpellAbility>, ) -> Vec<CardId>
Choose cards to tap for a tapXType cost that has a total-power floor
such as Crew. card_powers carries the effective tap-power value for
each candidate under the active ability; card_sort_powers carries the
normal net power value used by Forge’s deterministic cost plumbing when
ordering candidates.
Sourcefn choose_entities_for_effect(
&mut self,
_player: PlayerId,
candidates: &[GameEntity],
_min: usize,
max: usize,
) -> Vec<GameEntity>
fn choose_entities_for_effect( &mut self, _player: PlayerId, candidates: &[GameEntity], _min: usize, max: usize, ) -> Vec<GameEntity>
Choose game entities (players and/or permanents) for an effect like Proliferate.
Sourcefn choose_single_card_for_zone_change(
&mut self,
_game: &GameState,
player: PlayerId,
valid: &[CardId],
_select_prompt: &str,
_is_optional: bool,
) -> Option<CardId>
fn choose_single_card_for_zone_change( &mut self, _game: &GameState, player: PlayerId, valid: &[CardId], _select_prompt: &str, _is_optional: bool, ) -> Option<CardId>
Choose a single card for hidden-origin zone changes (e.g. library search).
Sourcefn choose_cards_for_zone_change(
&mut self,
_game: &GameState,
player: PlayerId,
valid: &[CardId],
min: usize,
max: usize,
_select_prompt: &str,
) -> Vec<CardId>
fn choose_cards_for_zone_change( &mut self, _game: &GameState, player: PlayerId, valid: &[CardId], min: usize, max: usize, _select_prompt: &str, ) -> Vec<CardId>
Choose multiple cards for hidden-origin zone changes (e.g. tutor multi-select).
Sourcefn choose_type(
&mut self,
_player: PlayerId,
_type_category: &str,
valid_types: &[String],
) -> Option<String>
fn choose_type( &mut self, _player: PlayerId, _type_category: &str, valid_types: &[String], ) -> Option<String>
Choose a creature/card type (for ChooseType effect).
type_category is “Creature”, “Card”, “Land”, etc.
valid_types lists the legal type choices.
Default: pick the first valid type.
Sourcefn choose_counter_type(
&mut self,
_player: PlayerId,
options: &[CounterType],
_prompt: &str,
) -> Option<CounterType>
fn choose_counter_type( &mut self, _player: PlayerId, options: &[CounterType], _prompt: &str, ) -> Option<CounterType>
Choose a counter type.
Sourcefn choose_card_name(
&mut self,
_player: PlayerId,
valid_names: &[String],
) -> Option<String>
fn choose_card_name( &mut self, _player: PlayerId, valid_names: &[String], ) -> Option<String>
Choose a card name (for NameCard effect).
valid_names lists the legal card name choices (for ChooseFromList mode).
Default: pick the first valid name.
Sourcefn choose_number(
&mut self,
_player: PlayerId,
_source: Option<CardId>,
_title: &str,
_description: Option<&str>,
min: i32,
_max: i32,
) -> Option<i32>
fn choose_number( &mut self, _player: PlayerId, _source: Option<CardId>, _title: &str, _description: Option<&str>, min: i32, _max: i32, ) -> Option<i32>
Choose a number within [min, max]. title/description present the
choice and source is the card driving it (shown in the prompt).
Default: pick the minimum.
Sourcefn choose_number_for_keyword_cost(
&mut self,
_player: PlayerId,
_max: i32,
_prompt: &str,
_source: Option<CardId>,
) -> i32
fn choose_number_for_keyword_cost( &mut self, _player: PlayerId, _max: i32, _prompt: &str, _source: Option<CardId>, ) -> i32
Choose how many times to pay an optional keyword cost. Default: decline optional keyword costs.
Sourcefn choose_number_from_list(
&mut self,
_player: PlayerId,
choices: &[i32],
_message: &str,
_source_card_id: Option<CardId>,
) -> Option<i32>
fn choose_number_from_list( &mut self, _player: PlayerId, choices: &[i32], _message: &str, _source_card_id: Option<CardId>, ) -> Option<i32>
Choose one number from an explicit list of legal rolled values.
Sourcefn choose_roll_to_ignore(
&mut self,
_player: PlayerId,
rolls: &[i32],
_source: Option<CardId>,
) -> Option<i32>
fn choose_roll_to_ignore( &mut self, _player: PlayerId, rolls: &[i32], _source: Option<CardId>, ) -> Option<i32>
Choose one die result from a rolled list to ignore.
Sourcefn choose_roll_to_swap(
&mut self,
_player: PlayerId,
rolls: &[i32],
_source: Option<CardId>,
) -> Option<i32>
fn choose_roll_to_swap( &mut self, _player: PlayerId, rolls: &[i32], _source: Option<CardId>, ) -> Option<i32>
Choose one rolled result to exchange with a card’s power or toughness.
Sourcefn choose_dice_to_reroll(
&mut self,
_player: PlayerId,
_rolls: &[i32],
_source: Option<CardId>,
) -> Vec<i32>
fn choose_dice_to_reroll( &mut self, _player: PlayerId, _rolls: &[i32], _source: Option<CardId>, ) -> Vec<i32>
Choose one or more dice to reroll from the current natural roll list.
Sourcefn choose_roll_to_modify(
&mut self,
_player: PlayerId,
rolls: &[i32],
_source: Option<CardId>,
) -> Option<i32>
fn choose_roll_to_modify( &mut self, _player: PlayerId, rolls: &[i32], _source: Option<CardId>, ) -> Option<i32>
Choose one rolled result to increment or decrement by 1.
Sourcefn choose_roll_swap_value(
&mut self,
_player: PlayerId,
_current_result: i32,
_power: i32,
_toughness: i32,
_source: Option<CardId>,
) -> Option<RollSwapChoice>
fn choose_roll_swap_value( &mut self, _player: PlayerId, _current_result: i32, _power: i32, _toughness: i32, _source: Option<CardId>, ) -> Option<RollSwapChoice>
Choose whether a swap should use power or toughness.
Sourcefn flip_coin_call(&mut self, _player: PlayerId) -> bool
fn flip_coin_call(&mut self, _player: PlayerId) -> bool
Choose heads or tails for a coin flip. Returns true for heads, false for tails. Default: always call heads.
Sourcefn choose_phyrexian_pay_life(
&mut self,
_player: PlayerId,
_color: &str,
_source: Option<CardId>,
) -> bool
fn choose_phyrexian_pay_life( &mut self, _player: PlayerId, _color: &str, _source: Option<CardId>, ) -> bool
Choose whether to pay life instead of mana for a Phyrexian mana shard. Returns true to pay 2 life, false to pay the color. Default: always pay color (never pay life).
Sourcefn pay_combat_cost(
&mut self,
_player: PlayerId,
_attacker: CardId,
_cost: i32,
_description: &str,
_mana_ability_options: &[ManaAbilityOption],
_tappable_lands: &[CardId],
_untappable_lands: &[CardId],
_mana_pool_total: i32,
) -> CombatCostAction
fn pay_combat_cost( &mut self, _player: PlayerId, _attacker: CardId, _cost: i32, _description: &str, _mana_ability_options: &[ManaAbilityOption], _tappable_lands: &[CardId], _untappable_lands: &[CardId], _mana_pool_total: i32, ) -> CombatCostAction
Pay an attack cost for a creature (Propaganda, Ghostly Prison). Called in a loop: tap lands to build mana, then Pay or Decline.
Sourcefn choose_delve(
&mut self,
_player: PlayerId,
valid: &[CardId],
max: usize,
_source: Option<CardId>,
) -> Vec<CardId>
fn choose_delve( &mut self, _player: PlayerId, valid: &[CardId], max: usize, _source: Option<CardId>, ) -> Vec<CardId>
Choose graveyard cards to exile for Delve (reduces generic cost).
valid lists graveyard card IDs, max is the maximum that can be exiled.
Default: exile max cards (maximize cost reduction). The interactive UI
resolves delve inside the mana-payment session, not via this callback.
Sourcefn choose_improvise(
&mut self,
_player: PlayerId,
_untapped_artifacts: &[CardId],
_remaining_cost: &ManaCost,
_source: Option<CardId>,
) -> Vec<CardId>
fn choose_improvise( &mut self, _player: PlayerId, _untapped_artifacts: &[CardId], _remaining_cost: &ManaCost, _source: Option<CardId>, ) -> Vec<CardId>
Choose artifacts to tap for Improvise (each pays {1} generic).
untapped_artifacts lists available artifacts to tap.
Default: don’t improvise (AI default — auto-tap handles mana).
Sourcefn choose_convoke(
&mut self,
_player: PlayerId,
_untapped_creatures: &[CardId],
_remaining_cost: &ManaCost,
_source: Option<CardId>,
) -> Vec<CardId>
fn choose_convoke( &mut self, _player: PlayerId, _untapped_creatures: &[CardId], _remaining_cost: &ManaCost, _source: Option<CardId>, ) -> Vec<CardId>
Choose creatures to tap for Convoke (each pays {1} or a matching colored mana).
untapped_creatures lists available creatures to tap.
Default: don’t convoke (AI default — auto-tap handles mana).
Sourcefn pay_mana_cost(
&mut self,
_player: PlayerId,
_card_id: CardId,
_card_name: &str,
_mana_cost: &str,
_mana_cost_display: &str,
_mana_cost_checkpoint: &str,
_can_confirm_from_pool: bool,
_allow_reserved_source_reuse: bool,
_reserved_sacrifices: &[CardId],
_mana_ability_options: &[ManaAbilityOption],
_tappable_lands: &[CardId],
_untappable_lands: &[CardId],
_mana_pool: &ManaPool,
) -> ManaCostAction
fn pay_mana_cost( &mut self, _player: PlayerId, _card_id: CardId, _card_name: &str, _mana_cost: &str, _mana_cost_display: &str, _mana_cost_checkpoint: &str, _can_confirm_from_pool: bool, _allow_reserved_source_reuse: bool, _reserved_sacrifices: &[CardId], _mana_ability_options: &[ManaAbilityOption], _tappable_lands: &[CardId], _untappable_lands: &[CardId], _mana_pool: &ManaPool, ) -> ManaCostAction
Pay a mana cost within a single payment session.
Called in a loop for manual interaction: tap lands to build mana, then
Pay { auto: false } or Cancel. Agents can also return
Pay { auto: true } to delegate the rest of the session to engine
auto-pay.
Default: always cancel.
Sourcefn await_display_ack(&mut self)
fn await_display_ack(&mut self)
Block until this agent acknowledges a display-only prompt that requires UI dwell time (e.g. dice roll animations). Default implementation is a no-op — only human-driven transports need to wait for an ack.
Used to make multi-agent broadcasts run their UI in parallel:
the broadcast loop dispatches the prompt to every agent in one
pass (so all clients receive it simultaneously), then a second
pass calls await_display_ack on each agent so the engine
blocks until the slowest player finishes their animation.
Sourcefn decide_cost_part(
&mut self,
_player: PlayerId,
_source: CardId,
_cost_part: &CostPart,
_game: &GameState,
) -> Option<PaymentDecision>
fn decide_cost_part( &mut self, _player: PlayerId, _source: CardId, _cost_part: &CostPart, _game: &GameState, ) -> Option<PaymentDecision>
Decide how to pay a single cost part.
Sourcefn pays_right_after_decision(&self) -> bool
fn pays_right_after_decision(&self) -> bool
Whether this agent pays each cost part immediately after deciding (true) or batches all decisions first, then pays (false).
Sourcefn order_cost_parts(&mut self, parts: Vec<CostPart>) -> Vec<CostPart>
fn order_cost_parts(&mut self, parts: Vec<CostPart>) -> Vec<CostPart>
Reorder cost parts before payment (for human players to choose payment order).
Sourcefn specify_mana_combo(
&mut self,
_player: PlayerId,
available_colors: &[String],
amount: usize,
_source: Option<CardId>,
_express_choice: Option<u16>,
) -> Vec<String>
fn specify_mana_combo( &mut self, _player: PlayerId, available_colors: &[String], amount: usize, _source: Option<CardId>, _express_choice: Option<u16>, ) -> Vec<String>
Specify mana color distribution for combo/any mana production.
available_colors lists which colors can be produced.
amount is the total mana to distribute across colors.
Returns a list of color letters (e.g. [“W”, “W”, “U”]) totaling amount.
Default: picks the color with least mana in pool for each unit (AI heuristic).
Sourcefn notify(&mut self, _event: GameNotification)
fn notify(&mut self, _event: GameNotification)
Receive engine notifications for UI/game-log observers. Default is a no-op so simple agents do not need to handle them.
Sourcefn choose_single_replacement_effect(
&mut self,
_player: PlayerId,
_descriptions: &[String],
) -> usize
fn choose_single_replacement_effect( &mut self, _player: PlayerId, _descriptions: &[String], ) -> usize
Choose which replacement effect to apply when multiple effects match the same event.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".