Skip to content

Commit

Permalink
Adding specs and fixing bugs and typings
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolas Howard committed Feb 27, 2024
1 parent b5ec03b commit db1c489
Show file tree
Hide file tree
Showing 20 changed files with 588 additions and 90 deletions.
8 changes: 4 additions & 4 deletions dist/Agent.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CompleteState } from "./State";
import State, { CompleteState } from "./State";
/**
* A type representing an agent that a behavior tree instance would operate on.
*/
Expand All @@ -10,6 +10,6 @@ export type ExitFunctionArg = {
aborted: boolean;
};
export type FunctionArg = number | string | boolean | null | ExitFunctionArg;
export type ActionResult = CompleteState | Promise<CompleteState> | boolean | void;
export type AgentFunction = (this: Agent, ...args: FunctionArg[]) => ActionResult;
export type GlobalFunction = (agent: Agent, ...args: FunctionArg[]) => ActionResult;
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;
6 changes: 3 additions & 3 deletions dist/Lookup.d.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { ActionResult, Agent, GlobalFunction } from "./Agent";
import { RootNodeDefinition } from "./BehaviourTreeDefinition";
export type InvokerFunction = (args: any[]) => ActionResult;
export type InvokerFunction = (args: any[]) => ActionResult | boolean;
/**
* A singleton used to store and lookup registered functions and subtrees.
*/
export default class Lookup {
/**
* The object holding any registered functions keyed on function name.
*/
private static functionTable;
private static registeredFunctions;
/**
* The object holding any registered subtree root node definitions keyed on tree name.
*/
private static subtreeTable;
private static registeredSubtrees;
/**
* Gets the function with the specified name.
* @param name The name of the function.
Expand Down
48 changes: 27 additions & 21 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.

48 changes: 27 additions & 21 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.

8 changes: 4 additions & 4 deletions src/Agent.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CompleteState } from "./State";
import State, { CompleteState } from "./State";

/**
* A type representing an agent that a behavior tree instance would operate on.
Expand Down Expand Up @@ -35,6 +35,6 @@ export type Agent = {

export type ExitFunctionArg = { succeeded: boolean; aborted: boolean };
export type FunctionArg = number | string | boolean | null | ExitFunctionArg;
export type ActionResult = CompleteState | Promise<CompleteState> | boolean | void;
export type AgentFunction = (this: Agent, ...args: FunctionArg[]) => ActionResult;
export type GlobalFunction = (agent: Agent, ...args: FunctionArg[]) => ActionResult;
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;
11 changes: 7 additions & 4 deletions src/BehaviourTreeBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,13 @@ export default function buildRootNode(definition: RootNodeDefinition[]): Root {
// Create a mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.
const rootNodeDefinitionMap = createRootNodeDefinitionMap(definition);

// Now that we have all of our root node definitons (those part of the tree definition and those globally
// registered) we should validate the definition. This will also double-check that we dont have any circular
// dependencies in our branch -> subtree references and that we have no broken branch -> subtree links.
validateBranchSubtreeLinks(definition, true);
// Now that we have all of our root node definitions (those part of the tree definition and those globally registered)
// we should validate the branch-subtree links. This will also double-check that we dont have any circular dependencies
// in our branch-subtree references and that we have no broken branch-subtree links.
validateBranchSubtreeLinks(
[rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], ...Object.values(rootNodeDefinitionMap)],
true
);

// Create our populated tree of node instances, starting with our main root node.
const rootNode = nodeFactory(rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], rootNodeDefinitionMap) as Root;
Expand Down
33 changes: 17 additions & 16 deletions src/Lookup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ActionResult, Agent, GlobalFunction } from "./Agent";
import { RootNodeDefinition } from "./BehaviourTreeDefinition";

export type InvokerFunction = (args: any[]) => ActionResult;
export type InvokerFunction = (args: any[]) => ActionResult | boolean;

/**
* A singleton used to store and lookup registered functions and subtrees.
Expand All @@ -10,19 +10,19 @@ export default class Lookup {
/**
* The object holding any registered functions keyed on function name.
*/
private static functionTable: { [key: string]: GlobalFunction } = {};
private static registeredFunctions: { [key: string]: GlobalFunction } = {};
/**
* The object holding any registered subtree root node definitions keyed on tree name.
*/
private static subtreeTable: { [key: string]: RootNodeDefinition } = {};
private static registeredSubtrees: { [key: string]: RootNodeDefinition } = {};

/**
* Gets the function with the specified name.
* @param name The name of the function.
* @returns The function with the specified name.
*/
public static getFunc(name: string): GlobalFunction {
return this.functionTable[name];
return this.registeredFunctions[name];
}

/**
Expand All @@ -31,7 +31,7 @@ export default class Lookup {
* @param func The function.
*/
public static setFunc(name: string, func: GlobalFunction): void {
this.functionTable[name] = func;
this.registeredFunctions[name] = func;
}

/**
Expand All @@ -44,14 +44,15 @@ export default class Lookup {
*/
static getFuncInvoker(agent: Agent, name: string): InvokerFunction | null {
// Check whether the agent contains the specified function.
const foundOnAgent = agent[name];
if (foundOnAgent && typeof foundOnAgent === "function") {
return (args: any[]): boolean | ActionResult => foundOnAgent.apply(agent, args);
const agentFunction = agent[name];
if (agentFunction && typeof agentFunction === "function") {
return (args: any[]) => agentFunction.apply(agent, args);
}

// The agent does not contain the specified function but it may have been registered at some point.
if (this.functionTable[name] && typeof this.functionTable[name] === "function") {
return (args: any[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));
if (this.registeredFunctions[name] && typeof this.registeredFunctions[name] === "function") {
const registeredFunction = this.registeredFunctions[name];
return (args: any[]) => registeredFunction(agent, ...args.map((arg) => arg.value));
}

// We have no function to invoke.
Expand All @@ -62,7 +63,7 @@ export default class Lookup {
* Gets all registered subtree root node definitions.
*/
static getSubtrees(): { [key: string]: RootNodeDefinition } {
return this.subtreeTable;
return this.registeredSubtrees;
}

/**
Expand All @@ -71,23 +72,23 @@ export default class Lookup {
* @param subtree The subtree.
*/
static setSubtree(name: string, subtree: RootNodeDefinition) {
this.subtreeTable[name] = subtree;
this.registeredSubtrees[name] = subtree;
}

/**
* Removes the registered function or subtree with the specified name.
* @param name The name of the registered function or subtree.
*/
static remove(name: string) {
delete this.functionTable[name];
delete this.subtreeTable[name];
delete this.registeredFunctions[name];
delete this.registeredSubtrees[name];
}

/**
* Remove all registered functions and subtrees.
*/
static empty() {
this.functionTable = {};
this.subtreeTable = {};
this.registeredFunctions = {};
this.registeredSubtrees = {};
}
}
Loading

0 comments on commit db1c489

Please sign in to comment.