Skip to content

Commit

Permalink
Fixed issue where args were not passed to registered funcs properly a…
Browse files Browse the repository at this point in the history
…nd subtrees couldnt be registered
  • Loading branch information
Nikolas Howard committed Mar 1, 2024
1 parent 1aa7712 commit 814c995
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 37 deletions.
2 changes: 1 addition & 1 deletion dist/Agent.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type ExitFunctionArg = {
succeeded: boolean;
aborted: boolean;
};
export type FunctionArg = number | string | boolean | null | ExitFunctionArg;
export type FunctionArg = any | ExitFunctionArg;
export type ActionResult = CompleteState | Promise<CompleteState> | State.RUNNING | void;
export type AgentFunction = (this: Agent, ...args: FunctionArg[]) => ActionResult | boolean;
export type GlobalFunction = (agent: Agent, ...args: FunctionArg[]) => ActionResult | boolean;
4 changes: 2 additions & 2 deletions dist/bundle.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions dist/bundle.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions dist/index.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/Agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export type Agent = {
*/

export type ExitFunctionArg = { succeeded: boolean; aborted: boolean };
export type FunctionArg = number | string | boolean | null | ExitFunctionArg;
export type FunctionArg = any | ExitFunctionArg;
export type ActionResult = CompleteState | Promise<CompleteState> | State.RUNNING | void;
export type AgentFunction = (this: Agent, ...args: FunctionArg[]) => ActionResult | boolean;
export type GlobalFunction = (agent: Agent, ...args: FunctionArg[]) => ActionResult | boolean;
2 changes: 1 addition & 1 deletion src/BehaviourTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export class BehaviourTree {
}

// This function should only ever be called with a definition containing a single unnamed root node.
if (rootNodeDefinitions.length != 1 || rootNodeDefinitions[0].id !== null) {
if (rootNodeDefinitions.length != 1 || typeof rootNodeDefinitions[0].id !== "undefined") {
throw new Error("error registering definition: expected a single unnamed root node");
}

Expand Down
2 changes: 1 addition & 1 deletion src/Lookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default class Lookup {
// The agent does not contain the specified function but it may have been registered at some point.
if (this.registeredFunctions[name] && typeof this.registeredFunctions[name] === "function") {
const registeredFunction = this.registeredFunctions[name];
return (args: any[]) => registeredFunction(agent, ...args.map((arg) => arg.value));
return (args: any[]) => registeredFunction(agent, ...args);
}

// We have no function to invoke.
Expand Down
29 changes: 15 additions & 14 deletions test/nodes/leaf/Action.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { assert } from "chai";
import sinon from "sinon";

import { BehaviourTree, State } from "../../../src/index";
import { RootNodeDefinition } from "../../../src/BehaviourTreeDefinition";
import { Agent } from "../../../src/Agent";

import { findNode } from "../../TestUtilities";

Expand Down Expand Up @@ -41,39 +41,40 @@ describe("An Action node", () => {
describe("when the referenced function is", () => {
describe("a registered function", () => {
it("(MDSL)", () => {
const definition = "root { action [doAction] }";

BehaviourTree.register("doAction", () => {
return State.SUCCEEDED;
});
const registeredActionFunction = sinon.stub().returns(State.SUCCEEDED);
BehaviourTree.register("doAction", registeredActionFunction);

const tree = new BehaviourTree(definition, {});
const definition = `root { action [doAction, "some-argument"] }`;
const agent = { mock: "agent" };
const tree = new BehaviourTree(definition, agent);

tree.step();

const node = findNode(tree, "action", "doAction");
assert.strictEqual(node.state, State.SUCCEEDED);
assert.isTrue(registeredActionFunction.calledWith(agent, "some-argument"));
});

it("(JSON)", () => {
const registeredActionFunction = sinon.stub().returns(State.SUCCEEDED);
BehaviourTree.register("doAction", registeredActionFunction);

const definition: RootNodeDefinition = {
type: "root",
child: {
type: "action",
call: "doAction"
call: "doAction",
args: ["some-argument"]
}
};

BehaviourTree.register("doAction", () => {
return State.SUCCEEDED;
});

const tree = new BehaviourTree(definition, {});
const agent = { mock: "agent" };
const tree = new BehaviourTree(definition, agent);

tree.step();

const node = findNode(tree, "action", "doAction");
assert.strictEqual(node.state, State.SUCCEEDED);
assert.isTrue(registeredActionFunction.calledWith(agent, "some-argument"));
});
});

Expand Down
25 changes: 14 additions & 11 deletions test/nodes/leaf/Condition.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { assert } from "chai";
import sinon from "sinon";

import { BehaviourTree, State } from "../../../src/index";
import { RootNodeDefinition } from "../../../src/BehaviourTreeDefinition";
import { Agent } from "../../../src/Agent";

import { findNode } from "../../TestUtilities";

Expand Down Expand Up @@ -41,37 +41,40 @@ describe("A Condition node", () => {
describe("when the referenced function is", () => {
describe("a registered function", () => {
it("(MDSL)", () => {
BehaviourTree.register("someCondition", () => {
return true;
});
const registeredConditionFunction = sinon.stub().returns(true);
BehaviourTree.register("someCondition", registeredConditionFunction);

const definition = "root { condition [someCondition] }";
const tree = new BehaviourTree(definition, {});
const definition = `root { condition [someCondition, "some-argument"] }`;
const agent = { mock: "agent" };
const tree = new BehaviourTree(definition, agent);

tree.step();

const node = findNode(tree, "condition", "someCondition");
assert.strictEqual(node.state, State.SUCCEEDED);
assert.isTrue(registeredConditionFunction.calledWith(agent, "some-argument"));
});

it("(JSON)", () => {
BehaviourTree.register("someCondition", () => {
return true;
});
const registeredConditionFunction = sinon.stub().returns(true);
BehaviourTree.register("someCondition", registeredConditionFunction);

const definition: RootNodeDefinition = {
type: "root",
child: {
type: "condition",
call: "someCondition"
call: "someCondition",
args: ["some-argument"]
}
};
const tree = new BehaviourTree(definition, {});
const agent = { mock: "agent" };
const tree = new BehaviourTree(definition, agent);

tree.step();

const node = findNode(tree, "condition", "someCondition");
assert.strictEqual(node.state, State.SUCCEEDED);
assert.isTrue(registeredConditionFunction.calledWith(agent, "some-argument"));
});
});

Expand Down

0 comments on commit 814c995

Please sign in to comment.