Skip to content

Commit

Permalink
Merge pull request #86 from nikkorn/#40
Browse files Browse the repository at this point in the history
#40 Improve debugging capabilities
  • Loading branch information
nikkorn authored Mar 26, 2024
2 parents 000d535 + d756636 commit e09e912
Show file tree
Hide file tree
Showing 59 changed files with 1,540 additions and 659 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[![npm version](https://badge.fury.io/js/mistreevous.svg)](https://badge.fury.io/js/mistreevous)
[![Node.js CI](https://github.com/nikkorn/mistreevous/actions/workflows/node.js.yml/badge.svg?branch=master)](https://github.com/nikkorn/mistreevous/actions/workflows/node.js.yml)

A library to declaratively define, build and execute behaviour trees, written in Typescript for Node and browsers. Behaviour trees are used to create complex AI via the modular hierarchical composition of individual tasks.
A library to declaratively define, build and execute behaviour trees, written in TypeScript for Node and browsers. Behaviour trees are used to create complex AI via the modular hierarchical composition of individual tasks.

Using this tool, trees can be defined with either JSON or a simple and minimal built-in DSL (MDSL), avoiding the need to write verbose definitions in JSON.

Expand All @@ -15,7 +15,7 @@ There is an in-browser editor and tree visualiser that you can try [HERE](https:
```sh
$ npm install --save mistreevous
```
This package is built using esbuild to target both Node and browsers. If you would like to use this package in a browser you can just reference `dist/build.js` in a `<script>` tag.
This package is built using esbuild to target both Node and browsers. If you would like to use this package in a browser you can just reference `dist/bundle.js` in a `<script>` tag.

# Example
```js
Expand Down Expand Up @@ -58,27 +58,31 @@ behaviourTree.step();
```
# Behaviour Tree Methods

#### .isRunning()
#### isRunning()
Returns `true` if the tree is in the `RUNNING` state, otherwise `false`.

#### .getState()
#### getState()
Gets the current tree state of `SUCCEEDED`, `FAILED` or `RUNNING`.

#### .step()
#### step()
Carries out a node update that traverses the tree from the root node outwards to any child nodes, skipping those that are already in a resolved state of `SUCCEEDED` or `FAILED`. After being updated, leaf nodes will have a state of `SUCCEEDED`, `FAILED` or `RUNNING`. Leaf nodes that are left in the `RUNNING` state as part of a tree step will be revisited each subsequent step until they move into a resolved state of either `SUCCEEDED` or `FAILED`, after which execution will move through the tree to the next node with a state of `READY`.

Calling this method when the tree is already in a resolved state of `SUCCEEDED` or `FAILED` will cause it to be reset before tree traversal begins.

#### .reset()
#### reset()
Resets the tree from the root node outwards to each nested node, giving each a state of `READY`.

#### getTreeNodeDetails()
Gets the details of every node in the tree, starting from the root. This will include the current state of each node, which is useful for debugging a running tree instance.

# Behaviour Tree Options
The `BehaviourTree` constructor can take an options object as an argument, the properties of which are shown below.

| Option |Type | Description |
| :--------------------|:- |:- |
| getDeltaTime |() => number| A function returning a delta time in seconds that is used to calculate the elapsed duration of any `wait` nodes. If this function is not defined then `Date.prototype.getTime()` is used instead by default. |
| random |() => number| A function returning a floating-point number between 0 (inclusive) and 1 (exclusive). If defined, this function is used to source a pseudo-random number to use in operations such as the selection of active children for any `lotto` nodes as well as the selection of durations for `wait` nodes, iterations for `repeat` nodes and attempts for `retry` nodes when minimum and maximum bounds are defined. If not defined then `Math.random()` will be used instead by default. This function can be useful in seeding all random numbers used in the running of a tree instance to make any behaviour completely deterministic. |
| onNodeStateChange |(change: NodeStateChange) => void| An event handler that is called whenever the state of a node changes. The change object will contain details of the updated node and will include the previous state and current state. |

# Nodes

Expand Down
23 changes: 6 additions & 17 deletions dist/BehaviourTree.d.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
import { AnyState } from "./State";
import State from "./State";
import { NodeDetails } from "./nodes/Node";
import { Agent, GlobalFunction } from "./Agent";
import { CallbackAttributeDetails } from "./attributes/callbacks/Callback";
import { GuardAttributeDetails } from "./attributes/guards/Guard";
import { BehaviourTreeOptions } from "./BehaviourTreeOptions";
import { RootNodeDefinition } from "./BehaviourTreeDefinition";
export type FlattenedTreeNode = {
id: string;
type: string;
caption: string;
state: AnyState;
guards: GuardAttributeDetails[];
callbacks: CallbackAttributeDetails[];
args: any[];
parentId: string | null;
};
/**
* A representation of a behaviour tree.
*/
Expand All @@ -40,7 +29,7 @@ export declare class BehaviourTree {
* Gets the current tree state of SUCCEEDED, FAILED, READY or RUNNING.
* @returns The current tree state.
*/
getState(): AnyState;
getState(): State;
/**
* Step the tree.
* Carries out a node update that traverses the tree from the root node outwards to any child nodes, skipping those that are already in a resolved state of SUCCEEDED or FAILED.
Expand All @@ -55,10 +44,10 @@ export declare class BehaviourTree {
*/
reset(): void;
/**
* Gets the flattened details of every node in the tree.
* @returns The flattened details of every node in the tree.
* Gets the details of every node in the tree, starting from the root.
* @returns The details of every node in the tree, starting from the root.
*/
getFlattenedNodeDetails(): FlattenedTreeNode[];
getTreeNodeDetails(): NodeDetails;
/**
* Registers the action/condition/guard/callback function or subtree with the given name.
* @param name The name of the function or subtree to register.
Expand Down
4 changes: 3 additions & 1 deletion dist/BehaviourTreeBuilder.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { RootNodeDefinition } from "./BehaviourTreeDefinition";
import Root from "./nodes/decorator/Root";
import { BehaviourTreeOptions } from "./BehaviourTreeOptions";
/**
* Build and populate the root nodes based on the provided definition, assuming that the definition has been validated.
* @param definition The root node definitions.
* @param options The behaviour tree options.
* @returns The built and populated root node definitions.
*/
export default function buildRootNode(definition: RootNodeDefinition[]): Root;
export default function buildRootNode(definition: RootNodeDefinition[], options: BehaviourTreeOptions): Root;
52 changes: 52 additions & 0 deletions dist/BehaviourTreeOptions.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,50 @@
import { State } from "./State";
import { AttributeDetails } from "./attributes/Attribute";
/**
* An object representing a change in state for a node in a behaviour tree instance.
*/
export type NodeStateChange = {
/**
* The node unique identifier.
*/
id: string;
/**
* The node type.
*/
type: string;
/**
* The array of agent or globally registered function arguments if this is an action or condition node.
*/
args?: any[];
/**
* The 'while' guard attribute configured for this node.
*/
while?: AttributeDetails;
/**
* The 'until' guard attribute configured for this node.
*/
until?: AttributeDetails;
/**
* The 'entry' callback attribute configured for this node.
*/
entry?: AttributeDetails;
/**
* The 'step' callback attribute configured for this node.
*/
step?: AttributeDetails;
/**
* The 'exit' callback attribute configured for this node.
*/
exit?: AttributeDetails;
/**
* The previous state of the node.
*/
previousState: State;
/**
* The current state of the node.
*/
state: State;
};
/**
* The options object that can be passed as an argument when instantiating the BehaviourTree class.
*/
Expand All @@ -17,4 +64,9 @@ export interface BehaviourTreeOptions {
* @returns A floating-point number between 0 (inclusive) and 1 (exclusive)
*/
random?(): number;
/**
* An event handler that is called whenever the state of a node changes.
* @param change The object representing a change in state for a node in a behaviour tree instance.
*/
onNodeStateChange?(change: NodeStateChange): void;
}
12 changes: 12 additions & 0 deletions dist/State.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@
* Enumeration of node state types.
*/
export declare enum State {
/**
* The state that a node will be in when it has not been visited yet in the execution of the tree.
*/
READY = "mistreevous.ready",
/**
* The state that a node will be in when it is still being processed and will usually represent or encompass a long-running action.
*/
RUNNING = "mistreevous.running",
/**
* The state that a node will be in when it is no longer being processed and has succeeded.
*/
SUCCEEDED = "mistreevous.succeeded",
/**
* The state that a node will be in when it is no longer being processed but has failed.
*/
FAILED = "mistreevous.failed"
}
export { State as default };
Expand Down
5 changes: 5 additions & 0 deletions dist/Utilities.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* Create a randomly generated node uid.
* @returns A randomly generated node uid.
*/
export declare function createUid(): string;
5 changes: 4 additions & 1 deletion dist/attributes/callbacks/Callback.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Agent } from "../../Agent";
import Attribute, { AttributeDetails } from "../Attribute";
/**
* Details of a node callback attribute.
*/
export type CallbackAttributeDetails = {
/** The name of the agent function that is called. */
functionName: string;
calls: string;
} & AttributeDetails;
/**
* A base node callback attribute.
Expand Down
5 changes: 4 additions & 1 deletion dist/attributes/guards/Guard.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Agent } from "../../Agent";
import Attribute, { AttributeDetails } from "../Attribute";
/**
* Details of a node guard attribute.
*/
export type GuardAttributeDetails = {
/** The name of the condition function that determines whether the guard is satisfied. */
condition: string;
calls: string;
} & AttributeDetails;
/**
* A base node guard attribute.
Expand Down
Loading

0 comments on commit e09e912

Please sign in to comment.