Skip to main content

manabrew_engine/replacement/
replacement_type.rs

1//! Replacement effect event types.
2//!
3//! Mirrors Java `ReplacementType.java` in `forge/game/replacement/`.
4//! Each variant corresponds to an `Event$ <Value>` entry in card scripts.
5
6use serde::{Deserialize, Serialize};
7use strum_macros::EnumString;
8
9use crate::parsing::{keys, Params};
10
11use super::replacement_effect::{parse_zone_list, ReplacementEffect, ReplacementLayer};
12
13/// The type of game event a replacement effect intercepts. Mirrors Java
14/// `ReplacementType` enum. `EnumString` derives a case-insensitive
15/// `FromStr` that maps `"<VariantName>"` (any case) to the variant.
16/// `#[strum(default)]` on `Other` makes unknown values fall through
17/// instead of erroring.
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, EnumString)]
19#[strum(ascii_case_insensitive)]
20pub enum ReplacementType {
21    AddCounter,
22    AssembleContraption,
23    AssignDealDamage,
24    Attached,
25    BeginPhase,
26    BeginTurn,
27    Cascade,
28    Counter,
29    CopySpell,
30    CreateToken,
31    DamageDone,
32    DealtDamage,
33    DeclareBlocker,
34    Destroy,
35    Draw,
36    DrawCards,
37    Explore,
38    GainLife,
39    GameLoss,
40    GameWin,
41    Learn,
42    LifeReduced,
43    LoseMana,
44    Mill,
45    Moved,
46    PayLife,
47    PlanarDiceResult,
48    Planeswalk,
49    ProduceMana,
50    Proliferate,
51    RemoveCounter,
52    RollDice,
53    RollPlanarDice,
54    Scry,
55    SetInMotion,
56    Tap,
57    Transform,
58    TurnFaceUp,
59    Untap,
60    #[strum(default)]
61    Other(String),
62}
63
64impl ReplacementType {
65    pub fn smart_value_of(value: &str) -> Self {
66        value.trim().parse().expect("Other variant catches all")
67    }
68
69    pub fn create_replacement(event: &ReplacementType, params: &Params) -> ReplacementEffect {
70        let layer = params
71            .get(keys::LAYER)
72            .and_then(ReplacementLayer::smart_value_of)
73            .unwrap_or(ReplacementLayer::Other);
74        let active_zones = params
75            .get(keys::ACTIVE_ZONES)
76            .map(parse_zone_list)
77            .unwrap_or_default();
78        ReplacementEffect::new(event.clone(), layer, params.clone(), active_zones)
79    }
80}