Skip to main content

manabrew_engine/ability/effects/
manifest_dread_effect.rs

1//! ManifestDread effect — look at top 2 cards, manifest one, other goes to graveyard.
2//!
3//! Ported from Java's `ManifestDreadEffect.java`.
4//! Manifest Dread N: For each, look at top 2, choose one to manifest, rest to graveyard.
5
6use forge_foundation::ZoneType;
7
8use super::manifest_base_effect::parse_manifest_params;
9use super::{emit_zone_trigger, EffectContext};
10use crate::ids::{CardId, PlayerId};
11use crate::spellability::SpellAbility;
12
13/// Struct form of this effect so it can participate in the
14/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
15/// `ManifestDreadEffect` class extending `SpellAbilityEffect`.
16#[manabrew_engine_macros::spell_effect(ManifestDreadEffect)]
17fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
18    let manifest_params = parse_manifest_params(ctx, sa);
19    let amount = manifest_params.amount;
20    let controller = sa.activating_player;
21
22    let players = if let Some(def) = sa.defined_player() {
23        super::resolve_defined_players(def, controller, ctx.game)
24    } else {
25        vec![controller]
26    };
27
28    for pid in players {
29        for _ in 0..amount {
30            manifest_dread_once(ctx, sa, pid);
31        }
32    }
33}
34
35/// One iteration of manifest dread: look at top 2, pick one to manifest, rest to graveyard.
36fn manifest_dread_once(ctx: &mut EffectContext, _sa: &SpellAbility, player: PlayerId) {
37    let lib = ctx.game.cards_in_zone(ZoneType::Library, player).to_vec();
38    // Top 2 cards (last 2 in the vec since top = end)
39    let top2: Vec<CardId> = lib.into_iter().rev().take(2).collect();
40    if top2.is_empty() {
41        return;
42    }
43
44    // Player chooses one to manifest
45    ctx.agents[player.index()].snapshot_state(ctx.game, ctx.mana_pools);
46    let chosen = if top2.len() == 1 {
47        top2[0]
48    } else {
49        ctx.agents[player.index()]
50            .choose_single_card_for_zone_change(
51                ctx.game,
52                player,
53                &top2,
54                "Choose a card to manifest",
55                false,
56            )
57            .unwrap_or(top2[0])
58    };
59
60    // Manifest the chosen card
61    let old_zone = ctx.game.card(chosen).zone;
62    ctx.game.card_mut(chosen).set_face_down(true);
63    ctx.game.card_mut(chosen).set_manifested(true);
64    ctx.game.card_mut(chosen).set_base_pt(Some(2), Some(2));
65    ctx.game.card_mut(chosen).set_controller(player);
66    ctx.move_card(chosen, ZoneType::Battlefield, player);
67    ctx.trigger_handler
68        .register_active_trigger(ctx.game, chosen);
69    emit_zone_trigger(ctx.trigger_handler, chosen, old_zone, ZoneType::Battlefield);
70
71    // Put the rest into graveyard
72    for &card_id in &top2 {
73        if card_id != chosen {
74            let gz = ctx.game.card(card_id).zone;
75            ctx.move_card(card_id, ZoneType::Graveyard, player);
76            emit_zone_trigger(ctx.trigger_handler, card_id, gz, ZoneType::Graveyard);
77        }
78    }
79}