moonbtkit

MoonBit native behavior tree and agent decision toolkit for games, robotics, and WASM apps.

behavior-tree
game-ai
agent
robotics
wasm
moon add liu666789987/moonbtkit@0.1.3
Download zip
Version
0.1.3
License
Apache-2.0
Last updated
17 days ago
Downloads
8
README

#MoonBTKit

MoonBTKit 是一个 MoonBit 原生行为树与智能体决策工具包,面向游戏 AI、机器人任务编排、NPC 行为控制、AI Agent 工作流分支和 Wasm 应用中的可测试决策逻辑。

#项目目标

行为树常用于游戏引擎、仿真系统、机器人任务流和智能体编排。MoonBTKit 提供可复用的 MoonBit 实现,让开发者可以用类型安全、确定性、可测试、可运行到 Wasm/JS 的方式描述和验证决策逻辑。

本项目不绑定 Unity、Unreal、Godot、Raylib 等具体引擎;它提供的是可被这些系统调用的决策层。

#当前状态

项目状态
包名liu666789987/moonbtkit
版本0.1.3
MoonBit 实现核心功能均由 MoonBit 实现
代码规模有效 MoonBit 代码超过 5000 行
测试117 个测试,覆盖核心路径、错误路径、fixture、recipe、可视化、coverage、matrix、profile、audit 和白盒 helper
示例cmd/mainexamples/basicexamples/export 均可运行
CIGitHub Actions 覆盖检查、构建、测试、JS 目标、示例和包清单
许可证Apache-2.0

#安装

已发布到 Mooncakes:

moon add liu666789987/moonbtkit

moon.pkg 中引用:

import {
"liu666789987/moonbtkit",
}

当前 Mooncakes 包名为 liu666789987/moonbtkit

#最小示例

let source =
"root root\n" +
"blackboard enemy_visible true\n" +
"blackboard ammo 2\n" +
"selector root engage patrol\n" +
"sequence engage see_enemy has_ammo aim fire\n" +
"condition see_enemy enemy_visible eq true\n" +
"condition has_ammo ammo gt 0\n" +
"action aim aim_weapon running,success mode=aiming\n" +
"action fire fire_weapon success ammo=1 result=hit\n" +
"action patrol patrol_area success mode=patrol\n"

match @moonbtkit.parse_dsl(source) {
Ok(doc) => {
let engine = @moonbtkit.new_engine(doc.tree, blackboard=doc.blackboard)
match engine.run_until_done(max_ticks=6) {
Ok(result) => println(result.summary())
Err(err) => println(err.message())
}
}
Err(err) => println(err.message())
}

#运行示例

moon run cmd/main moon run examples/basic moon run examples/export

cmd/main 会运行内置 fixture 和 recipe;examples/basic 展示一个最小 NPC 战斗决策树,并输出 timeline;examples/export 展示 DOT、Mermaid、coverage 和 matrix 输出。

#主要功能

  • 行为树节点:SequenceSelectorParallelAllParallelAny
  • Decorator:InverterSucceederFailerRepeatRetry
  • Leaf:条件判断、黑板写入、脚本化 action、wait、emit
  • Blackboard:支持 bool、int、text、empty 值
  • DSL:使用行式文本描述树和初始黑板
  • Builder:使用 MoonBit API 直接构建行为树
  • Fixture:内置 NPC、机器人、Agent、Boss、教程、潜行等场景
  • Recipe:内置可参数化游戏/机器人/Agent 行为模板
  • Trace:tick 事件、digest、timeline、过滤与统计
  • Visualization:导出 Graphviz DOT、Mermaid flowchart 和 Mermaid sequence diagram
  • Coverage:统计 trace 覆盖节点、遗漏节点和执行覆盖率
  • Matrix:对黑板变量做场景矩阵回归测试
  • Profile:聚合节点执行次数、状态分布和热点节点
  • Audit:生成 fixture/catalog 级别的验收审计报告
  • Validation/Lint:结构校验、常见风险提示
  • Case Runner:批量运行行为树用例并输出断言报告

#API 概览

分类API
黑板new_blackboard, blackboard_from_pairs, Blackboard::set, Blackboard::get_*
节点node, sequence, selector, condition, set_value, wait, action_success
new_tree, tree_from_nodes, BehaviorTree::add, BehaviorTree::validate
引擎new_engine, BtEngine::tick, BtEngine::run_until_done, BtEngine::trace_digest
DSLparse_dsl, parse_tree_dsl, serialize_tree, parse_blackboard_dsl
分析analyze_tree, lint_tree, tree_markdown_report, smoke_run
测试run_case, run_cases, fixture_cases, recipe_cases, assert_*
示例fixture_catalog, run_fixture, recipe_catalog, run_recipe_catalog
Timelinetimeline_from_trace, timeline_text, summarize_trace, compact_trace
Visualizationtree_to_dot, tree_to_mermaid, trace_to_mermaid_sequence, visualization_bundle
Coveragecoverage_from_trace, fixture_coverage, fixture_catalog_coverage
Matrixrun_matrix, boolean_matrix, int_sweep_matrix, fixture_matrix_report
Profileprofile_trace, profile_fixture, fixture_profile_report, profile_markdown
Auditaudit_fixture, audit_fixture_catalog, audit_catalog_markdown

#支持范围

  • 内存版行为树执行
  • 确定性 tick
  • 文本 DSL 和 MoonBit Builder 两种构建方式
  • 可复现 trace digest
  • 可导出的 DOT / Mermaid 结构图和 trace 图
  • 可统计的节点执行覆盖率
  • 可参数化的场景矩阵回归测试
  • 可输出节点热点画像和 catalog 审计报告
  • 游戏 AI、Agent 分支、机器人任务流等通用决策场景
  • Wasm-GC 和 JS 目标构建测试

#暂不支持范围

  • 不直接绑定具体游戏引擎
  • 不内置图形渲染、物理引擎或导航网格
  • 不提供多线程任务调度
  • 不执行外部脚本或不可信代码
  • 不承诺兼容某个第三方行为树编辑器格式

#测试与验收命令

moon check moon build moon test moon check --target js moon build --target js moon test --target js moon run cmd/main moon run examples/basic moon run examples/export moon package --list

以上命令覆盖检查、构建、测试、JS 目标、示例运行和包结构检查。

#开源许可证

本项目采用 Apache-2.0 许可证。项目为原创 MoonBit 开源库,不移植第三方代码;测试数据和示例场景为项目自有内容。

#
AgentRecipeOptions

pub(all) struct AgentRecipeOptions {
needs_current_info : Bool
tool_allowed : Bool
ambiguity : Int
} derive(Eq,
Debug
)

#
AssertionReport

pub(all) struct AssertionReport {
name : String
assertions : Array[BtAssertion]
} derive(Eq,
Debug
)

#
AssertionReport::add

fn AssertionReport::add(self : AssertionReport, assertion : BtAssertion) -> Unit

#
AssertionReport::failed_count

fn AssertionReport::failed_count(self : AssertionReport) -> Int

#
AssertionReport::lines

fn AssertionReport::lines(self : AssertionReport) -> Array[String]

#
AssertionReport::ok

fn AssertionReport::ok(self : AssertionReport) -> Bool

#
AssertionReport::summary

fn AssertionReport::summary(self : AssertionReport) -> String

#
AuditReport

pub(all) struct AuditReport {
name : String
run : RunSummary
coverage : TraceCoverage
profile : ProfileReport
lint : LintReport
visual_assets : Int
} derive(Eq,
Debug
)

A compact audit report for one behavior tree run.

#
AuditReport::markdown

fn AuditReport::markdown(self : AuditReport) -> String

#
AuditReport::ok

fn AuditReport::ok(self : AuditReport) -> Bool

#
AuditReport::summary

fn AuditReport::summary(self : AuditReport) -> String

#
BehaviorTree

pub(all) struct BehaviorTree {
root : String
nodes : Array[BtNode]
} derive(Eq,
Debug
)

#
BehaviorTree::add

fn BehaviorTree::add(self : BehaviorTree, node : BtNode) -> Result[Unit, BtError]

#
BehaviorTree::has_node

fn BehaviorTree::has_node(self : BehaviorTree, id : String) -> Bool

#
BehaviorTree::ids

fn BehaviorTree::ids(self : BehaviorTree) -> Array[String]

#
BehaviorTree::leaf_count

fn BehaviorTree::leaf_count(self : BehaviorTree) -> Int

#
BehaviorTree::node

fn BehaviorTree::node(self : BehaviorTree, id : String) -> BtNode?

#
BehaviorTree::node_count

fn BehaviorTree::node_count(self : BehaviorTree) -> Int

#
BehaviorTree::validate

#
Blackboard

pub(all) struct Blackboard {
values : Array[(String, BtValue)]
} derive(Eq,
Debug
)

Key-value state shared by all nodes.

#
Blackboard::get

fn Blackboard::get(self : Blackboard, key : String) -> BtValue?

#
Blackboard::get_bool

fn Blackboard::get_bool(self : Blackboard, key : String) -> Bool?

#
Blackboard::get_int

fn Blackboard::get_int(self : Blackboard, key : String) -> Int?

#
Blackboard::get_text

fn Blackboard::get_text(self : Blackboard, key : String) -> String?

#
Blackboard::has

fn Blackboard::has(self : Blackboard, key : String) -> Bool

#
Blackboard::is_empty

fn Blackboard::is_empty(self : Blackboard) -> Bool

#
Blackboard::keys

fn Blackboard::keys(self : Blackboard) -> Array[String]

#
Blackboard::len

fn Blackboard::len(self : Blackboard) -> Int

#
Blackboard::remove

fn Blackboard::remove(self : Blackboard, key : String) -> Bool

#
Blackboard::set

fn Blackboard::set(self : Blackboard, key : String, value : BtValue) -> Unit

#
Blackboard::snapshot

fn Blackboard::snapshot(self : Blackboard) -> Array[(String, BtValue)]

#
Blackboard::to_lines

fn Blackboard::to_lines(self : Blackboard) -> Array[String]

#
BtAssertion

pub(all) struct BtAssertion {
name : String
ok : Bool
detail : String
} derive(Eq,
Debug
)

#
BtAssertion::to_line

fn BtAssertion::to_line(self : BtAssertion) -> String

#
BtEngine

pub(all) struct BtEngine {
tree : BehaviorTree
blackboard : Blackboard
config : TickConfig
tick_count : Int
memory : Array[NodeMemory]
trace : Array[TickEvent]
} derive(Eq,
Debug
)

#
BtEngine::reset

fn BtEngine::reset(self : BtEngine) -> Unit

#
BtEngine::run_until_done

fn BtEngine::run_until_done(self : BtEngine, max_ticks? : Int) -> Result[TickResult, BtError]

#
BtEngine::tick

fn BtEngine::tick(self : BtEngine) -> Result[TickResult, BtError]

#
BtEngine::trace_digest

fn BtEngine::trace_digest(self : BtEngine) -> String

#
BtEngine::trace_lines

fn BtEngine::trace_lines(self : BtEngine) -> Array[String]

#
BtError

pub(all) enum BtError {
DuplicateNode(String)
MissingNode(String)
InvalidTree(String)
ParseError(String)
LimitExceeded(String)
} derive(Eq,
Debug
)

#
BtError::message

fn BtError::message(self : BtError) -> String

#
BtNode

pub(all) struct BtNode {
id : String
name : String
kind : NodeKind
children : Array[String]
} derive(Eq,
Debug
)

#
BtStatus

pub(all) enum BtStatus {
Success
Failure
Running
} derive(Eq,
Debug
)

Result of one behavior tree node tick.

#
BtStatus::is_done

fn BtStatus::is_done(self : BtStatus) -> Bool

#
BtStatus::to_text

fn BtStatus::to_text(self : BtStatus) -> String

#
BtValue

pub(all) enum BtValue {
BoolValue(Bool)
IntValue(Int)
TextValue(String)
EmptyValue
} derive(Eq,
Debug
)

Small value type used by the blackboard and the line-based DSL.

#
BtValue::kind

fn BtValue::kind(self : BtValue) -> String

#
BtValue::to_text

fn BtValue::to_text(self : BtValue) -> String

#
CaseExpectation

pub(all) struct CaseExpectation {
final_status : BtStatus
required_board : Array[(String, BtValue)]
max_ticks : Int
} derive(Eq,
Debug
)

#
CaseReport

pub(all) struct CaseReport {
name : String
parsed : Bool
run : RunSummary
assertions : AssertionReport
} derive(Eq,
Debug
)

#
CaseReport::ok

fn CaseReport::ok(self : CaseReport) -> Bool

#
CaseReport::to_line

fn CaseReport::to_line(self : CaseReport) -> String

#
CaseSpec

pub(all) struct CaseSpec {
name : String
dsl : String
expectation : CaseExpectation
} derive(Eq,
Debug
)

#
CatalogAudit

pub(all) struct CatalogAudit {
reports : Array[AuditReport]
} derive(Eq,
Debug
)

#
CatalogAudit::failed

fn CatalogAudit::failed(self : CatalogAudit) -> Int

#
CatalogAudit::lines

fn CatalogAudit::lines(self : CatalogAudit) -> Array[String]

#
CatalogAudit::passed

fn CatalogAudit::passed(self : CatalogAudit) -> Int

#
CatalogAudit::summary

fn CatalogAudit::summary(self : CatalogAudit) -> String

#
CatalogCoverage

pub(all) struct CatalogCoverage {
fixtures : Int
full_coverage : Int
partial_coverage : Int
lines : Array[String]
} derive(Eq,
Debug
)

#
CatalogCoverage::summary

fn CatalogCoverage::summary(self : CatalogCoverage) -> String

#
CombatRecipeOptions

pub(all) struct CombatRecipeOptions {
enemy_visible : Bool
ammo : Int
stamina : Int
aim_ticks : Int
reload_ticks : Int
} derive(Eq,
Debug
)

#
CompareOp

pub(all) enum CompareOp {
Eq
NotEq
Greater
GreaterEq
Less
LessEq
Exists
Missing
} derive(Eq,
Debug
)

#
CompareOp::to_text

fn CompareOp::to_text(self : CompareOp) -> String

#
DslDocument

pub(all) struct DslDocument {
tree : BehaviorTree
blackboard : Blackboard
warnings : Array[String]
} derive(Eq,
Debug
)

#
DslDocument::summary

fn DslDocument::summary(self : DslDocument) -> String

#
DslOptions

pub(all) struct DslOptions {
allow_comments : Bool
validate_after_parse : Bool
default_root : String
} derive(Eq,
Debug
)

Parser options for the line-based MoonBTKit DSL.

#
FixtureSpec

pub(all) struct FixtureSpec {
name : String
description : String
dsl : String
expected : BtStatus
max_ticks : Int
} derive(Eq,
Debug
)

#
FixtureSpec::summary

fn FixtureSpec::summary(self : FixtureSpec) -> String

#
LintIssue

pub(all) struct LintIssue {
severity : String
node_id : String
message : String
} derive(Eq,
Debug
)

#
LintIssue::to_line

fn LintIssue::to_line(self : LintIssue) -> String

#
LintReport

pub(all) struct LintReport {
ok : Bool
issues : Array[LintIssue]
} derive(Eq,
Debug
)

#
LintReport::lines

fn LintReport::lines(self : LintReport) -> Array[String]

#
LintReport::summary

fn LintReport::summary(self : LintReport) -> String

#
MarkdownReport

pub(all) struct MarkdownReport {
title : String
lines : Array[String]
} derive(Eq,
Debug
)

#
MarkdownReport::text

fn MarkdownReport::text(self : MarkdownReport) -> String

#
MatrixReport

pub(all) struct MatrixReport {
name : String
results : Array[VariantResult]
} derive(Eq,
Debug
)

#
MatrixReport::failed

fn MatrixReport::failed(self : MatrixReport) -> Int

#
MatrixReport::lines

fn MatrixReport::lines(self : MatrixReport) -> Array[String]

#
MatrixReport::ok

fn MatrixReport::ok(self : MatrixReport) -> Bool

#
MatrixReport::passed

fn MatrixReport::passed(self : MatrixReport) -> Int

#
MatrixReport::summary

fn MatrixReport::summary(self : MatrixReport) -> String

#
NodeKind

pub(all) enum NodeKind {
Sequence
Selector
ParallelAll
ParallelAny
Inverter
Succeeder
Failer
Repeat(Int)
Retry(Int)
Condition(String, CompareOp, BtValue)
SetValue(String, BtValue)
ActionPlan(String, Array[BtStatus], Array[(String, BtValue)])
Wait(Int)
Emit(String)
} derive(Eq,
Debug
)

Behavior tree node kind.

#
NodeKind::to_text

fn NodeKind::to_text(self : NodeKind) -> String

#
NodeMemory

pub(all) struct NodeMemory {
id : String
cursor : Int
ticks : Int
attempts : Int
last_status : BtStatus
} derive(Eq,
Debug
)

#
NodeProfile

pub(all) struct NodeProfile {
node_id : String
kind : String
total : Int
success : Int
failure : Int
running : Int
first_tick : Int
last_tick : Int
} derive(Eq,
Debug
)

Aggregated execution data for one node.

#
NodeProfile::dominant_status

fn NodeProfile::dominant_status(self : NodeProfile) -> BtStatus

#
NodeProfile::to_line

fn NodeProfile::to_line(self : NodeProfile) -> String

#
ParsedLine

type ParsedLine derive(Eq,
Debug
)

#
ProfileReport

pub(all) struct ProfileReport {
name : String
profiles : Array[NodeProfile]
total_events : Int
total_ticks : Int
} derive(Eq,
Debug
)

#
ProfileReport::hotspot_lines

fn ProfileReport::hotspot_lines(self : ProfileReport, limit : Int) -> Array[String]

#
ProfileReport::hotspots

fn ProfileReport::hotspots(self : ProfileReport, limit : Int) -> Array[NodeProfile]

#
ProfileReport::lines

fn ProfileReport::lines(self : ProfileReport) -> Array[String]

#
ProfileReport::summary

fn ProfileReport::summary(self : ProfileReport) -> String

#
RecipeBundle

pub(all) struct RecipeBundle {
name : String
description : String
tree : BehaviorTree
blackboard : Blackboard
expected : BtStatus
max_ticks : Int
} derive(Eq,
Debug
)

#
RecipeBundle::run

#
RecipeBundle::summary

fn RecipeBundle::summary(self : RecipeBundle) -> String

#
RobotRecipeOptions

pub(all) struct RobotRecipeOptions {
battery : Int
package_ready : Bool
charge_threshold : Int
charge_ticks : Int
navigate_ticks : Int
} derive(Eq,
Debug
)

#
RunSummary

pub(all) struct RunSummary {
name : String
final_status : BtStatus
ticks : Int
trace_events : Int
digest : String
ok : Bool
detail : String
} derive(Eq,
Debug
)

#
RunSummary::to_line

fn RunSummary::to_line(self : RunSummary) -> String

#
TickConfig

