So I've setup a minimal (little rough) behavior tree structure in Js. Here is the code:
var Idle = Symbol("Idle"),
Running = Symbol("Running"),
Success = Symbol("Sucess"),
Failure = Symbol("Failure");
var b = {
"select": function() {
return {
status: Idle,
current: 0,
children: Array.from(arguments),
tick: function() {
if (this.status == Idle) {
this.current = 0;
this.status = Running;
}
if (this.children[this.current].status == Success) {
this.children[this.current].status = Idle;
this.status = Success;
return;
}
if (this.children[this.current].status == Failure) {
this.children[this.current].status = Idle;
this.current++;
if (this.current == this.children.length) {
this.status = Failure;
}
return;
}
tick(this.children[this.current]);
}
};
},
"sequence": function() {
return {
status: Idle,
current: 0,
children: Array.from(arguments),
tick: function() {
if (this.status == Idle) {
this.current = 0;
this.status = Running;
}
if (this.children[this.current].status == Success) {
this.children[this.current].status = Idle;
this.current++;
if (this.current == this.children.length) {
this.status = Success;
}
return;
}
if (this.children[this.current].status == Failure) {
this.children[this.current].status = Idle;
this.status = Failure;
return;
}
tick(this.children[this.current]);
}
};
},
"selectMaxUtility": function() {
return {
status: Idle,
children: Array.from(arguments),
tick: function() {
if (this.children.length == 0) return;
var max = 0;
var best = 0;
for (var c=0; c<this.children.length; c++) {
var u = this.children[c].utility();
if (u > max) {
max = u;
best = c;
}
}
tick(this.children[best]);
}
};
},
"print": function() {
return {
status: Idle,
text: Array.from(arguments).join(''),
tick: function() {
console.log(this.text);
this.status = Success;
}
};
},
"fail": function() {
return {
status: Idle,
tick: function() {
this.status = Failure;
}
};
}
}
function tick(node) {
return node.tick(node);
}
Used like this:
var bt = b.sequence(
b.print("1 foo"),
b.select(
b.fail(),
b.fail(),
b.print("2 foo"),
b.fail(),
b.print("3 foo")
),
b.print("4 foo"),
b.fail(),
b.print("5 foo")
);
while ((bt.status != Success) && (bt.status != Failure)) {
tick(bt);
console.log(bt.status);
}
It logs:
1 foo
Symbol(Running)
2 foo
Symbol(Running)
4 foo
Symbol(Running)
Symbol(Failure)
Which is ok.
Now I'll try and insert the utility concept, with new node types that fetch utility score from children, and make feedback to their parents.
Ed: Added, start testing now.