beetry_core/lib.rs
1//! # Beetry Core
2//!
3//! This crate is an internal Beetry implementation crate and is not considered
4//! part of the public API. For public APIs, use the `beetry` crate.
5//!
6//! `beetry-core` defines foundational behavior tree framework traits and
7//! concepts.
8//!
9//! - [`Node`]: the trait every executable tree node implements
10//! - [`Ticker`]: a driver that advances a tree from an external tick source
11//! - [`ConditionBehavior`]: the behavior contract used by [`Condition`] leaf
12//! nodes
13//! - [`ActionBehavior`]: the behavior contract used by [`Action`] leaf nodes
14//!
15//! ## `Node`
16//!
17//! [`Node`] is the central runtime trait in Beetry. Every control node,
18//! decorator, condition, action, or whole tree is ultimately driven through the
19//! same interface. This keeps the tree runtime uniform: composite nodes can
20//! schedule children without needing a different protocol from leaf nodes, and
21//! higher-level drivers only need to understand the node lifecycle.
22//!
23//! ## `Ticker`
24//!
25//! [`Ticker`] ticks a tree from an external tick source.
26//!
27//! Because [`Ticker`] can be built from a custom stream, each application can
28//! define its own ticking mechanism without changing the tree implementation.
29//!
30//! ## Leaf behavior concepts
31//!
32//! ### `Condition`
33//!
34//! [`ConditionBehavior`] is the minimal synchronous leaf contract. It is used
35//! by [`Condition`], which wraps the behavior and maps its condition evaluation
36//! to [`TickStatus::Success`] or [`TickStatus::Failure`].
37//!
38//! ### `Action`
39//!
40//! [`ActionBehavior`] is the asynchronous leaf contract used by [`Action`].
41//! [`Action`] wraps the behavior and uses it to construct an [`ActionTask`]
42//! that can be registered with an executor instead of directly returning a
43//! [`TickStatus`] from `tick`.
44//!
45//! Note: Action abort is currently implemented as a blocking operation: it
46//! signals the executor to abort the task, then waits until the task reaches a
47//! terminal state.
48
49pub mod leaf;
50mod node;
51mod root;
52mod task;
53mod tree;
54
55pub use leaf::{
56 Action, ActionBehavior, BoxActionBehavior, BoxConditionBehavior, Condition, ConditionBehavior,
57};
58#[cfg(any(test, feature = "mock"))]
59pub use node::MockNode;
60pub use node::{BoxNode, Node, NonEmptyNodes};
61pub use root::Root;
62pub use tree::{PeriodicTick, Ticker, TickerError, Tree};
63pub type PeriodicTicker = Ticker<PeriodicTick>;
64
65pub use task::{
66 AbortTask, ActionTask, BoxTaskFuture, ExecutorConcept, QueryTask, RegisterTask, Task,
67 TaskDescription, TaskHandle, TaskStatus,
68};
69
70#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
71/// Result of a single node tick.
72pub enum TickStatus {
73 /// The node finished unsuccessfully.
74 Failure,
75 /// The node finished successfully.
76 Success,
77 /// The node is still in progress.
78 Running,
79}
80
81impl TickStatus {
82 /// Returns `true` if the status is terminal.
83 #[must_use]
84 pub fn is_terminal(&self) -> bool {
85 matches!(self, Self::Success | Self::Failure)
86 }
87}