pub(all) struct TickConfig {
max_ticks : Int
max_trace_events : Int
record_trace : Bool
} derive(Eq,
Debug
)

#
TickEvent

pub(all) struct TickEvent {
tick : Int
node_id : String
node_name : String
kind : String
status : BtStatus
detail : String
} derive(Eq,
Debug
)

#
TickEvent::to_line

fn TickEvent::to_line(self : TickEvent) -> String

#
TickResult

pub(all) struct TickResult {
tick : Int
status : BtStatus
events : Array[TickEvent]
blackboard : Array[(String, BtValue)]
} derive(Eq,
Debug
)

#
TickResult::summary

fn TickResult::summary(self : TickResult) -> String

#
TimelineFrame

pub(all) struct TimelineFrame {
tick : Int
events : Array[TickEvent]
} derive(Eq,
Debug
)

#
TimelineFrame::lines

fn TimelineFrame::lines(self : TimelineFrame) -> Array[String]

#
TimelineFrame::summary

fn TimelineFrame::summary(self : TimelineFrame) -> String

#
TraceCoverage

pub(all) struct TraceCoverage {
total_nodes : Int
visited_nodes : Array[String]
missed_nodes : Array[String]
success_nodes : Array[String]
failure_nodes : Array[String]
running_nodes : Array[String]
} derive(Eq,
Debug
)

Coverage report for one behavior tree execution trace.

#
TraceCoverage::is_full

fn TraceCoverage::is_full(self : TraceCoverage) -> Bool

#
TraceCoverage::lines

fn TraceCoverage::lines(self : TraceCoverage) -> Array[String]

#
TraceCoverage::missed_count

fn TraceCoverage::missed_count(self : TraceCoverage) -> Int

#
TraceCoverage::percent

fn TraceCoverage::percent(self : TraceCoverage) -> Int

#
TraceCoverage::summary

fn TraceCoverage::summary(self : TraceCoverage) -> String

#
TraceCoverage::visited_count

fn TraceCoverage::visited_count(self : TraceCoverage) -> Int

#
TraceSummary

pub(all) struct TraceSummary {
total : Int
success : Int
failure : Int
running : Int
unique_nodes : Int
} derive(Eq,
Debug
)

#
TraceSummary::to_line

fn TraceSummary::to_line(self : TraceSummary) -> String

#
TreeBuilder

pub(all) struct TreeBuilder {
root : String
nodes : Array[BtNode]
notes : Array[String]
} derive(Eq,
Debug
)

Programmatic builder for users who prefer typed MoonBit code over DSL text.

#
TreeBuilder::action

fn TreeBuilder::action(self : TreeBuilder, id : String, name : String, statuses : Array[BtStatus], writes? : Array[(String, BtValue)]) -> Result[TreeBuilder, BtError]

#
TreeBuilder::add_node

fn TreeBuilder::add_node(self : TreeBuilder, n : BtNode) -> Result[TreeBuilder, BtError]

#
TreeBuilder::condition

fn TreeBuilder::condition(self : TreeBuilder, id : String, key : String, op : CompareOp, expected : BtValue) -> Result[TreeBuilder, BtError]

#
TreeBuilder::decorator

fn TreeBuilder::decorator(self : TreeBuilder, id : String, kind : NodeKind, child : String) -> Result[TreeBuilder, BtError]

#
TreeBuilder::emit

fn TreeBuilder::emit(self : TreeBuilder, id : String, label : String) -> Result[TreeBuilder, BtError]

#
TreeBuilder::finish

fn TreeBuilder::finish(self : TreeBuilder) -> Result[BehaviorTree, BtError]

#
TreeBuilder::has_node

fn TreeBuilder::has_node(self : TreeBuilder, id : String) -> Bool

#
TreeBuilder::node_count

fn TreeBuilder::node_count(self : TreeBuilder) -> Int

#
TreeBuilder::note

fn TreeBuilder::note(self : TreeBuilder, text : String) -> TreeBuilder

#
TreeBuilder::note_lines

fn TreeBuilder::note_lines(self : TreeBuilder) -> Array[String]

#
TreeBuilder::parallel_all

fn TreeBuilder::parallel_all(self : TreeBuilder, id : String, children : Array[String]) -> Result[TreeBuilder, BtError]

#
TreeBuilder::parallel_any

fn TreeBuilder::parallel_any(self : TreeBuilder, id : String, children : Array[String]) -> Result[TreeBuilder, BtError]

#
TreeBuilder::selector

fn TreeBuilder::selector(self : TreeBuilder, id : String, children : Array[String]) -> Result[TreeBuilder, BtError]

#
TreeBuilder::sequence

fn TreeBuilder::sequence(self : TreeBuilder, id : String, children : Array[String]) -> Result[TreeBuilder, BtError]

#
TreeBuilder::set

fn TreeBuilder::set(self : TreeBuilder, id : String, key : String, value : BtValue) -> Result[TreeBuilder, BtError]

