import Stack from "ts-data.stack" ; import BehaviorTreeStatus from "./BehaviorTreeStatus" ; import BehaviorTreeError from "./Error/BehaviorTreeError" ; import Errors from "./Error/Errors" ; import ActionNode from "./Node/ActionNode" ; import BehaviorTreeNodeInterface from "./Node/BehaviorTreeNodeInterface" ; import InverterNode from "./Node/InverterNode" ; import ParallelNode from "./Node/ParallelNode" ; import ParentBehaviorTreeNodeInterface from "./Node/ParentBehaviorTreeNodeInterface" ; import SelectorNode from "./Node/SelectorNode" ; import SequenceNode from "./Node/SequenceNode" ; import StateData from "./StateData" ; export default class BehaviorTreeBuilder { /**
     * Last node created
     */ private curNode ? : BehaviorTreeNodeInterface ; type { Stack < ParentBehaviorTreeNodeInterface > } private parentNodeStack : Stack < ParentBehaviorTreeNodeInterface > = new Stack < ParentBehaviorTreeNodeInterface > ( ) ; param { string } name param { ( state : StateData ) => BehaviorTreeStatus } fn returns { BehaviorTreeBuilder } public do ( name , fn ) { if ( this . parentNodeStack . isEmpty ( ) ) { throw new BehaviorTreeError ( Errors . UNNESTED_ACTION_NODE ) ; } const actionNode = new ActionNode ( name , fn ) ; this . parentNodeStack . peek ( ) . addChild ( actionNode ) ; return this ; } param { string } name param { ( state : StateData ) => boolean } fn returns { BehaviorTreeBuilder } public condition ( name , fn ) { return this . do ( name , async ( t ) => await fn ( t ) ? BehaviorTreeStatus . Success : BehaviorTreeStatus . Failure ) ; } param { string } name returns { BehaviorTreeBuilder } public inverter ( name ) { return this . addParentNode ( new InverterNode ( name ) ) ; } param { string } name param { boolean } keepState returns { BehaviorTreeBuilder } public sequence ( name , keepState = true ) { return this . addParentNode ( new SequenceNode ( name , keepState ) ) ; } param { string } name param { number } requiredToFail param { number } requiredToSucceed returns { BehaviorTreeBuilder } public parallel ( name , requiredToFail , requiredToSucceed ) { return this . addParentNode ( new ParallelNode ( name , requiredToFail , requiredToSucceed ) ) ; } param { string } name param { boolean } keepState returns { BehaviorTreeBuilder } public selector ( name , keepState = true ) { return this . addParentNode ( new SelectorNode ( name , keepState ) ) ; } param { BehaviorTreeNodeInterface } subTree returns { BehaviorTreeBuilder } public splice ( subTree ) { if ( this . parentNodeStack . isEmpty ( ) ) { throw new BehaviorTreeError ( Errors . SPLICE_UNNESTED_TREE ) ; } this . parentNodeStack . peek ( ) . addChild ( subTree ) ; return this ; } returns { BehaviorTreeNodeInterface } public build ( ) { if ( ! this . curNode ) { throw new BehaviorTreeError ( Errors . NO_NODES ) ; } return this . curNode ; } returns { BehaviorTreeBuilder } public end ( ) { this . curNode = this . parentNodeStack . pop ( ) ; return this ; } param { ParentBehaviorTreeNodeInterface } node returns { BehaviorTreeBuilder } private addParentNode ( node ) { if ( ! this . parentNodeStack . isEmpty ( ) ) { this . parentNodeStack . peek ( ) . addChild ( node ) ; } this . parentNodeStack . push ( node ) ; return this ; } }