From eed8322cd7e1d0919ff47584469df33ffa07e0b8 Mon Sep 17 00:00:00 2001 From: andriyDev Date: Fri, 17 Jan 2025 17:52:11 -0800 Subject: [PATCH] Delete `BlackBoard` struct. (#38) This struct doesn't do anything special and is just a newtype without providing anything. I believe in the past this did more, but now it is just a needless wrapper. --- bonsai/Cargo.toml | 4 +- bonsai/src/bt.rs | 63 +++++++----------------------- bonsai/src/lib.rs | 5 +-- bonsai/src/visualizer.rs | 1 - bonsai/tests/blackboard_tests.rs | 5 +-- examples/src/3d/main.rs | 4 +- examples/src/boids/boid.rs | 2 +- examples/src/simple_npc_ai/main.rs | 4 +- 8 files changed, 25 insertions(+), 63 deletions(-) diff --git a/bonsai/Cargo.toml b/bonsai/Cargo.toml index e9000f6..b21fffa 100644 --- a/bonsai/Cargo.toml +++ b/bonsai/Cargo.toml @@ -12,7 +12,7 @@ name = "bonsai-bt" readme = "../README.md" repository = "https://github.com/sollimann/bonsai.git" rust-version = "1.80.0" -version = "0.8.1" +version = "0.9.0" [lib] name = "bonsai_bt" @@ -20,7 +20,7 @@ path = "src/lib.rs" [dependencies] petgraph = "0.6.2" -serde = { version = "1.0.137", features = ["derive"] , optional = true } +serde = { version = "1.0.137", features = ["derive"], optional = true } [dev-dependencies] serde_json = { version = "1.0.81" } diff --git a/bonsai/src/bt.rs b/bonsai/src/bt.rs index 9e7f04b..8b03709 100644 --- a/bonsai/src/bt.rs +++ b/bonsai/src/bt.rs @@ -8,46 +8,30 @@ use petgraph::Graph; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -/// A "blackboard" is a simple key/value storage shared by all the nodes of the Tree. -/// -/// It is essentially a database in which the behavior tree can store information -/// whilst traversing the tree. Certain action nodes depend on state that might be -/// dynamically created by other nodes in the tree. State is written to and read from -/// a blackboard, a messaging capability that allows nodes to share state in the behavior tree. -/// -/// An "entry" of the Blackboard is a key/value pair. +/// The execution state of a behavior tree, along with a "blackboard" (state +/// shared between all nodes in the tree). #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct BlackBoard(K); - -impl BlackBoard { - pub fn get_db(&mut self) -> &mut K { - &mut self.0 - } -} - -/// The BT struct contains a compiled (immutable) version -/// of the behavior and a blackboard key/value storage -#[derive(Clone, Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct BT { +pub struct BT { /// constructed behavior tree pub state: State, /// keep the initial state initial_behavior: Behavior, - /// blackboard - bb: BlackBoard, + /// The data storage shared by all nodes in the tree. This is generally + /// referred to as a "blackboard". State is written to and read from a + /// blackboard, allowing nodes to share state and communicate each other. + bb: B, } -impl BT { - pub fn new(behavior: Behavior, blackboard: K) -> Self { +impl BT { + pub fn new(behavior: Behavior, blackboard: B) -> Self { let backup_behavior = behavior.clone(); let bt = State::new(behavior); Self { state: bt, initial_behavior: backup_behavior, - bb: BlackBoard(blackboard), + bb: blackboard, } } @@ -67,20 +51,20 @@ impl BT { pub fn tick(&mut self, e: &E, f: &mut F) -> (Status, f64) where E: UpdateEvent, - F: FnMut(ActionArgs, &mut BlackBoard) -> (Status, f64), + F: FnMut(ActionArgs, &mut B) -> (Status, f64), { self.state.tick(e, &mut self.bb, f) } /// Retrieve a mutable reference to the blackboard for /// this Behavior Tree - pub fn get_blackboard(&mut self) -> &mut BlackBoard { + pub fn get_blackboard(&mut self) -> &mut B { &mut self.bb } /// Retrieve a mutable reference to the internal state /// of the Behavior Tree - pub fn get_state(bt: &mut BT) -> &mut State { + pub fn get_state(bt: &mut BT) -> &mut State { &mut bt.state } @@ -101,7 +85,7 @@ impl BT { } } -impl BT { +impl BT { /// Compile the behavior tree into a [graphviz](https://graphviz.org/) compatible [DiGraph](https://docs.rs/petgraph/latest/petgraph/graph/type.DiGraph.html). /// /// ```rust @@ -147,22 +131,3 @@ impl BT { (format!("{:?}", digraph), graph) } } - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - - use super::BlackBoard; - - #[test] - fn test_bb() { - // add some values to blackboard - let mut db: HashMap = HashMap::new(); - db.insert("win_width".to_string(), 10.0); - db.insert("win_height".to_string(), 12.0); - - let mut blackboard = BlackBoard(db); - let win_width = blackboard.get_db().get("win_width").unwrap().to_owned(); - assert_eq!(win_width, 10.0); - } -} diff --git a/bonsai/src/lib.rs b/bonsai/src/lib.rs index 1e710af..88747e5 100644 --- a/bonsai/src/lib.rs +++ b/bonsai/src/lib.rs @@ -65,8 +65,7 @@ //! // update counter in blackboard //! let bb = bt.get_blackboard(); //! -//! bb.get_db() -//! .entry("count".to_string()) +//! bb.entry("count".to_string()) //! .and_modify(|count| *count = acc) //! .or_insert(0) //! .to_owned(); @@ -109,7 +108,7 @@ //! assert_eq!(a, 1); //! //! let bb = bt.get_blackboard(); -//! let count = bb.get_db().get("count").unwrap(); +//! let count = bb.get("count").unwrap(); //! assert_eq!(*count, 1); //! //! // if the behavior tree concludes (reaches a steady state) diff --git a/bonsai/src/visualizer.rs b/bonsai/src/visualizer.rs index 0c267ef..41534b8 100644 --- a/bonsai/src/visualizer.rs +++ b/bonsai/src/visualizer.rs @@ -132,7 +132,6 @@ impl BT { #[cfg(test)] mod tests { use super::*; - use crate::bt::BlackBoard; use crate::visualizer::tests::TestActions::{Dec, Inc}; use crate::Behavior::{ Action, After, AlwaysSucceed, If, Invert, Select, Sequence, Wait, WaitForever, WhenAll, WhenAny, While, diff --git a/bonsai/tests/blackboard_tests.rs b/bonsai/tests/blackboard_tests.rs index 31d3b04..7b4e5f0 100644 --- a/bonsai/tests/blackboard_tests.rs +++ b/bonsai/tests/blackboard_tests.rs @@ -31,8 +31,7 @@ fn tick(mut acc: i32, dt: f64, bt: &mut BT>) - // update counter in blackboard let bb = bt.get_blackboard(); - bb.get_db() - .entry("count".to_string()) + bb.entry("count".to_string()) .and_modify(|count| *count = acc) .or_insert(0) .to_owned() @@ -64,6 +63,6 @@ fn test_crate_bt() { assert_eq!(a, 1); let bb = bt.get_blackboard(); - let count = bb.get_db().get("count").unwrap(); + let count = bb.get("count").unwrap(); assert_eq!(*count, 1); } diff --git a/examples/src/3d/main.rs b/examples/src/3d/main.rs index 7e42401..4612ea0 100644 --- a/examples/src/3d/main.rs +++ b/examples/src/3d/main.rs @@ -90,7 +90,7 @@ fn game_tick( let e: Event = UpdateArgs { dt }.into(); // get data from blackboard - let db = &*bt.get_blackboard().get_db(); + let db = bt.get_blackboard(); let inc: u64 = db.get("count").map_or(Some(0), |x| x.as_u64()).unwrap(); let mut last_pos = mouse_pos(0.0, 0.0); @@ -197,7 +197,7 @@ fn game_tick( ); // update blackboard - let db = bt.get_blackboard().get_db(); + let db = bt.get_blackboard(); // update count let _count = db diff --git a/examples/src/boids/boid.rs b/examples/src/boids/boid.rs index 9777c66..4bf09c7 100644 --- a/examples/src/boids/boid.rs +++ b/examples/src/boids/boid.rs @@ -60,7 +60,7 @@ pub fn game_tick(dt: f32, cursor: mint::Point2, boid: &mut Boid, other_boid // unwrap bt for boid let mut bt = boid.bt.clone(); - let db = &*bt.get_blackboard().get_db(); + let db = bt.get_blackboard(); let win_width: f32 = *db.get("win_width").unwrap(); let win_height: f32 = *db.get("win_height").unwrap(); diff --git a/examples/src/simple_npc_ai/main.rs b/examples/src/simple_npc_ai/main.rs index e806d1b..e891da9 100644 --- a/examples/src/simple_npc_ai/main.rs +++ b/examples/src/simple_npc_ai/main.rs @@ -36,7 +36,7 @@ fn game_tick(bt: &mut BT, state: &mut EnemyNPCState) - // for the sake of example we get access to blackboard and update // one of its values here: - blackboard.get_db().times_shot += 1; + blackboard.times_shot += 1; (Success, 0.0) } @@ -174,7 +174,7 @@ fn main() { } println!( "NPC shot {} times during the simulation.", - bt.get_blackboard().get_db().times_shot + bt.get_blackboard().times_shot ); }