Skip to main content

manabrew_engine/card/
counter_type.rs

1use serde::{Deserialize, Serialize};
2use strum_macros::{Display, EnumString};
3
4/// Counter types commonly used in MTG.
5/// Note: `Copy` is intentionally absent because the `Named(String)` variant
6/// holds heap-allocated data. Use `.clone()` when an owned copy is needed.
7#[derive(
8    Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumString, Display,
9)]
10pub enum CounterType {
11    P1P1,
12    M1M1,
13    Poison,
14    Loyalty,
15    Charge,
16    Quest,
17    Study,
18    Age,
19    Fade,
20    Time,
21    Depletion,
22    Storage,
23    Mining,
24    Brick,
25    Level,
26    Lore,
27    Page,
28    Dream,
29    /// Catch-all for counter types not in the enum (e.g. SUPPLY, VERSE, LUCK).
30    /// Stored as uppercase name for consistent comparison.
31    Named(String),
32}
33
34/// Parse a counter type string to CounterType enum (case-insensitive).
35/// Unknown types produce `CounterType::Named(UPPER)` instead of silently
36/// falling back to P1P1, so cards like Stocking the Pantry get the correct
37/// SUPPLY counters.
38pub fn parse_counter_type(s: &str) -> CounterType {
39    match s.to_uppercase().as_str() {
40        "P1P1" | "+1/+1" => CounterType::P1P1,
41        "M1M1" | "-1/-1" => CounterType::M1M1,
42        "LOYALTY" => CounterType::Loyalty,
43        "CHARGE" => CounterType::Charge,
44        "QUEST" => CounterType::Quest,
45        "STUDY" => CounterType::Study,
46        "AGE" => CounterType::Age,
47        "FADE" => CounterType::Fade,
48        "TIME" => CounterType::Time,
49        "DEPLETION" => CounterType::Depletion,
50        "STORAGE" => CounterType::Storage,
51        "MINING" => CounterType::Mining,
52        "BRICK" => CounterType::Brick,
53        "LEVEL" => CounterType::Level,
54        "LORE" => CounterType::Lore,
55        "PAGE" => CounterType::Page,
56        "DREAM" => CounterType::Dream,
57        other => CounterType::Named(other.to_string()),
58    }
59}
60
61impl CounterType {
62    /// Java parity helper for interface-style checks.
63    pub fn is(&self, other: &CounterType) -> bool {
64        self == other
65    }
66
67    /// Java parity helper for "keyword counter" classification.
68    pub fn is_keyword_counter(&self) -> bool {
69        matches!(self, CounterType::Named(_))
70    }
71}