Skip to main content

manabrew_engine/ability/effects/
reveal_hand_effect.rs

1use forge_foundation::ZoneType;
2
3use super::{resolve_defined_player, EffectContext};
4use crate::agent::GameLogEvent;
5
6/// Mirrors Java's `RevealHandEffect.java`.
7///
8/// `SP$ RevealHand | Defined$ Player`
9/// The target player reveals their entire hand to all other players.
10/// In the engine this is informational — we notify all agents.
11/// Struct form of this effect so it can participate in the
12/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
13/// `RevealHandEffect` class extending `SpellAbilityEffect`.
14#[manabrew_engine_macros::spell_effect(RevealHandEffect)]
15fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
16    let target = sa
17        .target_chosen
18        .target_player
19        .or_else(|| {
20            sa.defined()
21                .and_then(|d| resolve_defined_player(d, sa.activating_player, ctx.game))
22        })
23        .unwrap_or(sa.activating_player);
24
25    if sa.ir.optional {
26        let _source_name = sa.source.map(|cid| ctx.game.card(cid).card_name.as_str());
27        let accepted = ctx.agents[target.index()].confirm_action(
28            target,
29            None,
30            "Do you want to reveal your hand?",
31            &[],
32            sa.source,
33            Some(crate::ability::api_type::ApiType::RevealHand),
34        );
35        if !accepted {
36            return;
37        }
38    }
39
40    let hand = ctx.game.cards_in_zone(ZoneType::Hand, target).to_vec();
41
42    let names: Vec<String> = hand
43        .iter()
44        .map(|&id| ctx.game.card(id).card_name.clone())
45        .collect();
46    let msg = format!(
47        "Player {} reveals their hand: [{}]",
48        target.0,
49        names.join(", ")
50    );
51    for agent in ctx.agents.iter_mut() {
52        agent.notify(crate::agent::notification::GameNotification::Event(
53            GameLogEvent::rule(msg.clone()).with_player(target),
54        ));
55    }
56
57    // Mirrors `host.getGame().getAction().reveal(hand, p)` in
58    // RevealHandEffect.java:54 — broadcast a modal of the full hand to every
59    // player so the reveal is publicly visible, not just a log entry.
60    if !hand.is_empty() {
61        let source_name = sa.source.map(|cid| ctx.game.card(cid).card_name.clone());
62        for agent in ctx.agents.iter_mut() {
63            agent.reveal_cards(
64                ctx.game,
65                target,
66                &hand,
67                ZoneType::Hand,
68                target,
69                source_name.as_deref(),
70            );
71        }
72    }
73}