manabrew_engine/ability/effects/
explore_effect.rs1use forge_foundation::ZoneType;
2
3use super::{emit_zone_trigger, EffectContext};
4use crate::ability::ability_ir::DefinedRef;
5use crate::card::CounterType;
6use crate::event::RunParams;
7use crate::parsing::keys;
8use crate::replacement::replacement_handler::{apply_replacements, ReplacementEvent};
9use crate::replacement::ReplacementResult;
10use crate::trigger::TriggerType;
11
12#[manabrew_engine_macros::spell_effect(ExploreEffect)]
28fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
29 let controller = sa.activating_player;
30
31 let explorer = sa
33 .target_chosen
34 .target_card
35 .or_else(|| match sa.defined_ref() {
36 Some(DefinedRef::SelfCard) => sa.source,
37 Some(DefinedRef::ParentTarget) => ctx.parent_target_card,
38 _ => sa.source,
39 });
40
41 let explorer_id = match explorer {
42 Some(id) if ctx.game.card(id).zone == ZoneType::Battlefield => id,
43 _ => return,
44 };
45
46 let mut event = ReplacementEvent::Explore { card: explorer_id };
48 let result = apply_replacements(ctx.game, &mut event);
49 if result == ReplacementResult::Skipped || result == ReplacementResult::Replaced {
50 return;
51 }
52
53 let amount = super::resolve_numeric_svar(ctx.game, sa, keys::NUM, 1).max(1);
56
57 for _ in 0..amount {
58 if ctx.game.card(explorer_id).zone != ZoneType::Battlefield {
60 return;
61 }
62 ctx.game.player_record_explore(controller, 1);
63
64 let lib = ctx.game.cards_in_zone(ZoneType::Library, controller);
66 if lib.is_empty() {
67 if !crate::staticability::static_ability_cant_put_counter::any_cant_put_counter_on_card(
69 &ctx.game.cards,
70 ctx.game.card(explorer_id),
71 &CounterType::P1P1,
72 ) {
73 ctx.game
74 .card_mut(explorer_id)
75 .add_counter(&CounterType::P1P1, 1);
76 }
77 ctx.trigger_handler.run_trigger(
78 TriggerType::CounterAdded,
79 RunParams {
80 card: Some(explorer_id),
81 counter_type: Some("P1P1".to_string()),
82 counter_amount: Some(1),
83 ..Default::default()
84 },
85 false,
86 );
87 continue;
88 }
89
90 let top_card = *lib.last().unwrap();
92
93 let is_land = ctx.game.card(top_card).is_land();
94
95 if is_land {
96 let owner = ctx.game.card(top_card).owner;
98 ctx.move_card(top_card, ZoneType::Hand, owner);
99 emit_zone_trigger(
100 ctx.trigger_handler,
101 top_card,
102 ZoneType::Library,
103 ZoneType::Hand,
104 );
105 } else {
106 if !crate::staticability::static_ability_cant_put_counter::any_cant_put_counter_on_card(
108 &ctx.game.cards,
109 ctx.game.card(explorer_id),
110 &CounterType::P1P1,
111 ) {
112 ctx.game
113 .card_mut(explorer_id)
114 .add_counter(&CounterType::P1P1, 1);
115 }
116 ctx.trigger_handler.run_trigger(
117 TriggerType::CounterAdded,
118 RunParams {
119 card: Some(explorer_id),
120 counter_type: Some("P1P1".to_string()),
121 counter_amount: Some(1),
122 ..Default::default()
123 },
124 false,
125 );
126
127 let card_name = ctx.game.card(top_card).card_name.clone();
132 let explorer_name = ctx.game.card(explorer_id).card_name.clone();
133 let msg = format!("Put {} into your graveyard?", card_name);
134 let put_in_gy = ctx.agents[controller.index()].confirm_action(
135 controller,
136 None,
137 &msg,
138 &[],
139 sa.source,
140 Some(crate::ability::api_type::ApiType::Explore),
141 );
142
143 if put_in_gy {
144 let owner = ctx.game.card(top_card).owner;
145 ctx.move_card(top_card, ZoneType::Graveyard, owner);
146 emit_zone_trigger(
147 ctx.trigger_handler,
148 top_card,
149 ZoneType::Library,
150 ZoneType::Graveyard,
151 );
152 }
153 }
154 ctx.trigger_handler.run_trigger(
155 TriggerType::Explored,
156 RunParams {
157 card: Some(explorer_id),
158 explored: Some(top_card),
159 ..Default::default()
160 },
161 false,
162 );
163 }
164}