Created
April 18, 2014 01:24
-
-
Save shimdh/11020212 to your computer and use it in GitHub Desktop.
btree module in behavior tree for node.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "use strict"; | |
| var Base = require('./base'); | |
| var countUnnamed = 0, | |
| BehaviorTree; | |
| BehaviorTree = Base.extend({ | |
| constructor: function(config) { | |
| countUnnamed += 1; | |
| this.title = config.title || 'btree' + (countUnnamed); | |
| this._rootNode = config.tree; | |
| this._object = config.object; | |
| }, | |
| setObject: function(obj) { | |
| this._object = obj; | |
| }, | |
| step: function() { | |
| if (this._started) { | |
| console.log('the BehaviorTree "' + this.title + '" did call step but one Task did not finish on last call of step.'); | |
| } | |
| this._started = true; | |
| var node = BehaviorTree.getNode(this._rootNode); | |
| this._actualNode = node; | |
| node.setControl(this); | |
| node.start(this._object); | |
| node.run(this._object); | |
| }, | |
| running: function() { | |
| this._started = false; | |
| }, | |
| success: function() { | |
| this._actualNode.end(this._object); | |
| this._started = false; | |
| }, | |
| fail: function() { | |
| this._actualNode.end(this._object); | |
| this._started = false; | |
| } | |
| }); | |
| BehaviorTree._registeredNodes = {}; | |
| BehaviorTree.register = function(name, node) { | |
| if (typeof name === 'string') { | |
| this._registeredNodes[name] = node; | |
| } else { | |
| // name is the node | |
| this._registeredNodes[name.title] = name; | |
| } | |
| }; | |
| BehaviorTree.getNode = function(name) { | |
| var node = name instanceof BehaviorTree.Node ? name : this._registeredNodes[name]; | |
| if (!node) { | |
| console.log('The node "' + name + '" could not be looked up. Maybe it was never registered?'); | |
| } | |
| return node; | |
| }; | |
| module.exports = BehaviorTree; | |
| var Node = Base.extend({ | |
| constructor: function(config) { | |
| // let config override instance properties | |
| this.base(config); | |
| }, | |
| start: function() {}, | |
| end: function() {}, | |
| run: function() { | |
| console.log('Warning: run of ' + this.title + ' not implemented!'); | |
| this.fail(); | |
| }, | |
| setControl: function(control) { | |
| this._control = control; | |
| }, | |
| running: function() { | |
| this._control.running(this); | |
| }, | |
| success: function() { | |
| this._control.success(); | |
| }, | |
| fail: function() { | |
| this._control.fail(); | |
| } | |
| }); | |
| BehaviorTree.Node = Node; | |
| var BranchNode = BehaviorTree.Node.extend({ | |
| constructor: function(config) { | |
| this.base(config); | |
| this.children = this.nodes || []; | |
| }, | |
| start: function() { | |
| this._actualTask = 0; | |
| }, | |
| run: function(object) { | |
| this._object = object; | |
| this.start(); | |
| if (this._actualTask < this.children.length) { | |
| this._run(); | |
| } | |
| this.end(); | |
| }, | |
| _run: function() { | |
| var node = BehaviorTree.getNode(this.children[this._actualTask]); | |
| this._runningNode = node; | |
| node.setControl(this); | |
| node.start(this._object); | |
| node.run(this._object); | |
| }, | |
| running: function(node) { | |
| this._nodeRunning = node; | |
| this._control.running(node); | |
| }, | |
| success: function() { | |
| this._nodeRunning = null; | |
| this._runningNode.end(this._object); | |
| }, | |
| fail: function() { | |
| this._nodeRunning = null; | |
| this._runningNode.end(this._object); | |
| } | |
| }); | |
| BehaviorTree.BranchNode = BranchNode; | |
| var Priority = BehaviorTree.BranchNode.extend({ | |
| success: function() { | |
| this.base(); | |
| this._control.success(); | |
| }, | |
| fail: function() { | |
| this.base(); | |
| this._actualTask += 1; | |
| if (this._actualTask < this.children.length) { | |
| this._run(this._object); | |
| } else { | |
| this._control.fail(); | |
| } | |
| } | |
| }); | |
| BehaviorTree.Priority = Priority; | |
| var Sequence = BehaviorTree.BranchNode.extend({ | |
| _run: function() { | |
| if (this._nodeRunning) { | |
| this._nodeRunning.run(this._object); | |
| this._nodeRunning = null; | |
| } else { | |
| this.base(); | |
| } | |
| }, | |
| success: function() { | |
| this.base(); | |
| this._actualTask += 1; | |
| if (this._actualTask < this.children.length) { | |
| this._run(this._object); | |
| } else { | |
| this._control.success(); | |
| } | |
| }, | |
| fail: function() { | |
| this.base(); | |
| this._control.fail(); | |
| } | |
| }); | |
| BehaviorTree.Sequence = Sequence; | |
| var Random = BehaviorTree.BranchNode.extend({ | |
| start: function() { | |
| this.base(); | |
| if (!this._nodeRunning) { | |
| this._actualTask = Math.floor(Math.random() * this.children.length); | |
| } | |
| }, | |
| success: function() { | |
| this.base(); | |
| this._control.success(); | |
| }, | |
| fail: function() { | |
| this.base(); | |
| this._control.fail(); | |
| }, | |
| _run: function() { | |
| if (!this._runningNode) { | |
| this.base(); | |
| } else { | |
| this._runningNode.run(this._object); | |
| } | |
| } | |
| }); | |
| BehaviorTree.Random = Random; | |
| var Task = BehaviorTree.Node.extend({}); | |
| BehaviorTree.Task = Task; | |
| var Decorator = BehaviorTree.Node.extend({ | |
| constructor: function(config) { | |
| // let config override instance properties | |
| this.base(config); | |
| if (this.node) { | |
| this.node = BehaviorTree.getNode(this.node); | |
| } | |
| }, | |
| setNode: function(node) { | |
| this.node = BehaviorTree.getNode(node); | |
| }, | |
| start: function() { | |
| this.node.setControl(this); | |
| this.node.start(); | |
| }, | |
| end: function() { | |
| this.node.end(); | |
| }, | |
| run: function(blackboard) { | |
| this.node.run(blackboard); | |
| }, | |
| }); | |
| BehaviorTree.Decorator = Decorator; | |
| var InvertDecorator = BehaviorTree.Decorator.extend({ | |
| success: function() { | |
| this._control.fail(); | |
| }, | |
| fail: function() { | |
| this._control.success(); | |
| }, | |
| }); | |
| BehaviorTree.InvertDecorator = InvertDecorator; | |
| var AlwaysSucceedDecorator = BehaviorTree.Decorator.extend({ | |
| success: function() { | |
| this._control.success(); | |
| }, | |
| fail: function() { | |
| this._control.success(); | |
| }, | |
| }); | |
| BehaviorTree.AlwaysSucceedDecorator = AlwaysSucceedDecorator; | |
| var AlwaysFailDecorator = BehaviorTree.Decorator.extend({ | |
| success: function() { | |
| this._control.fail(); | |
| }, | |
| fail: function() { | |
| this._control.fail(); | |
| }, | |
| }); | |
| BehaviorTree.AlwaysFailDecorator = AlwaysFailDecorator; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment