simple_bt 1.0.1

minimal(-ish) behavior tree implementation
Documentation
use crate::{BehaviorArc, BehaviorNode, NodeResult, ReportStatus};
use std::sync::Arc;

/// Always succeedes.
pub struct Succeeder<B> {
    child: Option<BehaviorArc<B>>,
    has_run: bool,
}

impl<B> std::fmt::Debug for Succeeder<B> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Succeeder")
            .field("child", &self.child)
            .finish()
    }
}

impl<B> Clone for Succeeder<B> {
    fn clone(&self) -> Self {
        Self {
            child: self.child.clone(),
            has_run: self.has_run,
        }
    }
}

impl<B> Default for Succeeder<B> {
    fn default() -> Self {
        Self {
            child: None,
            has_run: false,
        }
    }
}

impl<B> Succeeder<B> {
    pub fn new(child: BehaviorArc<B>) -> Self {
        Self {
            child: Some(child),
            has_run: false,
        }
    }
}

impl<B: 'static> BehaviorNode<B> for Succeeder<B> {
    fn tick(mut self: Arc<Self>, blackboard: &mut B) -> crate::NodeResult<B> {
        if self.child.is_some() {
            let inner = Arc::make_mut(&mut self);
            if let Some(child) = inner.child.take() {
                match child.tick(blackboard) {
                    NodeResult::Failure | NodeResult::Success => NodeResult::Success,
                    NodeResult::Running(resume) => {
                        inner.child = Some(resume);
                        inner.has_run = true;
                        NodeResult::Running(self)
                    }
                }
            } else {
                unreachable!()
            }
        } else {
            NodeResult::Success
        }
    }

    fn status(&self, _parent: ReportStatus, context: &B) -> crate::BehaviorStatus {
        let status = if self.has_run {
            ReportStatus::Running
        } else {
            ReportStatus::Unexecuted
        };
        crate::BehaviorStatus {
            name: std::any::type_name_of_val(self).into(),
            status,
            children: self
                .child
                .iter()
                .map(|c| c.status(status, context))
                .collect(),
            current: if self.has_run { Some(0) } else { None },
        }
    }
}

#[cfg(test)]
mod tests {}