boseiju/ability_tree/
imperative.rs1mod choose_imperative;
2mod create_token_imperative;
3mod deals_damage_imperative;
4mod destroy_imperative;
5mod discard_imperative;
6mod draw_imperative;
7mod exile_imperative;
8mod gain_life;
9mod generate_continuous_effect_imperative;
10mod put_counters_imperative;
11mod remove_counters_imperative;
12mod return_imperative;
13mod sacrifice_imperative;
14
15pub use choose_imperative::ChooseImperative;
16pub use create_token_imperative::CreateTokenImperative;
17pub use create_token_imperative::CreatedTokenKind;
18pub use create_token_imperative::TokenCreation;
19pub use deals_damage_imperative::DamagesDealt;
20pub use deals_damage_imperative::DealsDamageImperative;
21pub use destroy_imperative::DestroyImperative;
22pub use discard_imperative::DiscardImperative;
23pub use draw_imperative::DrawImperative;
24pub use exile_imperative::ExileFollowUp;
25pub use exile_imperative::ExileFollowUpReturn;
26pub use exile_imperative::ExileImperative;
27pub use gain_life::GainLifeImperative;
28pub use generate_continuous_effect_imperative::GenerateContinuousEffectImperative;
29pub use put_counters_imperative::CounterKind;
30pub use put_counters_imperative::CounterOnPermanent;
31pub use put_counters_imperative::PutCountersImperative;
32pub use remove_counters_imperative::RemovableCounterKind;
33pub use remove_counters_imperative::RemovableCounterOnPermanent;
34pub use remove_counters_imperative::RemoveCountersImperative;
35pub use return_imperative::ReturnImperative;
36pub use sacrifice_imperative::SacrificeImperative;
37
38use crate::ability_tree::AbilityTreeNode;
39use crate::ability_tree::MAX_CHILDREN_PER_NODE;
40
41#[derive(serde::Serialize, serde::Deserialize)]
48#[derive(Debug, Clone, PartialEq, Eq)]
49pub enum Imperative {
50 Choose(ChooseImperative),
51 CreateToken(CreateTokenImperative),
52 DealsDamage(DealsDamageImperative),
53 Destroy(DestroyImperative),
54 Discard(DiscardImperative),
55 Draw(DrawImperative),
56 Exile(ExileImperative),
57 GainLife(GainLifeImperative),
58 GenerateContinuousEffect(GenerateContinuousEffectImperative),
59 PutCounters(PutCountersImperative),
60 RemoveCounters(RemoveCountersImperative),
61 Return(ReturnImperative),
62 Sacrifice(SacrificeImperative),
63}
64
65impl AbilityTreeNode for Imperative {
66 fn node_id(&self) -> usize {
67 use idris::Idris;
68 crate::ability_tree::NodeKind::Imperative.id()
69 }
70
71 fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
72 let mut children = arrayvec::ArrayVec::new_const();
73 match self {
74 Self::Choose(child) => children.push(child as &dyn AbilityTreeNode),
75 Self::CreateToken(child) => children.push(child as &dyn AbilityTreeNode),
76 Self::DealsDamage(child) => children.push(child as &dyn AbilityTreeNode),
77 Self::Destroy(child) => children.push(child as &dyn AbilityTreeNode),
78 Self::Discard(child) => children.push(child as &dyn AbilityTreeNode),
79 Self::Draw(child) => children.push(child as &dyn AbilityTreeNode),
80 Self::Exile(child) => children.push(child as &dyn AbilityTreeNode),
81 Self::GainLife(child) => children.push(child as &dyn AbilityTreeNode),
82 Self::GenerateContinuousEffect(child) => children.push(child as &dyn AbilityTreeNode),
83 Self::PutCounters(child) => children.push(child as &dyn AbilityTreeNode),
84 Self::RemoveCounters(child) => children.push(child as &dyn AbilityTreeNode),
85 Self::Return(child) => children.push(child as &dyn AbilityTreeNode),
86 Self::Sacrifice(child) => children.push(child as &dyn AbilityTreeNode),
87 }
88 children
89 }
90
91 fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
92 use std::io::Write;
93 write!(out, "imperative:")?;
94 out.push_final_branch()?;
95 match self {
96 Imperative::Choose(imperative) => imperative.display(out)?,
97 Imperative::CreateToken(imperative) => imperative.display(out)?,
98 Imperative::DealsDamage(imperative) => imperative.display(out)?,
99 Imperative::Destroy(imperative) => imperative.display(out)?,
100 Imperative::Discard(imperative) => imperative.display(out)?,
101 Imperative::Draw(imperative) => imperative.display(out)?,
102 Imperative::Exile(imperative) => imperative.display(out)?,
103 Imperative::GainLife(imperative) => imperative.display(out)?,
104 Imperative::GenerateContinuousEffect(imperative) => imperative.display(out)?,
105 Imperative::PutCounters(imperative) => imperative.display(out)?,
106 Imperative::RemoveCounters(imperative) => imperative.display(out)?,
107 Imperative::Return(imperative) => imperative.display(out)?,
108 Imperative::Sacrifice(imperative) => imperative.display(out)?,
109 }
110 out.pop_branch();
111 Ok(())
112 }
113
114 fn node_tag(&self) -> &'static str {
115 "imperative"
116 }
117
118 #[cfg(feature = "spanned_tree")]
119 fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
120 match self {
121 Self::Choose(child) => child.node_span(),
122 Self::CreateToken(child) => child.node_span(),
123 Self::DealsDamage(child) => child.node_span(),
124 Self::Destroy(child) => child.node_span(),
125 Self::Discard(child) => child.node_span(),
126 Self::Draw(child) => child.node_span(),
127 Self::Exile(child) => child.node_span(),
128 Self::GainLife(child) => child.node_span(),
129 Self::GenerateContinuousEffect(child) => child.node_span(),
130 Self::PutCounters(child) => child.node_span(),
131 Self::RemoveCounters(child) => child.node_span(),
132 Self::Return(child) => child.node_span(),
133 Self::Sacrifice(child) => child.node_span(),
134 }
135 }
136}
137
138#[cfg(feature = "parser")]
139impl crate::utils::DummyInit for Imperative {
140 fn dummy_init() -> Self {
141 Self::Destroy(crate::utils::dummy())
142 }
143}
144
145#[derive(serde::Serialize, serde::Deserialize)]
151#[derive(Debug, Clone, PartialEq, Eq)]
152pub struct ImperativeList {
153 pub executing_player: crate::ability_tree::player::PlayerSpecifier,
154 pub condition: Option<crate::ability_tree::conditional::Conditional>,
155 pub imperatives: crate::utils::HeapArrayVec<Imperative, MAX_CHILDREN_PER_NODE>,
156 #[cfg(feature = "spanned_tree")]
157 pub span: crate::ability_tree::span::TreeSpan,
158}
159
160impl AbilityTreeNode for ImperativeList {
161 fn node_id(&self) -> usize {
162 use idris::Idris;
163 crate::ability_tree::NodeKind::ImperativeList.id()
164 }
165
166 fn children(&self) -> arrayvec::ArrayVec<&dyn AbilityTreeNode, MAX_CHILDREN_PER_NODE> {
167 use crate::ability_tree::dummy_terminal::TreeNodeDummyTerminal;
168
169 let mut children = arrayvec::ArrayVec::new_const();
170 children.push(&self.executing_player as &dyn AbilityTreeNode);
171 match self.condition.as_ref() {
172 Some(condition) => children.push(condition as &dyn AbilityTreeNode),
173 None => children.push(TreeNodeDummyTerminal::none_node() as &dyn AbilityTreeNode),
174 }
175 for imperative in self.imperatives.iter() {
176 children.push(imperative as &dyn AbilityTreeNode);
177 }
178 children
179 }
180
181 fn display(&self, out: &mut crate::utils::TreeFormatter<'_>) -> std::io::Result<()> {
182 use std::io::Write;
183 write!(out, "imperative list:")?;
184 out.push_inter_branch()?;
185 write!(out, "executing player:")?;
186 self.executing_player.display(out)?;
187 out.next_inter_branch()?;
188 match self.condition.as_ref() {
189 Some(condition) => condition.display(out)?,
190 None => write!(out, "if condition: none")?,
191 }
192 out.next_final_branch()?;
193 write!(out, "imperatives:")?;
194 for imperative in self.imperatives.iter().take(self.imperatives.len().saturating_sub(1)) {
195 out.push_inter_branch()?;
196 imperative.display(out)?;
197 out.pop_branch();
198 }
199 if let Some(imperative) = self.imperatives.last() {
200 out.push_final_branch()?;
201 imperative.display(out)?;
202 out.pop_branch();
203 }
204 out.pop_branch();
205 Ok(())
206 }
207
208 fn node_tag(&self) -> &'static str {
209 "imperative list"
210 }
211
212 #[cfg(feature = "spanned_tree")]
213 fn node_span(&self) -> crate::ability_tree::span::TreeSpan {
214 self.span
215 }
216}
217
218#[cfg(feature = "parser")]
219impl crate::utils::DummyInit for ImperativeList {
220 fn dummy_init() -> Self {
221 Self {
222 executing_player: crate::utils::dummy(),
223 imperatives: crate::utils::dummy(),
224 condition: None,
225 #[cfg(feature = "spanned_tree")]
226 span: Default::default(),
227 }
228 }
229}