boseiju/ability_tree/ability/
statik.rs

1pub mod alterative_casting_permissions;
2pub mod continuous_effect;
3pub mod cost_modification_effect;
4
5use crate::ability_tree::AbilityTreeNode;
6use crate::ability_tree::MAX_CHILDREN_PER_NODE;
7
8/// A static ability, from the comprehensive rules:
9///
10/// A kind of ability.
11/// Static abilities do something all the time rather than being activated or triggered.
12/// See rule 113, “Abilities”, and rule 604, “Handling Static Abilities”.
13///
14/// See also <https://mtg.fandom.com/wiki/Static_ability>
15#[derive(serde::Serialize, serde::Deserialize)]
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct StaticAbility {
18    pub kind: StaticAbilityKind,
19    pub condition: Option<crate::ability_tree::conditional::Conditional>,
20    #[cfg(feature = "spanned_tree")]
21    pub span: crate::ability_tree::span::TreeSpan,
22}
23
24impl AbilityTreeNode for StaticAbility {
25    fn node_id(&self) -> usize {
26        use idris::Idris;
27        crate::ability_tree::NodeKind::StaticAbility.id()
28    }
29
30    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
31        let mut children = arrayvec::ArrayVec::new_const();
32        children.push(&self.kind as &dyn AbilityTreeNode);
33        match self.condition.as_ref() {
34            Some(condition) => children.push(condition as &dyn AbilityTreeNode),
35            None => {
36                children.push(crate::ability_tree::dummy_terminal::TreeNodeDummyTerminal::none_node() as &dyn AbilityTreeNode)
37            }
38        }
39        children
40    }
41
42    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
43        use std::io::Write;
44        write!(out, "static ability:")?;
45        out.push_inter_branch()?;
46        self.kind.display(out)?;
47        out.next_final_branch()?;
48        match self.condition.as_ref() {
49            Some(condition) => condition.display(out)?,
50            None => write!(out, "if condition: none")?,
51        }
52        out.pop_branch();
53        Ok(())
54    }
55
56    fn node_tag(&self) -> &'static str {
57        "static ability"
58    }
59
60    #[cfg(feature = "spanned_tree")]
61    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
62        self.span
63    }
64}
65
66#[cfg(feature = "parser")]
67impl crate::utils::DummyInit for StaticAbility {
68    fn dummy_init() -> Self {
69        Self {
70            kind: crate::utils::dummy(),
71            condition: None,
72            #[cfg(feature = "spanned_tree")]
73            span: Default::default(),
74        }
75    }
76}
77
78/// The kind of a static ability.
79///
80/// All of the different static abilities that there is.
81#[derive(serde::Serialize, serde::Deserialize)]
82#[derive(Debug, Clone, PartialEq, Eq)]
83pub enum StaticAbilityKind {
84    ContinuousEffect(continuous_effect::ContinuousEffect),
85    CostModificationEffect(cost_modification_effect::CostModificationEffect), /* Fixme: that's a continuous effect */
86    AlternativeCastingPermissions(alterative_casting_permissions::AlternativeCastingPermissions), /* Fixme: that's a continuous effect */
87}
88
89#[cfg(feature = "spanned_tree")]
90impl StaticAbilityKind {
91    pub fn span(&self) -> crate::ability_tree::span::TreeSpan {
92        match self {
93            Self::ContinuousEffect(child) => child.span,
94            Self::CostModificationEffect(child) => child.span,
95            Self::AlternativeCastingPermissions(child) => child.span,
96        }
97    }
98}
99
100impl AbilityTreeNode for StaticAbilityKind {
101    fn node_id(&self) -> usize {
102        use idris::Idris;
103        crate::ability_tree::NodeKind::StaticAbilityKind.id()
104    }
105
106    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
107        let mut children = arrayvec::ArrayVec::new_const();
108        match self {
109            Self::ContinuousEffect(child) => children.push(child as &dyn AbilityTreeNode),
110            Self::CostModificationEffect(child) => children.push(child as &dyn AbilityTreeNode),
111            Self::AlternativeCastingPermissions(child) => children.push(child as &dyn AbilityTreeNode),
112        }
113        children
114    }
115
116    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
117        use std::io::Write;
118        write!(out, "static ability kind:")?;
119        out.push_final_branch()?;
120        match self {
121            Self::ContinuousEffect(child) => child.display(out)?,
122            Self::CostModificationEffect(child) => child.display(out)?,
123            Self::AlternativeCastingPermissions(child) => child.display(out)?,
124        }
125        out.pop_branch();
126        Ok(())
127    }
128
129    fn node_tag(&self) -> &'static str {
130        "static ability kind"
131    }
132
133    #[cfg(feature = "spanned_tree")]
134    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
135        match self {
136            Self::ContinuousEffect(child) => child.node_span(),
137            Self::CostModificationEffect(child) => child.node_span(),
138            Self::AlternativeCastingPermissions(child) => child.node_span(),
139        }
140    }
141}
142
143#[cfg(feature = "parser")]
144impl crate::utils::DummyInit for StaticAbilityKind {
145    fn dummy_init() -> Self {
146        Self::ContinuousEffect(crate::utils::dummy())
147    }
148}