manabrew_engine/ability/effects/
counters_put_or_remove_effect.rs1use forge_foundation::ZoneType;
2
3use super::{resolve_numeric_svar, EffectContext};
4use crate::agent::BinaryChoiceKind;
5use crate::parsing::keys;
6
7#[manabrew_engine_macros::spell_effect(CountersPutOrRemoveEffect)]
14fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
15 let Some(source_id) = sa.source else { return };
16 let controller = sa.activating_player;
17 let source_name = ctx.game.card(source_id).card_name.clone();
18
19 let amount = resolve_numeric_svar(ctx.game, sa, keys::COUNTER_NUM, 1);
20 if amount <= 0 {
21 return;
22 }
23
24 let target_id = sa.target_chosen.target_card.or(sa.source);
25 let Some(target_id) = target_id else { return };
26 if ctx.game.card(target_id).zone != ZoneType::Battlefield {
27 return;
28 }
29
30 let counter_type = sa.ir.counter_type.clone().or_else(|| {
31 let mut keys: Vec<_> = ctx.game.card(target_id).counters.keys().cloned().collect();
33 keys.sort_by(|a, b| format!("{:?}", a).cmp(&format!("{:?}", b)));
34 keys.into_iter().next()
35 });
36 let Some(counter_type) = counter_type else {
37 return;
38 };
39
40 let can_add =
41 !crate::staticability::static_ability_cant_put_counter::any_cant_put_counter_on_card(
42 &ctx.game.cards,
43 ctx.game.card(target_id),
44 &counter_type,
45 );
46 let can_remove = ctx.game.card(target_id).counter_count(&counter_type) > 0;
47 if !can_add && !can_remove {
48 return;
49 }
50
51 let put_counter = if can_add && can_remove {
52 let prompt = format!(
53 "Add or remove {:?} counter on {}?",
54 counter_type,
55 ctx.game.card(target_id).card_name
56 );
57 ctx.agents[controller.index()].choose_binary(
58 controller,
59 &prompt,
60 BinaryChoiceKind::AddOrRemove,
61 None,
62 Some(source_id),
63 sa.api,
64 )
65 } else {
66 can_add
67 };
68
69 if put_counter {
70 ctx.add_counter(
71 target_id,
72 &counter_type,
73 amount,
74 sa,
75 crate::event::RunParams {
76 source_player: Some(controller),
77 ..Default::default()
78 },
79 );
80 } else {
81 ctx.game
82 .card_mut(target_id)
83 .remove_counter(&counter_type, amount);
84 ctx.trigger_handler.run_trigger(
85 crate::trigger::TriggerType::CounterRemoved,
86 crate::event::RunParams {
87 card: Some(target_id),
88 counter_type: Some(format!("{:?}", counter_type)),
89 counter_amount: Some(amount),
90 cause_player: Some(controller),
91 ..Default::default()
92 },
93 false,
94 );
95 if sa.ir.remember_removed_cards {
96 ctx.game.card_mut(source_id).add_remembered_card(target_id);
97 }
98 }
99}