Skip to main content

manabrew_engine/ability/effects/
counters_remove_all_effect.rs

1//! CountersRemoveAll effect — remove all counters of a type from permanents.
2//!
3//! Ported from Java's `CountersRemoveAllEffect.java`.
4
5use super::{parse_counter_type, EffectContext};
6use crate::card::valid_filter;
7use forge_foundation::ZoneType;
8
9/// Struct form of this effect so it can participate in the
10/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
11/// `CountersRemoveAllEffect` class extending `SpellAbilityEffect`.
12#[manabrew_engine_macros::spell_effect(CountersRemoveAllEffect)]
13fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
14    let counter_type_str = sa
15        .ir
16        .counter_type_text
17        .clone()
18        .unwrap_or_else(|| "P1P1".to_string());
19    let counter_type = parse_counter_type(&counter_type_str);
20
21    let targets: Vec<crate::ids::CardId> = if sa.uses_targeting() {
22        sa.target_chosen.target_card.into_iter().collect()
23    } else {
24        // Remove from all permanents matching ValidCard$.
25        let valid = sa.valid_card();
26        let source = sa.source.map(|id| ctx.game.card(id));
27        ctx.game
28            .cards
29            .iter()
30            .filter(|c| {
31                c.zone == ZoneType::Battlefield
32                    && source.is_none_or(|source| {
33                        valid_filter::matches_valid_card_selector_opt_in_game(
34                            valid, c, source, ctx.game,
35                        )
36                    })
37            })
38            .map(|c| c.id)
39            .collect()
40    };
41
42    for card_id in targets {
43        let current = *ctx
44            .game
45            .card(card_id)
46            .counters
47            .get(&counter_type)
48            .unwrap_or(&0);
49        if current > 0 {
50            ctx.game
51                .card_mut(card_id)
52                .remove_counter(&counter_type, current);
53        }
54    }
55}