#
TreeBuilder::wait

fn TreeBuilder::wait(self : TreeBuilder, id : String, ticks : Int) -> Result[TreeBuilder, BtError]

#
TreeStats

pub(all) struct TreeStats {
nodes : Int
leaves : Int
composites : Int
decorators : Int
conditions : Int
actions : Int
waits : Int
max_children : Int
max_depth : Int
} derive(Eq,
Debug
)

#
TreeStats::to_line

fn TreeStats::to_line(self : TreeStats) -> String

#
ValidationReport

pub(all) struct ValidationReport {
ok : Bool
issues : Array[String]
} derive(Eq,
Debug
)

#
ValidationReport::message

fn ValidationReport::message(self : ValidationReport) -> String

#
VariantResult

pub(all) struct VariantResult {
name : String
status : BtStatus
expected : BtStatus
ticks : Int
digest : String
ok : Bool
detail : String
} derive(Eq,
Debug
)

#
VariantResult::to_line

fn VariantResult::to_line(self : VariantResult) -> String

#
VariantSpec

pub(all) struct VariantSpec {
name : String
overrides : Array[(String, BtValue)]
expected : BtStatus
max_ticks : Int
} derive(Eq,
Debug
)

#
VisualOptions

pub(all) struct VisualOptions {
include_node_names : Bool
include_node_kinds : Bool
show_leaf_shape : Bool
} derive(Eq,
Debug
)

Options for rendering behavior trees into graph descriptions.

#
action_failure

fn action_failure(id : String, name? : String) -> BtNode

#
action_running_then

fn action_running_then(id : String, name : String, running_ticks : Int, final_status : BtStatus, writes? : Array[(String, BtValue)]) -> BtNode

#
action_success

fn action_success(id : String, name? : String, writes? : Array[(String, BtValue)]) -> BtNode

#
agent_recipe

fn agent_recipe(options? : AgentRecipeOptions) -> Result[RecipeBundle, BtError]

#
agent_tool_dsl

fn agent_tool_dsl() -> String

#
agent_tool_fixture

fn agent_tool_fixture() -> FixtureSpec

#
all_cases_ok

fn all_cases_ok(reports : Array[CaseReport]) -> Bool

#
analyze_tree

fn analyze_tree(tree : BehaviorTree) -> TreeStats

#
append_status

fn append_status(base : Array[BtStatus], tail : BtStatus) -> Array[BtStatus]

#
apply_overrides

fn apply_overrides(source : String, overrides : Array[(String, BtValue)]) -> String

#
assert_board_value

fn assert_board_value(board : Array[(String, BtValue)], key : String, value : BtValue) -> BtAssertion

#
assert_has_node

fn assert_has_node(tree : BehaviorTree, id : String) -> BtAssertion

#
assert_lint_ok

fn assert_lint_ok(tree : BehaviorTree) -> BtAssertion

#
assert_node_count

fn assert_node_count(tree : BehaviorTree, expected : Int) -> BtAssertion

#
assert_status

fn assert_status(actual : BtStatus, expected : BtStatus) -> BtAssertion

#
assert_trace_has

fn assert_trace_has(events : Array[TickEvent], node_id : String, status : BtStatus) -> BtAssertion

#
assert_tree_valid

fn assert_tree_valid(tree : BehaviorTree) -> BtAssertion

#
assert_true

fn assert_true(name : String, condition : Bool, detail : String) -> BtAssertion

#
audit_catalog_markdown

fn audit_catalog_markdown() -> String

#
audit_fixture

fn audit_fixture(name : String) -> Result[AuditReport, BtError]

#
audit_fixture_catalog

fn audit_fixture_catalog() -> CatalogAudit

#
blackboard_from_pairs

fn blackboard_from_pairs(pairs : Array[(String, BtValue)]) -> Blackboard

#
board_contains

fn board_contains(board : Array[(String, BtValue)], key : String, value : BtValue) -> Bool

#
bool_value

fn bool_value(value : Bool) -> BtValue

#
boolean_matrix

fn boolean_matrix(name : String, source : String, key : String, true_expected : BtStatus, false_expected : BtStatus, max_ticks? : Int) -> MatrixReport

#
boolean_variants

fn boolean_variants(base_name : String, source : String, key : String, expected_true : BtStatus, expected_false : BtStatus, max_ticks : Int) -> Array[CaseSpec]

#
boss_phase_dsl

fn boss_phase_dsl() -> String

#
boss_phase_fixture

fn boss_phase_fixture() -> FixtureSpec

#
case_from_fixture

fn case_from_fixture(spec : FixtureSpec) -> CaseSpec

#
case_report_lines

fn case_report_lines(reports : Array[CaseReport]) -> Array[String]

#
combat_recipe

fn combat_recipe(options? : CombatRecipeOptions) -> Result[RecipeBundle, BtError]

#
combine_assertion_reports

