manabrew_engine/ability/effects/
clash_effect.rs1use forge_foundation::ZoneType;
8
9use super::EffectContext;
10use crate::ids::{CardId, PlayerId};
11use crate::parsing::keys;
12
13#[manabrew_engine_macros::spell_effect(ClashEffect)]
17fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
18 let controller = sa.activating_player;
19
20 let opponent = if let Some(def) = sa.defined() {
22 super::resolve_defined_players(def, controller, ctx.game)
23 .into_iter()
24 .next()
25 .unwrap_or_else(|| ctx.game.opponent_of(controller))
26 } else {
27 ctx.game.opponent_of(controller)
28 };
29
30 if sa.param_is_true(keys::REMEMBER_CLASHER) {
32 if let Some(sid) = sa.source {
33 ctx.game.card_mut(sid).add_remembered_player(opponent);
34 }
35 }
36
37 let p_lib = ctx
38 .game
39 .cards_in_zone(ZoneType::Library, controller)
40 .to_vec();
41 let o_lib = ctx.game.cards_in_zone(ZoneType::Library, opponent).to_vec();
42
43 if p_lib.is_empty() && o_lib.is_empty() {
44 return;
45 }
46
47 let p_card: Option<CardId> = p_lib.last().copied();
48 let o_card: Option<CardId> = o_lib.last().copied();
49
50 let p_cmc = p_card
51 .map(|cid| ctx.game.card(cid).mana_cost.cmc())
52 .unwrap_or(-1);
53 let o_cmc = o_card
54 .map(|cid| ctx.game.card(cid).mana_cost.cmc())
55 .unwrap_or(-1);
56
57 let mut revealed = Vec::new();
58 if let Some(cid) = p_card {
59 revealed.push(cid);
60 }
61 if let Some(cid) = o_card {
62 revealed.push(cid);
63 }
64
65 let activator_wins = p_cmc > o_cmc;
69
70 clash_move(ctx, controller, p_card);
71 clash_move(ctx, opponent, o_card);
72
73 let sub_key = if activator_wins {
77 "WinSubAbility"
78 } else {
79 "OtherwiseSubAbility"
80 };
81 if let Some(sub_sa) = sa.get_additional_ability(sub_key).cloned() {
82 super::resolve_effect(ctx, &sub_sa);
83 }
84}
85
86fn clash_move(ctx: &mut EffectContext, player: PlayerId, card: Option<CardId>) {
88 let Some(card_id) = card else { return };
89
90 ctx.agents[player.index()].snapshot_state(ctx.game, ctx.mana_pools);
92 let put_on_top = ctx.agents[player.index()].confirm_action(
93 player,
94 Some("ClashTopOrBottom"),
95 &format!(
96 "Put {} on top or bottom of your library?",
97 ctx.game.card(card_id).card_name
98 ),
99 &["Top".to_string(), "Bottom".to_string()],
100 Some(card_id),
101 None,
102 );
103
104 if !put_on_top {
105 ctx.game
107 .reorder_card_in_zone(ZoneType::Library, player, card_id, 0);
108 }
109 }