1.1.2 • Published 7 years ago

wbt v1.1.2

Weekly downloads
2
License
ISC
Repository
github
Last release
7 years ago

WBT

Node.js Behavior Tree, this a Node.js library to design a Behavior Tree. This is inspired from http://guineashots.com/2014/09/24/implementing-a-behavior-tree-part-1/

Example

First let's define some Actions. We start by creating a DoRandom action and then we will simulate a success action SuccessAction and a fail action FailAction.

// dorandom.js
"use strict";

let BaseNode = require('./basenode');
let Status = require('./status');

let DoRandom = function(text, time) {
	this.text = text;
  
  // this is to simulate a long time execution task
	this.endTime = time;
	
  this.initialize();
}

DoRandom.prototype = new BaseNode();
DoRandom.prototype.open = function(tick) {
	let startTime = (new Date()).getTime();
  
  // Save the starttime value
	tick.blackboard.set('startTime', startTime, tick.tree.id, this.id);
  
  // Check if event variable exists if not set it to 0
	if (tick.blackboard.get('event', tick.tree.id) == undefined) {
		tick.blackboard.set('event', 0, tick.tree.id);
	}

	console.log("Starting " + this.text);
}

DoRandom.prototype.tick = function(tick) {
	let currTime = (new Date()).getTime();
	let startTime = tick.blackboard.get('startTime', tick.tree.id, this.id);

	if (currTime - startTime > this.endTime) {
		console.log("Finished " + this.text);
    
    // Increment event variable when the execution succeed
		let e = tick.blackboard.get('event', tick.tree.id) + 1;
		tick.blackboard.set('event', e, tick.tree.id);

		return Status.SUCCESS;
	}

	return Status.RUNNING;
}

module.exports = DoRandom;
// successaction.js
"use strict";

let BaseNode = require('./basenode');
let Status = require('./status');

let SuccessAction = function(text) {
	this.text = text;
	this.initialize(arguments);
}

SuccessAction.prototype = new BaseNode();
SuccessAction.prototype.tick = function(tick) {
	console.info('Success Action : ' + this.text);
  
  // reinitialize event variable
	tick.blackboard.set('event', 0, tick.tree.id);
	return Status.SUCCESS;
}

module.exports = SuccessAction;
// failaction.js
"use strict";

let BaseNode = require('./basenode');
let Status = require('./status');

let FailAction = function(text) {
	this.text = text;
	this.initialize();
}

FailAction.prototype = new BaseNode();
FailAction.prototype.tick = function(tick) {
	console.error(this.text);
	return Status.FAILURE;
}

module.exports = FailAction;

Now let's create a condition node that check whether the value of the variable event in blackboard is greater than 5 or not.

// iseventreceived.js
"use strict";

let BaseNode = require('./basenode');
let Status = require('./status');

let IsEventReceived = function() {
	this.initialize();
}

IsEventReceived.prototype = new BaseNode();
IsEventReceived.prototype.tick = function(tick) {
	let e = tick.blackboard.get('event', tick.tree.id);

	if (e && e > 5) {
		console.info("Event Received");
		return Status.SUCCESS;
	}

	console.error("No Event " + e);
	return Status.FAILURE;
}

module.exports = IsEventReceived;

And the main file

// main.js
"use strict";

let Blackboard = require('./blackboard');
let BehaviorTree = require('./behaviortree');

let Selector = require('./selector');
let Sequence = require('./sequence');
let MemSelector = require('./memselector');
let Random = require('./random');

let IsEventReceived = require('./iseventreceived');
let FailAction = require('./failaction');
let SuccessAction = require('./successaction');
let DoRandom = require('./dorandom');

let blackboard, tree;

blackboard = new Blackboard();
tree = new BehaviorTree();

tree.root = new Selector(
	new Sequence(
		new IsEventReceived(),
		new MemSelector(
			new FailAction("Fail 1"),
			new SuccessAction("Success 1"),
			new FailAction("Fail 2")
		)
	),
	new Random(
		new DoRandom("Random 1", 2000), // Simulate a 2 seconds task
		new DoRandom("Random 2", 500), // Simulate a 0.5 second task
		new DoRandom("Random 3", 4000), // Simulate a 4 seconds task
		new DoRandom("Random 4", 6000) // Simulate a 6 seconds task
	)
);

// Run the Behavior Tree each 300ms (this can be changed to what the designer want)
var intervalID = setInterval(function() {
	tree.tick(null, blackboard);
}, 300);