1#![warn(missing_docs)]
22
23use crate::plugin::error::GameError;
37use crate::{
38 core::{
39 pool::{Handle, Pool},
40 visitor::prelude::*,
41 },
42 utils::behavior::{
43 composite::{CompositeNode, CompositeNodeKind},
44 inverter::Inverter,
45 leaf::LeafNode,
46 },
47};
48use fyrox_core::pool::PoolError;
49use std::{
50 fmt::Debug,
51 ops::{Index, IndexMut},
52};
53
54pub mod composite;
55pub mod inverter;
56pub mod leaf;
57
58pub type BehaviorResult = Result<Status, GameError>;
60
61pub enum Status {
63 Success,
65 Failure,
67 Running,
69}
70
71pub trait BaseBehavior: Visit + Default + PartialEq + Debug + Clone + 'static {}
73impl<T: Visit + Default + PartialEq + Debug + Clone + 'static> BaseBehavior for T {}
74
75pub trait Behavior<'a>: BaseBehavior {
77 type Context;
79
80 fn tick(&mut self, context: &mut Self::Context) -> Result<Status, GameError>;
84}
85
86#[derive(Debug, PartialEq, Visit, Eq, Clone)]
88pub struct RootNode<B>
89where
90 B: BaseBehavior,
91{
92 child: Handle<BehaviorNode<B>>,
93}
94
95impl<B> Default for RootNode<B>
96where
97 B: BaseBehavior,
98{
99 fn default() -> Self {
100 Self {
101 child: Default::default(),
102 }
103 }
104}
105
106#[derive(Debug, PartialEq, Visit, Eq, Clone, Default)]
108pub enum BehaviorNode<B>
109where
110 B: BaseBehavior,
111{
112 #[doc(hidden)]
113 #[default]
114 Unknown,
115 Root(RootNode<B>),
117 Composite(CompositeNode<B>),
119 Leaf(LeafNode<B>),
121 Inverter(Inverter<B>),
124}
125
126#[derive(Debug, PartialEq, Visit, Clone)]
128pub struct BehaviorTree<B>
129where
130 B: BaseBehavior,
131{
132 nodes: Pool<BehaviorNode<B>>,
133 root: Handle<BehaviorNode<B>>,
134}
135
136impl<B> Default for BehaviorTree<B>
137where
138 B: BaseBehavior,
139{
140 fn default() -> Self {
141 Self {
142 nodes: Default::default(),
143 root: Default::default(),
144 }
145 }
146}
147
148impl<B> BehaviorTree<B>
149where
150 B: BaseBehavior,
151{
152 pub fn new() -> Self {
154 let mut nodes = Pool::new();
155 let root = nodes.spawn(BehaviorNode::Root(RootNode {
156 child: Default::default(),
157 }));
158 Self { nodes, root }
159 }
160
161 pub fn add_node(&mut self, node: BehaviorNode<B>) -> Handle<BehaviorNode<B>> {
163 self.nodes.spawn(node)
164 }
165
166 pub fn set_entry_node(&mut self, entry: Handle<BehaviorNode<B>>) {
168 if let BehaviorNode::Root(root) = &mut self.nodes[self.root] {
169 root.child = entry;
170 } else {
171 unreachable!("must be root")
172 }
173 }
174
175 fn tick_recursive<'a, Ctx>(
176 &self,
177 handle: Handle<BehaviorNode<B>>,
178 context: &mut Ctx,
179 ) -> Result<Status, GameError>
180 where
181 B: Behavior<'a, Context = Ctx>,
182 {
183 match self.nodes[handle] {
184 BehaviorNode::Root(ref root) => {
185 if root.child.is_some() {
186 self.tick_recursive(root.child, context)
187 } else {
188 Ok(Status::Success)
189 }
190 }
191 BehaviorNode::Composite(ref composite) => match composite.kind {
192 CompositeNodeKind::Sequence => {
193 let mut all_succeeded = true;
194 for child in composite.children.iter() {
195 match self.tick_recursive(*child, context)? {
196 Status::Failure => {
197 all_succeeded = false;
198 break;
199 }
200 Status::Running => {
201 return Ok(Status::Running);
202 }
203 _ => (),
204 }
205 }
206 if all_succeeded {
207 Ok(Status::Success)
208 } else {
209 Ok(Status::Failure)
210 }
211 }
212 CompositeNodeKind::Selector => {
213 for child in composite.children.iter() {
214 match self.tick_recursive(*child, context)? {
215 Status::Success => return Ok(Status::Success),
216 Status::Running => return Ok(Status::Running),
217 _ => (),
218 }
219 }
220 Ok(Status::Failure)
221 }
222 },
223 BehaviorNode::Leaf(ref leaf) => {
224 leaf.behavior.as_ref().unwrap().borrow_mut().tick(context)
225 }
226 BehaviorNode::Inverter(ref inverter) => {
227 match self.tick_recursive(inverter.child, context)? {
228 Status::Success => Ok(Status::Failure),
229 Status::Failure => Ok(Status::Success),
230 Status::Running => Ok(Status::Running),
231 }
232 }
233 BehaviorNode::Unknown => {
234 unreachable!()
235 }
236 }
237 }
238
239 pub fn node(&self, handle: Handle<BehaviorNode<B>>) -> Result<&BehaviorNode<B>, PoolError> {
241 self.nodes.try_borrow(handle)
242 }
243
244 pub fn node_mut(
246 &mut self,
247 handle: Handle<BehaviorNode<B>>,
248 ) -> Result<&mut BehaviorNode<B>, PoolError> {
249 self.nodes.try_borrow_mut(handle)
250 }
251
252 pub fn tick<'a, Ctx>(&self, context: &mut Ctx) -> Result<Status, GameError>
254 where
255 B: Behavior<'a, Context = Ctx>,
256 {
257 self.tick_recursive(self.root, context)
258 }
259}
260
261impl<B: BaseBehavior> Index<Handle<BehaviorNode<B>>> for BehaviorTree<B> {
262 type Output = BehaviorNode<B>;
263
264 fn index(&self, index: Handle<BehaviorNode<B>>) -> &Self::Output {
265 &self.nodes[index]
266 }
267}
268
269impl<B: BaseBehavior> IndexMut<Handle<BehaviorNode<B>>> for BehaviorTree<B> {
270 fn index_mut(&mut self, index: Handle<BehaviorNode<B>>) -> &mut Self::Output {
271 &mut self.nodes[index]
272 }
273}
274
275pub fn sequence<B, const N: usize>(
277 children: [Handle<BehaviorNode<B>>; N],
278 tree: &mut BehaviorTree<B>,
279) -> Handle<BehaviorNode<B>>
280where
281 B: BaseBehavior,
282{
283 CompositeNode::new_sequence(children.to_vec()).add_to(tree)
284}
285
286pub fn selector<B, const N: usize>(
288 children: [Handle<BehaviorNode<B>>; N],
289 tree: &mut BehaviorTree<B>,
290) -> Handle<BehaviorNode<B>>
291where
292 B: BaseBehavior,
293{
294 CompositeNode::new_selector(children.to_vec()).add_to(tree)
295}
296
297pub fn leaf<B>(behavior: B, tree: &mut BehaviorTree<B>) -> Handle<BehaviorNode<B>>
299where
300 B: BaseBehavior,
301{
302 LeafNode::new(behavior).add_to(tree)
303}
304
305pub fn inverter<B>(
307 child: Handle<BehaviorNode<B>>,
308 tree: &mut BehaviorTree<B>,
309) -> Handle<BehaviorNode<B>>
310where
311 B: BaseBehavior,
312{
313 Inverter::new(child).add_to(tree)
314}
315
316#[macro_export]
319macro_rules! dispatch_behavior_variants {
320 ($type_name:ident, $context:ty, $($variants:ident),*) => {
321 impl<'a> $crate::utils::behavior::Behavior<'a> for $type_name {
322 type Context = $context;
323
324 fn tick(&mut self, context: &mut Self::Context) -> $crate::utils::behavior::BehaviorResult
325 {
326 match self {
327 $(
328 $type_name::$variants(v) => v.tick(context)
329 ),*
330 }
331 }
332 }
333 };
334}
335
336#[cfg(test)]
337mod test {
338 use crate::utils::behavior::BehaviorResult;
339 use crate::{
340 core::{futures::executor::block_on, visitor::prelude::*},
341 utils::behavior::{leaf, sequence, Behavior, BehaviorTree, Status},
342 };
343 use std::{env, fs::File, io::Write, path::PathBuf};
344
345 #[derive(Visit)]
346 struct Environment {
347 distance_to_door: f32,
350 door_opened: bool,
351 done: bool,
352 }
353
354 impl Default for Environment {
355 fn default() -> Self {
356 Self {
357 distance_to_door: 3.0,
358 door_opened: false,
359 done: false,
360 }
361 }
362 }
363
364 #[derive(Debug, PartialEq, Default, Visit, Clone)]
365 struct WalkAction;
366
367 impl Behavior<'_> for WalkAction {
368 type Context = Environment;
369
370 fn tick(&mut self, context: &mut Self::Context) -> BehaviorResult {
371 if context.distance_to_door <= 0.0 {
372 Ok(Status::Success)
373 } else {
374 context.distance_to_door -= 0.1;
375 println!(
376 "Approaching door, remaining distance: {}",
377 context.distance_to_door
378 );
379 Ok(Status::Running)
380 }
381 }
382 }
383
384 #[derive(Debug, PartialEq, Default, Visit, Clone)]
385 struct OpenDoorAction;
386
387 impl Behavior<'_> for OpenDoorAction {
388 type Context = Environment;
389
390 fn tick(&mut self, context: &mut Self::Context) -> BehaviorResult {
391 if !context.door_opened {
392 context.door_opened = true;
393 println!("Door was opened!");
394 }
395 Ok(Status::Success)
396 }
397 }
398
399 #[derive(Debug, PartialEq, Default, Visit, Clone)]
400 struct StepThroughAction;
401
402 impl Behavior<'_> for StepThroughAction {
403 type Context = Environment;
404
405 fn tick(&mut self, context: &mut Self::Context) -> BehaviorResult {
406 if context.distance_to_door < -1.0 {
407 Ok(Status::Success)
408 } else {
409 context.distance_to_door -= 0.1;
410 println!(
411 "Stepping through doorway, remaining distance: {}",
412 -1.0 - context.distance_to_door
413 );
414 Ok(Status::Running)
415 }
416 }
417 }
418
419 #[derive(Debug, PartialEq, Default, Visit, Clone)]
420 struct CloseDoorAction;
421
422 impl Behavior<'_> for CloseDoorAction {
423 type Context = Environment;
424
425 fn tick(&mut self, context: &mut Self::Context) -> BehaviorResult {
426 if context.door_opened {
427 context.door_opened = false;
428 context.done = true;
429 println!("Door was closed");
430 }
431 Ok(Status::Success)
432 }
433 }
434
435 #[derive(Debug, PartialEq, Visit, Clone)]
436 enum BotAction {
437 Walk(WalkAction),
438 OpenDoor(OpenDoorAction),
439 StepThrough(StepThroughAction),
440 CloseDoor(CloseDoorAction),
441 }
442
443 impl Default for BotAction {
444 fn default() -> Self {
445 Self::Walk(Default::default())
446 }
447 }
448
449 dispatch_behavior_variants!(
450 BotAction,
451 Environment,
452 Walk,
453 OpenDoor,
454 StepThrough,
455 CloseDoor
456 );
457
458 fn create_tree() -> BehaviorTree<BotAction> {
459 let mut tree = BehaviorTree::new();
460
461 let entry = sequence(
462 [
463 leaf(BotAction::Walk(WalkAction), &mut tree),
464 leaf(BotAction::OpenDoor(OpenDoorAction), &mut tree),
465 leaf(BotAction::StepThrough(StepThroughAction), &mut tree),
466 leaf(BotAction::CloseDoor(CloseDoorAction), &mut tree),
467 ],
468 &mut tree,
469 );
470
471 tree.set_entry_node(entry);
472
473 tree
474 }
475
476 #[test]
477 fn test_behavior() {
478 let tree = create_tree();
479
480 let mut ctx = Environment::default();
481
482 while !ctx.done {
483 tree.tick(&mut ctx).unwrap();
484 }
485 }
486
487 #[test]
488 fn test_behavior_save_load() {
489 let (bin, txt) = {
490 let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
491 let root = PathBuf::from(manifest_dir).join("test_output");
492 if !root.exists() {
493 std::fs::create_dir(&root).unwrap();
494 }
495 (
496 root.join(format!("{}.bin", "behavior_save_load")),
497 root.join(format!("{}.txt", "behavior_save_load")),
498 )
499 };
500
501 let mut saved_tree = create_tree();
503 let mut visitor = Visitor::new();
504 saved_tree.visit("Tree", &mut visitor).unwrap();
505 visitor.save_binary_to_file(bin.clone()).unwrap();
506 let mut file = File::create(txt).unwrap();
507 file.write_all(visitor.save_ascii_to_string().as_bytes())
508 .unwrap();
509
510 let mut visitor = block_on(Visitor::load_from_file(bin)).unwrap();
512 let mut loaded_tree = BehaviorTree::<BotAction>::default();
513 loaded_tree.visit("Tree", &mut visitor).unwrap();
514
515 assert_eq!(saved_tree, loaded_tree);
516 }
517}