| Crates.io | bonsai-mdsl |
| lib.rs | bonsai-mdsl |
| version | 0.1.0 |
| created_at | 2025-05-29 23:01:41.245134+00 |
| updated_at | 2025-05-29 23:01:41.245134+00 |
| description | A Rust library for parsing and executing behavior trees defined in MDSL (Mistreevous Domain Specific Language) into bonsai Behaviour Trees |
| homepage | https://github.com/bx2h/bonsai-mdsl |
| repository | https://github.com/bx2h/bonsai-mdsl |
| max_upload_size | |
| id | 1694485 |
| size | 118,453 |
A Rust library for parsing and executing behavior trees defined in MDSL (Mistreevous Domain Specific Language). Heavily inspired by Bonsai.
Add this to your Cargo.toml:
[dependencies]
bonsai-mdsl = "0.1"
use bonsai_mdsl::{BehaviorTree, TreeContext, NodeResult};
// Define your behavior tree in MDSL
let mdsl = r#"
root {
sequence {
action [check_health]
selector {
action [attack_enemy]
action [find_cover]
}
}
}
"#;
// Create a context with your action implementations
let mut context = TreeContext::new();
context.register_action("check_health", |ctx| {
println!("Checking health...");
NodeResult::Success
});
context.register_action("attack_enemy", |ctx| {
println!("Attacking enemy!");
NodeResult::Success
});
context.register_action("find_cover", |ctx| {
println!("Finding cover...");
NodeResult::Success
});
// Parse and execute the tree
let mut tree = BehaviorTree::from_mdsl(mdsl)?;
let result = tree.tick(&mut context)?;
assert_eq!(result, NodeResult::Success);
Bonsai MDSL supports the same syntax as the original mistreevous library:
sequence { ... } - Execute children in order, fail on first failureselector { ... } - Execute children in order, succeed on first successparallel { ... } - Execute all children concurrentlyrace { ... } - Execute children concurrently, finish on first completionlotto { ... } - Randomly select one child to executerepeat [n] { ... } - Repeat child n timesretry [n] { ... } - Retry child up to n times on failureflip { ... } - Invert success/failure resultsucceed { ... } - Always return successfail { ... } - Always return failureaction [name] - Execute an actioncondition [name] - Evaluate a conditionwait [ms] - Wait for specified milliseconds// Actions with arguments
action [move_to, 10, 20]
// Guards
action [patrol] while(enemy_not_visible)
action [attack] until(enemy_defeated)
// Callbacks
sequence entry(start_combat) exit(end_combat) {
action [ready_weapon]
action [attack]
}
The library supports two types of loop constructs for compatibility with bonsai-bt:
while - Standard While Loopwhile [condition] {
action [some_action]
}
Checks the condition between child executions. This matches bonsai-bt's While behavior.
while_all - WhileAll Loopwhile_all [condition] {
action [some_action]
}
Executes all children first as a sequence, then checks the condition. This matches bonsai-bt's WhileAll behavior.
until - Until Loopuntil [condition] {
action [some_action]
}
Similar to while but continues until the condition becomes true (inverse of while).
For long-running actions, use async support:
use bonsai_mdsl::{BehaviorTree, AsyncTreeContext, NodeResult};
let mut context = AsyncTreeContext::new();
context.register_async_action("long_task", |ctx| async move {
tokio::time::sleep(Duration::from_secs(1)).await;
NodeResult::Success
});
let result = tree.tick_async(&mut context).await?;
This library is designed to be easily integrated into existing Rust projects. You can:
Cargo.toml and import# As a workspace member
[workspace]
members = ["bonsai-mdsl", "your-game"]
# Or as a git dependency
[dependencies]
bonsai-mdsl = { git = "https://github.com/bx2h/bonsai-mdsl" }
See the examples/ directory:
basic_tree - Simple behavior tree exampleasync_drone - Async action handlingboids - A simple boids implementationsimple_npc_ai - A simple NPC AI implementationContributions are welcome! Please see CONTRIBUTING.md for guidelines.
MIT License (LICENSE)
This library is inspired by the excellent mistreevous TypeScript library and Bonsai.