boseiju/ability_tree/
ability.rs

1pub mod activated;
2pub mod keyword;
3pub mod spell;
4pub mod statik;
5pub mod triggered;
6
7use crate::ability_tree::AbilityTreeNode;
8use crate::ability_tree::MAX_CHILDREN_PER_NODE;
9
10/// Fixme: doc
11#[derive(serde::Serialize, serde::Deserialize)]
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum AbilityKind {
14    AbilityWord(AbilityWordAbility),
15    Keyword(KeywordAbility),
16    Written(Ability),
17}
18
19#[cfg(feature = "spanned_tree")]
20impl AbilityKind {
21    pub fn span(&self) -> crate::ability_tree::span::TreeSpan {
22        match self {
23            Self::AbilityWord(ability) => ability.span,
24            Self::Keyword(ability) => ability.span,
25            Self::Written(ability) => ability.node_span(),
26        }
27    }
28}
29
30impl AbilityTreeNode for AbilityKind {
31    fn node_id(&self) -> usize {
32        use idris::Idris;
33        super::NodeKind::AbilityKind.id()
34    }
35
36    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
37        let mut abilities = arrayvec::ArrayVec::new_const();
38        match self {
39            Self::AbilityWord(ability) => abilities.push(ability as &dyn AbilityTreeNode),
40            Self::Keyword(ability) => abilities.push(ability as &dyn AbilityTreeNode),
41            Self::Written(ability) => abilities.push(ability as &dyn AbilityTreeNode),
42        };
43        abilities
44    }
45
46    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
47        match self {
48            Self::AbilityWord(ability) => ability.display(out),
49            Self::Keyword(ability) => ability.display(out),
50            Self::Written(ability) => ability.display(out),
51        }
52    }
53
54    fn node_tag(&self) -> &'static str {
55        "ability kind"
56    }
57
58    #[cfg(feature = "spanned_tree")]
59    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
60        match self {
61            Self::AbilityWord(child) => child.node_span(),
62            Self::Keyword(child) => child.node_span(),
63            Self::Written(child) => child.node_span(),
64        }
65    }
66}
67
68#[cfg(feature = "parser")]
69impl crate::utils::DummyInit for AbilityKind {
70    fn dummy_init() -> Self {
71        Self::Written(crate::utils::dummy())
72    }
73}
74
75/// A MTG Ability.
76///
77/// From the comprehensive rules 113:
78/// 1. Text on an object that explains what that object does or can do.
79/// 2. An activated or triggered ability on the stack. This kind of ability is an object.
80/// See rule 113, “Abilities,” and section 6, “Spells, Abilities, and Effects.”
81///
82/// See also <https://mtg.fandom.com/wiki/Ability>
83#[derive(serde::Serialize, serde::Deserialize)]
84#[derive(Debug, Clone, PartialEq, Eq)]
85pub enum Ability {
86    /// A spell abilty, [CR 113.3a]
87    Spell(spell::SpellAbility),
88    /// An activated abilty, [CR 113.3b]
89    Activated(activated::ActivatedAbility),
90    /// A triggerd abilty, [CR 113.3c]
91    Triggered(triggered::TriggeredAbility),
92    /// A static abilty, [CR 113.3d]
93    Static(statik::StaticAbility),
94}
95
96#[cfg(feature = "spanned_tree")]
97impl Ability {
98    pub fn span(&self) -> crate::ability_tree::span::TreeSpan {
99        match self {
100            Self::Spell(ability) => ability.span,
101            Self::Activated(ability) => ability.span,
102            Self::Triggered(ability) => ability.span,
103            Self::Static(ability) => ability.span,
104        }
105    }
106}
107
108impl AbilityTreeNode for Ability {
109    fn node_id(&self) -> usize {
110        use idris::Idris;
111        super::NodeKind::Ability.id()
112    }
113
114    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
115        let mut abilities = arrayvec::ArrayVec::new_const();
116        match self {
117            Self::Spell(ability) => abilities.push(ability as &dyn AbilityTreeNode),
118            Self::Activated(ability) => abilities.push(ability as &dyn AbilityTreeNode),
119            Self::Triggered(ability) => abilities.push(ability as &dyn AbilityTreeNode),
120            Self::Static(ability) => abilities.push(ability as &dyn AbilityTreeNode),
121        };
122        abilities
123    }
124
125    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
126        match self {
127            Ability::Spell(spell) => spell.display(out)?,
128            Ability::Activated(activated) => activated.display(out)?,
129            Ability::Triggered(triggered) => triggered.display(out)?,
130            Ability::Static(statik) => statik.display(out)?,
131        }
132        Ok(())
133    }
134
135    fn node_tag(&self) -> &'static str {
136        "text ability"
137    }
138
139    #[cfg(feature = "spanned_tree")]
140    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
141        match self {
142            Self::Spell(child) => child.node_span(),
143            Self::Activated(child) => child.node_span(),
144            Self::Triggered(child) => child.node_span(),
145            Self::Static(child) => child.node_span(),
146        }
147    }
148}
149
150#[cfg(feature = "parser")]
151impl crate::utils::DummyInit for Ability {
152    fn dummy_init() -> Self {
153        Self::Spell(crate::utils::dummy())
154    }
155}
156
157/// A Keyword Ability.
158///
159/// From the comprehensive rules:
160/// A game term, such as “flying” or “haste,” used as shorthand for a longer
161/// ability or group of abilities. See rule 702, “Keyword Abilities.”
162///
163/// In the tree, keyword abilities are expanded such that they keep the
164/// keyword, but also carry the full ability expanded to its actual meaning.
165///
166/// See also <https://mtg.fandom.com/wiki/Keyword_ability>
167#[derive(serde::Serialize, serde::Deserialize)]
168#[derive(Debug, Clone, PartialEq, Eq)]
169pub struct KeywordAbility {
170    pub keyword: keyword::ExpandedKeywordAbility,
171    pub ability: Ability,
172    #[cfg(feature = "spanned_tree")]
173    pub span: crate::ability_tree::span::TreeSpan,
174}
175
176impl AbilityTreeNode for KeywordAbility {
177    fn node_id(&self) -> usize {
178        use idris::Idris;
179        super::NodeKind::KeywordAbilityIdMarker.id()
180    }
181
182    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
183        let mut abilities = arrayvec::ArrayVec::new_const();
184        abilities.push(&self.keyword as &dyn AbilityTreeNode);
185        abilities.push(&self.ability as &dyn AbilityTreeNode);
186        abilities
187    }
188
189    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
190        use std::io::Write;
191        write!(out, "keyword ability:")?;
192        out.push_inter_branch()?;
193        write!(out, "keyword: ")?;
194        self.keyword.display(out)?;
195        out.next_final_branch()?;
196        write!(out, "expanded ability: ")?;
197        self.ability.display(out)?;
198        out.pop_branch();
199        Ok(())
200    }
201
202    fn node_tag(&self) -> &'static str {
203        "keyword ability"
204    }
205
206    #[cfg(feature = "spanned_tree")]
207    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
208        self.span
209    }
210}
211
212#[cfg(feature = "parser")]
213impl crate::utils::DummyInit for KeywordAbility {
214    fn dummy_init() -> Self {
215        Self {
216            keyword: crate::utils::dummy(),
217            ability: crate::utils::dummy(),
218            #[cfg(feature = "spanned_tree")]
219            span: Default::default(),
220        }
221    }
222}
223
224/// A Keyword Ability.
225///
226/// An ability word is a word that thematically groups cards with a common functionality,
227/// but has no special meaning in the Comprehensive Rules.
228///
229/// See also <https://mtg.fandom.com/wiki/Ability_word>
230#[derive(serde::Serialize, serde::Deserialize)]
231#[derive(Debug, Clone, PartialEq, Eq)]
232pub struct AbilityWordAbility {
233    pub word: crate::ability_tree::terminals::AbilityWord,
234    pub ability: Ability,
235    #[cfg(feature = "spanned_tree")]
236    pub span: crate::ability_tree::span::TreeSpan,
237}
238
239impl AbilityTreeNode for AbilityWordAbility {
240    fn node_id(&self) -> usize {
241        use idris::Idris;
242        super::NodeKind::AbilityWordAbility.id()
243    }
244
245    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
246        let mut abilities = arrayvec::ArrayVec::new_const();
247        abilities.push(&self.word as &dyn AbilityTreeNode);
248        abilities.push(&self.ability as &dyn AbilityTreeNode);
249        abilities
250    }
251
252    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
253        use std::io::Write;
254        write!(out, "keyword ability:")?;
255        out.push_inter_branch()?;
256        write!(out, "keyword: ")?;
257        self.word.display(out)?;
258        out.next_final_branch()?;
259        write!(out, "expanded ability: ")?;
260        self.ability.display(out)?;
261        out.pop_branch();
262        Ok(())
263    }
264
265    fn node_tag(&self) -> &'static str {
266        "ability word"
267    }
268
269    #[cfg(feature = "spanned_tree")]
270    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
271        self.span
272    }
273}
274
275#[cfg(feature = "parser")]
276impl crate::utils::DummyInit for AbilityWordAbility {
277    fn dummy_init() -> Self {
278        Self {
279            word: crate::utils::dummy(),
280            ability: crate::utils::dummy(),
281            #[cfg(feature = "spanned_tree")]
282            span: Default::default(),
283        }
284    }
285}