Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete BlackBoard struct. #38

Merged
merged 5 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bonsai/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ 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"
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" }
Expand Down
63 changes: 14 additions & 49 deletions bonsai/src/bt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Sollimann marked this conversation as resolved.
Show resolved Hide resolved
/// 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>(K);

impl<K> BlackBoard<K> {
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<A, K> {
pub struct BT<A, B> {
/// constructed behavior tree
pub state: State<A>,
/// keep the initial state
initial_behavior: Behavior<A>,
/// blackboard
bb: BlackBoard<K>,
/// 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<A: Clone, K> BT<A, K> {
pub fn new(behavior: Behavior<A>, blackboard: K) -> Self {
impl<A: Clone, B> BT<A, B> {
pub fn new(behavior: Behavior<A>, 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,
}
}

Expand All @@ -67,20 +51,20 @@ impl<A: Clone, K> BT<A, K> {
pub fn tick<E, F>(&mut self, e: &E, f: &mut F) -> (Status, f64)
where
E: UpdateEvent,
F: FnMut(ActionArgs<E, A>, &mut BlackBoard<K>) -> (Status, f64),
F: FnMut(ActionArgs<E, A>, &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<K> {
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<A, K>) -> &mut State<A> {
pub fn get_state(bt: &mut BT<A, B>) -> &mut State<A> {
&mut bt.state
}

Expand All @@ -101,7 +85,7 @@ impl<A: Clone, K> BT<A, K> {
}
}

impl<A: Clone + Debug, K: Debug> BT<A, K> {
impl<A: Clone + Debug, B: Debug> BT<A, B> {
/// Compile the behavior tree into a [graphviz](https://graphviz.org/) compatible [DiGraph](https://docs.rs/petgraph/latest/petgraph/graph/type.DiGraph.html).
///
/// ```rust
Expand Down Expand Up @@ -147,22 +131,3 @@ impl<A: Clone + Debug, K: Debug> BT<A, K> {
(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<String, f32> = 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);
Sollimann marked this conversation as resolved.
Show resolved Hide resolved
}
}
5 changes: 2 additions & 3 deletions bonsai/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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)
Expand Down
1 change: 0 additions & 1 deletion bonsai/src/visualizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ impl<A: Clone + Debug, K: Debug> BT<A, K> {
#[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,
Expand Down
5 changes: 2 additions & 3 deletions bonsai/tests/blackboard_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ fn tick(mut acc: i32, dt: f64, bt: &mut BT<TestActions, HashMap<String, i32>>) -
// 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()
Expand Down Expand Up @@ -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);
}
4 changes: 2 additions & 2 deletions examples/src/3d/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion examples/src/boids/boid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub fn game_tick(dt: f32, cursor: mint::Point2<f32>, 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();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can you check here if the &* which is first a reference () followed by a dereference (&) on line 63, followed by a reference again () on line 64 and 65 is redundant? I think this can be simplified

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Also found another case in the 3d example.


Expand Down
4 changes: 2 additions & 2 deletions examples/src/simple_npc_ai/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fn game_tick(bt: &mut BT<EnemyNPC, BlackBoardData>, 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)
}
Expand Down Expand Up @@ -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
);
}

Expand Down
Loading