Skip to main content

manabrew_engine/staticability/
static_ability_mana_convert.rs

1use forge_foundation::ZoneType;
2
3use crate::card::{valid_filter, Card};
4use crate::ids::PlayerId;
5use crate::staticability::StaticMode;
6
7/// Check if a player can spend mana as though it were any color/type
8/// when casting a particular spell.
9///
10/// Mirrors Java's `StaticAbilityManaConvert.manaConvert()`.
11///
12/// Returns true if any active ManaConvert static on the battlefield allows
13/// the player to spend mana freely for the given card.
14pub fn can_spend_mana_as_any_color(cards: &[Card], player: PlayerId, spell_card: &Card) -> bool {
15    for source in cards
16        .iter()
17        .filter(|c| c.zone == ZoneType::Battlefield || c.zone == ZoneType::Command)
18    {
19        for st_ab in source
20            .static_abilities
21            .iter()
22            .filter(|sa| sa.check_mode(&StaticMode::ManaConvert))
23        {
24            // Check ValidPlayer$
25            if !valid_filter::matches_valid_player_selector_opt(
26                st_ab.ir.valid_player.as_ref(),
27                player,
28                source.controller,
29            ) {
30                continue;
31            }
32
33            // Check ValidCard$ (what spell this applies to)
34            if !valid_filter::matches_valid_card_selector_opt(
35                st_ab.ir.valid_card.as_ref(),
36                spell_card,
37                source,
38            ) {
39                continue;
40            }
41
42            // Check ManaConversion$ — we support the dominant pattern
43            if let Some(conversion) = st_ab.ir.mana_conversion.as_deref() {
44                if conversion.contains("AnyColor") || conversion.contains("AnyType") {
45                    return true;
46                }
47            }
48        }
49    }
50    false
51}
52
53pub fn mana_convert(cards: &[Card], player: PlayerId, spell_card: &Card) -> bool {
54    can_spend_mana_as_any_color(cards, player, spell_card)
55}
56
57pub fn check_mana_convert(
58    st_ab: &crate::staticability::StaticAbility,
59    source: &Card,
60    player: PlayerId,
61    spell_card: &Card,
62) -> bool {
63    if !valid_filter::matches_valid_player_selector_opt(
64        st_ab.ir.valid_player.as_ref(),
65        player,
66        source.controller,
67    ) {
68        return false;
69    }
70    if !valid_filter::matches_valid_card_selector_opt(
71        st_ab.ir.valid_card.as_ref(),
72        spell_card,
73        source,
74    ) {
75        return false;
76    }
77    st_ab
78        .ir
79        .mana_conversion
80        .as_deref()
81        .is_some_and(|conversion| conversion.contains("AnyColor") || conversion.contains("AnyType"))
82}