UNPKG

behaviortree

Version:

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

105 lines (104 loc) 4.17 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-env jest */ const sinon_1 = __importDefault(require("sinon")); const constants_1 = require("./constants"); const BehaviorTree_1 = __importDefault(require("./BehaviorTree")); const BehaviorTreeImporter_1 = __importDefault(require("./BehaviorTreeImporter")); const Decorator_1 = __importDefault(require("./Decorator")); const Task_1 = __importDefault(require("./Task")); const Introspector_1 = __importDefault(require("./Introspector")); class EnemyInSightDecorator extends Decorator_1.default { constructor() { super(...arguments); this.nodeType = 'EnemyInSightDecorator'; } decorate(run, blackboard) { return blackboard.enemyInSight ? run() : constants_1.FAILURE; } } describe('BehaviorTreeImporter', () => { let clock; let blackboard; let importer; beforeEach(() => { clock = sinon_1.default.useFakeTimers(); blackboard = { timesJumped: 0 }; BehaviorTree_1.default.register('walk', new Task_1.default({ run: function (blackboard) { blackboard.walking = true; return constants_1.SUCCESS; } })); BehaviorTree_1.default.register('idle', new Task_1.default({ run: function (blackboard) { blackboard.walking = false; return constants_1.SUCCESS; } })); BehaviorTree_1.default.register('jump', new Task_1.default({ run: function (blackboard) { blackboard.timesJumped++; return constants_1.SUCCESS; } })); importer = new BehaviorTreeImporter_1.default(); importer.defineType('ifEnemyInSight', EnemyInSightDecorator); }); describe('importing a complex JSON tree into a usable behavior tree', () => { const json = { type: 'selector', name: 'the root', nodes: [ { type: 'ifEnemyInSight', name: 'handling enemies', node: { type: 'walk', name: 'go to enemy' } }, { type: 'cooldown', name: 'jumping around', cooldown: 1, node: { type: 'jump', name: 'jump up' } // beacuse we can ;) }, { type: 'idle', name: 'doing nothing' } ] }; let bTree; let introspector; beforeEach(() => { introspector = new Introspector_1.default(); bTree = new BehaviorTree_1.default({ tree: importer.parse(json), blackboard }); }); it('works', () => { bTree.step({ introspector }); expect(introspector.lastResult?.name).toEqual('the root'); const selectorNodes = introspector.lastResult?.children || []; expect(selectorNodes.length).toEqual(2); expect(selectorNodes.map((x) => x.name)).toEqual(['handling enemies', 'jumping around']); expect(selectorNodes.map((x) => x.result)).toEqual([false, true]); }); it('passes in the config as it is supposed to', () => { bTree.step({ introspector }); bTree.step({ introspector }); let selectorNodes = introspector.lastResult?.children || []; expect(selectorNodes.map((x) => x.result)).toEqual([false, false, true]); clock.tick(999); bTree.step({ introspector }); selectorNodes = introspector.lastResult?.children || []; expect(selectorNodes.map((x) => x.result)).toEqual([false, false, true]); clock.tick(1); bTree.step({ introspector }); selectorNodes = introspector.lastResult?.children || []; expect(selectorNodes.map((x) => x.result)).toEqual([false, true]); }); }); });