pub struct ManaPool {
pub total_sources: Option<i32>,
pub source_colors: Option<Vec<u16>>,
pub color_matrix: ManaConversionMatrix,
/* private fields */
}Expand description
Tracks available mana for a player during a turn. Uses individual Mana objects to support source tracking, snow, and future restrictions.
Fields§
§total_sources: Option<i32>When set, caps total producible mana for playability checks.
Used by calculate_available_mana to prevent multi-color sources
(dual lands, Command Tower) from being counted as multiple mana.
source_colors: Option<Vec<u16>>Per-source color bitmasks for source-level matching in can_pay.
Each entry is a bitmask of ManaAtom colors that one mana source can produce.
Used by calculate_available_mana to prevent dual lands from satisfying
multiple colored requirements simultaneously.
color_matrix: ManaConversionMatrixMana conversion/restriction matrix controlling what colors can pay for what.
Mirrors Java’s ManaPool inheriting from ManaConversionMatrix.
Implementations§
Source§impl ManaPool
impl ManaPool
pub fn new() -> Self
pub fn clear_last_payment_atoms(&mut self)
pub fn last_payment_atoms(&self) -> &[u16]
Sourcepub fn restore_color_replacements(&mut self)
pub fn restore_color_replacements(&mut self)
Reset the color conversion matrix to identity.
Mirrors Java’s ManaPool.restoreColorReplacements().
Sourcepub fn apply_card_matrix(&mut self, other: &ManaConversionMatrix)
pub fn apply_card_matrix(&mut self, other: &ManaConversionMatrix)
Merge another matrix into this pool’s matrix.
Mirrors Java’s ManaPool.applyCardMatrix(ManaConversionMatrix).
pub fn add(&mut self, atom: u16, amount: i32)
Sourcepub fn add_snow(&mut self, atom: u16, amount: i32)
pub fn add_snow(&mut self, atom: u16, amount: i32)
Add mana with snow flag set (from a snow permanent source).
Sourcepub fn add_restricted(&mut self, atom: u16, restriction: String)
pub fn add_restricted(&mut self, atom: u16, restriction: String)
Add mana with a restriction (from RestrictValid$).
Sourcepub fn count_uncounterable(&self) -> i32
pub fn count_uncounterable(&self) -> i32
Count mana in pool that has the “can’t be countered” flag.
Sourcepub fn collect_keyword_mana(&self) -> Vec<(String, Option<String>)>
pub fn collect_keyword_mana(&self) -> Vec<(String, Option<String>)>
Collect keywords that should be added to a spell based on consumed mana. Call this before and after payment to diff.
Sourcepub fn collect_counter_mana(&self) -> Vec<(String, Option<String>)>
pub fn collect_counter_mana(&self) -> Vec<(String, Option<String>)>
Collect counter specs from mana that should be applied to permanents cast with it.
Sourcepub fn collect_trigger_mana(&self) -> Vec<(String, CardId)>
pub fn collect_trigger_mana(&self) -> Vec<(String, CardId)>
Collect trigger SVars from mana that should fire when spent. Returns (svar_name, source_card_id) pairs.
Sourcepub fn mana_colors(&self) -> Vec<u16>
pub fn mana_colors(&self) -> Vec<u16>
Get the color of each mana in the pool (for tracking consumed colors).
pub fn mana_entries(&self) -> &[Mana]
Sourcepub fn colors_present(&self) -> u16
pub fn colors_present(&self) -> u16
Get a bitmask of all colors present in the pool.
Sourcepub fn count_snow(&self) -> i32
pub fn count_snow(&self) -> i32
Count snow mana in the pool (any color).
pub fn add_mana(&mut self, m: Mana)
Sourcepub fn total_mana(&self) -> i32
pub fn total_mana(&self) -> i32
Total floating mana count.
Mirrors Java’s ManaPool.totalMana().
pub fn count_color(&self, atom: u16) -> i32
pub fn white(&self) -> i32
pub fn blue(&self) -> i32
pub fn black(&self) -> i32
pub fn red(&self) -> i32
pub fn green(&self) -> i32
pub fn colorless(&self) -> i32
Sourcepub fn remove(&mut self, atom: u16, amount: i32)
pub fn remove(&mut self, atom: u16, amount: i32)
Remove amount of a given mana atom from the pool, saturating at 0.
Sourcepub fn has_atom(&self, atom: u16, amount: i32) -> bool
pub fn has_atom(&self, atom: u16, amount: i32) -> bool
Returns true if the pool contains at least amount of the given atom.
Sourcepub fn spend_generic(&mut self, amount: i32) -> i32
pub fn spend_generic(&mut self, amount: i32) -> i32
Spend generic mana from the pool, consuming colorless first then any color. Returns the amount actually spent.
Sourcepub fn reset_pool(&mut self)
pub fn reset_pool(&mut self)
Reset the pool completely (empties all floating mana).
Mirrors Java’s ManaPool.resetPool().
Sourcepub fn clear_pool(&mut self, phase: PhaseType) -> usize
pub fn clear_pool(&mut self, phase: PhaseType) -> usize
Clear mana pool at phase transitions, retaining persistent and combat mana. Mirrors Java’s PhaseHandler.onPhaseEnd() → clearPool(true) (MTG rule 500.4).
Sourcepub fn clear_pool_with_keep(
&mut self,
phase: PhaseType,
keep_colors: u16,
) -> usize
pub fn clear_pool_with_keep( &mut self, phase: PhaseType, keep_colors: u16, ) -> usize
Clear the mana pool, retaining persistent mana, combat mana (if in combat),
and mana of colors specified by keep_colors bitmask (from UnspentMana statics).
Returns the number of mana cleared (for mana burn calculation).
Sourcepub fn can_pay(&self, cost: &ManaCost) -> bool
pub fn can_pay(&self, cost: &ManaCost) -> bool
Try to pay a mana cost. Returns true if successful and deducts the mana. This is a simplified payment algorithm that handles colored and generic mana.
Sourcepub fn can_pay_any_color(&self, cost: &ManaCost) -> bool
pub fn can_pay_any_color(&self, cost: &ManaCost) -> bool
Check if the pool can pay a cost with any-color conversion active.
Sourcepub fn can_pay_for_spell(
&self,
cost: &ManaCost,
ctx: &ManaPaymentContext,
) -> bool
pub fn can_pay_for_spell( &self, cost: &ManaCost, ctx: &ManaPaymentContext, ) -> bool
Check if pool can pay a cost, respecting mana restrictions for the given spell context.
Sourcepub fn try_pay_for_spell(
&mut self,
cost: &ManaCost,
ctx: &ManaPaymentContext,
) -> bool
pub fn try_pay_for_spell( &mut self, cost: &ManaCost, ctx: &ManaPaymentContext, ) -> bool
Pay a cost, skipping restricted mana that doesn’t match the context. Returns true if successful and deducts the mana from the ORIGINAL pool.
Sourcepub fn try_pay_for_spell_converted(
&mut self,
cost: &ManaCost,
ctx: &ManaPaymentContext,
any_color: bool,
) -> bool
pub fn try_pay_for_spell_converted( &mut self, cost: &ManaCost, ctx: &ManaPaymentContext, any_color: bool, ) -> bool
Pay a cost with restriction filtering and optional any-color conversion.
Sourcepub fn try_pay_for_spell_converted_with_phyrexian_life(
&mut self,
cost: &ManaCost,
ctx: &ManaPaymentContext,
any_color: bool,
player_life: i32,
) -> Option<i32>
pub fn try_pay_for_spell_converted_with_phyrexian_life( &mut self, cost: &ManaCost, ctx: &ManaPaymentContext, any_color: bool, player_life: i32, ) -> Option<i32>
Pay a spell cost with restriction filtering and phyrexian-life fallback.
Returns the life that must be paid after mana is deducted, or None if
the cost cannot be covered by the current pool plus phyrexian life.
pub fn try_pay_for_spell_converted_with_phyrexian_life_result( &mut self, cost: &ManaCost, ctx: &ManaPaymentContext, any_color: bool, player_life: i32, ) -> Option<ManaPaymentOutcome>
Sourcepub fn try_pay_cost_with_phyrexian_life(
&mut self,
cost: &ManaCost,
any_color: bool,
player_life: i32,
) -> Option<i32>
pub fn try_pay_cost_with_phyrexian_life( &mut self, cost: &ManaCost, any_color: bool, player_life: i32, ) -> Option<i32>
Pay a mana cost with phyrexian-life fallback and return the life paid. Used for generic cost payments that don’t need spell restriction filtering.
Sourcepub fn can_pay_with_extra_generic(
&self,
cost: &ManaCost,
extra_generic: i32,
) -> bool
pub fn can_pay_with_extra_generic( &self, cost: &ManaCost, extra_generic: i32, ) -> bool
Returns true if the pool can pay cost plus extra_generic additional generic mana.
Used for commander tax checks.
Sourcepub fn can_pay_with_phyrexian_life(
&self,
cost: &ManaCost,
player_life: i32,
) -> bool
pub fn can_pay_with_phyrexian_life( &self, cost: &ManaCost, player_life: i32, ) -> bool
Check if a cost with phyrexian shards can be paid, allowing phyrexian shards to fall back to life payment (2 life each) when no mana source is available.
Matches Java’s ComputerUtilMana.payManaCost() greedy simulation:
- Try to match phyrexian shards with mana sources (highest priority)
- Unmatched phyrexian shards are paid with life
- Non-phyrexian colored shards must be matched with remaining sources
- Generic cost must be covered by remaining sources
Sourcepub fn try_pay_extra_generic(&mut self, extra_generic: i32) -> bool
pub fn try_pay_extra_generic(&mut self, extra_generic: i32) -> bool
Pay extra_generic additional generic mana from the pool.
Returns true if successful.
Sourcepub fn try_pay(&mut self, cost: &ManaCost) -> bool
pub fn try_pay(&mut self, cost: &ManaCost) -> bool
Try to pay a mana cost, deducting from the pool. Returns true if successful.
Sourcepub fn try_pay_any_color(&mut self, cost: &ManaCost) -> bool
pub fn try_pay_any_color(&mut self, cost: &ManaCost) -> bool
Try to pay a mana cost with any-color conversion active. All colored mana can pay for any colored shard.
pub fn pay_color(&mut self, atoms: u16) -> bool
pub fn pay_generic(&mut self, amount: i32)
Sourcepub fn will_mana_be_lost_at_end_of_phase(&self) -> bool
pub fn will_mana_be_lost_at_end_of_phase(&self) -> bool
Whether floating mana will be lost at end of phase.
Mirrors Java’s ManaPool.willManaBeLostAtEndOfPhase().
Sourcepub fn has_burn(&self) -> bool
pub fn has_burn(&self) -> bool
Whether the game has mana burn rules active.
Mirrors Java’s ManaPool.hasBurn().
Sourcepub fn remove_mana(&mut self, mana: &Mana) -> bool
pub fn remove_mana(&mut self, mana: &Mana) -> bool
Remove a specific Mana object from the pool.
Mirrors Java’s ManaPool.removeMana(Mana).
Sourcepub fn pay_mana_from_ability(&mut self, produced_color: u16, amount: i32)
pub fn pay_mana_from_ability(&mut self, produced_color: u16, amount: i32)
Pay mana cost using mana produced by a mana ability.
Mirrors Java’s ManaPool.payManaFromAbility().
Sourcepub fn try_pay_cost_with_color(&mut self, color: u16) -> bool
pub fn try_pay_cost_with_color(&mut self, color: u16) -> bool
Try to pay a cost shard using floating mana of a specific color.
Mirrors Java’s ManaPool.tryPayCostWithColor().
Sourcepub fn try_pay_cost_with_mana(&mut self, mana: &Mana) -> bool
pub fn try_pay_cost_with_mana(&mut self, mana: &Mana) -> bool
Try to pay with a specific Mana object.
Mirrors Java’s ManaPool.tryPayCostWithMana().
Sourcepub fn account_for(&self, color: u16) -> bool
pub fn account_for(&self, color: u16) -> bool
Account for mana produced by a mana ability (verify it’s in the pool).
Mirrors Java’s ManaPool.accountFor().
Sourcepub fn refund_mana(&mut self, mana_spent: &mut Vec<Mana>)
pub fn refund_mana(&mut self, mana_spent: &mut Vec<Mana>)
Refund mana back to the pool.
Mirrors Java’s ManaPool.refundMana().
Sourcepub fn can_pay_for_shard_with_color(
&self,
shard_color: u16,
pay_color: u16,
) -> bool
pub fn can_pay_for_shard_with_color( &self, shard_color: u16, pay_color: u16, ) -> bool
Check if a mana cost shard can be paid by a given color.
Mirrors Java’s ManaPool.canPayForShardWithColor().
Sourcepub fn pay_mana_cost_from_pool(&mut self, cost: &ManaCost) -> bool
pub fn pay_mana_cost_from_pool(&mut self, cost: &ManaCost) -> bool
Pay an entire mana cost from floating mana.
Mirrors Java’s ManaPool.payManaCostFromPool().
Sourcepub fn take_last_payment_triggers_consumed(&mut self) -> Vec<(String, CardId)>
pub fn take_last_payment_triggers_consumed(&mut self) -> Vec<(String, CardId)>
Drain and return the trigger metadata recorded by the most recent
try_pay* call that consumed mana whose source set
TriggersWhenSpent$.
Sourcepub fn try_pay_with_phyrexian_life_unrestricted(
&mut self,
cost: &ManaCost,
player_life: i32,
) -> Option<i32>
pub fn try_pay_with_phyrexian_life_unrestricted( &mut self, cost: &ManaCost, player_life: i32, ) -> Option<i32>
Pay a non-spell cost with phyrexian-life fallback.
Unlike try_pay_for_spell_converted_with_phyrexian_life, this does not
filter mana by spell restriction context first.
Sourcepub fn iterator(&self) -> impl Iterator<Item = &Mana>
pub fn iterator(&self) -> impl Iterator<Item = &Mana>
Iterator over all floating mana.
Mirrors Java’s ManaPool.iterator().
Sourcepub fn begin_tap_tracking(&self) -> Vec<u16>
pub fn begin_tap_tracking(&self) -> Vec<u16>
Snapshot the pool state before a land tap. Call this BEFORE producing mana.
Returns a snapshot (list of mana colors) that end_tap_tracking will diff against.
Sourcepub fn end_tap_tracking(&self, pool_before: &[u16]) -> Vec<u16>
pub fn end_tap_tracking(&self, pool_before: &[u16]) -> Vec<u16>
Compute what mana was produced since begin_tap_tracking was called.
Returns the list of mana atoms that were added to the pool.
Sourcepub fn rollback_tap(&mut self, produced: &[u16])
pub fn rollback_tap(&mut self, produced: &[u16])
Remove the exact mana that was produced by a previous tap. Used for mana rollback (untap) — removes ALL mana from that tap, including base production, aura triggers, static doublers, etc.
Sourcepub fn produce_mana_from_string(
&mut self,
mana_string: &str,
source_card: Option<CardId>,
is_snow: bool,
restriction: Option<String>,
adds_no_counter: bool,
adds_keywords: Option<String>,
adds_keywords_valid: Option<String>,
adds_counters: Option<String>,
adds_counters_valid: Option<String>,
triggers_when_spent: Option<String>,
)
pub fn produce_mana_from_string( &mut self, mana_string: &str, source_card: Option<CardId>, is_snow: bool, restriction: Option<String>, adds_no_counter: bool, adds_keywords: Option<String>, adds_keywords_valid: Option<String>, adds_counters: Option<String>, adds_counters_valid: Option<String>, triggers_when_spent: Option<String>, )
Produce mana from a mana string (e.g. “W”, “U U”, “R G”) and add to pool. Handles source tracking, snow, restrictions, keywords, counters, triggers. This is the core mana production logic — the single source of truth.
Call this from game_action.rs::resolve_mana_ability after determining what mana string to produce.
Sourcepub fn atom_to_letter(atom: u16) -> &'static str
pub fn atom_to_letter(atom: u16) -> &'static str
Convert a ManaAtom to its short letter string.