boseiju/ability_tree/imperative/
remove_counters_imperative.rs

1use crate::ability_tree::AbilityTreeNode;
2use crate::ability_tree::MAX_CHILDREN_PER_NODE;
3
4const MAX_COUNTER_AMOUNT: usize = MAX_CHILDREN_PER_NODE - 1;
5
6/// Imperative to put counters on objects.
7#[derive(serde::Serialize, serde::Deserialize)]
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct RemoveCountersImperative {
10    pub object: crate::ability_tree::object::ObjectReference,
11    pub counters: crate::utils::HeapArrayVec<RemovableCounterOnPermanent, MAX_COUNTER_AMOUNT>,
12    #[cfg(feature = "spanned_tree")]
13    pub span: crate::ability_tree::span::TreeSpan,
14}
15
16impl AbilityTreeNode for RemoveCountersImperative {
17    fn node_id(&self) -> usize {
18        use idris::Idris;
19        crate::ability_tree::NodeKind::PutCountersImperative.id()
20    }
21
22    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
23        let mut children = arrayvec::ArrayVec::new_const();
24        children.push(&self.object as &dyn AbilityTreeNode);
25        for counter in self.counters.iter() {
26            children.push(counter as &dyn AbilityTreeNode);
27        }
28        children
29    }
30
31    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
32        use std::io::Write;
33        write!(out, "remove counters:")?;
34        out.push_inter_branch()?;
35        write!(out, "on object:")?;
36        out.push_final_branch()?;
37        self.object.display(out)?;
38        out.pop_branch();
39        out.next_final_branch()?;
40        write!(out, "counters:")?;
41        for (i, counter) in self.counters.iter().enumerate() {
42            if i == self.counters.len() - 1 {
43                out.push_final_branch()?;
44            } else {
45                out.push_inter_branch()?;
46            }
47            counter.display(out)?;
48            out.pop_branch();
49        }
50        out.pop_branch();
51        Ok(())
52    }
53
54    fn node_tag(&self) -> &'static str {
55        "remove counters imperative"
56    }
57
58    #[cfg(feature = "spanned_tree")]
59    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
60        self.span
61    }
62}
63
64#[cfg(feature = "parser")]
65impl crate::utils::DummyInit for RemoveCountersImperative {
66    fn dummy_init() -> Self {
67        Self {
68            object: crate::utils::dummy(),
69            counters: crate::utils::dummy(),
70            #[cfg(feature = "spanned_tree")]
71            span: Default::default(),
72        }
73    }
74}
75
76/// An amount and a kind of counters to be put on a permanent.
77#[derive(serde::Serialize, serde::Deserialize)]
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct RemovableCounterOnPermanent {
80    pub amount: crate::ability_tree::number::Number,
81    pub counter: RemovableCounterKind,
82    #[cfg(feature = "spanned_tree")]
83    pub span: crate::ability_tree::span::TreeSpan,
84}
85
86impl crate::ability_tree::AbilityTreeNode for RemovableCounterOnPermanent {
87    fn node_id(&self) -> usize {
88        use idris::Idris;
89        crate::ability_tree::NodeKind::RemovableCounterOnPermanent.id()
90    }
91
92    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
93        let mut children = arrayvec::ArrayVec::new_const();
94        children.push(&self.amount as &dyn AbilityTreeNode);
95        children.push(&self.counter as &dyn AbilityTreeNode);
96        children
97    }
98
99    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
100        use std::io::Write;
101        write!(out, "counter on permanent:")?;
102        out.push_inter_branch()?;
103        write!(out, "amount:")?;
104        out.push_final_branch()?;
105        self.amount.display(out)?;
106        out.pop_branch();
107        out.next_final_branch()?;
108        write!(out, "of counter:")?;
109        out.push_final_branch()?;
110        self.counter.display(out)?;
111        out.pop_branch();
112        out.pop_branch();
113        Ok(())
114    }
115
116    fn node_tag(&self) -> &'static str {
117        "removable counter from permanent"
118    }
119
120    #[cfg(feature = "spanned_tree")]
121    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
122        self.span
123    }
124}
125
126/// Kind of counter that is put on a permanent.
127///
128/// It's either a given kind of counter, e.g. "put a shield counter" or
129/// a previously mentionned kind of counter, e.g. "that many counters on...".
130#[derive(serde::Serialize, serde::Deserialize)]
131#[derive(Debug, Clone, PartialEq, Eq)]
132pub enum RemovableCounterKind {
133    AnyCounter {
134        #[cfg(feature = "spanned_tree")]
135        span: crate::ability_tree::span::TreeSpan,
136    },
137    NewCounter(crate::ability_tree::terminals::Counter),
138}
139
140#[cfg(feature = "spanned_tree")]
141impl RemovableCounterKind {
142    pub fn span(&self) -> crate::ability_tree::span::TreeSpan {
143        match self {
144            Self::AnyCounter { span } => *span,
145            Self::NewCounter(child) => child.span,
146        }
147    }
148}
149
150impl AbilityTreeNode for RemovableCounterKind {
151    fn node_id(&self) -> usize {
152        use idris::Idris;
153        crate::ability_tree::NodeKind::RemovableCounterKind.id()
154    }
155
156    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
157        use idris::Idris;
158
159        let mut children = arrayvec::ArrayVec::new_const();
160        match self {
161            Self::AnyCounter { .. } => children.push(crate::ability_tree::dummy_terminal::TreeNodeDummyTerminal::new(
162                crate::ability_tree::NodeKind::PreviouslyMentionnedCounter.id(),
163            ) as &dyn AbilityTreeNode),
164            Self::NewCounter(counter) => children.push(counter as &dyn AbilityTreeNode),
165        }
166        children
167    }
168
169    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
170        use std::io::Write;
171        write!(out, "counter kind:")?;
172        out.push_final_branch()?;
173        match self {
174            Self::AnyCounter { .. } => write!(out, "any kind of counter")?,
175            Self::NewCounter(counter) => counter.display(out)?,
176        }
177        out.pop_branch();
178        Ok(())
179    }
180
181    fn node_tag(&self) -> &'static str {
182        "removable counter kind"
183    }
184
185    #[cfg(feature = "spanned_tree")]
186    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
187        match self {
188            Self::AnyCounter { span } => *span,
189            Self::NewCounter(child) => child.node_span(),
190        }
191    }
192}
193
194#[cfg(feature = "parser")]
195impl crate::utils::DummyInit for RemovableCounterKind {
196    fn dummy_init() -> Self {
197        Self::AnyCounter {
198            #[cfg(feature = "spanned_tree")]
199            span: Default::default(),
200        }
201    }
202}