fn combine_assertion_reports(name : String, reports : Array[AssertionReport]) -> AssertionReport

#
compact_trace

fn compact_trace(events : Array[TickEvent]) -> Array[String]

#
compact_visual_options

fn compact_visual_options() -> VisualOptions

#
compare_values

fn compare_values(actual : BtValue?, op : CompareOp, expected : BtValue) -> Bool

#
condition

fn condition(id : String, key : String, op : CompareOp, expected : BtValue) -> BtNode

#
count_status

fn count_status(events : Array[TickEvent], status : BtStatus) -> Int

#
coverage_from_trace

fn coverage_from_trace(tree : BehaviorTree, events : Array[TickEvent]) -> TraceCoverage

#
coverage_markdown

fn coverage_markdown(name : String, coverage : TraceCoverage) -> String

#
default_agent_options

fn default_agent_options() -> AgentRecipeOptions

#
default_combat_options

fn default_combat_options() -> CombatRecipeOptions

#
default_dsl_options

fn default_dsl_options() -> DslOptions

#
default_robot_options

fn default_robot_options() -> RobotRecipeOptions

#
default_tick_config

fn default_tick_config() -> TickConfig

#
default_visual_options

fn default_visual_options() -> VisualOptions

#
empty_value

fn empty_value() -> BtValue

#
explain_trace

fn explain_trace(events : Array[TickEvent]) -> Array[String]

#
filter_trace_by_node

fn filter_trace_by_node(events : Array[TickEvent], node_id : String) -> Array[TickEvent]

#
filter_trace_by_status

fn filter_trace_by_status(events : Array[TickEvent], status : BtStatus) -> Array[TickEvent]

#
find_fixture

fn find_fixture(name : String) -> FixtureSpec?

#
fixture_cases

fn fixture_cases() -> Array[CaseSpec]

#
fixture_catalog

fn fixture_catalog() -> Array[FixtureSpec]

#
fixture_catalog_coverage

fn fixture_catalog_coverage() -> CatalogCoverage

#
fixture_coverage

fn fixture_coverage(name : String) -> Result[TraceCoverage, BtError]

#
fixture_matrix_report

fn fixture_matrix_report() -> MatrixReport

#
fixture_names

fn fixture_names() -> Array[String]

#
fixture_profile_report

fn fixture_profile_report() -> Array[String]

#
fixture_report_lines

fn fixture_report_lines() -> Array[String]

#
guarded_attack_dsl

fn guarded_attack_dsl() -> String

#
guarded_attack_fixture

fn guarded_attack_fixture() -> FixtureSpec

#
harvest_worker_dsl

fn harvest_worker_dsl() -> String

#
harvest_worker_fixture

fn harvest_worker_fixture() -> FixtureSpec

#
int_sweep_matrix

fn int_sweep_matrix(name : String, source : String, key : String, values : Array[Int], expected : BtStatus, max_ticks? : Int) -> MatrixReport

#
int_value

fn int_value(value : Int) -> BtValue

#
last_event_for_node

fn last_event_for_node(events : Array[TickEvent], node_id : String) -> TickEvent?

#
lint_tree

fn lint_tree(tree : BehaviorTree) -> LintReport

#
load_fixture

fn load_fixture(name : String) -> Result[DslDocument, BtError]

#
matrix_markdown

fn matrix_markdown(report : MatrixReport) -> String

#
mission_selector_dsl

fn mission_selector_dsl() -> String

#
mission_selector_fixture

fn mission_selector_fixture() -> FixtureSpec

#
new_assertion_report

fn new_assertion_report(name : String) -> AssertionReport

#
new_blackboard

fn new_blackboard() -> Blackboard

#
new_builder

fn new_builder(root : String) -> TreeBuilder

#
new_engine

fn new_engine(tree : BehaviorTree, blackboard? : Blackboard, config? : TickConfig) -> BtEngine

#
new_tree

fn new_tree(root : String) -> BehaviorTree

#
node

fn node(id : String, kind : NodeKind, children? : Array[String], name? : String) -> BtNode

#
parse_blackboard_dsl

fn parse_blackboard_dsl(source : String) -> Result[Blackboard, BtError]

#
parse_compare_op

fn parse_compare_op(raw : String) -> CompareOp?

#
parse_dsl

fn parse_dsl(source : String, options? : DslOptions) -> Result[DslDocument, BtError]

Parse a behavior tree and initial blackboard from a compact line DSL.

Supported examples:

  • root root
  • selector root engage patrol
  • condition see_enemy enemy_visible eq true
  • action chase chase_enemy running,success mode=chasing
  • blackboard ammo 3

#
parse_tree_dsl

fn parse_tree_dsl(source : String) -> Result[BehaviorTree, BtError]

#
parse_value

fn parse_value(raw : String) -> BtValue

#
patrol_dsl

fn patrol_dsl() -> String

#
patrol_fixture

