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