pub enum BTNode {
Sequence(Vec<BTNode>),
Selector(Vec<BTNode>),
Parallel(ParallelMode, Vec<BTNode>),
Action(fn() -> BTStatus),
Condition(fn() -> BTStatus),
}
#[derive(Clone, PartialEq)]
pub enum ParallelMode {
AllSuccess,
AnySuccess,
}
pub enum BTStatus {
Success,
Failure,
Running,
}
impl BTNode {
pub fn tick(&mut self) -> BTStatus {
match self {
BTNode::Sequence(nodes) => {
for node in nodes {
match node.tick() {
BTStatus::Failure => return BTStatus::Failure,
BTStatus::Running => return BTStatus::Running,
BTStatus::Success => continue,
}
}
BTStatus::Success
}
BTNode::Selector(nodes) => {
for node in nodes {
match node.tick() {
BTStatus::Success => return BTStatus::Success,
BTStatus::Running => return BTStatus::Running,
BTStatus::Failure => continue
}
}
BTStatus::Failure
}
BTNode::Action(action) => action(),
BTNode::Condition(condition) => condition(),
BTNode::Parallel(_, _) => self.tick_parallel(),
}
}
fn tick_parallel(&mut self) -> BTStatus {
if let BTNode::Parallel(mode, nodes) = self {
let mut success_count = 0;
let mut failure_count = 0;
for node in nodes.iter_mut() {
match node.tick() {
BTStatus::Success => success_count += 1,
BTStatus::Failure => failure_count += 1,
BTStatus::Running => return BTStatus::Running,
}
}
match mode {
ParallelMode::AllSuccess if success_count == nodes.len() => BTStatus::Success,
ParallelMode::AnySuccess if success_count > 0 => BTStatus::Success,
_ if failure_count > 0 => BTStatus::Failure,
_ => BTStatus::Running,
}
} else {
panic!("tick_parallel called on a non-parallel node!");
}
}
}