Skip to main content

manabrew_engine/ability/effects/
look_at_effect.rs

1use forge_foundation::ZoneType;
2
3use super::{resolve_defined_player, resolve_numeric_svar, EffectContext};
4use crate::agent::GameLogEvent;
5
6/// Mirrors Java's `LookAtEffect.java`.
7///
8/// `SP$ LookAt | Defined$ You | NumCards$ N`
9/// The activating player looks at cards in a hidden zone (e.g. top of library or opponent's hand)
10/// without revealing them to others.
11/// In the engine this is informational — we notify only the activating player's agent.
12/// Struct form of this effect so it can participate in the
13/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
14/// `LookAtEffect` class extending `SpellAbilityEffect`.
15#[manabrew_engine_macros::spell_effect(LookAtEffect)]
16fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
17    let num = if sa.ir.num_cards_text.is_some() {
18        resolve_numeric_svar(ctx.game, sa, "NumCards", 1)
19    } else {
20        resolve_numeric_svar(ctx.game, sa, "ScryNum", 1)
21    }
22    .max(0) as usize;
23
24    let source_zone = sa.ir.source_zone.unwrap_or(ZoneType::Library);
25
26    let look_player = sa
27        .target_chosen
28        .target_player
29        .or_else(|| {
30            sa.defined()
31                .and_then(|d| resolve_defined_player(d, sa.activating_player, ctx.game))
32        })
33        .unwrap_or(sa.activating_player);
34
35    let zone_cards = ctx.game.cards_in_zone(source_zone, look_player).to_vec();
36    let count = num.min(zone_cards.len());
37
38    let top = &zone_cards[zone_cards.len() - count..];
39    let names: Vec<String> = top
40        .iter()
41        .map(|&id| ctx.game.card(id).card_name.clone())
42        .collect();
43    let msg = format!(
44        "Looking at top {} card(s) of {:?}: [{}]",
45        count,
46        source_zone,
47        names.join(", ")
48    );
49    // Only the activating player can see these.
50    ctx.agents[sa.activating_player.index()].notify(
51        crate::agent::notification::GameNotification::Event(
52            GameLogEvent::info(msg).with_player(sa.activating_player),
53        ),
54    );
55}