Skip to main content

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}