Skip to main content

arora_behavior/
lib.rs

1//! The behavior abstraction: anything the Arora runtime can tick.
2//!
3//! A [`Behavior`] is the runtime's "what to do each step". The behavior tree is
4//! one (`arora-behavior-tree`'s `TreeBehavior`); a Vizij node graph is another.
5//! The runtime accepts any of them interchangeably — it just swaps the
6//! interpreter.
7//!
8//! Each tick a behavior gets a [`BehaviorContext`]: the shared
9//! [`DataStore`](arora_types::data::DataStore) (read inputs, write intent /
10//! outputs) and a [`CallBridge`](arora_types::call::CallBridge) (so module-calling
11//! behaviors like the behavior tree can reach the engine). A behavior uses
12//! whichever it needs — a graph reads/writes the store; the tree drives the
13//! caller.
14//!
15//! Timing is not a tick argument. The runtime publishes the frame's clock into
16//! the store under the [`golden`] keys before it ticks, so a behavior that needs
17//! `dt` or elapsed time reads it from the store like any other slot.
18
19use arora_types::call::CallBridge;
20use arora_types::data::DataStore;
21
22pub mod golden;
23
24/// Whether a behavior wants to be ticked again.
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum BehaviorStatus {
27    /// Tick me again next step (a node graph; a tree still running).
28    Running,
29    /// I reached a terminal state; the runtime may drop me.
30    Done,
31}
32
33/// What a [`Behavior`] receives each [`tick`](Behavior::tick).
34pub struct BehaviorContext<'a> {
35    /// The shared blackboard: read inputs, write intent / outputs.
36    pub store: &'a dyn DataStore,
37    /// The module-call bridge (the engine), for behaviors that call modules.
38    pub caller: &'a mut dyn CallBridge,
39}
40
41/// A behavior failed to tick.
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct BehaviorError {
44    /// Human-readable description.
45    pub message: String,
46}
47
48impl std::fmt::Display for BehaviorError {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.write_str(&self.message)
51    }
52}
53
54impl std::error::Error for BehaviorError {}
55
56/// Something the Arora runtime ticks once per step.
57///
58/// Implemented by the behavior tree (`arora-behavior-tree`'s `TreeBehavior`) and
59/// by external interpreters such as a Vizij node graph. The runtime holds a
60/// queue of `Box<dyn Behavior>` and ticks them without knowing which is which.
61///
62/// Not `Send`: the runtime is a single-owner, single-thread step loop.
63pub trait Behavior {
64    /// Advance one step. Return [`BehaviorStatus::Running`] to be ticked again,
65    /// or [`BehaviorStatus::Done`] to be dropped.
66    fn tick(&mut self, ctx: &mut BehaviorContext) -> Result<BehaviorStatus, BehaviorError>;
67}