Skip to main content

manabrew_engine/spellability/
ability.rs

1//! Ability -- helper functions for in-play abilities.
2//! Mirrors Java's `Ability.java` (base class for abilities on permanents).
3//! In Rust the subclass is flattened into SpellAbility.
4
5use forge_foundation::ZoneType;
6
7use crate::game::GameState;
8use crate::spellability::SpellAbility;
9
10/// Type alias for SpellAbility when used as an in-play ability.
11/// In Java, `Ability` is a subclass; in Rust it's the same struct with `is_activated = true`.
12pub type Ability = super::SpellAbility;
13
14/// Whether this in-play ability can currently be played.
15/// Mirrors Java's `Ability.canPlay()`.
16///
17/// Checks:
18/// 1. Split second not on stack (unless this is a mana ability).
19/// 2. The source card is on the battlefield (in play).
20/// 3. The source card is not face down (face-down cards can't use abilities
21///    except morph/megamorph turn-face-up).
22pub fn can_play(sa: &SpellAbility, game: &GameState) -> bool {
23    let card_id = match sa.source {
24        Some(id) => id,
25        None => return false,
26    };
27
28    // Split second check: mana abilities bypass split second
29    if !sa.is_mana_ability && super::has_split_second_on_stack(game) {
30        return false;
31    }
32
33    // The card must be on the battlefield to activate in-play abilities
34    if !game.card_is_in_zone(card_id, ZoneType::Battlefield) {
35        return false;
36    }
37
38    let card = game.card(card_id);
39
40    // Face-down cards cannot activate abilities (except morph turn-face-up,
41    // which is handled by AbilityStatic, not Ability)
42    if card.face_down {
43        return false;
44    }
45
46    // Delegate to general restriction check
47    sa.can_play(game)
48}