manabrew_engine/ability/effects/
tap_or_untap_all_effect.rs1use forge_foundation::ZoneType;
2
3use super::{matches_valid_cards_for_sa, resolve_defined_players, EffectContext};
4use crate::agent::BinaryChoiceKind;
5use crate::ids::{CardId, PlayerId};
6
7#[manabrew_engine_macros::spell_effect(TapOrUntapAllEffect)]
14fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
15 let controller = sa.activating_player;
16 let source_name = sa
17 .source
18 .map(|cid| ctx.game.card(cid).card_name.clone())
19 .unwrap_or_else(|| "Ability".to_string());
20
21 let prompt = "Tap or untap all matching permanents?";
22 let to_tap = ctx.agents[controller.index()].choose_binary(
23 controller,
24 prompt,
25 BinaryChoiceKind::TapOrUntap,
26 None,
27 sa.source,
28 sa.api,
29 );
30
31 let valid_filter = sa
32 .ir
33 .valid_cards_text
34 .as_deref()
35 .unwrap_or("Permanent")
36 .to_string();
37 let valid_selector = sa.ir.valid_cards_selector.as_ref();
38
39 let restrict_controllers: Option<Vec<PlayerId>> =
40 if let Some(pid) = sa.target_chosen.target_player {
41 Some(vec![pid])
42 } else if let Some(defined) = sa.ir.defined_text.as_deref() {
43 Some(resolve_defined_players(defined, controller, ctx.game))
44 } else {
45 None
46 };
47
48 let mut cards: Vec<CardId> = Vec::new();
49 for &pid in &ctx.game.player_order {
50 for cid in ctx
51 .game
52 .cards_in_zone(ZoneType::Battlefield, pid)
53 .iter()
54 .copied()
55 {
56 if let Some(ref allowed) = restrict_controllers {
57 if !allowed.contains(&ctx.game.card(cid).controller) {
58 continue;
59 }
60 }
61 if matches_valid_cards_for_sa(
62 ctx.game,
63 sa,
64 ctx.game.card(cid),
65 valid_selector,
66 &valid_filter,
67 ) {
68 cards.push(cid);
69 }
70 }
71 }
72
73 for cid in cards {
74 if ctx.game.card(cid).zone != ZoneType::Battlefield {
75 continue;
76 }
77 if to_tap {
78 if ctx.game.tap(cid) {
79 ctx.trigger_handler.run_trigger(
80 crate::trigger::TriggerType::Taps,
81 crate::event::RunParams {
82 card: Some(cid),
83 player: Some(controller),
84 ..Default::default()
85 },
86 false,
87 );
88 }
89 } else if ctx.game.untap(cid) {
90 ctx.trigger_handler.run_trigger(
91 crate::trigger::TriggerType::Untaps,
92 crate::event::RunParams {
93 card: Some(cid),
94 player: Some(controller),
95 ..Default::default()
96 },
97 false,
98 );
99 }
100 }
101}