behaviortree 0.7.4

A #![no_std] compatible behavior tree library similar to 'BehaviorTree.CPP'.
Documentation
// Copyright © 2025 Stephan Kunz
//! [`SimpleBehavior`]  implementation for registering functions as behavior.

use super::{Behavior, BehaviorCreationFn, BehaviorExecution, BehaviorResult};
use crate::{BehaviorKind, behavior::BehaviorData, port::PortList, tree::BehaviorTreeElementList};
use alloc::{boxed::Box, sync::Arc};
use core::any::Any;
use tinyscript::SharedRuntime;

/// Signature of a simple registered behavior function called by `SimpleBehavior`'s tick
pub type SimpleBhvrTickFn = Arc<dyn Fn() -> BehaviorResult + Send + Sync>;

/// Signature of a registered behavior function called by `SimpleBehavior`'s tick
pub type ComplexBhvrTickFn = Arc<dyn Fn(&mut BehaviorData) -> BehaviorResult + Send + Sync>;

/// A simple behavior
#[derive(Default)]
pub struct SimpleBehavior {
	/// The function to be called on tick
	simple_tick_fn: Option<SimpleBhvrTickFn>,
	/// The function to be called on tick if ports exist
	complex_tick_fn: Option<ComplexBhvrTickFn>,
	/// List of provided ports
	provided_ports: PortList,
}

impl BehaviorExecution for SimpleBehavior {
	fn as_any(&self) -> &dyn Any {
		self
	}

	fn as_any_mut(&mut self) -> &mut dyn Any {
		self
	}

	fn creation_fn() -> Box<BehaviorCreationFn> {
		alloc::boxed::Box::new(|| alloc::boxed::Box::new(Self::default()))
	}

	fn kind() -> BehaviorKind {
		BehaviorKind::Action
	}

	fn static_provided_ports(&self) -> PortList {
		self.provided_ports.clone()
	}
}

#[async_trait::async_trait]
impl Behavior for SimpleBehavior {
	async fn tick(
		&mut self,
		behavior: &mut BehaviorData,
		_children: &mut BehaviorTreeElementList,
		_runtime: &SharedRuntime,
	) -> BehaviorResult {
		self.complex_tick_fn.as_ref().map_or_else(
			|| {
				self.simple_tick_fn.as_ref().map_or_else(
					|| {
						Err(super::BehaviorError::Composition {
							txt: "SimpleBehavior without tick function".into(),
						})
					},
					|func| func(),
				)
			},
			|func| func(behavior),
		)
	}
}

/// Implementation resembles the macro generated impl code
impl SimpleBehavior {
	/// Create a `SimpleBehavior` with the given function
	pub fn create(tick_fn: SimpleBhvrTickFn) -> Box<BehaviorCreationFn> {
		Box::new(move || {
			Box::new(Self {
				simple_tick_fn: Some(tick_fn.clone()),
				complex_tick_fn: None,
				provided_ports: PortList::default(),
			})
		})
	}

	/// Create a `SimpleBehavior` with the given function and list of ports
	pub fn new_create_with_ports(tick_fn: ComplexBhvrTickFn, port_list: PortList) -> Box<BehaviorCreationFn> {
		Box::new(move || {
			Box::new(Self {
				simple_tick_fn: None,
				complex_tick_fn: Some(tick_fn.clone()),
				provided_ports: port_list.clone(),
			})
		})
	}
}