UNPKG

behaviortree

Version:

A JavaScript implementation of Behavior Trees. They are useful for implementing AIs. For Browsers and NodeJS.

3 lines (2 loc) 6.26 kB
var M=Object.defineProperty;var v=(n,t)=>{for(var e in t)M(n,e,{get:t[e],enumerable:!0})};var i=Symbol("running"),l=!0,s=!1;function u(n){return n===i||typeof n=="object"&&n.total===i}var W=()=>!1,q=()=>{},J=()=>{},g=class{_name;blueprint;nodeType="Node";constructor({run:t=W,start:e=q,end:o=J,...a}){this.blueprint={run:t,start:e,end:o,...a}}run(t,{introspector:e,rerun:o=!1,registryLookUp:a=r=>r,...f}={}){o||this.blueprint.start(t);let r=this.blueprint.run(t,{...f,rerun:o,registryLookUp:a});return r!==i&&this.blueprint.end(t),e&&e.push(this,r,t),r}get name(){return this._name||this.blueprint.name}set name(t){this._name=t}};var N=class extends g{nodeType="Task"};var O={};function $(){return O}function E(n){if(typeof n=="string"){let t=O[n];if(!t)throw new Error(`No node with name ${n} registered.`);return t}return n}var k=class{tree;blackboard;lastResult;constructor({tree:t,blackboard:e}){this.tree=t,this.blackboard=e,this.lastResult=void 0}step({introspector:t}={}){let e=this.lastResult&&typeof this.lastResult=="object"?this.lastResult:void 0,o=u(this.lastResult);t&&t.start(this),this.lastResult=E(this.tree).run(this.blackboard,{lastRun:e,introspector:t,rerun:o,registryLookUp:E}),t&&t.end()}static register(t,e){O[t]=typeof e=="function"?new N({name:t,run:e}):e}static cleanRegistry(){O={}}};var G={};v(G,{AlwaysFailDecorator:()=>C,AlwaysSucceedDecorator:()=>x,CooldownDecorator:()=>y,InvertDecorator:()=>T,LoopDecorator:()=>b});var d=class extends g{config;nodeType="Decorator";constructor({config:t={},...e}={config:{}}){super(e),this.setConfig(t)}decorate(t,e,o){return t(t,e,o)}run(t,{introspector:e,rerun:o,registryLookUp:a=r=>r,...f}={}){o||this.blueprint.start(t);let r=0,c=this.decorate(()=>(++r,a(this.blueprint.node).run(t,{...f,rerun:o,introspector:e,registryLookUp:a})),t,this.config);return c!==i&&this.blueprint.end(t),e&&e.wrapLast(r,this,c,t),c}setConfig(t){this.config=t}};var C=class extends d{nodeType="AlwaysFailDecorator";decorate(t){let e=t();return u(e)?e:s}};var x=class extends d{nodeType="AlwaysSucceedDecorator";decorate(t){let e=t();return u(e)?e:l}};var y=class extends d{lock=!1;nodeType="CooldownDecorator";setConfig({cooldown:t=5}){this.config={cooldown:t}}decorate(t){if(this.lock)return s;let e=t();return u(e)||(this.lock=!0,setTimeout(()=>{this.lock=!1},this.config.cooldown*1e3)),e}};var T=class extends d{nodeType="InvertDecorator";decorate(t){let e=t();return u(e)?e:e===l?s:l}};var b=class extends d{nodeType="LoopDecorator";setConfig({loop:t=1/0}){this.config={loop:t}}decorate(t){let e=0,o=s;for(;e++<this.config.loop;)if(o=t(),o===s)return s;return o}};var h=class extends g{numNodes;nodes;OPT_OUT_CASE=l;START_CASE=l;nodeType="BranchNode";constructor(t){super(t),this.nodes=t.nodes||[],this.numNodes=this.nodes.length}run(t={},{lastRun:e,introspector:o,rerun:a,registryLookUp:f=r=>r}={}){a||this.blueprint.start(t);let r=this.START_CASE,c=[],p=typeof e=="object"&&e.state||[],R=Math.max(p.findIndex(w=>u(w)),0),m=0;for(;m<this.numNodes;++m){if(m<R){c[m]=p[m];continue}let A=f(this.nodes[m]).run(t,{lastRun:p[m],introspector:o,rerun:a,registryLookUp:f});if(c[m]=A,A===i||typeof A=="object"){r=i;break}else if(A===this.OPT_OUT_CASE){r=A;break}else a=!1}let D=u(r);if(D||this.blueprint.end(t),o){let w=D?i:r;o.wrapLast(Math.min(m+1,this.numNodes),this,w,t)}return r===i?{total:r,state:c}:r}};var I=class extends h{nodeType="Random";run(t={},{lastRun:e,introspector:o,rerun:a,registryLookUp:f=r=>r}={}){let r=0;a?r=e.state.findIndex(m=>u(m)):(this.blueprint.start(t),r=Math.floor(Math.random()*this.numNodes));let p=f(this.nodes[r]).run(t,{lastRun:e,introspector:o,rerun:a,registryLookUp:f}),R=u(p);if(R||this.blueprint.end(t),o){let m=R?i:p;o.wrapLast(1,this,m,t)}if(R){let m={total:i,state:new Array(this.numNodes).fill(void 0)};return m.state[r]=p,m}return p}};var B=class extends h{nodeType="Selector";START_CASE=s;OPT_OUT_CASE=l};var U=class extends h{nodeType="Sequence";START_CASE=l;OPT_OUT_CASE=s};var _=class{types={task:N,decorator:d,selector:B,sequence:U,random:I,invert:T,fail:C,succeed:x,cooldown:y,loop:b};defineType(t,e){this.types[t]=e}parse(t){let{type:e,name:o,...a}=t,f=this.types[e];if(!f){let r=E(e);if(r)return r.name=o,r;throw new Error(`Don't know how to handle type ${e}. Please register this first.`)}return new f({name:o,node:t.node?this.parse(t.node):null,nodes:t.nodes?t.nodes.map(r=>this.parse(r)):null,config:a})}};var L=class{currentResult;results;tree;constructor(){this.currentResult=[],this.results=[]}start(t){this.tree=t,this.currentResult=[]}end(){let t=this.currentResult.pop();t&&this.results.push(t),delete this.tree,this.currentResult=[]}push(t,e,o){this.currentResult.push(this._toResult(t,e,o))}wrapLast(t,e,o,a){let f=this.currentResult.splice(this.currentResult.length-t,t);this.currentResult.push({...this._toResult(e,o,a),children:f})}_toResult(t,e,o){return{...t.name?{name:t.name}:{},result:e}}reset(){this.results=[]}get lastResult(){return this.results.length===0?null:this.results[this.results.length-1]}};var S=class extends h{numNodes;nodes;nodeType="Parallel";constructor(t){super(t),this.nodes=t.nodes||[],this.numNodes=this.nodes.length}run(t={},{lastRun:e,introspector:o,rerun:a,registryLookUp:f=r=>r}={}){a||this.blueprint.start(t);let r=[];for(let p=0;p<this.numNodes;++p){let R=e&&e.state[p];if(R&&!u(R)){r[p]=R;continue}let D=f(this.nodes[p]).run(t,{lastRun:R,introspector:o,rerun:a,registryLookUp:f});r[p]=D}let c=this.calcResult(r);if(u(c)||this.blueprint.end(t),o){let R=!!r.find(m=>u(m))?i:c;o.wrapLast(this.numNodes,this,R,t)}return c}calcResult(t){return t.includes(s)?s:!!t.find(o=>u(o))?{total:i,state:t}:l}};var P=class extends S{nodeType="ParallelComplete";calcResult(t){return t.includes(s)?s:t.includes(l)?l:{total:i,state:t}}};var F=class extends S{nodeType="ParallelSelector";calcResult(t){return t.includes(s)?s:!!t.find(o=>u(o))?{total:i,state:t}:l}};var Ue=k;export{k as BehaviorTree,_ as BehaviorTreeImporter,h as BranchNode,d as Decorator,s as FAILURE,L as Introspector,g as Node,S as Parallel,P as ParallelComplete,F as ParallelSelector,i as RUNNING,I as Random,l as SUCCESS,B as Selector,U as Sequence,N as Task,G as decorators,Ue as default,$ as getRegistry,E as registryLookUp}; //# sourceMappingURL=index.umd.js.map