Skip to main content

manabrew_engine/spellability/
spell_permanent.rs

1//! SpellPermanent -- factory for permanent spells.
2//! Mirrors Java's `SpellPermanent.java`.
3//! Creates SpellAbility instances configured as permanent spells (creatures
4//! and non-creatures) that resolve by moving to the battlefield.
5
6use std::collections::HashMap;
7
8use crate::ability::api_type::ApiType;
9use crate::ids::{CardId, PlayerId};
10use crate::spellability::target_choices::TargetChoices;
11use crate::spellability::{SpellAbility, SpellAbilityCondition, SpellAbilityRestriction};
12
13/// Create a SpellAbility configured as a permanent spell.
14/// Mirrors Java's `SpellPermanent` constructor.
15///
16/// - `card_id`: The card being cast.
17/// - `is_creature`: If true, the API type is `PermanentCreature`; otherwise
18///   `PermanentNoncreature`.
19/// - `player`: The casting player.
20pub fn create_permanent_spell(
21    card_id: CardId,
22    is_creature: bool,
23    player: PlayerId,
24) -> SpellAbility {
25    let api = if is_creature {
26        ApiType::PermanentCreature
27    } else {
28        ApiType::PermanentNoncreature
29    };
30
31    SpellAbility {
32        id: 0,
33        api: Some(api),
34        source: Some(card_id),
35        original_host: None,
36        activating_player: player,
37        targeting_player: None,
38        ability_text: String::new(),
39        record_type: crate::ability::ability_factory::AbilityRecordType::Spell,
40        ir: crate::ability::ability_ir::SpellAbilityIr::default(),
41        target_restrictions: None,
42        target_chosen: TargetChoices::default(),
43        pay_costs: None,
44        sub_ability: None,
45        wrapped_ability: None,
46        is_spell: true,
47        is_trigger: false,
48        is_activated: false,
49        intrinsic: false,
50        trigger_source: None,
51        trigger_source_zone_timestamp: None,
52        source_zone_timestamp: None,
53        source_trigger_id: None,
54        trigger_index: None,
55        alt_cost: None,
56        alt_cost_index: 0,
57        evoke_keyword_count: 0,
58        kicked: false,
59        buyback_paid: false,
60        overloaded: false,
61        is_copy: false,
62        paid_life_amount: 0,
63        kick_count: 0,
64        replicate_count: 0,
65        optional_generic_cost_paid: false,
66        trigger_remembered_amount: 0,
67        x_mana_cost_paid: 0,
68        discarded_cost_cards: Vec::new(),
69        optional_costs: Vec::new(),
70        paid_hash: HashMap::new(),
71        paying_mana: Vec::new(),
72        paid_abilities: Vec::new(),
73        mana_part: None,
74        express_mana_choice: None,
75        convoke_tapped: Vec::new(),
76        spliced_cards: Vec::new(),
77        announce_vars: HashMap::new(),
78        sacrificed_as_emerge: None,
79        sacrificed_as_offering: None,
80        description: String::new(),
81        stack_description: String::new(),
82        is_mana_ability: false,
83        is_land_ability: false,
84        cast_face_down: false,
85        trigger_objects: HashMap::new(),
86        trigger_spell_abilities: HashMap::new(),
87        additional_ability_lists: HashMap::new(),
88        replacing_objects: HashMap::new(),
89        trigger_remembered: Vec::new(),
90        restriction: SpellAbilityRestriction::default(),
91        condition: SpellAbilityCondition::default(),
92        rollback_effects: Vec::new(),
93        optional_keyword_amounts: HashMap::new(),
94        pips_to_reduce: Vec::new(),
95        may_choose_new_targets: false,
96        last_state: HashMap::new(),
97        change_zone_table: None,
98        damage_map: None,
99        prevent_map: None,
100    }
101}