Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 1,000,000+ packages pre-installed, including wbt with all npm packages installed. Try it out:

var wbt = require("wbt")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

wbt v1.1.2

Behavior Tree Implementation for NodeJS

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);
RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free