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.add_counter(explorer_id, &CounterType::P1P1, 1, sa, RunParams::default());
74 }
75 continue;
76 }
77
78 let top_card = *lib.last().unwrap();
80
81 let is_land = ctx.game.card(top_card).is_land();
82
83 if is_land {
84 let owner = ctx.game.card(top_card).owner;
86 ctx.move_card(top_card, ZoneType::Hand, owner);
87 emit_zone_trigger(
88 ctx.trigger_handler,
89 top_card,
90 ZoneType::Library,
91 ZoneType::Hand,
92 );
93 } else {
94 if !crate::staticability::static_ability_cant_put_counter::any_cant_put_counter_on_card(
96 &ctx.game.cards,
97 ctx.game.card(explorer_id),
98 &CounterType::P1P1,
99 ) {
100 ctx.add_counter(explorer_id, &CounterType::P1P1, 1, sa, RunParams::default());
101 }
102
103 let card_name = ctx.game.card(top_card).card_name.clone();
108 let _explorer_name = ctx.game.card(explorer_id).card_name.clone();
109 let msg = format!("Put {card_name} into your graveyard?");
110 let put_in_gy = ctx.agents[controller.index()].confirm_action(
111 controller,
112 None,
113 &msg,
114 &[],
115 sa.source,
116 Some(crate::ability::api_type::ApiType::Explore),
117 );
118
119 if put_in_gy {
120 let owner = ctx.game.card(top_card).owner;
121 ctx.move_card(top_card, ZoneType::Graveyard, owner);
122 emit_zone_trigger(
123 ctx.trigger_handler,
124 top_card,
125 ZoneType::Library,
126 ZoneType::Graveyard,
127 );
128 }
129 }
130 ctx.trigger_handler.run_trigger(
131 TriggerType::Explored,
132 RunParams {
133 card: Some(explorer_id),
134 explored: Some(top_card),
135 ..Default::default()
136 },
137 false,
138 );
139 }
140}