bonsai-mdsl

Crates.iobonsai-mdsl
lib.rsbonsai-mdsl
version0.1.0
created_at2025-05-29 23:01:41.245134+00
updated_at2025-05-29 23:01:41.245134+00
descriptionA Rust library for parsing and executing behavior trees defined in MDSL (Mistreevous Domain Specific Language) into bonsai Behaviour Trees
homepagehttps://github.com/bx2h/bonsai-mdsl
repositoryhttps://github.com/bx2h/bonsai-mdsl
max_upload_size
id1694485
size118,453
bx2h (bx2h)

documentation

https://docs.rs/bonsai-mdsl

README

Bonsai MDSL

A Rust library for parsing and executing behavior trees defined in MDSL (Mistreevous Domain Specific Language). Heavily inspired by Bonsai.

Features

  • ๐ŸŒณ MDSL Parser: Parse behavior trees from MDSL strings
  • โšก Fast Execution: High-performance behavior tree execution engine
  • ๐Ÿ”„ Async Support: Built-in async/await support for long-running actions
  • ๐ŸŽฏ Type Safety: Strongly typed tree nodes and states
  • ๐Ÿงช Well Tested: Comprehensive test suite with benchmarks

Quick Start

Add this to your Cargo.toml:

[dependencies]
bonsai-mdsl = "0.1"

Basic Usage

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);

MDSL Syntax

Bonsai MDSL supports the same syntax as the original mistreevous library:

Composite Nodes

  • sequence { ... } - Execute children in order, fail on first failure
  • selector { ... } - Execute children in order, succeed on first success
  • parallel { ... } - Execute all children concurrently
  • race { ... } - Execute children concurrently, finish on first completion
  • lotto { ... } - Randomly select one child to execute

Decorator Nodes

  • repeat [n] { ... } - Repeat child n times
  • retry [n] { ... } - Retry child up to n times on failure
  • flip { ... } - Invert success/failure result
  • succeed { ... } - Always return success
  • fail { ... } - Always return failure

Leaf Nodes

  • action [name] - Execute an action
  • condition [name] - Evaluate a condition
  • wait [ms] - Wait for specified milliseconds

Arguments and Guards

// 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]
}

Loop Constructs

The library supports two types of loop constructs for compatibility with bonsai-bt:

while - Standard While Loop

while [condition] {
    action [some_action]
}

Checks the condition between child executions. This matches bonsai-bt's While behavior.

while_all - WhileAll Loop

while_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 Loop

until [condition] {
    action [some_action]
}

Similar to while but continues until the condition becomes true (inverse of while).

Async Support

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?;

Integration with Existing Projects

This library is designed to be easily integrated into existing Rust projects. You can:

  1. Use as a dependency: Add to your Cargo.toml and import
  2. Local path dependency: Reference from a local workspace
  3. Git dependency: Reference directly from GitHub
# 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" }

Examples

See the examples/ directory:

  • basic_tree - Simple behavior tree example
  • async_drone - Async action handling
  • boids - A simple boids implementation
  • simple_npc_ai - A simple NPC AI implementation

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT License (LICENSE)

Acknowledgments

This library is inspired by the excellent mistreevous TypeScript library and Bonsai.

Commit count: 4

cargo fmt