Skip to main content

manabrew_engine/ability/effects/
open_attraction_effect.rs

1//! OpenAttraction — open an attraction from the attraction deck (Unfinity).
2//! Ported from Java's OpenAttractionEffect: moves top card of attraction
3//! deck to battlefield.
4
5use forge_foundation::ZoneType;
6
7use super::EffectContext;
8use crate::parsing::keys;
9
10/// Struct form of this effect so it can participate in the
11/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
12/// `OpenAttractionEffect` class extending `SpellAbilityEffect`.
13#[manabrew_engine_macros::spell_effect(OpenAttractionEffect)]
14fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
15    let source = match sa.source {
16        Some(s) => s,
17        None => return,
18    };
19
20    let amount = super::resolve_numeric_svar(ctx.game, sa, "Amount", 1).max(1);
21
22    let players = if let Some(def) = sa.defined() {
23        super::resolve_defined_players(def, sa.activating_player, ctx.game)
24    } else {
25        vec![sa.activating_player]
26    };
27
28    for player_id in players {
29        if ctx.game.player(player_id).has_lost {
30            continue;
31        }
32
33        for _ in 0..amount {
34            let attraction = ctx
35                .game
36                .cards_in_zone(ZoneType::AttractionDeck, player_id)
37                .first()
38                .copied()
39                .or_else(|| {
40                    // Compatibility fallback until full deck-section setup is wired.
41                    ctx.game
42                        .cards
43                        .iter()
44                        .find(|c| {
45                            c.zone == ZoneType::Sideboard
46                                && c.owner == player_id
47                                && c.type_line
48                                    .subtypes
49                                    .iter()
50                                    .any(|s| s.eq_ignore_ascii_case("Attraction"))
51                        })
52                        .map(|c| c.id)
53                });
54
55            if let Some(card_id) = attraction {
56                let old_zone = ctx.game.card(card_id).zone;
57                ctx.game
58                    .move_card(card_id, ZoneType::Battlefield, player_id);
59                super::emit_zone_trigger(
60                    ctx.trigger_handler,
61                    card_id,
62                    old_zone,
63                    ZoneType::Battlefield,
64                );
65
66                if sa.param_is_true(keys::REMEMBER) {
67                    ctx.game.card_mut(source).add_remembered_card(card_id);
68                }
69            }
70        }
71    }
72}