mecha10_behavior_runtime/
composition.rs1use crate::{BehaviorNode, BoxedBehavior, NodeStatus};
6use async_trait::async_trait;
7use mecha10_core::Context;
8use tracing::{debug, warn};
9
10#[derive(Debug)]
38pub struct SequenceNode {
39 children: Vec<BoxedBehavior>,
40 current_index: usize,
41}
42
43impl SequenceNode {
44 pub fn new(children: Vec<BoxedBehavior>) -> Self {
46 Self {
47 children,
48 current_index: 0,
49 }
50 }
51
52 pub fn add_child(&mut self, child: BoxedBehavior) {
54 self.children.push(child);
55 }
56
57 pub fn len(&self) -> usize {
59 self.children.len()
60 }
61
62 pub fn is_empty(&self) -> bool {
64 self.children.is_empty()
65 }
66}
67
68#[async_trait]
69impl BehaviorNode for SequenceNode {
70 async fn tick(&mut self, ctx: &Context) -> anyhow::Result<NodeStatus> {
71 if self.children.is_empty() {
73 return Ok(NodeStatus::Success);
74 }
75
76 let total_children = self.children.len();
78 while self.current_index < total_children {
79 debug!(
80 "Sequence: ticking child {} of {}",
81 self.current_index + 1,
82 total_children
83 );
84
85 let child = &mut self.children[self.current_index];
86 match child.tick(ctx).await? {
87 NodeStatus::Success => {
88 self.current_index += 1;
90 }
91 NodeStatus::Failure => {
92 debug!("Sequence: child {} failed", self.current_index + 1);
94 return Ok(NodeStatus::Failure);
95 }
96 NodeStatus::Running => {
97 return Ok(NodeStatus::Running);
99 }
100 }
101 }
102
103 debug!("Sequence: all children succeeded");
105 Ok(NodeStatus::Success)
106 }
107
108 async fn reset(&mut self) -> anyhow::Result<()> {
109 self.current_index = 0;
110 for child in &mut self.children {
111 child.reset().await?;
112 }
113 Ok(())
114 }
115
116 async fn on_init(&mut self, ctx: &Context) -> anyhow::Result<()> {
117 for child in &mut self.children {
118 child.on_init(ctx).await?;
119 }
120 Ok(())
121 }
122
123 async fn on_terminate(&mut self, ctx: &Context) -> anyhow::Result<()> {
124 for child in &mut self.children {
125 child.on_terminate(ctx).await?;
126 }
127 Ok(())
128 }
129
130 fn name(&self) -> &str {
131 "sequence"
132 }
133}
134
135#[derive(Debug)]
163pub struct SelectOrNode {
164 children: Vec<BoxedBehavior>,
165 current_index: usize,
166}
167
168impl SelectOrNode {
169 pub fn new(children: Vec<BoxedBehavior>) -> Self {
171 Self {
172 children,
173 current_index: 0,
174 }
175 }
176
177 pub fn add_child(&mut self, child: BoxedBehavior) {
179 self.children.push(child);
180 }
181
182 pub fn len(&self) -> usize {
184 self.children.len()
185 }
186
187 pub fn is_empty(&self) -> bool {
189 self.children.is_empty()
190 }
191}
192
193#[async_trait]
194impl BehaviorNode for SelectOrNode {
195 async fn tick(&mut self, ctx: &Context) -> anyhow::Result<NodeStatus> {
196 if self.children.is_empty() {
198 return Ok(NodeStatus::Failure);
199 }
200
201 let total_children = self.children.len();
203 while self.current_index < total_children {
204 debug!(
205 "Selector: ticking child {} of {}",
206 self.current_index + 1,
207 total_children
208 );
209
210 let child = &mut self.children[self.current_index];
211 match child.tick(ctx).await? {
212 NodeStatus::Success => {
213 debug!("Selector: child {} succeeded", self.current_index + 1);
215 return Ok(NodeStatus::Success);
216 }
217 NodeStatus::Failure => {
218 warn!("Selector: child {} failed, trying next", self.current_index + 1);
220 self.current_index += 1;
221 }
222 NodeStatus::Running => {
223 return Ok(NodeStatus::Running);
225 }
226 }
227 }
228
229 debug!("Selector: all children failed");
231 Ok(NodeStatus::Failure)
232 }
233
234 async fn reset(&mut self) -> anyhow::Result<()> {
235 self.current_index = 0;
236 for child in &mut self.children {
237 child.reset().await?;
238 }
239 Ok(())
240 }
241
242 async fn on_init(&mut self, ctx: &Context) -> anyhow::Result<()> {
243 for child in &mut self.children {
244 child.on_init(ctx).await?;
245 }
246 Ok(())
247 }
248
249 async fn on_terminate(&mut self, ctx: &Context) -> anyhow::Result<()> {
250 for child in &mut self.children {
251 child.on_terminate(ctx).await?;
252 }
253 Ok(())
254 }
255
256 fn name(&self) -> &str {
257 "selector"
258 }
259}
260
261#[derive(Debug, Clone, Copy, PartialEq, Eq)]
267pub enum ParallelPolicy {
268 RequireAll,
270
271 RequireOne,
273
274 RequireN(usize),
276}
277
278#[derive(Debug)]
305pub struct ParallelNode {
306 children: Vec<BoxedBehavior>,
307 policy: ParallelPolicy,
308 child_statuses: Vec<NodeStatus>,
309}
310
311impl ParallelNode {
312 pub fn new(children: Vec<BoxedBehavior>, policy: ParallelPolicy) -> Self {
314 let child_statuses = vec![NodeStatus::Running; children.len()];
315 Self {
316 children,
317 policy,
318 child_statuses,
319 }
320 }
321
322 pub fn add_child(&mut self, child: BoxedBehavior) {
324 self.children.push(child);
325 self.child_statuses.push(NodeStatus::Running);
326 }
327
328 pub fn len(&self) -> usize {
330 self.children.len()
331 }
332
333 pub fn is_empty(&self) -> bool {
335 self.children.is_empty()
336 }
337}
338
339#[async_trait]
340impl BehaviorNode for ParallelNode {
341 async fn tick(&mut self, ctx: &Context) -> anyhow::Result<NodeStatus> {
342 if self.children.is_empty() {
344 return Ok(NodeStatus::Success);
345 }
346
347 for (i, child) in self.children.iter_mut().enumerate() {
349 if self.child_statuses[i].is_running() {
350 let status = child.tick(ctx).await?;
351 self.child_statuses[i] = status;
352 debug!("Parallel: child {} status: {}", i + 1, status);
353 }
354 }
355
356 let success_count = self.child_statuses.iter().filter(|s| s.is_success()).count();
358 let failure_count = self.child_statuses.iter().filter(|s| s.is_failure()).count();
359 let _running_count = self.child_statuses.iter().filter(|s| s.is_running()).count();
360
361 match self.policy {
362 ParallelPolicy::RequireAll => {
363 if failure_count > 0 {
364 debug!("Parallel (RequireAll): at least one child failed");
365 Ok(NodeStatus::Failure)
366 } else if success_count == self.children.len() {
367 debug!("Parallel (RequireAll): all children succeeded");
368 Ok(NodeStatus::Success)
369 } else {
370 Ok(NodeStatus::Running)
371 }
372 }
373 ParallelPolicy::RequireOne => {
374 if success_count > 0 {
375 debug!("Parallel (RequireOne): at least one child succeeded");
376 Ok(NodeStatus::Success)
377 } else if failure_count == self.children.len() {
378 debug!("Parallel (RequireOne): all children failed");
379 Ok(NodeStatus::Failure)
380 } else {
381 Ok(NodeStatus::Running)
382 }
383 }
384 ParallelPolicy::RequireN(n) => {
385 if success_count >= n {
386 debug!("Parallel (RequireN({})): {} children succeeded", n, success_count);
387 Ok(NodeStatus::Success)
388 } else if (self.children.len() - failure_count) < n {
389 debug!("Parallel (RequireN({})): not enough children can succeed", n);
391 Ok(NodeStatus::Failure)
392 } else {
393 Ok(NodeStatus::Running)
394 }
395 }
396 }
397 }
398
399 async fn reset(&mut self) -> anyhow::Result<()> {
400 for i in 0..self.children.len() {
401 self.child_statuses[i] = NodeStatus::Running;
402 self.children[i].reset().await?;
403 }
404 Ok(())
405 }
406
407 async fn on_init(&mut self, ctx: &Context) -> anyhow::Result<()> {
408 for child in &mut self.children {
409 child.on_init(ctx).await?;
410 }
411 Ok(())
412 }
413
414 async fn on_terminate(&mut self, ctx: &Context) -> anyhow::Result<()> {
415 for child in &mut self.children {
416 child.on_terminate(ctx).await?;
417 }
418 Ok(())
419 }
420
421 fn name(&self) -> &str {
422 "parallel"
423 }
424}