3333//! - [Wikipedia article](https://en.wikipedia.org/wiki/Behavior_tree_(artificial_intelligence,_robotics_and_control))
3434//! - [Gamasutra](https://www.gamasutra.com/blogs/ChrisSimpson/20140717/221339/Behavior_trees_for_AI_How_they_work.php)
3535
36+ use crate :: plugin:: error:: GameError ;
3637use crate :: {
3738 core:: {
3839 pool:: { Handle , Pool } ,
@@ -72,7 +73,7 @@ pub trait Behavior<'a>: Visit + Default + PartialEq + Debug + Clone {
7273 /// A function that will be called each frame depending on
7374 /// the current execution path of the behavior tree it belongs
7475 /// to.
75- fn tick ( & mut self , context : & mut Self :: Context ) -> Status ;
76+ fn tick ( & mut self , context : & mut Self :: Context ) -> Result < Status , GameError > ;
7677}
7778
7879/// Root node of the tree.
@@ -164,7 +165,11 @@ where
164165 }
165166 }
166167
167- fn tick_recursive < ' a , Ctx > ( & self , handle : Handle < BehaviorNode < B > > , context : & mut Ctx ) -> Status
168+ fn tick_recursive < ' a , Ctx > (
169+ & self ,
170+ handle : Handle < BehaviorNode < B > > ,
171+ context : & mut Ctx ,
172+ ) -> Result < Status , GameError >
168173 where
169174 B : Behavior < ' a , Context = Ctx > ,
170175 {
@@ -173,49 +178,49 @@ where
173178 if root. child . is_some ( ) {
174179 self . tick_recursive ( root. child , context)
175180 } else {
176- Status :: Success
181+ Ok ( Status :: Success )
177182 }
178183 }
179184 BehaviorNode :: Composite ( ref composite) => match composite. kind {
180185 CompositeNodeKind :: Sequence => {
181186 let mut all_succeeded = true ;
182187 for child in composite. children . iter ( ) {
183- match self . tick_recursive ( * child, context) {
188+ match self . tick_recursive ( * child, context) ? {
184189 Status :: Failure => {
185190 all_succeeded = false ;
186191 break ;
187192 }
188193 Status :: Running => {
189- return Status :: Running ;
194+ return Ok ( Status :: Running ) ;
190195 }
191196 _ => ( ) ,
192197 }
193198 }
194199 if all_succeeded {
195- Status :: Success
200+ Ok ( Status :: Success )
196201 } else {
197- Status :: Failure
202+ Ok ( Status :: Failure )
198203 }
199204 }
200205 CompositeNodeKind :: Selector => {
201206 for child in composite. children . iter ( ) {
202- match self . tick_recursive ( * child, context) {
203- Status :: Success => return Status :: Success ,
204- Status :: Running => return Status :: Running ,
207+ match self . tick_recursive ( * child, context) ? {
208+ Status :: Success => return Ok ( Status :: Success ) ,
209+ Status :: Running => return Ok ( Status :: Running ) ,
205210 _ => ( ) ,
206211 }
207212 }
208- Status :: Failure
213+ Ok ( Status :: Failure )
209214 }
210215 } ,
211216 BehaviorNode :: Leaf ( ref leaf) => {
212217 leaf. behavior . as_ref ( ) . unwrap ( ) . borrow_mut ( ) . tick ( context)
213218 }
214219 BehaviorNode :: Inverter ( ref inverter) => {
215- match self . tick_recursive ( inverter. child , context) {
216- Status :: Success => Status :: Failure ,
217- Status :: Failure => Status :: Success ,
218- Status :: Running => Status :: Running ,
220+ match self . tick_recursive ( inverter. child , context) ? {
221+ Status :: Success => Ok ( Status :: Failure ) ,
222+ Status :: Failure => Ok ( Status :: Success ) ,
223+ Status :: Running => Ok ( Status :: Running ) ,
219224 }
220225 }
221226 BehaviorNode :: Unknown => {
@@ -238,7 +243,7 @@ where
238243 }
239244
240245 /// Performs a single update tick with given context.
241- pub fn tick < ' a , Ctx > ( & self , context : & mut Ctx ) -> Status
246+ pub fn tick < ' a , Ctx > ( & self , context : & mut Ctx ) -> Result < Status , GameError >
242247 where
243248 B : Behavior < ' a , Context = Ctx > ,
244249 {
@@ -303,6 +308,7 @@ where
303308
304309#[ cfg( test) ]
305310mod test {
311+ use crate :: plugin:: error:: GameError ;
306312 use crate :: {
307313 core:: { futures:: executor:: block_on, visitor:: prelude:: * } ,
308314 utils:: behavior:: {
@@ -319,16 +325,16 @@ mod test {
319325 impl Behavior < ' _ > for WalkAction {
320326 type Context = Environment ;
321327
322- fn tick ( & mut self , context : & mut Self :: Context ) -> Status {
328+ fn tick ( & mut self , context : & mut Self :: Context ) -> Result < Status , GameError > {
323329 if context. distance_to_door <= 0.0 {
324- Status :: Success
330+ Ok ( Status :: Success )
325331 } else {
326332 context. distance_to_door -= 0.1 ;
327333 println ! (
328334 "Approaching door, remaining distance: {}" ,
329335 context. distance_to_door
330336 ) ;
331- Status :: Running
337+ Ok ( Status :: Running )
332338 }
333339 }
334340 }
@@ -339,12 +345,12 @@ mod test {
339345 impl Behavior < ' _ > for OpenDoorAction {
340346 type Context = Environment ;
341347
342- fn tick ( & mut self , context : & mut Self :: Context ) -> Status {
348+ fn tick ( & mut self , context : & mut Self :: Context ) -> Result < Status , GameError > {
343349 if !context. door_opened {
344350 context. door_opened = true ;
345351 println ! ( "Door was opened!" ) ;
346352 }
347- Status :: Success
353+ Ok ( Status :: Success )
348354 }
349355 }
350356
@@ -354,16 +360,16 @@ mod test {
354360 impl Behavior < ' _ > for StepThroughAction {
355361 type Context = Environment ;
356362
357- fn tick ( & mut self , context : & mut Self :: Context ) -> Status {
363+ fn tick ( & mut self , context : & mut Self :: Context ) -> Result < Status , GameError > {
358364 if context. distance_to_door < -1.0 {
359- Status :: Success
365+ Ok ( Status :: Success )
360366 } else {
361367 context. distance_to_door -= 0.1 ;
362368 println ! (
363369 "Stepping through doorway, remaining distance: {}" ,
364370 -1.0 - context. distance_to_door
365371 ) ;
366- Status :: Running
372+ Ok ( Status :: Running )
367373 }
368374 }
369375 }
@@ -374,13 +380,13 @@ mod test {
374380 impl Behavior < ' _ > for CloseDoorAction {
375381 type Context = Environment ;
376382
377- fn tick ( & mut self , context : & mut Self :: Context ) -> Status {
383+ fn tick ( & mut self , context : & mut Self :: Context ) -> Result < Status , GameError > {
378384 if context. door_opened {
379385 context. door_opened = false ;
380386 context. done = true ;
381387 println ! ( "Door was closed" ) ;
382388 }
383- Status :: Success
389+ Ok ( Status :: Success )
384390 }
385391 }
386392
@@ -406,7 +412,7 @@ mod test {
406412 impl Behavior < ' _ > for BotBehavior {
407413 type Context = Environment ;
408414
409- fn tick ( & mut self , context : & mut Self :: Context ) -> Status {
415+ fn tick ( & mut self , context : & mut Self :: Context ) -> Result < Status , GameError > {
410416 match self {
411417 BotBehavior :: None => unreachable ! ( ) ,
412418 BotBehavior :: Walk ( v) => v. tick ( context) ,
@@ -447,7 +453,7 @@ mod test {
447453 } ;
448454
449455 while !ctx. done {
450- tree. tick ( & mut ctx) ;
456+ tree. tick ( & mut ctx) . unwrap ( ) ;
451457 }
452458 }
453459
0 commit comments