Skip to main content

CombatState

Struct CombatState 

Source
pub struct CombatState {
    pub attacking_player: Option<PlayerId>,
    pub defending_player: Option<PlayerId>,
    pub attackers: Vec<(CardId, DefenderId)>,
    pub attacker_zone_timestamps: HashMap<CardId, u64>,
    pub blockers: Vec<(CardId, CardId)>,
    pub blocked_attackers: HashSet<CardId>,
    pub blocker_zone_timestamps: HashMap<CardId, u64>,
    pub damage_order: HashMap<CardId, Vec<CardId>>,
    pub lki_cache: HashMap<CardId, CombatLki>,
}
Expand description

Tracks combat state for the current combat phase.

Fields§

§attacking_player: Option<PlayerId>

Attacking player.

§defending_player: Option<PlayerId>

Defending player.

§attackers: Vec<(CardId, DefenderId)>

(attacker CardId, defender — player or permanent)

§attacker_zone_timestamps: HashMap<CardId, u64>

Zone timestamp of each attacker at declare-attackers time.

§blockers: Vec<(CardId, CardId)>

(blocker CardId, attacker CardId)

§blocked_attackers: HashSet<CardId>

Attackers that became blocked at any point this combat, even if blockers later left combat before damage.

§blocker_zone_timestamps: HashMap<CardId, u64>

Zone timestamp of each blocker at declare-blockers time.

§damage_order: HashMap<CardId, Vec<CardId>>

Damage assignment order: attacker → ordered list of blockers. The attacker must assign lethal to each blocker in order before moving to the next. Set after blocker declaration.

§lki_cache: HashMap<CardId, CombatLki>

Last-known-information cache: snapshots of creatures that left combat. Persists until combat ends (cleared in clear()).

Implementations§

Source§

impl CombatState

Source

pub fn new() -> Self

Source

pub fn clear(&mut self)

Source

pub fn clear_with_cards(&mut self, cards: &mut [Card])

Clear combat state, including the attacking_player flag on each attacker card.

Source

pub fn declare_attacker( &mut self, attacker: CardId, defending: DefenderId, zone_timestamp: u64, )

Source

pub fn declare_blocker( &mut self, blocker: CardId, attacker: CardId, zone_timestamp: u64, )

Source

pub fn is_attacking(&self, card: CardId) -> bool

Source

pub fn is_blocked(&self, attacker: CardId) -> bool

Source

pub fn was_blocked_this_combat(&self, attacker: CardId) -> bool

True if attacker was blocked at any time this combat.

Source

pub fn get_blockers_for(&self, attacker: CardId) -> Vec<CardId>

Source

pub fn get_attackers_for(&self, blocker: CardId) -> Vec<CardId>

Source

pub fn has_attackers(&self) -> bool

Source

pub fn save_lki(&mut self, card_id: CardId) -> Option<CombatLki>

Snapshot a creature’s combat role before it leaves the battlefield.

Source

pub fn get_combat_lki(&self, card_id: CardId) -> Option<&CombatLki>

Get LKI for a creature that left combat.

Source

pub fn was_attacking(&self, card_id: CardId) -> bool

Check if a creature was (or is) attacking in this combat.

Source

pub fn was_blocking(&self, card_id: CardId) -> bool

Check if a creature was (or is) blocking in this combat.

Source

pub fn remove_absent_combatants(&mut self, cards: &[Card]) -> bool

Remove attackers/blockers that are no longer on the battlefield or are no longer creatures. Also cleans up damage_order keys. Returns true if any combatant was removed.

Mirrors Java Forge’s Combat.removeAbsentCombatants().

Source

pub fn has_first_strikers(&self, game: &GameState) -> bool

Check if any creature in combat has first strike or double strike.

Source

pub fn resolve_damage_step( &self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], first_strike_only: bool, as_unblocked_choices: &HashSet<CardId>, ) -> Vec<CombatDamageEvent>

Resolve one step of combat damage. If first_strike_only is true, only first-strike and double-strike creatures deal damage. If false, only non-first-strike and double-strike creatures deal damage. Returns a Vec of CombatDamageEvents so the caller can fire triggers.

Source

pub fn init_constraints(&self, game: &GameState) -> AttackConstraints

Initialize attack constraints for this combat. Mirrors Java Combat.initConstraints().

Source

pub fn end_combat(&mut self, game: &mut GameState)

End combat: clear all combat state and reset damage history on battlefield creatures. Mirrors Java Combat.endCombat().

Source

pub fn clear_attackers(&mut self, game: &mut GameState)

Remove all attacker registrations. Mirrors Java Combat.clearAttackers().

Source

pub fn add_attacker(&mut self, attacker: CardId, defender: DefenderId)

