Skip to main content

manabrew_engine/ability/effects/
flip_onto_battlefield_effect.rs

1//! FlipOntoBattlefield effect — Chaos Orb style flipping.
2//!
3//! Ported 1:1 from Java's `FlipOntoBattlefieldEffect.java`.
4//! Flip a card onto the battlefield from a height of at least one foot.
5//! Destroy any permanents it lands on. (Un-set / silver-bordered mechanic.)
6//! In digital, this is implemented as random selection.
7
8use forge_foundation::ZoneType;
9
10use super::resolve_numeric_svar;
11use super::EffectContext;
12use crate::ids::CardId;
13use crate::parsing::keys;
14
15/// Struct form of this effect so it can participate in the
16/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
17/// `FlipOntoBattlefieldEffect` class extending `SpellAbilityEffect`.
18#[manabrew_engine_macros::spell_effect(FlipOntoBattlefieldEffect)]
19fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
20    let _controller = sa.activating_player;
21
22    // Get all permanents on the battlefield (except the source)
23    let source = sa.source;
24    let targets: Vec<CardId> = ctx
25        .game
26        .cards
27        .iter()
28        .filter(|c| c.zone == ZoneType::Battlefield && (source != Some(c.id)))
29        .map(|c| c.id)
30        .collect();
31
32    if targets.is_empty() {
33        return;
34    }
35
36    // In digital: randomly select which permanents get "hit"
37    // Java uses actual physics simulation — we use RNG
38    let hit_count = resolve_numeric_svar(ctx.game, sa, keys::HIT_COUNT, 1).max(0) as usize;
39
40    let mut pool = targets;
41    ctx.rng.shuffle_cards(&mut pool);
42    let hits: Vec<CardId> = pool.into_iter().take(hit_count).collect();
43
44    // Destroy hit permanents
45    for card_id in hits {
46        if ctx.game.card(card_id).zone != ZoneType::Battlefield {
47            continue;
48        }
49        let old_zone = ctx.game.card(card_id).zone;
50        let owner = ctx.game.card(card_id).owner;
51        ctx.move_card(card_id, ZoneType::Graveyard, owner);
52        super::emit_zone_trigger(ctx.trigger_handler, card_id, old_zone, ZoneType::Graveyard);
53    }
54}