boseiju/ability_tree/
statement.rs

1use crate::ability_tree::AbilityTreeNode;
2use crate::ability_tree::MAX_CHILDREN_PER_NODE;
3
4/// Fixme: doc
5#[derive(serde::Serialize, serde::Deserialize)]
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum Statement {
8    Imperatives(crate::ability_tree::imperative::ImperativeList),
9    May(MayAbility),
10    ReplacableImperatives(ReplacableImperatives),
11}
12
13#[cfg(feature = "spanned_tree")]
14impl Statement {
15    pub fn span(&self) -> crate::ability_tree::span::TreeSpan {
16        match self {
17            Self::Imperatives(child) => child.span,
18            Self::May(child) => child.span,
19            Self::ReplacableImperatives(child) => child.span,
20        }
21    }
22}
23
24impl crate::ability_tree::AbilityTreeNode for Statement {
25    fn node_id(&self) -> usize {
26        use idris::Idris;
27        crate::ability_tree::NodeKind::Statement.id()
28    }
29
30    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
31        let mut abilities = arrayvec::ArrayVec::new_const();
32        match self {
33            Self::Imperatives(ability) => abilities.push(ability as &dyn AbilityTreeNode),
34            Self::May(ability) => abilities.push(ability as &dyn AbilityTreeNode),
35            Self::ReplacableImperatives(ability) => abilities.push(ability as &dyn AbilityTreeNode),
36        };
37        abilities
38    }
39
40    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
41        use std::io::Write;
42        write!(out, "statement:")?;
43        out.push_final_branch()?;
44        match self {
45            Statement::Imperatives(imp) => imp.display(out)?,
46            Statement::May(may) => may.display(out)?,
47            Statement::ReplacableImperatives(may) => may.display(out)?,
48        }
49        out.pop_branch();
50        Ok(())
51    }
52
53    fn node_tag(&self) -> &'static str {
54        "statement"
55    }
56
57    #[cfg(feature = "spanned_tree")]
58    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
59        match self {
60            Self::Imperatives(child) => child.node_span(),
61            Self::May(child) => child.node_span(),
62            Self::ReplacableImperatives(child) => child.node_span(),
63        }
64    }
65}
66
67#[cfg(feature = "parser")]
68impl crate::utils::DummyInit for Statement {
69    fn dummy_init() -> Self {
70        Self::Imperatives(crate::utils::dummy())
71    }
72}
73
74#[derive(serde::Serialize, serde::Deserialize)]
75#[derive(Debug, Clone, PartialEq, Eq)]
76pub struct MayAbility {
77    pub player: crate::ability_tree::player::PlayerSpecifier,
78    pub action: crate::ability_tree::imperative::ImperativeList,
79    pub if_it_is_done: Option<Box<Statement>>,
80    pub if_not_done: Option<Box<Statement>>,
81    #[cfg(feature = "spanned_tree")]
82    pub span: crate::ability_tree::span::TreeSpan,
83}
84
85impl crate::ability_tree::AbilityTreeNode for MayAbility {
86    fn node_id(&self) -> usize {
87        use idris::Idris;
88        crate::ability_tree::NodeKind::MayAbility.id()
89    }
90
91    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
92        use crate::ability_tree::dummy_terminal::TreeNodeDummyTerminal;
93
94        let mut children = arrayvec::ArrayVec::new_const();
95        children.push(&self.player as &dyn AbilityTreeNode);
96        children.push(&self.action as &dyn AbilityTreeNode);
97        match self.if_it_is_done.as_ref() {
98            Some(child) => children.push(child.as_ref() as &dyn AbilityTreeNode),
99            None => children.push(TreeNodeDummyTerminal::none_node() as &dyn AbilityTreeNode),
100        }
101        match self.if_not_done.as_ref() {
102            Some(child) => children.push(child.as_ref() as &dyn AbilityTreeNode),
103            None => children.push(TreeNodeDummyTerminal::none_node() as &dyn AbilityTreeNode),
104        }
105        children
106    }
107
108    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
109        use std::io::Write;
110        write!(out, "may ability")?;
111        out.push_inter_branch()?;
112        write!(out, "player:")?;
113        self.player.display(out)?;
114        out.next_inter_branch()?;
115        write!(out, "may:")?;
116        self.action.display(out)?;
117        out.next_inter_branch()?;
118        write!(out, "if it is done:")?;
119        match self.if_it_is_done.as_ref() {
120            Some(action) => action.display(out)?,
121            None => write!(out, "none")?,
122        }
123        out.next_final_branch()?;
124        write!(out, "if it is not done:")?;
125        match self.if_not_done.as_ref() {
126            Some(action) => action.display(out)?,
127            None => write!(out, "none")?,
128        }
129        out.pop_branch();
130        Ok(())
131    }
132
133    fn node_tag(&self) -> &'static str {
134        "may ability"
135    }
136
137    #[cfg(feature = "spanned_tree")]
138    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
139        self.span
140    }
141}
142
143#[cfg(feature = "parser")]
144impl crate::utils::DummyInit for MayAbility {
145    fn dummy_init() -> Self {
146        Self {
147            player: crate::utils::dummy(),
148            action: crate::utils::dummy(),
149            if_it_is_done: None,
150            if_not_done: None,
151            #[cfg(feature = "spanned_tree")]
152            span: Default::default(),
153        }
154    }
155}
156
157/// Replacable imperatives are a list of imperatives that can be replaced by another
158/// list if some condition is met.
159///
160/// They always take the form: "do X. if Y, do Z instead".
161#[derive(serde::Serialize, serde::Deserialize)]
162#[derive(Debug, Clone, PartialEq, Eq)]
163pub struct ReplacableImperatives {
164    pub first_clause: crate::ability_tree::imperative::ImperativeList,
165    pub condition: crate::ability_tree::conditional::Conditional,
166    pub replacing_clause: crate::ability_tree::imperative::ImperativeList,
167    #[cfg(feature = "spanned_tree")]
168    pub span: crate::ability_tree::span::TreeSpan,
169}
170
171impl crate::ability_tree::AbilityTreeNode for ReplacableImperatives {
172    fn node_id(&self) -> usize {
173        use idris::Idris;
174        crate::ability_tree::NodeKind::ReplacableImperatives.id()
175    }
176
177    fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
178        let mut abilities = arrayvec::ArrayVec::new_const();
179        abilities.push(&self.condition as &dyn AbilityTreeNode);
180        abilities.push(&self.first_clause as &dyn AbilityTreeNode);
181        abilities.push(&self.replacing_clause as &dyn AbilityTreeNode);
182        abilities
183    }
184
185    fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
186        use std::io::Write;
187        write!(out, "replacable imperative")?;
188        out.push_inter_branch()?;
189        write!(out, "first imperative:")?;
190        out.push_final_branch()?;
191        self.first_clause.display(out)?;
192        out.pop_branch();
193        out.next_inter_branch()?;
194        write!(out, "replacing condition:")?;
195        out.push_final_branch()?;
196        self.condition.display(out)?;
197        out.pop_branch();
198        out.next_inter_branch()?;
199        write!(out, "replacing imperative:")?;
200        out.push_final_branch()?;
201        self.replacing_clause.display(out)?;
202        out.pop_branch();
203        out.pop_branch();
204        Ok(())
205    }
206
207    fn node_tag(&self) -> &'static str {
208        "replacable imperative"
209    }
210
211    #[cfg(feature = "spanned_tree")]
212    fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
213        self.span
214    }
215}
216
217#[cfg(feature = "parser")]
218impl crate::utils::DummyInit for ReplacableImperatives {
219    fn dummy_init() -> Self {
220        Self {
221            first_clause: crate::utils::dummy(),
222            condition: crate::utils::dummy(),
223            replacing_clause: crate::utils::dummy(),
224            #[cfg(feature = "spanned_tree")]
225            span: Default::default(),
226        }
227    }
228}