Skip to main content

character_traits_warrior_capability/
capability_variant.rs

1// ---------------- [ File: character-traits-warrior-capability/src/capability_variant.rs ]
2crate::ix!();
3
4/// Implemented **once** for every *leaf‑level* capability enum
5/// (e.g. `WarriorApproachCapability`, `WarriorTechAdaptationCapability`, …).
6///
7/// The enum itself provides:
8/// * its **intrinsic ratings vector** (`intrinsic_ratings`);
9/// * a **static slice of all variants** (`all_variants`) for enumeration.
10pub trait CapabilityVariant: Clone + Eq + std::hash::Hash + Sized {
11    /// Return the *dense 115‑element* intrinsic‑dimension ratings that
12    /// characterize *this* capability variant.
13    fn intrinsic_ratings(&self) -> &WarriorCapabilityIntrinsicDimensionRatings;
14
15    /// Exhaustive slice of every variant value—used for enumeration
16    /// when computing probabilities.
17    fn all_variants() -> &'static [Self];
18}
19
20/// Blanket‑implement `CapabilityVariant` for every leaf enum that
21///   * derives **`EnumIter`** (from `strum_macros`) and  
22///   * provides `intrinsic_dimension_ratings()`.
23///
24/// The `OnceLock` caches avoid recomputing vectors on every call, while
25/// `EnumIter` eliminates any need for unstable `variant_count` or unsafe
26/// transmutes.
27#[macro_export]
28macro_rules! impl_capability_variant {
29    ( $($ty:ty),+ $(,)? ) => {
30        $(
31            impl CapabilityVariant for $ty {
32                fn intrinsic_ratings(&self) -> &WarriorCapabilityIntrinsicDimensionRatings {
33                    use std::sync::OnceLock;
34                    use strum::IntoEnumIterator;
35
36                    static CACHE: OnceLock<
37                        Vec<WarriorCapabilityIntrinsicDimensionRatings>
38                    > = OnceLock::new();
39
40                    let ratings = CACHE.get_or_init(|| {
41                        <$ty as IntoEnumIterator>::iter()
42                            .map(|v| v.intrinsic_dimension_ratings())
43                            .collect::<Vec<_>>()
44                    });
45
46                    // safe because `EnumIter` guarantees contiguous indices
47                    &ratings[*self as usize]
48                }
49
50                fn all_variants() -> &'static [Self] {
51                    use std::sync::OnceLock;
52                    use strum::IntoEnumIterator;
53
54                    static VARS: OnceLock<Vec<$ty>> = OnceLock::new();
55                    VARS.get_or_init(|| <$ty as IntoEnumIterator>::iter().collect())
56                }
57            }
58        )+
59    };
60}
61
62impl_capability_variant!{
63    WarriorApproachCapability,
64    WarriorBraveryCapability,
65    WarriorConflictMitigationCapability,
66    WarriorCyberDefenseCapability,
67    WarriorDefensiveMagicCapability,
68    WarriorEmbodimentCapability,
69    WarriorExplorationCapability,
70    WarriorIllusionaryMagicCapability,
71    WarriorLeadershipCapability,
72    WarriorMetaCapability,
73    WarriorOffensiveMagicCapability,
74    WarriorPhysicalCapability,
75    WarriorProtectiveCapability,
76    WarriorResilienceCapability,
77    WarriorResponsivenessCapability,
78    WarriorStrategicCapability,
79    WarriorTechAdaptationCapability,
80    WarriorThreatAdaptationCapability,
81}