Add an attacker to combat, targeting a defender. Mirrors Java Combat.addAttacker().

Source

pub fn add_blocker(&mut self, attacker: CardId, blocker: CardId)

Add a blocker assignment. Mirrors Java Combat.addBlocker().

Source

pub fn remove_block_assignment(&mut self, attacker: CardId, blocker: CardId)

Remove a specific blocker from a specific attacker. Mirrors Java Combat.removeBlockAssignment().

Source

pub fn undo_blocking_assignment(&mut self, blocker: CardId)

Remove a blocker from all attacker assignments. Mirrors Java Combat.undoBlockingAssignment().

Source

pub fn order_blockers_for_damage_assignment( &mut self, _game: &GameState, _agents: &mut [Box<dyn PlayerAgent>], )

Order blockers for damage assignment. For each attacker, store the blocker order. If only one blocker, auto-assign. Mirrors Java Combat.orderBlockersForDamageAssignment()Combat.java:494 short-circuits the agent prompt when GameRules.legacyOrderCombatants is false (default), so the deterministic parity harness never sees this callback. Mirror that.

Source

pub fn add_blocker_to_damage_assignment_order( &mut self, attacker: CardId, blocker: CardId, )

Add a late-entry blocker to an existing damage assignment order. Mirrors Java Combat.addBlockerToDamageAssignmentOrder().

Source

pub fn order_attackers_for_damage_assignment( &mut self, _game: &GameState, _agents: &mut [Box<dyn PlayerAgent>], )

Order attackers for damage assignment (blocker’s controller orders). Mirrors Java Combat.orderAttackersForDamageAssignment().

Source

pub fn unregister_attacker(&mut self, card: CardId)

Remove an attacker from combat, cleaning up all indices. Mirrors Java Combat.unregisterAttacker().

Source

pub fn unregister_defender(&mut self, card: CardId)

Remove a blocker from combat, cleaning up all indices. Mirrors Java Combat.unregisterDefender().

Source

pub fn remove_from_combat(&mut self, card: CardId, game: &mut GameState)

Remove a combatant (attacker or blocker) from combat. Mirrors Java Combat.removeFromCombat().

Source

pub fn fire_triggers_for_unblocked_attackers( &mut self, ) -> Vec<(CardId, DefenderId)>

Fire triggers for unblocked attackers after blockers are declared. Mirrors Java Combat.fireTriggersForUnblockedAttackers().

Returns the list of unblocked attacker IDs (for use by the game loop to fire TriggerType::AttackerUnblocked).

Source

pub fn assign_combat_damage( &self, game: &mut GameState, agents: &mut [Box<dyn PlayerAgent>], first_strike_damage: bool, as_unblocked_choices: &HashSet<CardId>, ) -> Vec<CombatDamageEvent>

Assign combat damage (delegates to resolve_damage_step). Mirrors Java Combat.assignCombatDamage().

Source

pub fn deal_assigned_damage(&self, game: &mut GameState)

Deal assigned damage (no-op in our architecture since resolve_damage_step applies damage immediately). Mirrors Java Combat.dealAssignedDamage().

Source

pub fn get_attackers(&self) -> Vec<CardId>

Get all attacker IDs.

Source

pub fn get_all_blockers(&self) -> Vec<CardId>

Get all blocker IDs (deduplicated).

Source

pub fn get_defender_by_attacker(&self, attacker: CardId) -> Option<DefenderId>

Get the defender for an attacker.

Source

pub fn get_defender_player_by_attacker( &self, attacker: CardId, game: &GameState, ) -> Option<PlayerId>

Get the defending player for an attacker (resolves planeswalker/battle defenders to their controller).

Source

pub fn is_blocking(&self, blocker: CardId) -> bool

Check if a card is currently blocking.

Source

pub fn is_blocking_attacker(&self, blocker: CardId, attacker: CardId) -> bool

Check if a card is blocking a specific attacker.

Source

pub fn is_unblocked(&self, attacker: CardId) -> bool

Check if an attacker is unblocked (declared, blockers declared, but none assigned).

Source

pub fn get_unblocked_attackers(&self) -> Vec<CardId>

Get all unblocked attacker IDs.

Trait Implementations§

Source§

impl Clone for CombatState

Source§

fn clone(&self) -> CombatState

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for CombatState

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for CombatState

Source§

fn default() -> CombatState

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for CombatState

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for CombatState

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<F, W, T, D> Deserialize<With<T, W>, D> for F
where W: DeserializeWith<F, T, D>, D: Fallible + ?Sized, F: ?Sized,

Source§

fn deserialize( &self, deserializer: &mut D, ) -> Result<With<T, W>, <D as Fallible>::Error>

Deserializes using the given deserializer
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Gets the layout of the type.
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The type for metadata in pointers and references to Self.
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V