use crate::simple_bt::{BehaviorArc, BehaviorNode, NodeResult};
use std::sync::Arc;
pub struct Inverter<B> {
child: BehaviorArc<B>,
}
impl<B> std::fmt::Debug for Inverter<B> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Inverter")
.field("child", &self.child)
.finish()
}
}
impl<B> Inverter<B> {
pub fn new(child: BehaviorArc<B>) -> Self {
Self { child }
}
}
impl<B: 'static> BehaviorNode<B> for Inverter<B> {
fn tick(self: Arc<Self>, blackboard: &mut B) -> NodeResult<B> {
match self.child.clone().tick(blackboard) {
NodeResult::Success => NodeResult::Failure,
NodeResult::Failure => NodeResult::Success,
NodeResult::Running(resume) => NodeResult::Running(Inverter::new(resume).arc()),
}
}
}
#[cfg(test)]
mod tests {
use assert2::check;
use super::*;
use crate::simple_bt::{
composite::{
tests::{test_with_context, Context},
Succeeder,
},
BehaviorNode, BehaviorRunner, NodeResult,
};
#[derive(Debug)]
struct SucceedAfterSteps {
steps: u32,
step: u32,
}
impl SucceedAfterSteps {
fn new(steps: u32) -> Self {
Self { steps, step: 0 }
}
}
impl BehaviorNode<Context> for SucceedAfterSteps {
fn tick(self: Arc<Self>, _context: &mut Context) -> crate::simple_bt::NodeResult<Context> {
if self.step < self.steps {
NodeResult::Running(
Self {
steps: self.steps,
step: self.step + 1,
}
.arc(),
)
} else {
NodeResult::Success
}
}
}
#[test]
fn inverter_inverts_properly() {
let runner1 =
BehaviorRunner::from_node(Inverter::<Context>::new(Succeeder::default().arc()));
let (res, context) = test_with_context(|| Context { stack: Vec::new() }, runner1, 0);
check!(res == Some(false));
check!(context.stack == Vec::<i32>::new());
let runner2 = BehaviorRunner::new(Inverter::new(SucceedAfterSteps::new(9).arc()).arc());
let (res, context) = test_with_context(|| Context { stack: Vec::new() }, runner2, 9);
check!(res == Some(false));
check!(context.stack == Vec::<i32>::new());
}
}