fn patrol_fixture() -> FixtureSpec

#
profile_fixture

fn profile_fixture(name : String) -> Result[ProfileReport, BtError]

#
profile_markdown

fn profile_markdown(report : ProfileReport, hotspot_limit? : Int) -> String

#
profile_trace

fn profile_trace(name : String, events : Array[TickEvent]) -> ProfileReport

#
qa_agent_dsl

fn qa_agent_dsl() -> String

#
qa_agent_fixture

fn qa_agent_fixture() -> FixtureSpec

#
recipe_cases

fn recipe_cases() -> Array[CaseSpec]

#
recipe_catalog

fn recipe_catalog() -> Array[RecipeBundle]

#
recipe_report_lines

fn recipe_report_lines() -> Array[String]

#
recipe_to_case

fn recipe_to_case(bundle : RecipeBundle) -> CaseSpec

#
repeat_status

fn repeat_status(status : BtStatus, count : Int) -> Array[BtStatus]

#
replace_blackboard_line

fn replace_blackboard_line(source : String, key : String, value : BtValue) -> String

#
robot_delivery_dsl

fn robot_delivery_dsl() -> String

#
robot_delivery_fixture

fn robot_delivery_fixture() -> FixtureSpec

#
robot_recipe

fn robot_recipe(options? : RobotRecipeOptions) -> Result[RecipeBundle, BtError]

#
run_case

fn run_case(spec : CaseSpec) -> CaseReport

#
run_cases

fn run_cases(cases : Array[CaseSpec]) -> Array[CaseReport]

#
run_fixture

fn run_fixture(name : String) -> RunSummary

#
run_fixture_catalog

fn run_fixture_catalog() -> Array[RunSummary]

#
run_matrix

fn run_matrix(name : String, base_dsl : String, variants : Array[VariantSpec]) -> MatrixReport

#
run_recipe_catalog

fn run_recipe_catalog() -> Array[RunSummary]

#
run_variant_dsl

fn run_variant_dsl(base_dsl : String, spec : VariantSpec) -> VariantResult

#
running_then_failure

fn running_then_failure(running_ticks : Int) -> Array[BtStatus]

#
running_then_success

fn running_then_success(running_ticks : Int) -> Array[BtStatus]

#
selector

fn selector(id : String, children : Array[String]) -> BtNode

#
sequence

fn sequence(id : String, children : Array[String]) -> BtNode

#
serialize_blackboard

fn serialize_blackboard(board : Blackboard) -> Array[String]

#
serialize_tree

fn serialize_tree(tree : BehaviorTree) -> Array[String]

#
set_value

fn set_value(id : String, key : String, value : BtValue) -> BtNode

#
smoke_run

fn smoke_run(name : String, tree : BehaviorTree, board : Blackboard, expected : BtStatus, max_ticks? : Int) -> RunSummary

#
stealth_guard_dsl

fn stealth_guard_dsl() -> String

#
stealth_guard_fixture

fn stealth_guard_fixture() -> FixtureSpec

#
strict_tick_config

fn strict_tick_config() -> TickConfig

#
summarize_trace

fn summarize_trace(events : Array[TickEvent]) -> TraceSummary

#
text_value

fn text_value(value : String) -> BtValue

#
timeline_from_trace

fn timeline_from_trace(events : Array[TickEvent]) -> Array[TimelineFrame]

#
timeline_text

fn timeline_text(events : Array[TickEvent]) -> String

#
trace_contains

fn trace_contains(events : Array[TickEvent], node_id : String, status : BtStatus) -> Bool

#
trace_to_mermaid_sequence

fn trace_to_mermaid_sequence(events : Array[TickEvent]) -> String

Render trace events as a Mermaid sequence diagram.

#
tree_from_nodes

fn tree_from_nodes(root : String, nodes : Array[BtNode]) -> BehaviorTree

#
tree_markdown_report

fn tree_markdown_report(title : String, tree : BehaviorTree, board : Blackboard) -> MarkdownReport

#
tree_to_dot

fn tree_to_dot(tree : BehaviorTree, options? : VisualOptions) -> String

Export a behavior tree to Graphviz DOT.

#
tree_to_mermaid

fn tree_to_mermaid(tree : BehaviorTree, options? : VisualOptions) -> String

Export a behavior tree to Mermaid flowchart syntax.

#
tutorial_hint_dsl

fn tutorial_hint_dsl() -> String

#
tutorial_hint_fixture

fn tutorial_hint_fixture() -> FixtureSpec

#
variant

fn variant(name : String, overrides : Array[(String, BtValue)], expected? : BtStatus, max_ticks? : Int) -> VariantSpec

#
visualization_bundle

fn visualization_bundle(tree : BehaviorTree, events : Array[TickEvent]) -> Array[(String, String)]

Return a short visualization bundle suitable for docs and issue comments.

#
wait

fn wait(id : String, ticks : Int) -> BtNode