manabrew_engine/ability/effects/
peek_and_reveal_effect.rs1use forge_foundation::ZoneType;
2
3use super::{resolve_numeric_svar, EffectContext};
4
5#[manabrew_engine_macros::spell_effect(PeekAndRevealEffect)]
7fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
8 let num = if sa.ir.peek_amount_text.is_some() {
9 resolve_numeric_svar(ctx.game, sa, "PeekAmount", 1)
10 } else {
11 resolve_numeric_svar(ctx.game, sa, "NumCards", 1)
12 }
13 .max(0) as usize;
14 let remember_revealed = sa.ir.remember_revealed;
15 let imprint_revealed = sa.ir.imprint_revealed;
16 let remember_peeked = sa.ir.remember_peeked;
17 let reveal_optional = sa.ir.reveal_optional;
18
19 let peeking_player = sa.activating_player;
20 let no_peek = sa.ir.no_peek;
21 let no_reveal = sa.ir.no_reveal;
22 let src_zone = sa.ir.source_zone.unwrap_or(ZoneType::Library);
23
24 let src_zone_players =
25 crate::ability::spell_ability_effect::get_defined_players_or_targeted(ctx.game, sa);
26 let players: Vec<_> = if src_zone_players.is_empty() {
27 vec![peeking_player]
28 } else {
29 src_zone_players
30 };
31
32 for zone_to_peek in players {
33 let peeked: Vec<_> = {
34 let zone_cards = ctx.game.cards_in_zone(src_zone, zone_to_peek);
35 let take = num.min(zone_cards.len());
36 let start = zone_cards.len().saturating_sub(take);
37 zone_cards[start..].to_vec()
38 };
39
40 let revealable: Vec<_> = if let Some(valid) = sa.ir.reveal_valid_text.as_deref() {
41 peeked
42 .iter()
43 .copied()
44 .filter(|&cid| {
45 crate::ability::ability_utils::matches_valid_cards_for_sa(
46 ctx.game,
47 sa,
48 ctx.game.card(cid),
49 sa.ir.reveal_valid_selector.as_ref(),
50 valid,
51 )
52 })
53 .collect()
54 } else {
55 peeked.clone()
56 };
57
58 if !no_peek && !peeked.is_empty() {
59 ctx.agents[peeking_player.index()].reveal_cards(
60 ctx.game,
61 peeking_player,
62 &peeked,
63 src_zone,
64 zone_to_peek,
65 sa.source.map(|cid| ctx.game.card(cid).card_name.as_str()),
66 );
67 }
68
69 let mut do_reveal = !no_reveal && !revealable.is_empty();
70 if do_reveal && reveal_optional {
71 do_reveal = ctx.agents[peeking_player.index()].confirm_action(
72 peeking_player,
73 None,
74 "Reveal the card to other players?",
75 &[],
76 sa.source,
77 sa.api,
78 );
79 }
80
81 if do_reveal {
82 let source_name = sa.source.map(|cid| ctx.game.card(cid).card_name.clone());
83 for agent in ctx.agents.iter_mut() {
84 agent.reveal_cards(
85 ctx.game,
86 peeking_player,
87 &revealable,
88 src_zone,
89 zone_to_peek,
90 source_name.as_deref(),
91 );
92 }
93 if let Some(source_id) = sa.source {
94 if remember_revealed {
95 for &card_id in &revealable {
96 ctx.game.card_mut(source_id).add_remembered_card(card_id);
97 }
98 }
99 if imprint_revealed {
100 for &card_id in &revealable {
101 ctx.game.card_mut(source_id).add_imprinted_card(card_id);
102 }
103 }
104 }
105 } else if remember_peeked {
106 if let Some(source_id) = sa.source {
107 for &card_id in &revealable {
108 ctx.game.card_mut(source_id).add_remembered_card(card_id);
109 }
110 }
111 }
112 }
113}