diff --git a/README.md b/README.md index d153f8d..f8ba680 100644 --- a/README.md +++ b/README.md @@ -243,6 +243,40 @@ root { } ``` +### All +This composite node will update each child node concurrently. It will stay in the `RUNNING` state until all of its children have moved to either the `SUCCEEDED` or `FAILED` state, after which this node will move to the `SUCCEEDED` state if any of its children have moved to the `SUCCEEDED` state, otherwise it will move to the `FAILED` state. +[Example](https://nikkorn.github.io/mistreevous-visualiser/index.html?example=all) + +*MDSL* +``` +root { + all { + action [Reload] + action [MoveToCover] + } +} +``` + +*JSON* +```json +{ + "type": "root", + "child": { + "type": "all", + "children": [ + { + "type": "action", + "call": "Reload" + }, + { + "type": "action", + "call": "MoveToCover" + } + ] + } +} +``` + ### Lotto This composite node will select a single child at random to run as the active running node. The state of this node will reflect the state of the active child. [Example](https://nikkorn.github.io/mistreevous-visualiser/index.html?example=lotto) diff --git a/dist/BehaviourTreeDefinition.d.ts b/dist/BehaviourTreeDefinition.d.ts index 0cffef4..f6672a6 100644 --- a/dist/BehaviourTreeDefinition.d.ts +++ b/dist/BehaviourTreeDefinition.d.ts @@ -167,6 +167,15 @@ export interface RaceNodeDefinition extends CompositeNodeDefinition { */ type: "race"; } +/** + * An all node. + */ +export interface AllNodeDefinition extends CompositeNodeDefinition { + /** + * The node type. + */ + type: "all"; +} /** * A root node. */ @@ -236,7 +245,7 @@ export interface FailNodeDefinition extends DecoratorNodeDefinition { /** * A type defining any node definition. */ -export type AnyNodeDefinition = BranchNodeDefinition | ActionNodeDefinition | ConditionNodeDefinition | WaitNodeDefinition | SequenceNodeDefinition | SelectorNodeDefinition | LottoNodeDefinition | ParallelNodeDefinition | RaceNodeDefinition | RootNodeDefinition | RepeatNodeDefinition | RetryNodeDefinition | FlipNodeDefinition | SucceedNodeDefinition | FailNodeDefinition; +export type AnyNodeDefinition = BranchNodeDefinition | ActionNodeDefinition | ConditionNodeDefinition | WaitNodeDefinition | SequenceNodeDefinition | SelectorNodeDefinition | LottoNodeDefinition | ParallelNodeDefinition | RaceNodeDefinition | AllNodeDefinition | RootNodeDefinition | RepeatNodeDefinition | RetryNodeDefinition | FlipNodeDefinition | SucceedNodeDefinition | FailNodeDefinition; /** * A type defining any node type that can be a child of composite parent node. */ diff --git a/dist/index.js b/dist/index.js index 8308ca2..3cfb535 100644 --- a/dist/index.js +++ b/dist/index.js @@ -317,7 +317,7 @@ function isDecoratorNode(node) { return ["root", "repeat", "retry", "flip", "succeed", "fail"].includes(node.type); } function isCompositeNode(node) { - return ["sequence", "selector", "lotto", "parallel", "race"].includes(node.type); + return ["sequence", "selector", "lotto", "parallel", "race", "all"].includes(node.type); } function flattenDefinition(nodeDefinition) { const nodes = []; @@ -563,6 +563,10 @@ function convertTokensToJSONDefinition(tokens, stringLiteralPlaceholders) { pushNode(createRaceNode(tokens, stringLiteralPlaceholders)); break; } + case "ALL": { + pushNode(createAllNode(tokens, stringLiteralPlaceholders)); + break; + } case "LOTTO": { pushNode(createLottoNode(tokens, stringLiteralPlaceholders)); break; @@ -729,6 +733,14 @@ function createRaceNode(tokens, stringLiteralPlaceholders) { popAndCheck(tokens, "{"); return node; } +function createAllNode(tokens, stringLiteralPlaceholders) { + const node = { + type: "all", + ...parseAttributeTokens(tokens, stringLiteralPlaceholders) + }; + popAndCheck(tokens, "{"); + return node; +} function createLottoNode(tokens, stringLiteralPlaceholders) { const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders); nodeArguments.filter((arg) => arg.type !== "number" || !arg.isInteger || arg.value < 0).forEach(() => { @@ -987,6 +999,9 @@ function validateNode(definition, depth) { case "race": validateRaceNode(definition, depth); break; + case "all": + validateAllNode(definition, depth); + break; case "lotto": validateLottoNode(definition, depth); break; @@ -1265,6 +1280,16 @@ function validateRaceNode(definition, depth) { validateNodeAttributes(definition, depth); definition.children.forEach((child) => validateNode(child, depth + 1)); } +function validateAllNode(definition, depth) { + if (definition.type !== "all") { + throw new Error(`expected node type of 'all' for all node at depth '${depth}'`); + } + if (!Array.isArray(definition.children) || definition.children.length === 0) { + throw new Error(`expected non-empty 'children' array to be defined for all node at depth '${depth}'`); + } + validateNodeAttributes(definition, depth); + definition.children.forEach((child) => validateNode(child, depth + 1)); +} function validateLottoNode(definition, depth) { if (definition.type !== "lotto") { throw new Error(`expected node type of 'lotto' for lotto node at depth '${depth}'`); @@ -1500,6 +1525,26 @@ var Race = class extends Composite { getName = () => "RACE"; }; +// src/nodes/composite/All.ts +var All = class extends Composite { + constructor(attributes, options, children) { + super("all", attributes, options, children); + } + onUpdate(agent) { + for (const child of this.children) { + if (child.getState() === "mistreevous.ready" /* READY */ || child.getState() === "mistreevous.running" /* RUNNING */) { + child.update(agent); + } + } + if (this.children.every((child) => child.is("mistreevous.succeeded" /* SUCCEEDED */) || child.is("mistreevous.failed" /* FAILED */))) { + this.setState(this.children.find((child) => child.is("mistreevous.succeeded" /* SUCCEEDED */)) ? "mistreevous.succeeded" /* SUCCEEDED */ : "mistreevous.failed" /* FAILED */); + return; + } + this.setState("mistreevous.running" /* RUNNING */); + } + getName = () => "ALL"; +}; + // src/nodes/composite/Selector.ts var Selector = class extends Composite { constructor(attributes, options, children) { @@ -2301,6 +2346,12 @@ function nodeFactory(definition, rootNodeDefinitionMap, options) { options, definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options)) ); + case "all": + return new All( + attributes, + options, + definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options)) + ); case "lotto": return new Lotto( attributes, diff --git a/dist/index.js.map b/dist/index.js.map index 0dafefd..4f23c9d 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../node_modules/lotto-draw/dist/Participant.js", "../node_modules/lotto-draw/dist/Utilities.js", "../node_modules/lotto-draw/dist/Lotto.js", "../node_modules/lotto-draw/dist/createLotto.js", "../node_modules/lotto-draw/dist/index.js", "../src/index.ts", "../src/State.ts", "../src/Lookup.ts", "../src/BehaviourTreeDefinitionUtilities.ts", "../src/mdsl/MDSLUtilities.ts", "../src/mdsl/MDSLNodeArgumentParser.ts", "../src/mdsl/MDSLNodeAttributeParser.ts", "../src/mdsl/MDSLDefinitionParser.ts", "../src/BehaviourTreeDefinitionValidator.ts", "../src/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/Utilities.ts", "../src/nodes/Node.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Parallel.ts", "../src/nodes/composite/Race.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/leaf/Leaf.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/attributes/Attribute.ts", "../src/attributes/guards/Guard.ts", "../src/attributes/guards/While.ts", "../src/attributes/guards/Until.ts", "../src/attributes/callbacks/Callback.ts", "../src/attributes/callbacks/Entry.ts", "../src/attributes/callbacks/Step.ts", "../src/attributes/callbacks/Exit.ts", "../src/BehaviourTreeBuilder.ts", "../src/BehaviourTree.ts"], - "sourcesContent": ["\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Participant = void 0;\r\n/**\r\n * A participant that holds a number of tickets.\r\n */\r\nvar Participant = /** @class */ (function () {\r\n /**\r\n * Creates an instance of the Participant class.\r\n * @param participant The actual participant.\r\n * @param tickets The number of tickets held by the participant.\r\n */\r\n function Participant(participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n this._participant = participant;\r\n this._tickets = tickets;\r\n }\r\n Object.defineProperty(Participant.prototype, \"participant\", {\r\n /** Gets the actual participant. */\r\n get: function () {\r\n return this._participant;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(Participant.prototype, \"tickets\", {\r\n /** Gets or sets the number of tickets held by the participant. */\r\n get: function () {\r\n return this._tickets;\r\n },\r\n set: function (value) {\r\n this._tickets = value;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n return Participant;\r\n}());\r\nexports.Participant = Participant;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.isNaturalNumber = exports.isNullOrUndefined = void 0;\r\n/**\r\n * Gets whether the value provided is null or undefined.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is null or undefined.\r\n */\r\nfunction isNullOrUndefined(value) {\r\n return value === null || value === undefined;\r\n}\r\nexports.isNullOrUndefined = isNullOrUndefined;\r\n/**\r\n * Gets whether the value provided is a natural number.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is a natural number.\r\n */\r\nfunction isNaturalNumber(value) {\r\n return typeof value === \"number\" && value >= 1 && Math.floor(value) === value;\r\n}\r\nexports.isNaturalNumber = isNaturalNumber;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Lotto = void 0;\r\nvar Participant_1 = require(\"./Participant\");\r\nvar Utilities_1 = require(\"./Utilities\");\r\n/**\r\n * Represents a lotto consisting of a number of pickable ticket-holding participants.\r\n */\r\nvar Lotto = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of Lotto.\r\n * @param customRandom The custom RNG to use in place of Math.random().\r\n */\r\n function Lotto(customRandom) {\r\n /** The array of participants that are holding tickets in the lotto. */\r\n this._participants = [];\r\n this._customRandom = customRandom;\r\n }\r\n /**\r\n * Adds a participant with the specified number of tickets, or adds to the participant ticket count if the participant already holds tickets.\r\n * @param participant The participant to add or to increase the ticket count for if they already hold tickets.\r\n * @param tickets The number of tickets, defaults to 1.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.add = function (participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n // Check whether this participant has already been added.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n if (existingParticipant) {\r\n // The participant has already been added to the lotto so just add to their ticket count.\r\n existingParticipant.tickets += tickets;\r\n }\r\n else {\r\n // The participant is not part of the lotto so we should add them.\r\n this._participants.push(new Participant_1.Participant(participant, tickets));\r\n }\r\n return this;\r\n };\r\n /**\r\n * Removes the specified number of tickets for the given participant from the draw, or all tickets if a ticket number is not defined.\r\n * @param participant The participant to remove tickets for.\r\n * @param tickets The number of tickets to remove, or undefined if all tickets are to be removed.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.remove = function (participant, tickets) {\r\n // Attempt to get the existing participant.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n // There is nothing to do if the specified participant isn't even part of the lotto.\r\n if (!existingParticipant) {\r\n return this;\r\n }\r\n // Check whether a tickets value was given.\r\n if (tickets !== undefined) {\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n existingParticipant.tickets -= tickets;\r\n // If the participant no longer holds any tickets then they should be removed.\r\n if (existingParticipant.tickets < 1) {\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n }\r\n else {\r\n // We are removing all tickets for the participant so just remove them from the lotto.\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n return this;\r\n };\r\n /**\r\n * Draw a winning ticket and return the participant that holds the ticket.\r\n * @param options The draw options.\r\n * @returns The participant that holds the winning ticket.\r\n */\r\n Lotto.prototype.draw = function (options) {\r\n if (options === void 0) { options = {}; }\r\n // If we have no participants then just return null.\r\n if (this._participants.length === 0) {\r\n return null;\r\n }\r\n var redrawable = (0, Utilities_1.isNullOrUndefined)(options.redrawable) ? true : options.redrawable;\r\n var pickable = [];\r\n this._participants.forEach(function (_a) {\r\n var participant = _a.participant, tickets = _a.tickets;\r\n for (var ticketCount = 0; ticketCount < tickets; ticketCount++) {\r\n pickable.push(participant);\r\n }\r\n });\r\n var random;\r\n // We need a random floating-point number between 0 (inclusive) and 1 to scale up to pick our winner.\r\n // If a custom random function exists then we should use that or fall back to Math.random().\r\n if (this._customRandom) {\r\n // Call our custom random function to get a random floating-point number.\r\n random = this._customRandom();\r\n // Verify that the result of calling our custom random function is a number between 0 (inclusive) and 1.\r\n if (typeof random !== \"number\" || random < 0 || random >= 1) {\r\n throw new Error(\"the 'random' function provided did not return a number between 0 (inclusive) and 1\");\r\n }\r\n }\r\n else {\r\n // No custom random function was defined so just use good ol' Math.random().\r\n random = Math.random();\r\n }\r\n // Pick a winning participant.\r\n var winner = pickable[Math.floor(random * pickable.length)];\r\n // If the ticket isn't redrawable then we should remove a ticket from the winning participants ticket count.\r\n if (!redrawable) {\r\n this.remove(winner, 1);\r\n }\r\n // Return the winning participant.\r\n return winner;\r\n };\r\n /**\r\n * Draws multiple winning tickets and return an array of the participants that hold the winning tickets.\r\n * @param tickets The number of winning tickets to draw.\r\n * @param options The draw multiple options.\r\n * @returns An array of the participants that hold the winning tickets.\r\n */\r\n Lotto.prototype.drawMultiple = function (tickets, options) {\r\n if (options === void 0) { options = {}; }\r\n var uniqueResults = (0, Utilities_1.isNullOrUndefined)(options.unique) ? false : options.unique;\r\n // Handle cases where the user has asked for zero tickets (no idea why they would do this be we should trust them).\r\n if (tickets === 0) {\r\n return [];\r\n }\r\n // Now that we know out tickets value is not zero we should check that it is a valid natural number.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n var result = [];\r\n // Keep drawing tickets until we either reach the number of required tickets or we simply run out of tickets to draw.\r\n // We can run out of tickets to draw if 'options.redrawable' is explicity 'false' or we just had no participants when 'drawMultiple' was called.\r\n while (result.length < tickets && this._participants.length > 0) {\r\n result.push(this.draw(options));\r\n }\r\n // If the 'unique' draw option is set then we need to remove duplicates from the result list.\r\n if (uniqueResults) {\r\n // Create an array to store our unique results.\r\n var unique = [];\r\n // Iterate over all of our participants (with potential duplicates) and populate our array of unique values.\r\n for (var _i = 0, result_1 = result; _i < result_1.length; _i++) {\r\n var participant = result_1[_i];\r\n if (unique.indexOf(participant) === -1) {\r\n unique.push(participant);\r\n }\r\n }\r\n result = unique;\r\n }\r\n return result;\r\n };\r\n return Lotto;\r\n}());\r\nexports.Lotto = Lotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.createLotto = void 0;\r\nvar Lotto_1 = require(\"./Lotto\");\r\n/**\r\n * A function that creates and returns a Lotto instance.\r\n * @param participantsOrOptions An array of initial participants or options relating to the creation of a Lotto instance.\r\n * @returns A new Lotto instance.\r\n */\r\nfunction createLotto(participantsOrOptions) {\r\n // If no initial participants or lotto options were provided as an argument then we can just return a new lotto instance now.\r\n if (!participantsOrOptions) {\r\n return new Lotto_1.Lotto();\r\n }\r\n // Check whether we were provided with an array of initial participants or a lotto options object.\r\n if (Array.isArray(participantsOrOptions)) {\r\n // We are dealing with a pre-defined array of participants.\r\n var participants = participantsOrOptions;\r\n var lotto_1 = new Lotto_1.Lotto();\r\n // If the lotto participants have been defined upfront then we will need to add them all to our lotto instance now.\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_1.add(participant, tokens);\r\n });\r\n // Return the Lotto instance.\r\n return lotto_1;\r\n }\r\n else {\r\n // We are dealing with some lotto options.\r\n var random = participantsOrOptions.random, participants = participantsOrOptions.participants;\r\n // Create a Lotto instance passing the custom RNG function to use in place of Math.random() (which could be undefined).\r\n var lotto_2 = new Lotto_1.Lotto(random);\r\n // If the lotto participants have been defined upfront as part of the options then we will need to add them all to our lotto instance now.\r\n if (participants) {\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_2.add(participant, tokens);\r\n });\r\n }\r\n // Return the Lotto instance.\r\n return lotto_2;\r\n }\r\n}\r\nexports.createLotto = createLotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar createLotto_1 = require(\"./createLotto\");\r\nexports.default = createLotto_1.createLotto;\r\n", "import State from \"./State\";\nimport { BehaviourTree } from \"./BehaviourTree\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { NodeDetails, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n /**\n * The state that a node will be in when it has not been visited yet in the execution of the tree.\n */\n READY = \"mistreevous.ready\",\n /**\n * The state that a node will be in when it is still being processed and will usually represent or encompass a long-running action.\n */\n RUNNING = \"mistreevous.running\",\n /**\n * The state that a node will be in when it is no longer being processed and has succeeded.\n */\n SUCCEEDED = \"mistreevous.succeeded\",\n /**\n * The state that a node will be in when it is no longer being processed but has failed.\n */\n FAILED = \"mistreevous.failed\"\n}\n\nexport { State as default };\n\nexport type CompleteState = State.SUCCEEDED | State.FAILED;\nexport type AnyState = State.READY | State.RUNNING | CompleteState;\n", "import { ActionResult, Agent, GlobalFunction } from \"./Agent\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\n\nexport type InvokerFunction = (args: any[]) => ActionResult | boolean;\n\n/**\n * A singleton used to store and lookup registered functions and subtrees.\n */\nexport default class Lookup {\n /**\n * The object holding any registered functions keyed on function name.\n */\n private static registeredFunctions: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered subtree root node definitions keyed on tree name.\n */\n private static registeredSubtrees: { [key: string]: RootNodeDefinition } = {};\n\n /**\n * Gets the function with the specified name.\n * @param name The name of the function.\n * @returns The function with the specified name.\n */\n public static getFunc(name: string): GlobalFunction {\n return this.registeredFunctions[name];\n }\n\n /**\n * Sets the function with the specified name for later lookup.\n * @param name The name of the function.\n * @param func The function.\n */\n public static setFunc(name: string, func: GlobalFunction): void {\n this.registeredFunctions[name] = func;\n }\n\n /**\n * Gets the function invoker for the specified agent and function name.\n * If a function with the specified name exists on the agent object then it will\n * be returned, otherwise we will then check the registered functions for a match.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param name The function name.\n * @returns The function invoker for the specified agent and function name.\n */\n static getFuncInvoker(agent: Agent, name: string): InvokerFunction | null {\n // Check whether the agent contains the specified function.\n const agentFunction = agent[name];\n if (agentFunction && typeof agentFunction === \"function\") {\n return (args: any[]) => agentFunction.apply(agent, args);\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.registeredFunctions[name] && typeof this.registeredFunctions[name] === \"function\") {\n const registeredFunction = this.registeredFunctions[name];\n return (args: any[]) => registeredFunction(agent, ...args);\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets all registered subtree root node definitions.\n */\n static getSubtrees(): { [key: string]: RootNodeDefinition } {\n return this.registeredSubtrees;\n }\n\n /**\n * Sets the subtree with the specified name for later lookup.\n * @param name The name of the subtree.\n * @param subtree The subtree.\n */\n static setSubtree(name: string, subtree: RootNodeDefinition) {\n this.registeredSubtrees[name] = subtree;\n }\n\n /**\n * Removes the registered function or subtree with the specified name.\n * @param name The name of the registered function or subtree.\n */\n static remove(name: string) {\n delete this.registeredFunctions[name];\n delete this.registeredSubtrees[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.registeredFunctions = {};\n this.registeredSubtrees = {};\n }\n}\n", "import {\n NodeDefinition,\n RootNodeDefinition,\n DecoratorNodeDefinition,\n CompositeNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition\n} from \"./BehaviourTreeDefinition\";\n\n/**\n * A type guard function that returns true if the specified node satisfies the RootNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the RootNodeDefinition type.\n */\nexport function isRootNode(node: NodeDefinition): node is RootNodeDefinition {\n return node.type === \"root\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the BranchNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the BranchNodeDefinition type.\n */\nexport function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition {\n return node.type === \"branch\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the NodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the NodeDefinition type.\n */\nexport function isLeafNode(node: NodeDefinition): node is NodeDefinition {\n return [\"branch\", \"action\", \"condition\", \"wait\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the DecoratorNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the DecoratorNodeDefinition type.\n */\nexport function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefinition {\n return [\"root\", \"repeat\", \"retry\", \"flip\", \"succeed\", \"fail\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the CompositeNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type.\n */\nexport function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition {\n return [\"sequence\", \"selector\", \"lotto\", \"parallel\", \"race\"].includes(node.type);\n}\n\n/**\n * Flatten a node definition into an array of all of its nested node definitions.\n * @param nodeDefinition The node definition to flatten.\n * @returns An array of all of nested node definitions.\n */\nexport function flattenDefinition(nodeDefinition: AnyNodeDefinition): AnyNodeDefinition[] {\n const nodes: AnyNodeDefinition[] = [];\n\n const processNode = (currentNodeDefinition: AnyNodeDefinition) => {\n nodes.push(currentNodeDefinition);\n\n if (isCompositeNode(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNode(currentNodeDefinition)) {\n processNode(currentNodeDefinition.child);\n }\n };\n\n processNode(nodeDefinition);\n\n return nodes;\n}\n\n/**\n * Determines whether the passed value is an integer.\n * @param value The value to check.\n * @returns Whether the passed value is an integer.\n */\nexport function isInteger(value: unknown): boolean {\n return typeof value === \"number\" && Math.floor(value) === value;\n}\n\n/**\n * Determines whether the passed value is null or undefined.\n * @param value The value to check.\n * @returns Whether the passed value is null or undefined.\n */\nexport function isNullOrUndefined(value: unknown): boolean {\n return typeof value === \"undefined\" || value === null;\n}\n", "/**\n * A type defining an object that holds a reference to substitued string literals parsed from the definition.\n */\nexport type StringLiteralPlaceholders = { [key: string]: string };\n\n/**\n * Pop the next raw token from the specified array of tokens and throw an error if it wasn't the expected one.\n * @param tokens The array of tokens.\n * @param expected An optional string or array or items, one of which must match the next popped token.\n * @returns The popped token.\n */\nexport function popAndCheck(tokens: string[], expected?: string | string[]): string {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token but there aren't any.\n if (popped === undefined) {\n throw new Error(\"unexpected end of definition\");\n }\n\n // Do we have an expected token/tokens array?\n if (expected != undefined) {\n // Get an array of expected values, if the popped token matches any then we are all good.\n const expectedValues = typeof expected === \"string\" ? [expected] : expected;\n\n // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase());\n\n // Throw an error if the popped token didn't match any of our expected items.\n if (!tokenMatchesExpectation) {\n const expectationString = expectedValues.map((item) => \"'\" + item + \"'\").join(\" or \");\n throw new Error(\"unexpected token found. Expected \" + expectationString + \" but got '\" + popped + \"'\");\n }\n }\n\n // Return the popped token.\n return popped;\n}\n\n/**\n * Swaps out any node/attribute argument string literals with placeholders.\n * @param definition The definition.\n * @returns An object containing a mapping of placeholders to original string values as well as the processed definition string.\n */\nexport function substituteStringLiterals(definition: string): {\n placeholders: StringLiteralPlaceholders;\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: StringLiteralPlaceholders = {};\n\n // Replace any string literals wrapped with double quotes in our definition with placeholders to be processed later.\n const processedDefinition = definition.replace(/\\\"(\\\\.|[^\"\\\\])*\\\"/g, (match) => {\n var strippedMatch = match.substring(1, match.length - 1);\n var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch);\n\n // If we have no existing string literal match then create a new placeholder.\n if (!placeholder) {\n placeholder = `@@${Object.keys(placeholders).length}@@`;\n placeholders[placeholder] = strippedMatch;\n }\n\n return placeholder;\n });\n\n return { placeholders, processedDefinition };\n}\n\n/**\n * Parse the tree definition into an array of raw tokens.\n * @param definition The definition.\n * @returns An array of tokens parsed from the definition.\n */\nexport function parseTokensFromDefinition(definition: string): string[] {\n // Add some space around various important characters so that they can be plucked out easier as individual tokens.\n definition = definition.replace(/\\(/g, \" ( \");\n definition = definition.replace(/\\)/g, \" ) \");\n definition = definition.replace(/\\{/g, \" { \");\n definition = definition.replace(/\\}/g, \" } \");\n definition = definition.replace(/\\]/g, \" ] \");\n definition = definition.replace(/\\[/g, \" [ \");\n definition = definition.replace(/\\,/g, \" , \");\n\n // Split the definition into raw token form and return it.\n return definition.replace(/\\s+/g, \" \").trim().split(\" \");\n}\n", "import { StringLiteralPlaceholders, popAndCheck } from \"./MDSLUtilities\";\n\n/**\n * A type representing any node function argument.\n */\ntype Argument = {\n /**\n * The argument value.\n */\n value: T;\n /**\n * The argument type, used for validation.\n */\n type: string;\n};\n\ntype NullArgument = Argument & {\n type: \"null\";\n};\n\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\n\ntype NumberArgument = Argument & {\n type: \"number\";\n /**\n * A flag defining whether the number argument value is a valid integer. (used for validation)\n */\n isInteger: boolean;\n};\n\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\n\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\n\n/**\n * A type representing a reference to any node function argument.\n */\ntype AnyArgument = NullArgument | BooleanArgument | NumberArgument | StringPlaceholderArgument | IdentifierArgument;\n\n/**\n * Parse an array of argument definitions from the specified tokens array.\n * @param tokens The array tokens to parse the argument definitions from.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @param argumentValidator The argument validator function.\n * @param validationFailedMessage The exception message to throw if argument validation fails.\n * @returns An array of argument definitions parsed from the specified tokens array.\n */\nexport function parseArgumentTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): AnyArgument[] {\n const argumentList: AnyArgument[] = [];\n\n // If the next token is not a '[' or '(' then we have no arguments to parse.\n if (![\"[\", \"(\"].includes(tokens[0])) {\n return argumentList;\n }\n\n // Any lists of arguments will always be wrapped in '[]' for node arguments or '()' for attribute arguments.\n // We are looking for a '[' or '(' opener that wraps the argument tokens and the relevant closer.\n const closingToken = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closingToken) {\n // The next token is part of our arguments list.\n argumentListTokens.push(tokens.shift()!);\n }\n\n // Validate the order of the argument tokens. Each token must either be a ',' or a single argument that satisfies the validator.\n argumentListTokens.forEach((token, index) => {\n // Get whether this token should be an actual argument.\n const shouldBeArgumentToken = !(index & 1);\n\n // If the current token should be an actual argument then validate it, otherwise it should be a ',' token.\n if (shouldBeArgumentToken) {\n // Get the argument definition.\n const argumentDefinition = getArgumentDefinition(token, stringArgumentPlaceholders);\n\n // This is a valid argument!\n argumentList.push(argumentDefinition);\n } else {\n // The current token should be a ',' token.\n if (token !== \",\") {\n throw new Error(`invalid argument list, expected ',' or ']' but got '${token}'`);\n }\n }\n });\n\n // The arguments list should terminate with a ']' or ')' token, depending on the opener.\n popAndCheck(tokens, closingToken);\n\n // Return the arguments.\n return argumentList;\n}\n\n/**\n * Gets an argument value definition.\n * @param token The argument token.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An argument value definition.\n */\nfunction getArgumentDefinition(token: string, stringArgumentPlaceholders: StringLiteralPlaceholders): AnyArgument {\n // Check whether the token represents a null value.\n if (token === \"null\") {\n return {\n value: null,\n type: \"null\"\n } as NullArgument;\n }\n\n // Check whether the token represents a boolean value.\n if (token === \"true\" || token === \"false\") {\n return {\n value: token === \"true\",\n type: \"boolean\"\n } as BooleanArgument;\n }\n\n // Check whether the token represents a number value.\n // TODO: Relies on broken isNaN - see MDN.\n // if (!Number.isNaN(token)) {\n if (!isNaN(token as any)) {\n return {\n value: parseFloat(token),\n isInteger: parseFloat(token) === parseInt(token, 10),\n type: \"number\"\n } as NumberArgument;\n }\n\n // Check whether the token is a placeholder (e.g. @@0@@) representing a string literal.\n if (token.match(/^@@\\d+@@$/g)) {\n return {\n value: stringArgumentPlaceholders[token].replace('\\\\\"', '\"'),\n type: \"string\"\n } as StringPlaceholderArgument;\n }\n\n // The only remaining option is that the argument value is an identifier.\n return {\n value: token,\n type: \"identifier\"\n } as IdentifierArgument;\n}\n", "import { NodeAttributeDefinition } from \"../BehaviourTreeDefinition\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { StringLiteralPlaceholders } from \"./MDSLUtilities\";\n\n/**\n * A type defining the attribute definitions of a node.\n */\ntype NodeAttributes = {\n while?: NodeAttributeDefinition;\n until?: NodeAttributeDefinition;\n entry?: NodeAttributeDefinition;\n exit?: NodeAttributeDefinition;\n step?: NodeAttributeDefinition;\n};\n\n/**\n * Parse any node attribute definitions from the specified tokens array.\n * @param tokens The array of remaining tokens.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An object of attribute definitions defined by any directly following tokens.\n */\nexport function parseAttributeTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): NodeAttributes {\n const nodeAttributeNames: (keyof NodeAttributes)[] = [\"while\", \"until\", \"entry\", \"exit\", \"step\"];\n\n // Create an object to hold any attributes found.\n const attributes: NodeAttributes = {};\n\n // Try to get the name of the attribute for the next token.\n let nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n\n // Pull attribute tokens as well as their arguments off of the tokens stack until we have no more.\n while (nodeAttributeNames.includes(nextAttributeName)) {\n // Check to make sure that we have not already created an attribute definition of this type.\n if (attributes[nextAttributeName]) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Remove the attribute name token from the array of tokens.\n tokens.shift();\n\n // Grab the attribute arguments, assuming the first to be an identifier.\n const [attributeCallIdentifier, ...attributeArguments] = parseArgumentTokens(\n tokens,\n stringArgumentPlaceholders\n );\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeCallIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected agent function or registered function name identifier argument for attribute\");\n }\n\n // Any attribute arguments (other than the expected call identifier) must have a type of string, number, boolean or null.\n attributeArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid attribute argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Create the attribute definition and add it to the object of attribute definitions found.\n attributes[nextAttributeName] = {\n call: attributeCallIdentifier.value,\n args: attributeArguments.map(({ value }) => value)\n };\n\n // Try to get the next attribute name token, as there could be multiple.\n nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n }\n\n return attributes;\n}\n", "import {\n ActionNodeDefinition,\n AnyChildNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition,\n ConditionNodeDefinition,\n FailNodeDefinition,\n FlipNodeDefinition,\n LottoNodeDefinition,\n ParallelNodeDefinition,\n RaceNodeDefinition,\n RepeatNodeDefinition,\n RetryNodeDefinition,\n RootNodeDefinition,\n SelectorNodeDefinition,\n SequenceNodeDefinition,\n SucceedNodeDefinition,\n WaitNodeDefinition\n} from \"../BehaviourTreeDefinition\";\nimport {\n isCompositeNode,\n isDecoratorNode,\n isLeafNode,\n isNullOrUndefined,\n isRootNode\n} from \"../BehaviourTreeDefinitionUtilities\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { parseAttributeTokens } from \"./MDSLNodeAttributeParser\";\nimport {\n StringLiteralPlaceholders,\n parseTokensFromDefinition,\n popAndCheck,\n substituteStringLiterals\n} from \"./MDSLUtilities\";\n\n/**\n * Convert the MDSL tree definition string into an equivalent JSON definition.\n * @param definition The tree definition string as MDSL.\n * @returns The root node JSON definitions.\n */\nexport function convertMDSLToJSON(definition: string): RootNodeDefinition[] {\n // Swap out any node/attribute argument string literals with a placeholder and get a mapping of placeholders to original values as well as the processed definition.\n const { placeholders, processedDefinition } = substituteStringLiterals(definition);\n\n // Parse our definition definition string into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\n return convertTokensToJSONDefinition(tokens, placeholders);\n}\n\n/**\n * Converts the specified tree definition tokens into a JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definitions.\n */\nfunction convertTokensToJSONDefinition(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RootNodeDefinition[] {\n // There must be at least 3 tokens for the tree definition to be valid. 'ROOT', '{' and '}'.\n if (tokens.length < 3) {\n throw new Error(\"invalid token count\");\n }\n\n // We should have a matching number of '{' and '}' tokens. If not, then there are scopes that have not been properly closed.\n if (tokens.filter((token) => token === \"{\").length !== tokens.filter((token) => token === \"}\").length) {\n throw new Error(\"scope character mismatch\");\n }\n\n // Create an array of tree stack arrays where root nodes will always be at the botton and the current composite/decorator node at the top.\n // There should be an element in this array for every root node defined and every element should be an array with a root note as the first element.\n // E.g. A definition with two root nodes defined:\n // [\n // [root, lotto, sequence],\n // [root, selector]\n // ]\n const treeStacks: [Partial, ...Partial[]][] = [];\n\n // Create an array of all root node definitions that we create.\n const rootNodes: Partial[] = [];\n\n // A helper function used to push node definitions onto the tree stack.\n const pushNode = (node: AnyNodeDefinition) => {\n // If the node is a root node then we need to create a new tree stack array with the root node at the root.\n if (isRootNode(node)) {\n // We need to double-check that this root node is not the child of another node.\n // We can do this by checking whether the top tree stack is not empty (contains an existing node)\n if (treeStacks[treeStacks.length - 1]?.length) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Add the root node definition to our array of all parsed root node definitions.\n rootNodes.push(node);\n\n // Add the root node definition to the root of a new tree stack.\n treeStacks.push([node]);\n\n return;\n }\n\n // All non-root nodes should be pushed after their root nodes so handle cases\n // where we may not have any tree stacks or our top-most tree stack is empty.\n if (!treeStacks.length || !treeStacks[treeStacks.length - 1].length) {\n throw new Error(\"expected root node at base of definition\");\n }\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Get the top-most node in the current tree stack, this will be a composite/decorator node\n // for which we will populate its children array if composite or setting its child if a decorator.\n const topTreeStackTopNode = topTreeStack[topTreeStack.length - 1] as AnyNodeDefinition;\n\n // If the top-most node in the current root stack is a composite or decorator\n // node then the current node should be added as a child of the top-most node.\n if (isCompositeNode(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNode(topTreeStackTopNode)) {\n // If the top node already has a child node set then throw an error as a decorator should only have a single child.\n if (topTreeStackTopNode.child) {\n throw new Error(\"a decorator node must only have a single child node\");\n }\n\n topTreeStackTopNode.child = node;\n }\n\n // If the node we are adding is also a composite or decorator node, then we should push it\n // onto the current tree stack, as subsequent nodes will be added as its child/children.\n if (!isLeafNode(node)) {\n topTreeStack.push(node);\n }\n };\n\n // A helper function used to pop the top-most node definition off of the tree stack and return it.\n const popNode = (): AnyNodeDefinition | null => {\n let poppedNode: AnyNodeDefinition | null = null;\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Pop the top-most node in the current tree stack if there is one.\n if (topTreeStack.length) {\n poppedNode = topTreeStack.pop() as AnyNodeDefinition;\n }\n\n // We don't want any empty tree stacks in our stack of tree stacks.\n if (!topTreeStack.length) {\n treeStacks.pop();\n }\n\n return poppedNode;\n };\n\n // We should keep processing the raw tokens until we run out of them.\n while (tokens.length) {\n // Grab the next token.\n const token = tokens.shift()!;\n\n // How we create the next node depends on the current raw token value.\n switch (token.toUpperCase()) {\n case \"ROOT\": {\n pushNode(createRootNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SUCCEED\": {\n pushNode(createSucceedNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FAIL\": {\n pushNode(createFailNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FLIP\": {\n pushNode(createFlipNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"REPEAT\": {\n pushNode(createRepeatNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RETRY\": {\n pushNode(createRetryNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SEQUENCE\": {\n pushNode(createSequenceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SELECTOR\": {\n pushNode(createSelectorNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"PARALLEL\": {\n pushNode(createParallelNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RACE\": {\n pushNode(createRaceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"LOTTO\": {\n pushNode(createLottoNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ACTION\": {\n pushNode(createActionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"CONDITION\": {\n pushNode(createConditionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"WAIT\": {\n pushNode(createWaitNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"BRANCH\": {\n pushNode(createBranchNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope and means that we have to pop a node off of the current stack.\n const poppedNode = popNode();\n\n // Now that we have a node definition we can carry out any validation that may require the node to be fully populated.\n if (poppedNode) {\n validatePoppedNode(poppedNode);\n }\n\n break;\n }\n\n default: {\n throw new Error(`unexpected token: ${token}`);\n }\n }\n }\n\n return rootNodes as RootNodeDefinition[];\n}\n\n/**\n * Creates a root node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definition.\n */\nfunction createRootNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RootNodeDefinition {\n // Create the root node definition.\n let node = {\n type: \"root\"\n } as Partial;\n\n // Parse any node arguments, we should only have one if any which will be an identifier argument for the root identifier.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Check whether any node arguments were defined.\n if (nodeArguments.length) {\n // We should only have one argument, if any, which will be an identifier argument for the root identifier.\n if (nodeArguments.length === 1 && nodeArguments[0].type === \"identifier\") {\n // The root node identifier will be the first and only node argument value.\n node.id = nodeArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the root node definition.\n return node as RootNodeDefinition;\n}\n\n/**\n * Creates a succeed node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The succeed node JSON definition.\n */\nfunction createSucceedNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SucceedNodeDefinition {\n const node = {\n type: \"succeed\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SucceedNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the succeed node definition.\n return node;\n}\n\n/**\n * Creates a fail node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The fail node JSON definition.\n */\nfunction createFailNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FailNodeDefinition {\n const node = {\n type: \"fail\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FailNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the fail node definition.\n return node;\n}\n\n/**\n * Creates a flip node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The flip node JSON definition.\n */\nfunction createFlipNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FlipNodeDefinition {\n const node = {\n type: \"flip\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FlipNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the flip node definition.\n return node;\n}\n\n/**\n * Creates a repeat node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The repeat node JSON definition.\n */\nfunction createRepeatNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RepeatNodeDefinition {\n let node = { type: \"repeat\" } as RepeatNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a repeat node are optional. We may have:\n // - No node arguments, in which case the repeat note will iterate indefinitely.\n // - One node argument which will be the explicit number of iterations to make.\n // - Two node arguments which define the min and max iteration bounds from which a random iteration count will be picked.\n if (nodeArguments.length) {\n // All repeat node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`repeat node iteration counts must be integer values`);\n });\n\n // We should have got one or two iteration counts.\n if (nodeArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = nodeArguments[0].value as number;\n\n // A repeat node must have a positive number of iterations if defined.\n if (node.iterations < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A repeat node must have a positive min and max iteration count if they are defined.\n if (node.iterations[0] < 0 || node.iterations[1] < 0) {\n throw new Error(\"a repeat node must have a positive minimum and maximum iteration count if defined\");\n }\n\n // A repeat node must not have an minimum iteration count that exceeds the maximum iteration count.\n if (node.iterations[0] > node.iterations[1]) {\n throw new Error(\n \"a repeat node must not have a minimum iteration count that exceeds the maximum iteration count\"\n );\n }\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of repeat node iteration count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the repeat node definition.\n return node;\n}\n\n/**\n * Creates a retry node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The retry node JSON definition.\n */\nfunction createRetryNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RetryNodeDefinition {\n let node = { type: \"retry\" } as RetryNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a retry node are optional. We may have:\n // - No node arguments, in which case the retry note will attempt indefinitely.\n // - One node argument which will be the explicit number of attempts to make.\n // - Two node arguments which define the min and max attempt bounds from which a random attempt count will be picked.\n if (nodeArguments.length) {\n // All retry node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`retry node attempt counts must be integer values`);\n });\n\n // We should have got one or two attempt counts.\n if (nodeArguments.length === 1) {\n // A static attempt count was defined.\n node.attempts = nodeArguments[0].value as number;\n\n // A retry node must have a positive number of attempts if defined.\n if (node.attempts < 0) {\n throw new Error(\"a retry node must have a positive number of attempts if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum attempt count was defined.\n node.attempts = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (node.attempts[0] < 0 || node.attempts[1] < 0) {\n throw new Error(\"a retry node must have a positive minimum and maximum attempt count if defined\");\n }\n\n // A retry node must not have a minimum attempt count that exceeds the maximum attempt count.\n if (node.attempts[0] > node.attempts[1]) {\n throw new Error(\n \"a retry node must not have a minimum attempt count that exceeds the maximum attempt count\"\n );\n }\n } else {\n // An incorrect number of attempt counts was defined.\n throw new Error(\"invalid number of retry node attempt count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the retry node definition.\n return node;\n}\n\n/**\n * Creates a sequence node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The sequence node JSON definition.\n */\nfunction createSequenceNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SequenceNodeDefinition {\n const node = {\n type: \"sequence\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SequenceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the sequence node definition.\n return node;\n}\n\n/**\n * Creates a selector node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The selector node JSON definition.\n */\nfunction createSelectorNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SelectorNodeDefinition {\n const node = {\n type: \"selector\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SelectorNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the selector node definition.\n return node;\n}\n\n/**\n * Creates a parallel node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The parallel node JSON definition.\n */\nfunction createParallelNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ParallelNodeDefinition {\n const node = {\n type: \"parallel\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as ParallelNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the parallel node definition.\n return node;\n}\n\n/**\n * Creates a race node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The race node JSON definition.\n */\nfunction createRaceNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RaceNodeDefinition {\n const node = {\n type: \"race\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as RaceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the race node definition.\n return node;\n}\n\n/**\n * Creates a lotto node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The lotto node JSON definition.\n */\nfunction createLottoNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): LottoNodeDefinition {\n // If any node arguments have been defined then they must be our weights.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // All lotto node arguments MUST be of type number and must be positive integers.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger || arg.value < 0)\n .forEach(() => {\n throw new Error(`lotto node weight arguments must be positive integer values`);\n });\n\n const node = {\n type: \"lotto\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as LottoNodeDefinition;\n\n // Apply the weights if any were defined.\n if (nodeArguments.length) {\n node.weights = nodeArguments.map(({ value }) => value) as number[];\n }\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the lotto node definition.\n return node;\n}\n\n/**\n * Creates an action node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The action node JSON definition.\n */\nfunction createActionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ActionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the action name\n // and agent function to invoke for the action, all other arguments are to be passed as arguments to that function.\n const [actionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require an action name argument.\n if (actionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid action node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the action node definition.\n return {\n type: \"action\",\n call: actionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a condition node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The condition node JSON definition.\n */\nfunction createConditionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ConditionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the condition name\n // and agent function to invoke for the condition, all other arguments are to be passed as arguments to that function.\n const [conditionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require a condition name argument.\n if (conditionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid condition node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the condition node definition.\n return {\n type: \"condition\",\n call: conditionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a wait node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The wait node JSON definition.\n */\nfunction createWaitNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): WaitNodeDefinition {\n let node = { type: \"wait\" } as WaitNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a wait node are optional. We may have:\n // - No node arguments, in which case the wait will be indefinite until it is aborted.\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n if (nodeArguments.length) {\n // All wait node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`wait node durations must be integer values`);\n });\n\n // We may have:\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n // - Too many arguments, which is not valid.\n if (nodeArguments.length === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0].value as number;\n\n // If an explict duration was defined then it must be a positive number.\n if (node.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.duration = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A wait node must have a positive min and max duration.\n if (node.duration[0] < 0 || node.duration[1] < 0) {\n throw new Error(\"a wait node must have a positive minimum and maximum duration\");\n }\n\n // A wait node must not have a minimum duration that exceeds the maximum duration.\n if (node.duration[0] > node.duration[1]) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else if (nodeArguments.length > 2) {\n // An incorrect number of duration arguments were defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n }\n\n // Return the wait node definition.\n return { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n}\n\n/**\n * Creates a branch node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The branch node JSON definition.\n */\nfunction createBranchNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): BranchNodeDefinition {\n // Parse any node arguments, we should have one which will be an identifier argument for the root ref.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // We should have only a single identifer argument for a branch node, which is the root ref.\n if (nodeArguments.length !== 1 || nodeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // Return the branch node definition.\n return { type: \"branch\", ref: nodeArguments[0].value };\n}\n\n/**\n * Validate a fully-populated node definition that was popped off of the tree stack.\n * @param definition The popped node to validate.\n */\nfunction validatePoppedNode(definition: AnyNodeDefinition): void {\n // Decorators MUST have a child defined.\n if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) {\n throw new Error(`a ${definition.type} node must have a single child node defined`);\n }\n\n // Composites MUST have at least one child defined.\n if (isCompositeNode(definition) && !definition.children?.length) {\n throw new Error(`a ${definition.type} node must have at least a single child node defined`);\n }\n\n // We need to make sure that lotto nodes that have weights defined have a number of weights matching the number of child nodes.\n if (definition.type === \"lotto\") {\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (definition.weights.length !== definition.children.length) {\n throw new Error(\n \"expected a number of weight arguments matching the number of child nodes for lotto node\"\n );\n }\n }\n }\n}\n", "import { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { flattenDefinition, isBranchNode, isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\n/**\n * An object representing the result of validating a tree definition.\n */\nexport type DefinitionValidationResult = {\n /**\n * A flag defining whether validation succeeded.\n */\n succeeded: boolean;\n /**\n * A string containing the error message if validation did not succeed.\n */\n errorMessage?: string;\n /**\n * The definition as json if the validation was successful, or undefined if validation did not succeed.\n */\n json?: RootNodeDefinition[];\n};\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON or MDSL, not taking any globally registered subtrees into consideration.\n * @param definition The behaviour tree definition in the form of JSON or MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateDefinition(definition: any): DefinitionValidationResult {\n // The definition must be defined.\n if (definition === null || typeof definition === \"undefined\") {\n return createValidationFailureResult(\"definition is null or undefined\");\n }\n\n // We are expecting a definition in one of three different forms:\n // - A string which we will assume is MDSL and we will parse this to JSON before validation.\n // - An array which we will assume is an array of root node definitions with at least one being the primary root node (no 'id' property)\n // - An object which we will assume is the primary root node and should not have an 'id' property.\n if (typeof definition === \"string\") {\n // The definition is a string which we can assume is MDSL, so attempt to validate it.\n return validateMDSLDefinition(definition);\n } else if (typeof definition === \"object\") {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n return validateJSONDefinition(definition);\n } else {\n return createValidationFailureResult(`unexpected definition type of '${typeof definition}'`);\n }\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of MDSL.\n * @param definition The behaviour tree definition in the form of MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nfunction validateMDSLDefinition(definition: string): DefinitionValidationResult {\n let rootNodeDefinitions;\n\n // The first thing the we need to do is to attempt to convert our MDSL into JSON.\n try {\n // The definition is a string which we can assume is MDSL, so attempt to parse it to a JSON definition in the form of an array of root node definitions.\n rootNodeDefinitions = convertMDSLToJSON(definition);\n } catch (exception) {\n // We failed to parse the JSON from the MDSL, this is likely to be the result of it not being a valid MDSL string.\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single unnamed root node at base of definition to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(`multiple root nodes found with duplicate name '${id}'`);\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON.\n * @param definition The behaviour tree definition in the form of JSON.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateJSONDefinition(\n definition: RootNodeDefinition | RootNodeDefinition[]\n): DefinitionValidationResult {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n const rootNodeDefinitions = Array.isArray(definition) ? definition : [definition];\n\n // Iterate over our array of root nodes and call validateNode for each, passing an initial depth of 0, wrapped in a try catch to handle validation failures.\n try {\n rootNodeDefinitions.forEach((rootNodeDefinition) => validateNode(rootNodeDefinition, 0));\n } catch (error) {\n // Handle cases where we have caught a thrown Error and return a failure result with the error message.\n if (error instanceof Error) {\n return createValidationFailureResult(error.message);\n }\n\n // No idea what happened here!\n return createValidationFailureResult(`unexpected error: ${error}`);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single root node without 'id' property defined to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(\n `multiple root nodes found with duplicate 'id' property value of '${id}'`\n );\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the branch -> subtree links across all provided root node definitions.\n * This will not consider branch nodes that reference any globally registered subtrees unless includesGlobalSubtrees\n * is set to true, in which case we will also verify that there are no broken branch -> subtree links.\n * @param rootNodeDefinitions The array of root node definitions.\n * @param includesGlobalSubtrees A flag defining whether the array includes all global subtree root node definitions.\n */\nexport function validateBranchSubtreeLinks(rootNodeDefinitions: RootNodeDefinition[], includesGlobalSubtrees: boolean) {\n // Create a mapping of root node identifiers to other root nodes that they reference via branch nodes.\n // Below is an example of a mapping that includes a circular dependency (root => a => b => c => a)\n // [{ refs: [\"a\", \"b\"] }, { id: \"a\", refs: [\"b\"] }, { id: \"b\", refs: [\"c\"] }, { id: \"c\", refs: [\"a\"] }]\n const rootNodeMappings: { id: string | undefined; refs: string[] }[] = rootNodeDefinitions.map(\n (rootNodeDefinition) => ({\n id: rootNodeDefinition.id,\n refs: flattenDefinition(rootNodeDefinition)\n .filter(isBranchNode)\n .map(({ ref }) => ref)\n })\n );\n\n // A recursive function to walk through the mappings, keeping track of which root nodes we have visited in the form of a path of root node identifiers.\n const followRefs = (mapping: { id: string | undefined; refs: string[] }, path: (string | undefined)[] = []) => {\n // Have we found a circular dependency?\n if (path.includes(mapping.id)) {\n // We found a circular dependency! Get the bad path of root node identifiers.\n const badPath = [...path, mapping.id];\n\n // Create the formatted path value. [undefined, \"a\", \"b\", \"c\", \"a\"] would be formatted as \"a -> b -> c -> a\".\n const badPathFormatted = badPath.filter((element) => !!element).join(\" => \");\n\n // No need to continue, we found a circular dependency.\n throw new Error(`circular dependency found in branch node references: ${badPathFormatted}`);\n }\n\n for (const ref of mapping.refs) {\n // Find the mapping for the root node with an identifer matching the current ref.\n const subMapping = rootNodeMappings.find(({ id }) => id === ref);\n\n // We may not have a mapping for this ref, which is normal when we aren't considering all globally registered subtrees.\n if (subMapping) {\n followRefs(subMapping, [...path, mapping.id]);\n } else if (includesGlobalSubtrees) {\n // We found a reference to a root node that doesn't exist, which is a problem seeing as the root node definitons includes all globally registered subtrees.\n throw new Error(\n mapping.id\n ? `subtree '${mapping.id}' has branch node that references root node '${ref}' which has not been defined`\n : `primary tree has branch node that references root node '${ref}' which has not been defined`\n );\n }\n }\n };\n\n // Start looking for circular dependencies and broken references from the primary root node definition.\n followRefs(rootNodeMappings.find((mapping) => typeof mapping.id === \"undefined\")!);\n}\n\n/**\n * Validate an object that we expect to be a node definition.\n * @param definition An object that we expect to be a node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateNode(definition: any, depth: number): void {\n // Every node must be valid object and have a non-empty 'type' string property.\n if (typeof definition !== \"object\" || typeof definition.type !== \"string\" || definition.type.length === 0) {\n throw new Error(\n `node definition is not an object or 'type' property is not a non-empty string at depth '${depth}'`\n );\n }\n\n // If this node is at the very base of the definition then it MUST be a root node.\n if (depth === 0 && definition.type !== \"root\") {\n throw new Error(`expected root node at base of definition but got node of type '${definition.type}'`);\n }\n\n // How we validate this node definition will depend on its type.\n switch (definition.type) {\n case \"action\":\n validateActionNode(definition, depth);\n break;\n\n case \"condition\":\n validateConditionNode(definition, depth);\n break;\n\n case \"wait\":\n validateWaitNode(definition, depth);\n break;\n\n case \"branch\":\n validateBranchNode(definition, depth);\n break;\n\n case \"root\":\n validateRootNode(definition, depth);\n break;\n\n case \"succeed\":\n validateSucceedNode(definition, depth);\n break;\n\n case \"fail\":\n validateFailNode(definition, depth);\n break;\n\n case \"flip\":\n validateFlipNode(definition, depth);\n break;\n\n case \"repeat\":\n validateRepeatNode(definition, depth);\n break;\n\n case \"retry\":\n validateRetryNode(definition, depth);\n break;\n\n case \"sequence\":\n validateSequenceNode(definition, depth);\n break;\n\n case \"selector\":\n validateSelectorNode(definition, depth);\n break;\n\n case \"parallel\":\n validateParallelNode(definition, depth);\n break;\n\n case \"race\":\n validateRaceNode(definition, depth);\n break;\n\n case \"lotto\":\n validateLottoNode(definition, depth);\n break;\n\n default:\n throw new Error(`unexpected node type of '${definition.type}' at depth '${depth}'`);\n }\n}\n\n/**\n * Validate any attributes for a given node definition.\n * @param definition The node definition.\n * @param depth The depth of the node in the behaviour tree definition.\n */\nfunction validateNodeAttributes(definition: any, depth: number): void {\n // Validate each of the attribute types for this node.\n [\"while\", \"until\", \"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n // Attempt to grab the definition for the current attribute from the node definition.\n const attributeDefinition = definition[attributeName];\n\n // All node attributes are optional, so there is nothing to do if the current attribute is not defined.\n if (typeof attributeDefinition === \"undefined\") {\n return;\n }\n\n // The attribute definition must be an object.\n if (typeof attributeDefinition !== \"object\") {\n throw new Error(\n `expected attribute '${attributeName}' to be an object for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // The 'call' property must be defined for any attribute definition.\n if (typeof attributeDefinition.call !== \"string\" || attributeDefinition.call.length === 0) {\n throw new Error(\n `expected 'call' property for attribute '${attributeName}' to be a non-empty string for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // If any node attribute arguments have been defined then they must have been defined in an array.\n if (typeof attributeDefinition.args !== \"undefined\" && !Array.isArray(attributeDefinition.args)) {\n throw new Error(\n `expected 'args' property for attribute '${attributeName}' to be an array for '${definition.type}' node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a root node definition.\n * @param definition An object that we expect to be a root node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRootNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"root\") {\n throw new Error(\"expected node type of 'root' for root node\");\n }\n\n // A root node cannot be the child of another node.\n if (depth > 0) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Check that, if the root node 'id' property is defined, it is a non-empty string.\n if (typeof definition.id !== \"undefined\" && (typeof definition.id !== \"string\" || definition.id.length === 0)) {\n throw new Error(\"expected non-empty string for 'id' property if defined for root node\");\n }\n\n // A root node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(\"expected property 'child' to be defined for root node\");\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a succeed node definition.\n * @param definition An object that we expect to be a succeed node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSucceedNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"succeed\") {\n throw new Error(`expected node type of 'succeed' for succeed node at depth '${depth}'`);\n }\n\n // A succeed node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for succeed node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a fail node definition.\n * @param definition An object that we expect to be a fail node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFailNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"fail\") {\n throw new Error(`expected node type of 'fail' for fail node at depth '${depth}'`);\n }\n\n // A fail node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for fail node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a flip node definition.\n * @param definition An object that we expect to be a flip node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFlipNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"flip\") {\n throw new Error(`expected node type of 'flip' for flip node at depth '${depth}'`);\n }\n\n // A flip node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for flip node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a repeat node definition.\n * @param definition An object that we expect to be a repeat node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRepeatNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"repeat\") {\n throw new Error(`expected node type of 'repeat' for repeat node at depth '${depth}'`);\n }\n\n // A repeat node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for repeat node at depth '${depth}'`);\n }\n\n // Check whether an 'iterations' property has been defined, it may not have been if this node is to repeat indefinitely.\n if (typeof definition.iterations !== \"undefined\") {\n if (Array.isArray(definition.iterations)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.iterations.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'iterations' property is an array then it MUST contain two integer values.\n if (definition.iterations.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must have a positive min and max iterations count if they are defined.\n if (definition.iterations[0] < 0 || definition.iterations[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must not have a minimum iterations count that exceeds the maximum iterations count.\n if (definition.iterations[0] > definition.iterations[1]) {\n throw new Error(\n `expected minimum iterations count that does not exceed the maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.iterations)) {\n // A repeat node must have a positive number of iterations if defined.\n if (definition.iterations < 0) {\n throw new Error(\n `expected positive iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a retry node definition.\n * @param definition An object that we expect to be a retry node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRetryNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"retry\") {\n throw new Error(`expected node type of 'retry' for retry node at depth '${depth}'`);\n }\n\n // A retry node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for retry node at depth '${depth}'`);\n }\n\n // Check whether an 'attempts' property has been defined, it may not have been if this node is to retry indefinitely.\n if (typeof definition.attempts !== \"undefined\") {\n if (Array.isArray(definition.attempts)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.attempts.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'attempts' property is an array then it MUST contain two integer values.\n if (definition.attempts.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (definition.attempts[0] < 0 || definition.attempts[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must not have a minimum attempts count that exceeds the maximum attempts count.\n if (definition.attempts[0] > definition.attempts[1]) {\n throw new Error(\n `expected minimum attempts count that does not exceed the maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.attempts)) {\n // A retry node must have a positive number of attempts if defined.\n if (definition.attempts < 0) {\n throw new Error(\n `expected positive attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a branch node definition.\n * @param definition An object that we expect to be a branch node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateBranchNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"branch\") {\n throw new Error(`expected node type of 'branch' for branch node at depth '${depth}'`);\n }\n\n // Check that the branch node 'ref' property is defined and is a non-empty string.\n if (typeof definition.ref !== \"string\" || definition.ref.length === 0) {\n throw new Error(`expected non-empty string for 'ref' property for branch node at depth '${depth}'`);\n }\n\n // It is invalid to define guard attributes for a branch node as they should be defined on the referenced root node.\n [\"while\", \"until\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `guards should not be defined for branch nodes but guard '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n\n // It is invalid to define callback attributes for a branch node as they should be defined on the referenced root node.\n [\"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `callbacks should not be defined for branch nodes but callback '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a action node definition.\n * @param definition An object that we expect to be a action node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateActionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"action\") {\n throw new Error(`expected node type of 'action' for action node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a action node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of action node at depth '${depth}'`);\n }\n\n // If any action function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for action node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a condition node definition.\n * @param definition An object that we expect to be a condition node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateConditionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"condition\") {\n throw new Error(`expected node type of 'condition' for condition node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a condition node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of condition node at depth '${depth}'`);\n }\n\n // If any condition function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for condition node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a wait node definition.\n * @param definition An object that we expect to be a wait node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateWaitNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"wait\") {\n throw new Error(`expected node type of 'wait' for wait node at depth '${depth}'`);\n }\n\n // Check whether a 'duration' property has been defined, it may not have been if this node is to wait indefinitely.\n if (typeof definition.duration !== \"undefined\") {\n if (Array.isArray(definition.duration)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.duration.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'duration' property is an array then it MUST contain two integer values.\n if (definition.duration.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must have a positive min and max duration value if they are defined.\n if (definition.duration[0] < 0 || definition.duration[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum duration for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must not have a minimum duration value that exceeds the maximum duration value.\n if (definition.duration[0] > definition.duration[1]) {\n throw new Error(\n `expected minimum duration value that does not exceed the maximum duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.duration)) {\n // A wait node must have a positive duration value if defined.\n if (definition.duration < 0) {\n throw new Error(\n `expected positive duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a sequence node definition.\n * @param definition An object that we expect to be a sequence node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSequenceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"sequence\") {\n throw new Error(`expected node type of 'sequence' for sequence node at depth '${depth}'`);\n }\n\n // A sequence node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for sequence node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a selector node definition.\n * @param definition An object that we expect to be a selector node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSelectorNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"selector\") {\n throw new Error(`expected node type of 'selector' for selector node at depth '${depth}'`);\n }\n\n // A selector node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for selector node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a parallel node definition.\n * @param definition An object that we expect to be a parallel node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateParallelNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"parallel\") {\n throw new Error(`expected node type of 'parallel' for parallel node at depth '${depth}'`);\n }\n\n // A parallel node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for parallel node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a race node definition.\n * @param definition An object that we expect to be a race node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRaceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"race\") {\n throw new Error(`expected node type of 'race' for race node at depth '${depth}'`);\n }\n\n // A race node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for race node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a lotto node definition.\n * @param definition An object that we expect to be a lotto node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateLottoNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"lotto\") {\n throw new Error(`expected node type of 'lotto' for lotto node at depth '${depth}'`);\n }\n\n // A lotto node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for lotto node at depth '${depth}'`);\n }\n\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (\n !Array.isArray(definition.weights) ||\n definition.weights.length !== definition.children.length ||\n definition.weights.filter((value: unknown) => !isInteger(value)).length ||\n definition.weights.filter((value: number) => value < 0).length\n ) {\n throw new Error(\n `expected an array of positive integer weight values with a length matching the number of child nodes for 'weights' property if defined for lotto node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * A helper function to create a failure validation result with the given error message.\n * @param errorMessage The validation failure error message.\n * @returns A failure validation result with the given error message.\n */\nfunction createValidationFailureResult(errorMessage: string): DefinitionValidationResult {\n return { succeeded: false, errorMessage };\n}\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nexport function createUid(): string {\n var S4 = function () {\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n };\n return S4() + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + S4() + S4();\n}\n", "import { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport State, { AnyState } from \"../State\";\nimport { Agent } from \"../Agent\";\nimport Leaf from \"./leaf/Leaf\";\nimport Attribute from \"../attributes/Attribute\";\nimport Entry from \"../attributes/callbacks/Entry\";\nimport Exit from \"../attributes/callbacks/Exit\";\nimport Step from \"../attributes/callbacks/Step\";\nimport While from \"../attributes/guards/While\";\nimport Until from \"../attributes/guards/Until\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\nimport { GuardAttributeDetails } from \"../attributes/guards/Guard\";\nimport { CallbackAttributeDetails } from \"../attributes/callbacks/Callback\";\nimport { createUid } from \"../Utilities\";\n\n/**\n * Details of a tree node instance.\n */\nexport type NodeDetails = {\n /**\n * The tree node identifier.\n */\n id: string;\n /**\n * The tree node type.\n */\n type: string;\n /**\n * The tree node name.\n */\n name: string;\n /**\n * The current state of the tree node.\n */\n state: AnyState;\n /**\n * The array of agent or globally registered function arguments, defined if this is an action or condition node.\n */\n args?: any[];\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: GuardAttributeDetails;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: GuardAttributeDetails;\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: CallbackAttributeDetails;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: CallbackAttributeDetails;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: CallbackAttributeDetails;\n /**\n * The array of the child nodes of this node, defined if this node is a composite or decorator node.\n */\n children?: NodeDetails[];\n};\n\n/**\n * A mapping of attribute names to attributes configured for a node.\n */\ntype Attributes = {\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: Entry;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: Step;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: Exit;\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: While;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: Until;\n};\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node unique identifier.\n */\n protected readonly uid: string;\n /**\n * The node attributes.\n */\n protected readonly attributes: Attributes;\n /**\n * The node state.\n */\n private _state: AnyState = State.READY;\n /**\n * The guard path to evaluate as part of a node update.\n */\n private _guardPath: GuardPath | undefined;\n\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n */\n constructor(private type: string, attributes: Attribute[], protected options: BehaviourTreeOptions) {\n // Create a unique identifier for this node.\n this.uid = createUid();\n\n // Create our attribute mapping.\n this.attributes = {\n entry: attributes.find(({ type }) => type === \"entry\") as Entry,\n step: attributes.find(({ type }) => type === \"step\") as Step,\n exit: attributes.find(({ type }) => type === \"exit\") as Exit,\n while: attributes.find(({ type }) => type === \"while\") as While,\n until: attributes.find(({ type }) => type === \"until\") as Until\n };\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected abstract onUpdate(agent: Agent): void;\n\n /**\n * Gets the name of the node.\n */\n public abstract getName(): string;\n\n /**\n * Gets whether this node is a leaf node.\n */\n public abstract isLeafNode: () => this is Leaf;\n\n /**\n * Gets/Sets the state of the node.\n */\n getState = (): AnyState => this._state;\n setState = (value: AnyState): void => {\n // Grab the original state of this node.\n const previousState = this._state;\n\n // Set the new node state.\n this._state = value;\n\n // If the state actually changed we should handle it.\n if (previousState !== value) {\n this.onStateChanged(previousState);\n }\n };\n\n /**\n * Gets the unique id of the node.\n */\n getUid = () => this.uid;\n\n /**\n * Gets the type of the node.\n */\n getType = () => this.type;\n\n /**\n * Gets the node attributes.\n */\n getAttributes = () => Object.values(this.attributes).filter((attribute) => !!attribute);\n\n /**\n * Sets the guard path to evaluate as part of a node update.\n */\n setGuardPath = (value: GuardPath) => (this._guardPath = value);\n\n /**\n * Gets whether a guard path is assigned to this node.\n */\n hasGuardPath = () => !!this._guardPath;\n\n /**\n * Gets whether this node is in the specified state.\n * @param value The value to compare to the node state.\n */\n public is(value: AnyState): boolean {\n return this._state === value;\n }\n\n /**\n * Reset the state of the node.\n */\n public reset(): void {\n this.setState(State.READY);\n }\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n public abort(agent: Agent): void {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @returns The result of the update.\n */\n public update(agent: Agent): void {\n // If this node is already in a 'SUCCEEDED' or 'FAILED' state then there is nothing to do.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n return;\n }\n\n try {\n // Evaluate all of the guard path conditions for the current tree path.\n this._guardPath!.evaluate(agent);\n\n // If this node is in the READY state then call the ENTRY for this node if it exists.\n if (this.is(State.READY)) {\n this.attributes.entry?.callAgentFunction(agent);\n }\n\n this.attributes.step?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent);\n\n // If this node is now in a 'SUCCEEDED' or 'FAILED' state then call the EXIT for this node if it exists.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n this.attributes.exit?.callAgentFunction(agent, this.is(State.SUCCEEDED), false);\n }\n } catch (error) {\n // If the error is a GuardUnsatisfiedException then we need to determine if this node is the source.\n if (error instanceof GuardUnsatisifedException && error.isSourceNode(this)) {\n // Abort the current node.\n this.abort(agent);\n\n // Any node that is the source of an abort will be a failed node.\n this.setState(State.FAILED);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n id: this.uid,\n name: this.getName(),\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n state: this._state\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n // We should call the onNodeStateChange callback if it was defined.\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this._state\n });\n }\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A composite node that wraps child nodes.\n */\nexport default abstract class Composite extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => this.children;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of any child nodes.\n this.children.forEach((child) => child.reset());\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort any child nodes.\n this.children.forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: this.children.map((child) => child.getDetails())\n };\n }\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A PARALLEL node.\n * The child nodes are executed concurrently until one fails or all succeed.\n */\nexport default class Parallel extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"parallel\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have failed then this node has also failed.\n if (this.children.find((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A parallel node will move into the succeeded state if all child nodes move into the succeeded state.\n if (this.children.every((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RACE node.\n * The child nodes are executed concurrently until one succeeds or all fail.\n */\nexport default class Race extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"race\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have succeeded then this node has also succeeded\n if (this.children.find((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A race node will move into the failed state if all child nodes move into the failed state as none can succeed.\n if (this.children.every((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"RACE\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SELECTOR node.\n * The child nodes are executed in sequence until one succeeds or all fail.\n */\nexport default class Selector extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"selector\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then this node is also a 'SUCCEEDED' node.\n if (child.getState() === State.SUCCEEDED) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the selector nodes.\n return;\n }\n\n // If the current child has a state of 'FAILED' then we should move on to the next child.\n if (child.getState() === State.FAILED) {\n // Find out if the current child is the last one in the selector.\n // If it is then this sequence node has also failed.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the selector as we have completed it.\n return;\n } else {\n // The child node failed, try the next one.\n continue;\n }\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the selector as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SELECTOR\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SEQUENCE node.\n * The child nodes are executed in sequence until one fails or all succeed.\n */\nexport default class Sequence extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"sequence\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then we should move on to the next child.\n if (child.getState() === State.SUCCEEDED) {\n // Find out if the current child is the last one in the sequence.\n // If it is then this sequence node has also succeeded.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the sequence as we have completed it.\n return;\n } else {\n // The child node succeeded, but we have not finished the sequence yet.\n continue;\n }\n }\n\n // If the current child has a state of 'FAILED' then this node is also a 'FAILED' node.\n if (child.getState() === State.FAILED) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the sequence.\n return;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the sequence as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SEQUENCE\";\n}\n", "import createLotto from \"lotto-draw\";\n\nimport Node from \"../Node\";\nimport Composite from \"./Composite\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A LOTTO node.\n * A winning child is picked on the initial update of this node, based on ticket weighting.\n * The state of this node will match the state of the winning child.\n */\nexport default class Lotto extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param weights The child node weights.\n * @param children The child nodes.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private weights: number[] | undefined,\n children: Node[]\n ) {\n super(\"lotto\", attributes, options, children);\n }\n\n /**\n * The child node selected to be the active one.\n */\n private selectedChild: Node | undefined;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to pick a winning child node.\n if (this.is(State.READY)) {\n // Create a lotto draw with which to randomly pick a child node to become the active one.\n const lottoDraw = createLotto({\n // Hook up the optional 'random' behaviour tree function option to the one used by 'lotto-draw'.\n random: this.options.random,\n // Pass in each child node as a participant in the lotto draw with their respective ticket count.\n participants: this.children.map((child, index) => [child, this.weights?.[index] || 1])\n });\n\n // Randomly pick a child based on ticket weighting, this will become the active child for this composite node.\n this.selectedChild = lottoDraw.draw() || undefined;\n }\n\n // If something went wrong and we don't have an active child then we should throw an error.\n if (!this.selectedChild) {\n throw new Error(\"failed to update lotto node as it has no active child\");\n }\n\n // If the selected child has never been updated or is running then we will need to update it now.\n if (this.selectedChild.getState() === State.READY || this.selectedChild.getState() === State.RUNNING) {\n this.selectedChild.update(agent);\n }\n\n // The state of the lotto node is the state of its selected child.\n this.setState(this.selectedChild.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => (this.weights ? `LOTTO [${this.weights.join(\",\")}]` : \"LOTTO\");\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A decorator node that wraps a single child node.\n */\nexport default abstract class Decorator extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected child: Node) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => [this.child];\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of the child node.\n this.child.reset();\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort the child node.\n this.child.abort(agent);\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: [this.child.getDetails()]\n };\n }\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Fail node.\n * This node wraps a single child and will always move to the 'FAILED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Fail extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"fail\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.FAILED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FAIL\";\n}\n", "import Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Flip node.\n * This node wraps a single child and will flip the state of the child state.\n */\nexport default class Flip extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"flip\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n this.setState(State.FAILED);\n break;\n\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FLIP\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A REPEAT node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The REPEAT node will stop and have a 'FAILED' state if its child is ever in a 'FAILED' state after an update.\n * The REPEAT node will attempt to move on to the next iteration if its child is ever in a 'SUCCEEDED' state.\n */\nexport default class Repeat extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param iterations The number of iterations to repeat the child node.\n * @param iterationsMin The minimum possible number of iterations to repeat the child node.\n * @param iterationsMax The maximum possible number of iterations to repeat the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, options, child);\n }\n\n /**\n * The number of target iterations to make.\n */\n private targetIterationCount: number | null = null;\n\n /**\n * The current iteration count.\n */\n private currentIterationCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target iteration count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the FAILED state when we updated it then there is nothing left to do and this node has also failed.\n // If it has moved into the SUCCEEDED state then we have completed the current iteration.\n if (this.child.getState() === State.FAILED) {\n // The child has failed, meaning that this node has failed.\n this.setState(State.FAILED);\n\n return;\n } else if (this.child.getState() === State.SUCCEEDED) {\n // We have completed an iteration.\n this.currentIterationCount += 1;\n }\n } else {\n // This node is in the 'SUCCEEDED' state as we cannot iterate any more.\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.iterations !== null) {\n return `REPEAT ${this.iterations}x`;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n return `REPEAT ${this.iterationsMin}x-${this.iterationsMax}x`;\n } else {\n return \"REPEAT\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with an explicit iteration count or will we be randomly picking a iteration count between the min and max iteration count.\n if (this.iterations !== null) {\n this.targetIterationCount = this.iterations;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n // We will be picking a random iteration count between a min and max iteration count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random iteration count between a min and max iteration count.\n this.targetIterationCount = Math.floor(\n random() * (this.iterationsMax - this.iterationsMin + 1) + this.iterationsMin\n );\n } else {\n this.targetIterationCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RETRY node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The RETRY node will stop and have a 'SUCCEEDED' state if its child is ever in a 'SUCCEEDED' state after an update.\n * The RETRY node will attempt to move on to the next iteration if its child is ever in a 'FAILED' state.\n */\nexport default class Retry extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param attempts The number of attempts to retry the child node.\n * @param attemptsMin The minimum possible number of attempts to retry the child node.\n * @param attemptsMax The maximum possible number of attempts to retry the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, options, child);\n }\n\n /**\n * The number of target attempts to make.\n */\n private targetAttemptCount: number | null = null;\n\n /**\n * The current attempt count.\n */\n private currentAttemptCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target attempt count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Set the target attempt count.\n this.setTargetAttemptCount();\n }\n\n // Do a check to see if we can attempt. If we can then this node will move into the 'RUNNING' state.\n // If we cannot attempt then we have hit our target attempt count, which means that the node has succeeded.\n if (this.canAttempt()) {\n // This node is in the running state and can do its initial attempt.\n this.setState(State.RUNNING);\n\n // We may have already completed an attempt, meaning that the child node will be in the FAILED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.FAILED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the SUCCEEDED state when we updated it then there is nothing left to do and this node has also succeeded.\n // If it has moved into the FAILED state then we have completed the current attempt.\n if (this.child.getState() === State.SUCCEEDED) {\n // The child has succeeded, meaning that this node has succeeded.\n this.setState(State.SUCCEEDED);\n\n return;\n } else if (this.child.getState() === State.FAILED) {\n // We have completed an attempt.\n this.currentAttemptCount += 1;\n }\n } else {\n // This node is in the 'FAILED' state as we cannot iterate any more.\n this.setState(State.FAILED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.attempts !== null) {\n return `RETRY ${this.attempts}x`;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n return `RETRY ${this.attemptsMin}x-${this.attemptsMax}x`;\n } else {\n return \"RETRY\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an attempt can be made.\n * @returns Whether an attempt can be made.\n */\n canAttempt = () => {\n if (this.targetAttemptCount !== null) {\n // We can attempt as long as we have not reached our target attempt count.\n return this.currentAttemptCount < this.targetAttemptCount;\n }\n\n // If neither an attempt count or a condition function were defined then we can attempt indefinitely.\n return true;\n };\n\n /**\n * Sets the target attempt count.\n */\n setTargetAttemptCount = () => {\n // Are we dealing with an explicit attempt count or will we be randomly picking an attempt count between the min and max attempt count.\n if (this.attempts !== null) {\n this.targetAttemptCount = this.attempts;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n // We will be picking a random attempt count between a min and max attempt count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random attempt count between a min and max attempt count.\n this.targetAttemptCount = Math.floor(\n random() * (this.attemptsMax - this.attemptsMin + 1) + this.attemptsMin\n );\n } else {\n this.targetAttemptCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Root node.\n * The root node will have a single child.\n */\nexport default class Root extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"root\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n // Update the child of this node.\n this.child.update(agent);\n }\n\n // The state of the root node is the state of its child.\n this.setState(this.child.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ROOT\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Succeed node.\n * This node wraps a single child and will always move to the 'SUCCEEDED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Succeed extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"succeed\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SUCCEED\";\n}\n", "import Node from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => true;\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State, { CompleteState } from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * The type representing a resolved/rejected update promise.\n */\ntype UpdatePromiseResult = {\n /**\n * Whether the promise was resolved rather than rejected.\n */\n isResolved: boolean;\n\n /**\n * The promise resolved value or rejection reason.\n */\n value: any;\n};\n\n/**\n * An Action leaf node.\n * This represents an immediate or ongoing state of behaviour.\n */\nexport default class Action extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param actionName The action name.\n * @param actionArguments The array of action arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private actionName: string,\n public actionArguments: any[]\n ) {\n super(\"action\", attributes, options);\n }\n\n /**\n * Whether there is a pending update promise.\n */\n private isUsingUpdatePromise = false;\n\n /**\n * The finished state result of an update promise.\n */\n private updatePromiseResult: UpdatePromiseResult | null = null;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the result of this action depends on an update promise then there is nothing to do until it settles.\n if (this.isUsingUpdatePromise) {\n // Are we still waiting for our update promise to settle?\n if (!this.updatePromiseResult) {\n return;\n }\n\n const { isResolved, value } = this.updatePromiseResult;\n\n // Our update promise settled, was it resolved or rejected?\n if (isResolved) {\n // Our promise resolved so check to make sure the result is a valid finished state.\n if (value !== State.SUCCEEDED && value !== State.FAILED) {\n throw new Error(\n \"action node promise resolved with an invalid value, expected a State.SUCCEEDED or State.FAILED value to be returned\"\n );\n }\n\n // Set the state of this node to match the state returned by the promise.\n this.setState(value);\n\n return;\n } else {\n // The promise was rejected, which isn't great.\n throw new Error(`action function '${this.actionName}' promise rejected with '${value}'`);\n }\n }\n\n // Attempt to get the invoker for the action function.\n const actionFuncInvoker = Lookup.getFuncInvoker(agent, this.actionName);\n\n // The action function should be defined.\n if (actionFuncInvoker === null) {\n throw new Error(\n `cannot update action node as the action '${this.actionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let actionFunctionResult;\n\n try {\n // Call the action function, the result of which may be:\n // - The finished state of this action node.\n // - A promise to return a finished node state.\n // - Undefined if the node should remain in the running state.\n actionFunctionResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`action function '${this.actionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`action function '${this.actionName}' threw: ${error}`);\n }\n }\n\n if (actionFunctionResult instanceof Promise) {\n actionFunctionResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the resolved update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: true,\n value: result\n };\n },\n (reason) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort or reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the rejected update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: false,\n value: reason\n };\n }\n );\n\n // This node will be in the 'RUNNING' state until the update promise resolves.\n this.setState(State.RUNNING);\n\n // We are now waiting for the promise returned by the use to resolve before we know what state this node is in.\n this.isUsingUpdatePromise = true;\n } else {\n // Validate the returned value.\n this.validateUpdateResult(actionFunctionResult);\n\n // Set the state of this node, this may be undefined, which just means that the node is still in the 'RUNNING' state.\n this.setState(actionFunctionResult || State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.actionName;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // There is no longer an update promise that we care about.\n this.isUsingUpdatePromise = false;\n this.updatePromiseResult = null;\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.actionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.actionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n\n /**\n * Validate the result of an update function call.\n * @param result The result of an update function call.\n */\n private validateUpdateResult = (result: CompleteState | State.RUNNING) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case State.RUNNING:\n case undefined:\n return;\n default:\n throw new Error(\n `expected action function '${this.actionName}' to return an optional State.SUCCEEDED or State.FAILED value but returned '${result}'`\n );\n }\n };\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * A Condition leaf node.\n * This will succeed or fail immediately based on an agent predicate, without moving to the 'RUNNING' state.\n */\nexport default class Condition extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param conditionName The name of the condition function.\n * @param conditionArguments The array of condition arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private conditionName: string,\n public conditionArguments: any[]\n ) {\n super(\"condition\", attributes, options);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.conditionName);\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot update condition node as the condition '${this.conditionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.conditionArguments);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`condition function '${this.conditionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`condition function '${this.conditionName}' threw: ${error}`);\n }\n }\n\n // The result of calling the condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected condition function '${this.conditionName}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Set the state of this node based on the result of calling the condition function.\n this.setState(!!conditionFunctionResult ? State.SUCCEEDED : State.FAILED);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.conditionName;\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.conditionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.conditionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { Agent } from \"../../Agent\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A WAIT node.\n * The state of this node will change to SUCCEEDED after a duration of time\n */\nexport default class Wait extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param duration The duration that this node will wait to succeed in milliseconds.\n * @param durationMin The minimum possible duration in milliseconds that this node will wait to succeed.\n * @param durationMax The maximum possible duration in milliseconds that this node will wait to succeed.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, options);\n }\n\n /**\n * The time in milliseconds at which this node was first updated.\n */\n private initialUpdateTime: number = 0;\n\n /**\n * The total duration in milliseconds that this node will be waiting for.\n */\n private totalDuration: number | null = null;\n\n /**\n * The duration in milliseconds that this node has been waiting for.\n */\n private waitedDuration: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to set the initial update time.\n if (this.is(State.READY)) {\n // Set the initial update time.\n this.initialUpdateTime = new Date().getTime();\n\n // Set the initial waited duration.\n this.waitedDuration = 0;\n\n // Are we dealing with an explicit duration or will we be randomly picking a duration between the min and max duration.\n if (this.duration !== null) {\n this.totalDuration = this.duration;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // We will be picking a random duration between a min and max duration, if the optional 'random' behaviour tree\n // function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random duration between a min and max duration.\n this.totalDuration = Math.floor(\n random() * (this.durationMax - this.durationMin + 1) + this.durationMin\n );\n } else {\n this.totalDuration = null;\n }\n\n // The node is now running until we finish waiting.\n this.setState(State.RUNNING);\n }\n\n // If we have no total duration then this wait node will wait indefinitely until it is aborted.\n if (this.totalDuration === null) {\n return;\n }\n\n // If we have a 'getDeltaTime' function defined as part of our options then we will use it to figure out how long we have waited for.\n if (typeof this.options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = this.options.getDeltaTime();\n\n // Our delta time must be a valid number and cannot be NaN.\n if (typeof deltaTime !== \"number\" || isNaN(deltaTime)) {\n throw new Error(\"The delta time must be a valid number and not NaN.\");\n }\n\n // Update the amount of time that this node has been waiting for based on the delta time.\n this.waitedDuration += deltaTime * 1000;\n } else {\n // We are not using a delta time, so we will just work out hom much time has passed since the first update.\n this.waitedDuration = new Date().getTime() - this.initialUpdateTime;\n }\n\n // Have we waited long enough?\n if (this.waitedDuration >= this.totalDuration) {\n // We have finished waiting!\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.duration !== null) {\n return `WAIT ${this.duration}ms`;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n return `WAIT ${this.durationMin}ms-${this.durationMax}ms`;\n } else {\n return \"WAIT\";\n }\n };\n}\n", "import Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: any[];\n};\n\n/**\n * A base node attribute.\n */\nexport default abstract class Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of attribute arguments.\n */\n constructor(public type: string, public args: any[]) {}\n\n /**\n * Gets the attribute details.\n */\n abstract getDetails(): TAttributeDetails;\n\n /**\n * Gets whether this attribute is a guard.\n */\n abstract isGuard: () => this is Guard;\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node guard attribute.\n */\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node guard attribute.\n */\nexport default abstract class Guard extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n */\n constructor(type: string, args: any[], private condition: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the condition function that determines whether the guard is satisfied.\n */\n getCondition = () => this.condition;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => true;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): GuardAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getCondition()\n };\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n abstract isSatisfied(agent: Agent): boolean;\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A WHILE guard which is satisfied as long as the given condition remains true.\n */\nexport default class While extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"while\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return conditionFunctionResult;\n };\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An UNTIL guard which is satisfied as long as the given condition remains false.\n */\nexport default class Until extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"until\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return !conditionFunctionResult;\n };\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node callback attribute.\n */\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node callback attribute.\n */\nexport default abstract class Callback extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param functionName The name of the agent function to call.\n */\n constructor(type: string, args: any[], private functionName: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the agent function to call.\n */\n getFunctionName = () => this.functionName;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => false;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): CallbackAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getFunctionName()\n };\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n abstract callAgentFunction: (agent: Agent, isSuccess: boolean, isAborted: boolean) => void;\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An ENTRY callback which defines an agent function to call when the associated node is updated and moves out of running state.\n */\nexport default class Entry extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"entry\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call entry function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A STEP callback which defines an agent function to call when the associated node is updated.\n */\nexport default class Step extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"step\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call step function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An EXIT callback which defines an agent function to call when the associated node is updated and moves to a finished state or is aborted.\n */\nexport default class Exit extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"exit\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n * @param isSuccess Whether the decorated node was left with a success state.\n * @param isAborted Whether the decorated node was aborted.\n */\n callAgentFunction = (agent: Agent, isSuccess: boolean, isAborted: boolean) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call exit function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function\n callbackFuncInvoker([{ succeeded: isSuccess, aborted: isAborted }, ...this.args]);\n };\n}\n", "import { AnyNodeDefinition, RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport { validateBranchSubtreeLinks } from \"./BehaviourTreeDefinitionValidator\";\nimport { isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport Node from \"./nodes/Node\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Race from \"./nodes/composite/Race\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Root from \"./nodes/decorator/Root\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Lookup from \"./Lookup\";\nimport Attribute from \"./attributes/Attribute\";\nimport Guard from \"./attributes/guards/Guard\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\n/**\n * A type representing any node instance in a behaviour tree.\n */\ntype AnyNode =\n | Root\n | Action\n | Condition\n | Wait\n | Sequence\n | Selector\n | Lotto\n | Parallel\n | Race\n | Repeat\n | Retry\n | Flip\n | Succeed\n | Fail;\n\n/**\n * A type defining a mapping of root node identifiers to root node definitions.\n */\ntype RootNodeDefinitionMap = { [key: string | symbol]: RootNodeDefinition };\n\n/**\n * A symbol to use as the main root key in any root node mappings.\n */\nconst MAIN_ROOT_NODE_KEY = Symbol(\"__root__\");\n\n/**\n * Build and populate the root nodes based on the provided definition, assuming that the definition has been validated.\n * @param definition The root node definitions.\n * @param options The behaviour tree options.\n * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[], options: BehaviourTreeOptions): Root {\n // Create a mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n const rootNodeDefinitionMap = createRootNodeDefinitionMap(definition);\n\n // Now that we have all of our root node definitions (those part of the tree definition and those globally registered)\n // we should validate the branch-subtree links. This will also double-check that we dont have any circular dependencies\n // in our branch-subtree references and that we have no broken branch-subtree links.\n validateBranchSubtreeLinks(\n [rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], ...Object.values(rootNodeDefinitionMap)],\n true\n );\n\n // Create our populated tree of node instances, starting with our main root node.\n const rootNode = nodeFactory(rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], rootNodeDefinitionMap, options) as Root;\n\n // Set a guard path on every leaf of the tree to evaluate as part of each update.\n applyLeafNodeGuardPaths(rootNode);\n\n // We only need to return the main root node.\n return rootNode;\n}\n\n/**\n * A factory function which creates a node instance based on the specified definition.\n * @param definition The node definition.\n * @param rootNodeDefinitionMap The mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n * @param options The behaviour tree options.\n * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(\n definition: AnyNodeDefinition,\n rootNodeDefinitionMap: RootNodeDefinitionMap,\n options: BehaviourTreeOptions\n): AnyNode {\n // Get the attributes for the node.\n const attributes = nodeAttributesFactory(definition);\n\n // Create the node instance based on the definition type.\n switch (definition.type) {\n case \"root\":\n return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"repeat\":\n let iterations: number | null = null;\n let iterationsMin: number | null = null;\n let iterationsMax: number | null = null;\n\n if (Array.isArray(definition.iterations)) {\n iterationsMin = definition.iterations[0];\n iterationsMax = definition.iterations[1];\n } else if (isInteger(definition.iterations)) {\n iterations = definition.iterations!;\n }\n\n return new Repeat(\n attributes,\n options,\n iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"retry\":\n let attempts: number | null = null;\n let attemptsMin: number | null = null;\n let attemptsMax: number | null = null;\n\n if (Array.isArray(definition.attempts)) {\n attemptsMin = definition.attempts[0];\n attemptsMax = definition.attempts[1];\n } else if (isInteger(definition.attempts)) {\n attempts = definition.attempts!;\n }\n\n return new Retry(\n attributes,\n options,\n attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"flip\":\n return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"succeed\":\n return new Succeed(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"fail\":\n return new Fail(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"race\":\n return new Race(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n options,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap, options);\n\n case \"action\":\n return new Action(attributes, options, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, options, definition.call, definition.args || []);\n\n case \"wait\":\n let duration: number | null = null;\n let durationMin: number | null = null;\n let durationMax: number | null = null;\n\n if (Array.isArray(definition.duration)) {\n durationMin = definition.duration[0];\n durationMax = definition.duration[1];\n } else if (isInteger(definition.duration)) {\n duration = definition.duration!;\n }\n\n return new Wait(attributes, options, duration, durationMin, durationMax);\n }\n}\n\n/**\n * Creates an array of node attribute instances based on the specified node definition.\n * @param definition The node definition.\n * @returns An array of node attribute instances based on the specified node definition.\n */\nfunction nodeAttributesFactory(definition: AnyNodeDefinition): Attribute[] {\n const attributes: Attribute[] = [];\n\n if (definition.while) {\n attributes.push(new While(definition.while.call, definition.while.args ?? []));\n }\n\n if (definition.until) {\n attributes.push(new Until(definition.until.call, definition.until.args ?? []));\n }\n\n if (definition.entry) {\n attributes.push(new Entry(definition.entry.call, definition.entry.args ?? []));\n }\n\n if (definition.step) {\n attributes.push(new Step(definition.step.call, definition.step.args ?? []));\n }\n\n if (definition.exit) {\n attributes.push(new Exit(definition.exit.call, definition.exit.args ?? []));\n }\n\n return attributes;\n}\n\n/**\n * Creates a mapping of root node identifers to root node definitions, mixing in globally registered subtree root node definitions.\n * @param definition The root node definitions.\n * @returns A mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n */\nfunction createRootNodeDefinitionMap(definition: RootNodeDefinition[]): RootNodeDefinitionMap {\n // Create a mapping of root node identifers to root node definitions.\n const rootNodeMap: RootNodeDefinitionMap = {};\n\n // Add in any registered subtree root node definitions.\n for (const [name, rootNodeDefinition] of Object.entries(Lookup.getSubtrees())) {\n // The name used when registering the subtree will be used as the root node identifier.\n rootNodeMap[name] = { ...rootNodeDefinition, id: name };\n }\n\n // Populate the map with the root node definitions that were included with the tree definition.\n // We do this after adding any registered subtrees as we want these to take presedence.\n for (const rootNodeDefinition of definition) {\n rootNodeMap[rootNodeDefinition.id ?? MAIN_ROOT_NODE_KEY] = rootNodeDefinition;\n }\n\n return rootNodeMap;\n}\n\n/**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param root The main root tree node.\n */\nfunction applyLeafNodeGuardPaths(root: Root) {\n const nodePaths: Node[][] = [];\n\n const findLeafNodes = (path: Node[], node: Node) => {\n // Add the current node to the path.\n path = path.concat(node);\n\n // Check whether the current node is a leaf node.\n if (node.isLeafNode()) {\n nodePaths.push(path);\n } else {\n (node as Composite | Decorator).getChildren().forEach((child) => findLeafNodes(path, child));\n }\n };\n\n // Find all leaf node paths, starting from the root.\n findLeafNodes([], root);\n\n nodePaths.forEach((path) => {\n // Each node in the current path will have to be assigned a guard path, working from the root outwards.\n for (let depth = 0; depth < path.length; depth++) {\n // Get the node in the path at the current depth.\n const currentNode = path[depth];\n\n // The node may already have been assigned a guard path, if so just skip it.\n if (currentNode.hasGuardPath()) {\n continue;\n }\n\n // Create the guard path for the current node.\n const guardPath = new GuardPath(\n path\n .slice(0, depth + 1)\n .map((node) => ({\n node,\n guards: node.getAttributes().filter((attribute) => attribute.isGuard()) as Guard[]\n }))\n .filter((details) => details.guards.length > 0)\n );\n\n // Assign the guard path to the current node.\n currentNode.setGuardPath(guardPath);\n }\n });\n}\n", "import State, { AnyState } from \"./State\";\nimport Lookup from \"./Lookup\";\nimport Node, { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport { Agent, GlobalFunction } from \"./Agent\";\nimport { CallbackAttributeDetails } from \"./attributes/callbacks/Callback\";\nimport { GuardAttributeDetails } from \"./attributes/guards/Guard\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { validateDefinition, validateJSONDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport buildRootNode from \"./BehaviourTreeBuilder\";\nimport { isNullOrUndefined } from \"./BehaviourTreeDefinitionUtilities\";\n\n/**\n * A representation of a behaviour tree.\n */\nexport class BehaviourTree {\n /**\n * The main root tree node.\n */\n private readonly _rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition as either an MDSL string, root node definition object or array of root node definition objects.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param options The behaviour tree options object.\n */\n constructor(\n definition: string | RootNodeDefinition | RootNodeDefinition[],\n private agent: Agent,\n private options: BehaviourTreeOptions = {}\n ) {\n // The tree definition must be defined.\n if (isNullOrUndefined(definition)) {\n throw new Error(\"tree definition not defined\");\n }\n\n // The agent must be defined and not null.\n if (typeof agent !== \"object\" || agent === null) {\n throw new Error(\"the agent must be an object and not null\");\n }\n\n // We should validate the definition before we try to build the tree nodes.\n const { succeeded, errorMessage, json } = validateDefinition(definition);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(`invalid definition: ${errorMessage}`);\n }\n\n // Double check that we did actually get our json definition as part of our definition validtion.\n if (!json) {\n throw new Error(\n \"expected json definition to be returned as part of successful definition validation response\"\n );\n }\n\n try {\n // Create the populated tree of behaviour tree nodes and get the root node.\n this._rootNode = buildRootNode(json, options);\n } catch (exception) {\n // There was an issue in trying build and populate the behaviour tree.\n throw new Error(`error building tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Gets whether the tree is in the RUNNING state.\n * @returns true if the tree is in the RUNNING state, otherwise false.\n */\n public isRunning(): boolean {\n return this._rootNode.getState() === State.RUNNING;\n }\n\n /**\n * Gets the current tree state of SUCCEEDED, FAILED, READY or RUNNING.\n * @returns The current tree state.\n */\n public getState(): State {\n return this._rootNode.getState();\n }\n\n /**\n * Step the tree.\n * 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.\n * 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\n * 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.\n *\n * 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.\n */\n public step(): void {\n // If the root node has already been stepped to completion then we need to reset it.\n if (this._rootNode.getState() === State.SUCCEEDED || this._rootNode.getState() === State.FAILED) {\n this._rootNode.reset();\n }\n\n try {\n this._rootNode.update(this.agent);\n } catch (exception) {\n throw new Error(`error stepping tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Resets the tree from the root node outwards to each nested node, giving each a state of READY.\n */\n public reset(): void {\n this._rootNode.reset();\n }\n\n /**\n * Gets the details of every node in the tree, starting from the root.\n * @returns The details of every node in the tree, starting from the root.\n */\n public getTreeNodeDetails(): NodeDetails {\n return this._rootNode.getDetails();\n }\n\n /**\n * Registers the action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the function or subtree to register.\n * @param value The function or subtree definition to register.\n */\n static register(name: string, value: GlobalFunction | string | RootNodeDefinition) {\n // Are we going to register a action/condition/guard/callback function?\n if (typeof value === \"function\") {\n Lookup.setFunc(name, value);\n return;\n }\n\n // We are not registering an action/condition/guard/callback function, so we must be registering a subtree.\n if (typeof value === \"string\") {\n let rootNodeDefinitions: RootNodeDefinition[];\n\n // We will assume that any string passed in will be a mdsl definition.\n try {\n rootNodeDefinitions = convertMDSLToJSON(value);\n } catch (exception) {\n throw new Error(`error registering definition, invalid MDSL: ${(exception as Error).message}`);\n }\n\n // This function should only ever be called with a definition containing a single unnamed root node.\n if (rootNodeDefinitions.length != 1 || typeof rootNodeDefinitions[0].id !== \"undefined\") {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(rootNodeDefinitions[0]);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, rootNodeDefinitions[0]);\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // We will assume that any object passed in is a root node definition.\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(value);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, value);\n } else {\n throw new Error(\"unexpected value, expected string mdsl definition, root node json definition or function\");\n }\n }\n\n /**\n * Unregisters the registered action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the registered action/condition/guard/callback function or subtree to unregister.\n */\n static unregister(name: string): void {\n Lookup.remove(name);\n }\n\n /**\n * Unregister all registered action/condition/guard/callback functions and subtrees.\n */\n static unregisterAll(): void {\n Lookup.empty();\n }\n}\n"], - "mappings": "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", + "sources": ["../node_modules/lotto-draw/dist/Participant.js", "../node_modules/lotto-draw/dist/Utilities.js", "../node_modules/lotto-draw/dist/Lotto.js", "../node_modules/lotto-draw/dist/createLotto.js", "../node_modules/lotto-draw/dist/index.js", "../src/index.ts", "../src/State.ts", "../src/Lookup.ts", "../src/BehaviourTreeDefinitionUtilities.ts", "../src/mdsl/MDSLUtilities.ts", "../src/mdsl/MDSLNodeArgumentParser.ts", "../src/mdsl/MDSLNodeAttributeParser.ts", "../src/mdsl/MDSLDefinitionParser.ts", "../src/BehaviourTreeDefinitionValidator.ts", "../src/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/Utilities.ts", "../src/nodes/Node.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Parallel.ts", "../src/nodes/composite/Race.ts", "../src/nodes/composite/All.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/leaf/Leaf.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/attributes/Attribute.ts", "../src/attributes/guards/Guard.ts", "../src/attributes/guards/While.ts", "../src/attributes/guards/Until.ts", "../src/attributes/callbacks/Callback.ts", "../src/attributes/callbacks/Entry.ts", "../src/attributes/callbacks/Step.ts", "../src/attributes/callbacks/Exit.ts", "../src/BehaviourTreeBuilder.ts", "../src/BehaviourTree.ts"], + "sourcesContent": ["\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Participant = void 0;\r\n/**\r\n * A participant that holds a number of tickets.\r\n */\r\nvar Participant = /** @class */ (function () {\r\n /**\r\n * Creates an instance of the Participant class.\r\n * @param participant The actual participant.\r\n * @param tickets The number of tickets held by the participant.\r\n */\r\n function Participant(participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n this._participant = participant;\r\n this._tickets = tickets;\r\n }\r\n Object.defineProperty(Participant.prototype, \"participant\", {\r\n /** Gets the actual participant. */\r\n get: function () {\r\n return this._participant;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(Participant.prototype, \"tickets\", {\r\n /** Gets or sets the number of tickets held by the participant. */\r\n get: function () {\r\n return this._tickets;\r\n },\r\n set: function (value) {\r\n this._tickets = value;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n return Participant;\r\n}());\r\nexports.Participant = Participant;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.isNaturalNumber = exports.isNullOrUndefined = void 0;\r\n/**\r\n * Gets whether the value provided is null or undefined.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is null or undefined.\r\n */\r\nfunction isNullOrUndefined(value) {\r\n return value === null || value === undefined;\r\n}\r\nexports.isNullOrUndefined = isNullOrUndefined;\r\n/**\r\n * Gets whether the value provided is a natural number.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is a natural number.\r\n */\r\nfunction isNaturalNumber(value) {\r\n return typeof value === \"number\" && value >= 1 && Math.floor(value) === value;\r\n}\r\nexports.isNaturalNumber = isNaturalNumber;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Lotto = void 0;\r\nvar Participant_1 = require(\"./Participant\");\r\nvar Utilities_1 = require(\"./Utilities\");\r\n/**\r\n * Represents a lotto consisting of a number of pickable ticket-holding participants.\r\n */\r\nvar Lotto = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of Lotto.\r\n * @param customRandom The custom RNG to use in place of Math.random().\r\n */\r\n function Lotto(customRandom) {\r\n /** The array of participants that are holding tickets in the lotto. */\r\n this._participants = [];\r\n this._customRandom = customRandom;\r\n }\r\n /**\r\n * Adds a participant with the specified number of tickets, or adds to the participant ticket count if the participant already holds tickets.\r\n * @param participant The participant to add or to increase the ticket count for if they already hold tickets.\r\n * @param tickets The number of tickets, defaults to 1.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.add = function (participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n // Check whether this participant has already been added.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n if (existingParticipant) {\r\n // The participant has already been added to the lotto so just add to their ticket count.\r\n existingParticipant.tickets += tickets;\r\n }\r\n else {\r\n // The participant is not part of the lotto so we should add them.\r\n this._participants.push(new Participant_1.Participant(participant, tickets));\r\n }\r\n return this;\r\n };\r\n /**\r\n * Removes the specified number of tickets for the given participant from the draw, or all tickets if a ticket number is not defined.\r\n * @param participant The participant to remove tickets for.\r\n * @param tickets The number of tickets to remove, or undefined if all tickets are to be removed.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.remove = function (participant, tickets) {\r\n // Attempt to get the existing participant.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n // There is nothing to do if the specified participant isn't even part of the lotto.\r\n if (!existingParticipant) {\r\n return this;\r\n }\r\n // Check whether a tickets value was given.\r\n if (tickets !== undefined) {\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n existingParticipant.tickets -= tickets;\r\n // If the participant no longer holds any tickets then they should be removed.\r\n if (existingParticipant.tickets < 1) {\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n }\r\n else {\r\n // We are removing all tickets for the participant so just remove them from the lotto.\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n return this;\r\n };\r\n /**\r\n * Draw a winning ticket and return the participant that holds the ticket.\r\n * @param options The draw options.\r\n * @returns The participant that holds the winning ticket.\r\n */\r\n Lotto.prototype.draw = function (options) {\r\n if (options === void 0) { options = {}; }\r\n // If we have no participants then just return null.\r\n if (this._participants.length === 0) {\r\n return null;\r\n }\r\n var redrawable = (0, Utilities_1.isNullOrUndefined)(options.redrawable) ? true : options.redrawable;\r\n var pickable = [];\r\n this._participants.forEach(function (_a) {\r\n var participant = _a.participant, tickets = _a.tickets;\r\n for (var ticketCount = 0; ticketCount < tickets; ticketCount++) {\r\n pickable.push(participant);\r\n }\r\n });\r\n var random;\r\n // We need a random floating-point number between 0 (inclusive) and 1 to scale up to pick our winner.\r\n // If a custom random function exists then we should use that or fall back to Math.random().\r\n if (this._customRandom) {\r\n // Call our custom random function to get a random floating-point number.\r\n random = this._customRandom();\r\n // Verify that the result of calling our custom random function is a number between 0 (inclusive) and 1.\r\n if (typeof random !== \"number\" || random < 0 || random >= 1) {\r\n throw new Error(\"the 'random' function provided did not return a number between 0 (inclusive) and 1\");\r\n }\r\n }\r\n else {\r\n // No custom random function was defined so just use good ol' Math.random().\r\n random = Math.random();\r\n }\r\n // Pick a winning participant.\r\n var winner = pickable[Math.floor(random * pickable.length)];\r\n // If the ticket isn't redrawable then we should remove a ticket from the winning participants ticket count.\r\n if (!redrawable) {\r\n this.remove(winner, 1);\r\n }\r\n // Return the winning participant.\r\n return winner;\r\n };\r\n /**\r\n * Draws multiple winning tickets and return an array of the participants that hold the winning tickets.\r\n * @param tickets The number of winning tickets to draw.\r\n * @param options The draw multiple options.\r\n * @returns An array of the participants that hold the winning tickets.\r\n */\r\n Lotto.prototype.drawMultiple = function (tickets, options) {\r\n if (options === void 0) { options = {}; }\r\n var uniqueResults = (0, Utilities_1.isNullOrUndefined)(options.unique) ? false : options.unique;\r\n // Handle cases where the user has asked for zero tickets (no idea why they would do this be we should trust them).\r\n if (tickets === 0) {\r\n return [];\r\n }\r\n // Now that we know out tickets value is not zero we should check that it is a valid natural number.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n var result = [];\r\n // Keep drawing tickets until we either reach the number of required tickets or we simply run out of tickets to draw.\r\n // We can run out of tickets to draw if 'options.redrawable' is explicity 'false' or we just had no participants when 'drawMultiple' was called.\r\n while (result.length < tickets && this._participants.length > 0) {\r\n result.push(this.draw(options));\r\n }\r\n // If the 'unique' draw option is set then we need to remove duplicates from the result list.\r\n if (uniqueResults) {\r\n // Create an array to store our unique results.\r\n var unique = [];\r\n // Iterate over all of our participants (with potential duplicates) and populate our array of unique values.\r\n for (var _i = 0, result_1 = result; _i < result_1.length; _i++) {\r\n var participant = result_1[_i];\r\n if (unique.indexOf(participant) === -1) {\r\n unique.push(participant);\r\n }\r\n }\r\n result = unique;\r\n }\r\n return result;\r\n };\r\n return Lotto;\r\n}());\r\nexports.Lotto = Lotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.createLotto = void 0;\r\nvar Lotto_1 = require(\"./Lotto\");\r\n/**\r\n * A function that creates and returns a Lotto instance.\r\n * @param participantsOrOptions An array of initial participants or options relating to the creation of a Lotto instance.\r\n * @returns A new Lotto instance.\r\n */\r\nfunction createLotto(participantsOrOptions) {\r\n // If no initial participants or lotto options were provided as an argument then we can just return a new lotto instance now.\r\n if (!participantsOrOptions) {\r\n return new Lotto_1.Lotto();\r\n }\r\n // Check whether we were provided with an array of initial participants or a lotto options object.\r\n if (Array.isArray(participantsOrOptions)) {\r\n // We are dealing with a pre-defined array of participants.\r\n var participants = participantsOrOptions;\r\n var lotto_1 = new Lotto_1.Lotto();\r\n // If the lotto participants have been defined upfront then we will need to add them all to our lotto instance now.\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_1.add(participant, tokens);\r\n });\r\n // Return the Lotto instance.\r\n return lotto_1;\r\n }\r\n else {\r\n // We are dealing with some lotto options.\r\n var random = participantsOrOptions.random, participants = participantsOrOptions.participants;\r\n // Create a Lotto instance passing the custom RNG function to use in place of Math.random() (which could be undefined).\r\n var lotto_2 = new Lotto_1.Lotto(random);\r\n // If the lotto participants have been defined upfront as part of the options then we will need to add them all to our lotto instance now.\r\n if (participants) {\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_2.add(participant, tokens);\r\n });\r\n }\r\n // Return the Lotto instance.\r\n return lotto_2;\r\n }\r\n}\r\nexports.createLotto = createLotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar createLotto_1 = require(\"./createLotto\");\r\nexports.default = createLotto_1.createLotto;\r\n", "import State from \"./State\";\nimport { BehaviourTree } from \"./BehaviourTree\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { NodeDetails, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n /**\n * The state that a node will be in when it has not been visited yet in the execution of the tree.\n */\n READY = \"mistreevous.ready\",\n /**\n * The state that a node will be in when it is still being processed and will usually represent or encompass a long-running action.\n */\n RUNNING = \"mistreevous.running\",\n /**\n * The state that a node will be in when it is no longer being processed and has succeeded.\n */\n SUCCEEDED = \"mistreevous.succeeded\",\n /**\n * The state that a node will be in when it is no longer being processed but has failed.\n */\n FAILED = \"mistreevous.failed\"\n}\n\nexport { State as default };\n\nexport type CompleteState = State.SUCCEEDED | State.FAILED;\nexport type AnyState = State.READY | State.RUNNING | CompleteState;\n", "import { ActionResult, Agent, GlobalFunction } from \"./Agent\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\n\nexport type InvokerFunction = (args: any[]) => ActionResult | boolean;\n\n/**\n * A singleton used to store and lookup registered functions and subtrees.\n */\nexport default class Lookup {\n /**\n * The object holding any registered functions keyed on function name.\n */\n private static registeredFunctions: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered subtree root node definitions keyed on tree name.\n */\n private static registeredSubtrees: { [key: string]: RootNodeDefinition } = {};\n\n /**\n * Gets the function with the specified name.\n * @param name The name of the function.\n * @returns The function with the specified name.\n */\n public static getFunc(name: string): GlobalFunction {\n return this.registeredFunctions[name];\n }\n\n /**\n * Sets the function with the specified name for later lookup.\n * @param name The name of the function.\n * @param func The function.\n */\n public static setFunc(name: string, func: GlobalFunction): void {\n this.registeredFunctions[name] = func;\n }\n\n /**\n * Gets the function invoker for the specified agent and function name.\n * If a function with the specified name exists on the agent object then it will\n * be returned, otherwise we will then check the registered functions for a match.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param name The function name.\n * @returns The function invoker for the specified agent and function name.\n */\n static getFuncInvoker(agent: Agent, name: string): InvokerFunction | null {\n // Check whether the agent contains the specified function.\n const agentFunction = agent[name];\n if (agentFunction && typeof agentFunction === \"function\") {\n return (args: any[]) => agentFunction.apply(agent, args);\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.registeredFunctions[name] && typeof this.registeredFunctions[name] === \"function\") {\n const registeredFunction = this.registeredFunctions[name];\n return (args: any[]) => registeredFunction(agent, ...args);\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets all registered subtree root node definitions.\n */\n static getSubtrees(): { [key: string]: RootNodeDefinition } {\n return this.registeredSubtrees;\n }\n\n /**\n * Sets the subtree with the specified name for later lookup.\n * @param name The name of the subtree.\n * @param subtree The subtree.\n */\n static setSubtree(name: string, subtree: RootNodeDefinition) {\n this.registeredSubtrees[name] = subtree;\n }\n\n /**\n * Removes the registered function or subtree with the specified name.\n * @param name The name of the registered function or subtree.\n */\n static remove(name: string) {\n delete this.registeredFunctions[name];\n delete this.registeredSubtrees[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.registeredFunctions = {};\n this.registeredSubtrees = {};\n }\n}\n", "import {\n NodeDefinition,\n RootNodeDefinition,\n DecoratorNodeDefinition,\n CompositeNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition\n} from \"./BehaviourTreeDefinition\";\n\n/**\n * A type guard function that returns true if the specified node satisfies the RootNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the RootNodeDefinition type.\n */\nexport function isRootNode(node: NodeDefinition): node is RootNodeDefinition {\n return node.type === \"root\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the BranchNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the BranchNodeDefinition type.\n */\nexport function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition {\n return node.type === \"branch\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the NodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the NodeDefinition type.\n */\nexport function isLeafNode(node: NodeDefinition): node is NodeDefinition {\n return [\"branch\", \"action\", \"condition\", \"wait\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the DecoratorNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the DecoratorNodeDefinition type.\n */\nexport function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefinition {\n return [\"root\", \"repeat\", \"retry\", \"flip\", \"succeed\", \"fail\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the CompositeNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type.\n */\nexport function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition {\n return [\"sequence\", \"selector\", \"lotto\", \"parallel\", \"race\", \"all\"].includes(node.type);\n}\n\n/**\n * Flatten a node definition into an array of all of its nested node definitions.\n * @param nodeDefinition The node definition to flatten.\n * @returns An array of all of nested node definitions.\n */\nexport function flattenDefinition(nodeDefinition: AnyNodeDefinition): AnyNodeDefinition[] {\n const nodes: AnyNodeDefinition[] = [];\n\n const processNode = (currentNodeDefinition: AnyNodeDefinition) => {\n nodes.push(currentNodeDefinition);\n\n if (isCompositeNode(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNode(currentNodeDefinition)) {\n processNode(currentNodeDefinition.child);\n }\n };\n\n processNode(nodeDefinition);\n\n return nodes;\n}\n\n/**\n * Determines whether the passed value is an integer.\n * @param value The value to check.\n * @returns Whether the passed value is an integer.\n */\nexport function isInteger(value: unknown): boolean {\n return typeof value === \"number\" && Math.floor(value) === value;\n}\n\n/**\n * Determines whether the passed value is null or undefined.\n * @param value The value to check.\n * @returns Whether the passed value is null or undefined.\n */\nexport function isNullOrUndefined(value: unknown): boolean {\n return typeof value === \"undefined\" || value === null;\n}\n", "/**\n * A type defining an object that holds a reference to substitued string literals parsed from the definition.\n */\nexport type StringLiteralPlaceholders = { [key: string]: string };\n\n/**\n * Pop the next raw token from the specified array of tokens and throw an error if it wasn't the expected one.\n * @param tokens The array of tokens.\n * @param expected An optional string or array or items, one of which must match the next popped token.\n * @returns The popped token.\n */\nexport function popAndCheck(tokens: string[], expected?: string | string[]): string {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token but there aren't any.\n if (popped === undefined) {\n throw new Error(\"unexpected end of definition\");\n }\n\n // Do we have an expected token/tokens array?\n if (expected != undefined) {\n // Get an array of expected values, if the popped token matches any then we are all good.\n const expectedValues = typeof expected === \"string\" ? [expected] : expected;\n\n // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase());\n\n // Throw an error if the popped token didn't match any of our expected items.\n if (!tokenMatchesExpectation) {\n const expectationString = expectedValues.map((item) => \"'\" + item + \"'\").join(\" or \");\n throw new Error(\"unexpected token found. Expected \" + expectationString + \" but got '\" + popped + \"'\");\n }\n }\n\n // Return the popped token.\n return popped;\n}\n\n/**\n * Swaps out any node/attribute argument string literals with placeholders.\n * @param definition The definition.\n * @returns An object containing a mapping of placeholders to original string values as well as the processed definition string.\n */\nexport function substituteStringLiterals(definition: string): {\n placeholders: StringLiteralPlaceholders;\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: StringLiteralPlaceholders = {};\n\n // Replace any string literals wrapped with double quotes in our definition with placeholders to be processed later.\n const processedDefinition = definition.replace(/\\\"(\\\\.|[^\"\\\\])*\\\"/g, (match) => {\n var strippedMatch = match.substring(1, match.length - 1);\n var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch);\n\n // If we have no existing string literal match then create a new placeholder.\n if (!placeholder) {\n placeholder = `@@${Object.keys(placeholders).length}@@`;\n placeholders[placeholder] = strippedMatch;\n }\n\n return placeholder;\n });\n\n return { placeholders, processedDefinition };\n}\n\n/**\n * Parse the tree definition into an array of raw tokens.\n * @param definition The definition.\n * @returns An array of tokens parsed from the definition.\n */\nexport function parseTokensFromDefinition(definition: string): string[] {\n // Add some space around various important characters so that they can be plucked out easier as individual tokens.\n definition = definition.replace(/\\(/g, \" ( \");\n definition = definition.replace(/\\)/g, \" ) \");\n definition = definition.replace(/\\{/g, \" { \");\n definition = definition.replace(/\\}/g, \" } \");\n definition = definition.replace(/\\]/g, \" ] \");\n definition = definition.replace(/\\[/g, \" [ \");\n definition = definition.replace(/\\,/g, \" , \");\n\n // Split the definition into raw token form and return it.\n return definition.replace(/\\s+/g, \" \").trim().split(\" \");\n}\n", "import { StringLiteralPlaceholders, popAndCheck } from \"./MDSLUtilities\";\n\n/**\n * A type representing any node function argument.\n */\ntype Argument = {\n /**\n * The argument value.\n */\n value: T;\n /**\n * The argument type, used for validation.\n */\n type: string;\n};\n\ntype NullArgument = Argument & {\n type: \"null\";\n};\n\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\n\ntype NumberArgument = Argument & {\n type: \"number\";\n /**\n * A flag defining whether the number argument value is a valid integer. (used for validation)\n */\n isInteger: boolean;\n};\n\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\n\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\n\n/**\n * A type representing a reference to any node function argument.\n */\ntype AnyArgument = NullArgument | BooleanArgument | NumberArgument | StringPlaceholderArgument | IdentifierArgument;\n\n/**\n * Parse an array of argument definitions from the specified tokens array.\n * @param tokens The array tokens to parse the argument definitions from.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @param argumentValidator The argument validator function.\n * @param validationFailedMessage The exception message to throw if argument validation fails.\n * @returns An array of argument definitions parsed from the specified tokens array.\n */\nexport function parseArgumentTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): AnyArgument[] {\n const argumentList: AnyArgument[] = [];\n\n // If the next token is not a '[' or '(' then we have no arguments to parse.\n if (![\"[\", \"(\"].includes(tokens[0])) {\n return argumentList;\n }\n\n // Any lists of arguments will always be wrapped in '[]' for node arguments or '()' for attribute arguments.\n // We are looking for a '[' or '(' opener that wraps the argument tokens and the relevant closer.\n const closingToken = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closingToken) {\n // The next token is part of our arguments list.\n argumentListTokens.push(tokens.shift()!);\n }\n\n // Validate the order of the argument tokens. Each token must either be a ',' or a single argument that satisfies the validator.\n argumentListTokens.forEach((token, index) => {\n // Get whether this token should be an actual argument.\n const shouldBeArgumentToken = !(index & 1);\n\n // If the current token should be an actual argument then validate it, otherwise it should be a ',' token.\n if (shouldBeArgumentToken) {\n // Get the argument definition.\n const argumentDefinition = getArgumentDefinition(token, stringArgumentPlaceholders);\n\n // This is a valid argument!\n argumentList.push(argumentDefinition);\n } else {\n // The current token should be a ',' token.\n if (token !== \",\") {\n throw new Error(`invalid argument list, expected ',' or ']' but got '${token}'`);\n }\n }\n });\n\n // The arguments list should terminate with a ']' or ')' token, depending on the opener.\n popAndCheck(tokens, closingToken);\n\n // Return the arguments.\n return argumentList;\n}\n\n/**\n * Gets an argument value definition.\n * @param token The argument token.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An argument value definition.\n */\nfunction getArgumentDefinition(token: string, stringArgumentPlaceholders: StringLiteralPlaceholders): AnyArgument {\n // Check whether the token represents a null value.\n if (token === \"null\") {\n return {\n value: null,\n type: \"null\"\n } as NullArgument;\n }\n\n // Check whether the token represents a boolean value.\n if (token === \"true\" || token === \"false\") {\n return {\n value: token === \"true\",\n type: \"boolean\"\n } as BooleanArgument;\n }\n\n // Check whether the token represents a number value.\n // TODO: Relies on broken isNaN - see MDN.\n // if (!Number.isNaN(token)) {\n if (!isNaN(token as any)) {\n return {\n value: parseFloat(token),\n isInteger: parseFloat(token) === parseInt(token, 10),\n type: \"number\"\n } as NumberArgument;\n }\n\n // Check whether the token is a placeholder (e.g. @@0@@) representing a string literal.\n if (token.match(/^@@\\d+@@$/g)) {\n return {\n value: stringArgumentPlaceholders[token].replace('\\\\\"', '\"'),\n type: \"string\"\n } as StringPlaceholderArgument;\n }\n\n // The only remaining option is that the argument value is an identifier.\n return {\n value: token,\n type: \"identifier\"\n } as IdentifierArgument;\n}\n", "import { NodeAttributeDefinition } from \"../BehaviourTreeDefinition\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { StringLiteralPlaceholders } from \"./MDSLUtilities\";\n\n/**\n * A type defining the attribute definitions of a node.\n */\ntype NodeAttributes = {\n while?: NodeAttributeDefinition;\n until?: NodeAttributeDefinition;\n entry?: NodeAttributeDefinition;\n exit?: NodeAttributeDefinition;\n step?: NodeAttributeDefinition;\n};\n\n/**\n * Parse any node attribute definitions from the specified tokens array.\n * @param tokens The array of remaining tokens.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An object of attribute definitions defined by any directly following tokens.\n */\nexport function parseAttributeTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): NodeAttributes {\n const nodeAttributeNames: (keyof NodeAttributes)[] = [\"while\", \"until\", \"entry\", \"exit\", \"step\"];\n\n // Create an object to hold any attributes found.\n const attributes: NodeAttributes = {};\n\n // Try to get the name of the attribute for the next token.\n let nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n\n // Pull attribute tokens as well as their arguments off of the tokens stack until we have no more.\n while (nodeAttributeNames.includes(nextAttributeName)) {\n // Check to make sure that we have not already created an attribute definition of this type.\n if (attributes[nextAttributeName]) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Remove the attribute name token from the array of tokens.\n tokens.shift();\n\n // Grab the attribute arguments, assuming the first to be an identifier.\n const [attributeCallIdentifier, ...attributeArguments] = parseArgumentTokens(\n tokens,\n stringArgumentPlaceholders\n );\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeCallIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected agent function or registered function name identifier argument for attribute\");\n }\n\n // Any attribute arguments (other than the expected call identifier) must have a type of string, number, boolean or null.\n attributeArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid attribute argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Create the attribute definition and add it to the object of attribute definitions found.\n attributes[nextAttributeName] = {\n call: attributeCallIdentifier.value,\n args: attributeArguments.map(({ value }) => value)\n };\n\n // Try to get the next attribute name token, as there could be multiple.\n nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n }\n\n return attributes;\n}\n", "import {\n ActionNodeDefinition,\n AnyChildNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition,\n ConditionNodeDefinition,\n FailNodeDefinition,\n FlipNodeDefinition,\n LottoNodeDefinition,\n ParallelNodeDefinition,\n RaceNodeDefinition,\n AllNodeDefinition,\n RepeatNodeDefinition,\n RetryNodeDefinition,\n RootNodeDefinition,\n SelectorNodeDefinition,\n SequenceNodeDefinition,\n SucceedNodeDefinition,\n WaitNodeDefinition\n} from \"../BehaviourTreeDefinition\";\nimport {\n isCompositeNode,\n isDecoratorNode,\n isLeafNode,\n isNullOrUndefined,\n isRootNode\n} from \"../BehaviourTreeDefinitionUtilities\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { parseAttributeTokens } from \"./MDSLNodeAttributeParser\";\nimport {\n StringLiteralPlaceholders,\n parseTokensFromDefinition,\n popAndCheck,\n substituteStringLiterals\n} from \"./MDSLUtilities\";\n\n/**\n * Convert the MDSL tree definition string into an equivalent JSON definition.\n * @param definition The tree definition string as MDSL.\n * @returns The root node JSON definitions.\n */\nexport function convertMDSLToJSON(definition: string): RootNodeDefinition[] {\n // Swap out any node/attribute argument string literals with a placeholder and get a mapping of placeholders to original values as well as the processed definition.\n const { placeholders, processedDefinition } = substituteStringLiterals(definition);\n\n // Parse our definition definition string into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\n return convertTokensToJSONDefinition(tokens, placeholders);\n}\n\n/**\n * Converts the specified tree definition tokens into a JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definitions.\n */\nfunction convertTokensToJSONDefinition(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RootNodeDefinition[] {\n // There must be at least 3 tokens for the tree definition to be valid. 'ROOT', '{' and '}'.\n if (tokens.length < 3) {\n throw new Error(\"invalid token count\");\n }\n\n // We should have a matching number of '{' and '}' tokens. If not, then there are scopes that have not been properly closed.\n if (tokens.filter((token) => token === \"{\").length !== tokens.filter((token) => token === \"}\").length) {\n throw new Error(\"scope character mismatch\");\n }\n\n // Create an array of tree stack arrays where root nodes will always be at the botton and the current composite/decorator node at the top.\n // There should be an element in this array for every root node defined and every element should be an array with a root note as the first element.\n // E.g. A definition with two root nodes defined:\n // [\n // [root, lotto, sequence],\n // [root, selector]\n // ]\n const treeStacks: [Partial, ...Partial[]][] = [];\n\n // Create an array of all root node definitions that we create.\n const rootNodes: Partial[] = [];\n\n // A helper function used to push node definitions onto the tree stack.\n const pushNode = (node: AnyNodeDefinition) => {\n // If the node is a root node then we need to create a new tree stack array with the root node at the root.\n if (isRootNode(node)) {\n // We need to double-check that this root node is not the child of another node.\n // We can do this by checking whether the top tree stack is not empty (contains an existing node)\n if (treeStacks[treeStacks.length - 1]?.length) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Add the root node definition to our array of all parsed root node definitions.\n rootNodes.push(node);\n\n // Add the root node definition to the root of a new tree stack.\n treeStacks.push([node]);\n\n return;\n }\n\n // All non-root nodes should be pushed after their root nodes so handle cases\n // where we may not have any tree stacks or our top-most tree stack is empty.\n if (!treeStacks.length || !treeStacks[treeStacks.length - 1].length) {\n throw new Error(\"expected root node at base of definition\");\n }\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Get the top-most node in the current tree stack, this will be a composite/decorator node\n // for which we will populate its children array if composite or setting its child if a decorator.\n const topTreeStackTopNode = topTreeStack[topTreeStack.length - 1] as AnyNodeDefinition;\n\n // If the top-most node in the current root stack is a composite or decorator\n // node then the current node should be added as a child of the top-most node.\n if (isCompositeNode(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNode(topTreeStackTopNode)) {\n // If the top node already has a child node set then throw an error as a decorator should only have a single child.\n if (topTreeStackTopNode.child) {\n throw new Error(\"a decorator node must only have a single child node\");\n }\n\n topTreeStackTopNode.child = node;\n }\n\n // If the node we are adding is also a composite or decorator node, then we should push it\n // onto the current tree stack, as subsequent nodes will be added as its child/children.\n if (!isLeafNode(node)) {\n topTreeStack.push(node);\n }\n };\n\n // A helper function used to pop the top-most node definition off of the tree stack and return it.\n const popNode = (): AnyNodeDefinition | null => {\n let poppedNode: AnyNodeDefinition | null = null;\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Pop the top-most node in the current tree stack if there is one.\n if (topTreeStack.length) {\n poppedNode = topTreeStack.pop() as AnyNodeDefinition;\n }\n\n // We don't want any empty tree stacks in our stack of tree stacks.\n if (!topTreeStack.length) {\n treeStacks.pop();\n }\n\n return poppedNode;\n };\n\n // We should keep processing the raw tokens until we run out of them.\n while (tokens.length) {\n // Grab the next token.\n const token = tokens.shift()!;\n\n // How we create the next node depends on the current raw token value.\n switch (token.toUpperCase()) {\n case \"ROOT\": {\n pushNode(createRootNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SUCCEED\": {\n pushNode(createSucceedNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FAIL\": {\n pushNode(createFailNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FLIP\": {\n pushNode(createFlipNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"REPEAT\": {\n pushNode(createRepeatNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RETRY\": {\n pushNode(createRetryNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SEQUENCE\": {\n pushNode(createSequenceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SELECTOR\": {\n pushNode(createSelectorNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"PARALLEL\": {\n pushNode(createParallelNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RACE\": {\n pushNode(createRaceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ALL\": {\n pushNode(createAllNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"LOTTO\": {\n pushNode(createLottoNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ACTION\": {\n pushNode(createActionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"CONDITION\": {\n pushNode(createConditionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"WAIT\": {\n pushNode(createWaitNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"BRANCH\": {\n pushNode(createBranchNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope and means that we have to pop a node off of the current stack.\n const poppedNode = popNode();\n\n // Now that we have a node definition we can carry out any validation that may require the node to be fully populated.\n if (poppedNode) {\n validatePoppedNode(poppedNode);\n }\n\n break;\n }\n\n default: {\n throw new Error(`unexpected token: ${token}`);\n }\n }\n }\n\n return rootNodes as RootNodeDefinition[];\n}\n\n/**\n * Creates a root node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definition.\n */\nfunction createRootNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RootNodeDefinition {\n // Create the root node definition.\n let node = {\n type: \"root\"\n } as Partial;\n\n // Parse any node arguments, we should only have one if any which will be an identifier argument for the root identifier.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Check whether any node arguments were defined.\n if (nodeArguments.length) {\n // We should only have one argument, if any, which will be an identifier argument for the root identifier.\n if (nodeArguments.length === 1 && nodeArguments[0].type === \"identifier\") {\n // The root node identifier will be the first and only node argument value.\n node.id = nodeArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the root node definition.\n return node as RootNodeDefinition;\n}\n\n/**\n * Creates a succeed node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The succeed node JSON definition.\n */\nfunction createSucceedNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SucceedNodeDefinition {\n const node = {\n type: \"succeed\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SucceedNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the succeed node definition.\n return node;\n}\n\n/**\n * Creates a fail node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The fail node JSON definition.\n */\nfunction createFailNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FailNodeDefinition {\n const node = {\n type: \"fail\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FailNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the fail node definition.\n return node;\n}\n\n/**\n * Creates a flip node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The flip node JSON definition.\n */\nfunction createFlipNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FlipNodeDefinition {\n const node = {\n type: \"flip\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FlipNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the flip node definition.\n return node;\n}\n\n/**\n * Creates a repeat node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The repeat node JSON definition.\n */\nfunction createRepeatNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RepeatNodeDefinition {\n let node = { type: \"repeat\" } as RepeatNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a repeat node are optional. We may have:\n // - No node arguments, in which case the repeat note will iterate indefinitely.\n // - One node argument which will be the explicit number of iterations to make.\n // - Two node arguments which define the min and max iteration bounds from which a random iteration count will be picked.\n if (nodeArguments.length) {\n // All repeat node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`repeat node iteration counts must be integer values`);\n });\n\n // We should have got one or two iteration counts.\n if (nodeArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = nodeArguments[0].value as number;\n\n // A repeat node must have a positive number of iterations if defined.\n if (node.iterations < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A repeat node must have a positive min and max iteration count if they are defined.\n if (node.iterations[0] < 0 || node.iterations[1] < 0) {\n throw new Error(\"a repeat node must have a positive minimum and maximum iteration count if defined\");\n }\n\n // A repeat node must not have an minimum iteration count that exceeds the maximum iteration count.\n if (node.iterations[0] > node.iterations[1]) {\n throw new Error(\n \"a repeat node must not have a minimum iteration count that exceeds the maximum iteration count\"\n );\n }\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of repeat node iteration count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the repeat node definition.\n return node;\n}\n\n/**\n * Creates a retry node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The retry node JSON definition.\n */\nfunction createRetryNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RetryNodeDefinition {\n let node = { type: \"retry\" } as RetryNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a retry node are optional. We may have:\n // - No node arguments, in which case the retry note will attempt indefinitely.\n // - One node argument which will be the explicit number of attempts to make.\n // - Two node arguments which define the min and max attempt bounds from which a random attempt count will be picked.\n if (nodeArguments.length) {\n // All retry node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`retry node attempt counts must be integer values`);\n });\n\n // We should have got one or two attempt counts.\n if (nodeArguments.length === 1) {\n // A static attempt count was defined.\n node.attempts = nodeArguments[0].value as number;\n\n // A retry node must have a positive number of attempts if defined.\n if (node.attempts < 0) {\n throw new Error(\"a retry node must have a positive number of attempts if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum attempt count was defined.\n node.attempts = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (node.attempts[0] < 0 || node.attempts[1] < 0) {\n throw new Error(\"a retry node must have a positive minimum and maximum attempt count if defined\");\n }\n\n // A retry node must not have a minimum attempt count that exceeds the maximum attempt count.\n if (node.attempts[0] > node.attempts[1]) {\n throw new Error(\n \"a retry node must not have a minimum attempt count that exceeds the maximum attempt count\"\n );\n }\n } else {\n // An incorrect number of attempt counts was defined.\n throw new Error(\"invalid number of retry node attempt count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the retry node definition.\n return node;\n}\n\n/**\n * Creates a sequence node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The sequence node JSON definition.\n */\nfunction createSequenceNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SequenceNodeDefinition {\n const node = {\n type: \"sequence\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SequenceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the sequence node definition.\n return node;\n}\n\n/**\n * Creates a selector node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The selector node JSON definition.\n */\nfunction createSelectorNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SelectorNodeDefinition {\n const node = {\n type: \"selector\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SelectorNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the selector node definition.\n return node;\n}\n\n/**\n * Creates a parallel node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The parallel node JSON definition.\n */\nfunction createParallelNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ParallelNodeDefinition {\n const node = {\n type: \"parallel\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as ParallelNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the parallel node definition.\n return node;\n}\n\n/**\n * Creates a race node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The race node JSON definition.\n */\nfunction createRaceNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RaceNodeDefinition {\n const node = {\n type: \"race\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as RaceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the race node definition.\n return node;\n}\n\n/**\n * Creates an all node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The all node JSON definition.\n */\nfunction createAllNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): AllNodeDefinition {\n const node = {\n type: \"all\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as AllNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the all node definition.\n return node;\n}\n\n/**\n * Creates a lotto node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The lotto node JSON definition.\n */\nfunction createLottoNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): LottoNodeDefinition {\n // If any node arguments have been defined then they must be our weights.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // All lotto node arguments MUST be of type number and must be positive integers.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger || arg.value < 0)\n .forEach(() => {\n throw new Error(`lotto node weight arguments must be positive integer values`);\n });\n\n const node = {\n type: \"lotto\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as LottoNodeDefinition;\n\n // Apply the weights if any were defined.\n if (nodeArguments.length) {\n node.weights = nodeArguments.map(({ value }) => value) as number[];\n }\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the lotto node definition.\n return node;\n}\n\n/**\n * Creates an action node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The action node JSON definition.\n */\nfunction createActionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ActionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the action name\n // and agent function to invoke for the action, all other arguments are to be passed as arguments to that function.\n const [actionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require an action name argument.\n if (actionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid action node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the action node definition.\n return {\n type: \"action\",\n call: actionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a condition node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The condition node JSON definition.\n */\nfunction createConditionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ConditionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the condition name\n // and agent function to invoke for the condition, all other arguments are to be passed as arguments to that function.\n const [conditionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require a condition name argument.\n if (conditionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid condition node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the condition node definition.\n return {\n type: \"condition\",\n call: conditionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a wait node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The wait node JSON definition.\n */\nfunction createWaitNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): WaitNodeDefinition {\n let node = { type: \"wait\" } as WaitNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a wait node are optional. We may have:\n // - No node arguments, in which case the wait will be indefinite until it is aborted.\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n if (nodeArguments.length) {\n // All wait node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`wait node durations must be integer values`);\n });\n\n // We may have:\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n // - Too many arguments, which is not valid.\n if (nodeArguments.length === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0].value as number;\n\n // If an explict duration was defined then it must be a positive number.\n if (node.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.duration = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A wait node must have a positive min and max duration.\n if (node.duration[0] < 0 || node.duration[1] < 0) {\n throw new Error(\"a wait node must have a positive minimum and maximum duration\");\n }\n\n // A wait node must not have a minimum duration that exceeds the maximum duration.\n if (node.duration[0] > node.duration[1]) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else if (nodeArguments.length > 2) {\n // An incorrect number of duration arguments were defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n }\n\n // Return the wait node definition.\n return { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n}\n\n/**\n * Creates a branch node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The branch node JSON definition.\n */\nfunction createBranchNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): BranchNodeDefinition {\n // Parse any node arguments, we should have one which will be an identifier argument for the root ref.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // We should have only a single identifer argument for a branch node, which is the root ref.\n if (nodeArguments.length !== 1 || nodeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // Return the branch node definition.\n return { type: \"branch\", ref: nodeArguments[0].value };\n}\n\n/**\n * Validate a fully-populated node definition that was popped off of the tree stack.\n * @param definition The popped node to validate.\n */\nfunction validatePoppedNode(definition: AnyNodeDefinition): void {\n // Decorators MUST have a child defined.\n if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) {\n throw new Error(`a ${definition.type} node must have a single child node defined`);\n }\n\n // Composites MUST have at least one child defined.\n if (isCompositeNode(definition) && !definition.children?.length) {\n throw new Error(`a ${definition.type} node must have at least a single child node defined`);\n }\n\n // We need to make sure that lotto nodes that have weights defined have a number of weights matching the number of child nodes.\n if (definition.type === \"lotto\") {\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (definition.weights.length !== definition.children.length) {\n throw new Error(\n \"expected a number of weight arguments matching the number of child nodes for lotto node\"\n );\n }\n }\n }\n}\n", "import { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { flattenDefinition, isBranchNode, isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\n/**\n * An object representing the result of validating a tree definition.\n */\nexport type DefinitionValidationResult = {\n /**\n * A flag defining whether validation succeeded.\n */\n succeeded: boolean;\n /**\n * A string containing the error message if validation did not succeed.\n */\n errorMessage?: string;\n /**\n * The definition as json if the validation was successful, or undefined if validation did not succeed.\n */\n json?: RootNodeDefinition[];\n};\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON or MDSL, not taking any globally registered subtrees into consideration.\n * @param definition The behaviour tree definition in the form of JSON or MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateDefinition(definition: any): DefinitionValidationResult {\n // The definition must be defined.\n if (definition === null || typeof definition === \"undefined\") {\n return createValidationFailureResult(\"definition is null or undefined\");\n }\n\n // We are expecting a definition in one of three different forms:\n // - A string which we will assume is MDSL and we will parse this to JSON before validation.\n // - An array which we will assume is an array of root node definitions with at least one being the primary root node (no 'id' property)\n // - An object which we will assume is the primary root node and should not have an 'id' property.\n if (typeof definition === \"string\") {\n // The definition is a string which we can assume is MDSL, so attempt to validate it.\n return validateMDSLDefinition(definition);\n } else if (typeof definition === \"object\") {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n return validateJSONDefinition(definition);\n } else {\n return createValidationFailureResult(`unexpected definition type of '${typeof definition}'`);\n }\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of MDSL.\n * @param definition The behaviour tree definition in the form of MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nfunction validateMDSLDefinition(definition: string): DefinitionValidationResult {\n let rootNodeDefinitions;\n\n // The first thing the we need to do is to attempt to convert our MDSL into JSON.\n try {\n // The definition is a string which we can assume is MDSL, so attempt to parse it to a JSON definition in the form of an array of root node definitions.\n rootNodeDefinitions = convertMDSLToJSON(definition);\n } catch (exception) {\n // We failed to parse the JSON from the MDSL, this is likely to be the result of it not being a valid MDSL string.\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single unnamed root node at base of definition to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(`multiple root nodes found with duplicate name '${id}'`);\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON.\n * @param definition The behaviour tree definition in the form of JSON.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateJSONDefinition(\n definition: RootNodeDefinition | RootNodeDefinition[]\n): DefinitionValidationResult {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n const rootNodeDefinitions = Array.isArray(definition) ? definition : [definition];\n\n // Iterate over our array of root nodes and call validateNode for each, passing an initial depth of 0, wrapped in a try catch to handle validation failures.\n try {\n rootNodeDefinitions.forEach((rootNodeDefinition) => validateNode(rootNodeDefinition, 0));\n } catch (error) {\n // Handle cases where we have caught a thrown Error and return a failure result with the error message.\n if (error instanceof Error) {\n return createValidationFailureResult(error.message);\n }\n\n // No idea what happened here!\n return createValidationFailureResult(`unexpected error: ${error}`);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single root node without 'id' property defined to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(\n `multiple root nodes found with duplicate 'id' property value of '${id}'`\n );\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the branch -> subtree links across all provided root node definitions.\n * This will not consider branch nodes that reference any globally registered subtrees unless includesGlobalSubtrees\n * is set to true, in which case we will also verify that there are no broken branch -> subtree links.\n * @param rootNodeDefinitions The array of root node definitions.\n * @param includesGlobalSubtrees A flag defining whether the array includes all global subtree root node definitions.\n */\nexport function validateBranchSubtreeLinks(rootNodeDefinitions: RootNodeDefinition[], includesGlobalSubtrees: boolean) {\n // Create a mapping of root node identifiers to other root nodes that they reference via branch nodes.\n // Below is an example of a mapping that includes a circular dependency (root => a => b => c => a)\n // [{ refs: [\"a\", \"b\"] }, { id: \"a\", refs: [\"b\"] }, { id: \"b\", refs: [\"c\"] }, { id: \"c\", refs: [\"a\"] }]\n const rootNodeMappings: { id: string | undefined; refs: string[] }[] = rootNodeDefinitions.map(\n (rootNodeDefinition) => ({\n id: rootNodeDefinition.id,\n refs: flattenDefinition(rootNodeDefinition)\n .filter(isBranchNode)\n .map(({ ref }) => ref)\n })\n );\n\n // A recursive function to walk through the mappings, keeping track of which root nodes we have visited in the form of a path of root node identifiers.\n const followRefs = (mapping: { id: string | undefined; refs: string[] }, path: (string | undefined)[] = []) => {\n // Have we found a circular dependency?\n if (path.includes(mapping.id)) {\n // We found a circular dependency! Get the bad path of root node identifiers.\n const badPath = [...path, mapping.id];\n\n // Create the formatted path value. [undefined, \"a\", \"b\", \"c\", \"a\"] would be formatted as \"a -> b -> c -> a\".\n const badPathFormatted = badPath.filter((element) => !!element).join(\" => \");\n\n // No need to continue, we found a circular dependency.\n throw new Error(`circular dependency found in branch node references: ${badPathFormatted}`);\n }\n\n for (const ref of mapping.refs) {\n // Find the mapping for the root node with an identifer matching the current ref.\n const subMapping = rootNodeMappings.find(({ id }) => id === ref);\n\n // We may not have a mapping for this ref, which is normal when we aren't considering all globally registered subtrees.\n if (subMapping) {\n followRefs(subMapping, [...path, mapping.id]);\n } else if (includesGlobalSubtrees) {\n // We found a reference to a root node that doesn't exist, which is a problem seeing as the root node definitons includes all globally registered subtrees.\n throw new Error(\n mapping.id\n ? `subtree '${mapping.id}' has branch node that references root node '${ref}' which has not been defined`\n : `primary tree has branch node that references root node '${ref}' which has not been defined`\n );\n }\n }\n };\n\n // Start looking for circular dependencies and broken references from the primary root node definition.\n followRefs(rootNodeMappings.find((mapping) => typeof mapping.id === \"undefined\")!);\n}\n\n/**\n * Validate an object that we expect to be a node definition.\n * @param definition An object that we expect to be a node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateNode(definition: any, depth: number): void {\n // Every node must be valid object and have a non-empty 'type' string property.\n if (typeof definition !== \"object\" || typeof definition.type !== \"string\" || definition.type.length === 0) {\n throw new Error(\n `node definition is not an object or 'type' property is not a non-empty string at depth '${depth}'`\n );\n }\n\n // If this node is at the very base of the definition then it MUST be a root node.\n if (depth === 0 && definition.type !== \"root\") {\n throw new Error(`expected root node at base of definition but got node of type '${definition.type}'`);\n }\n\n // How we validate this node definition will depend on its type.\n switch (definition.type) {\n case \"action\":\n validateActionNode(definition, depth);\n break;\n\n case \"condition\":\n validateConditionNode(definition, depth);\n break;\n\n case \"wait\":\n validateWaitNode(definition, depth);\n break;\n\n case \"branch\":\n validateBranchNode(definition, depth);\n break;\n\n case \"root\":\n validateRootNode(definition, depth);\n break;\n\n case \"succeed\":\n validateSucceedNode(definition, depth);\n break;\n\n case \"fail\":\n validateFailNode(definition, depth);\n break;\n\n case \"flip\":\n validateFlipNode(definition, depth);\n break;\n\n case \"repeat\":\n validateRepeatNode(definition, depth);\n break;\n\n case \"retry\":\n validateRetryNode(definition, depth);\n break;\n\n case \"sequence\":\n validateSequenceNode(definition, depth);\n break;\n\n case \"selector\":\n validateSelectorNode(definition, depth);\n break;\n\n case \"parallel\":\n validateParallelNode(definition, depth);\n break;\n\n case \"race\":\n validateRaceNode(definition, depth);\n break;\n\n case \"all\":\n validateAllNode(definition, depth);\n break;\n\n case \"lotto\":\n validateLottoNode(definition, depth);\n break;\n\n default:\n throw new Error(`unexpected node type of '${definition.type}' at depth '${depth}'`);\n }\n}\n\n/**\n * Validate any attributes for a given node definition.\n * @param definition The node definition.\n * @param depth The depth of the node in the behaviour tree definition.\n */\nfunction validateNodeAttributes(definition: any, depth: number): void {\n // Validate each of the attribute types for this node.\n [\"while\", \"until\", \"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n // Attempt to grab the definition for the current attribute from the node definition.\n const attributeDefinition = definition[attributeName];\n\n // All node attributes are optional, so there is nothing to do if the current attribute is not defined.\n if (typeof attributeDefinition === \"undefined\") {\n return;\n }\n\n // The attribute definition must be an object.\n if (typeof attributeDefinition !== \"object\") {\n throw new Error(\n `expected attribute '${attributeName}' to be an object for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // The 'call' property must be defined for any attribute definition.\n if (typeof attributeDefinition.call !== \"string\" || attributeDefinition.call.length === 0) {\n throw new Error(\n `expected 'call' property for attribute '${attributeName}' to be a non-empty string for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // If any node attribute arguments have been defined then they must have been defined in an array.\n if (typeof attributeDefinition.args !== \"undefined\" && !Array.isArray(attributeDefinition.args)) {\n throw new Error(\n `expected 'args' property for attribute '${attributeName}' to be an array for '${definition.type}' node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a root node definition.\n * @param definition An object that we expect to be a root node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRootNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"root\") {\n throw new Error(\"expected node type of 'root' for root node\");\n }\n\n // A root node cannot be the child of another node.\n if (depth > 0) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Check that, if the root node 'id' property is defined, it is a non-empty string.\n if (typeof definition.id !== \"undefined\" && (typeof definition.id !== \"string\" || definition.id.length === 0)) {\n throw new Error(\"expected non-empty string for 'id' property if defined for root node\");\n }\n\n // A root node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(\"expected property 'child' to be defined for root node\");\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a succeed node definition.\n * @param definition An object that we expect to be a succeed node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSucceedNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"succeed\") {\n throw new Error(`expected node type of 'succeed' for succeed node at depth '${depth}'`);\n }\n\n // A succeed node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for succeed node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a fail node definition.\n * @param definition An object that we expect to be a fail node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFailNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"fail\") {\n throw new Error(`expected node type of 'fail' for fail node at depth '${depth}'`);\n }\n\n // A fail node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for fail node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a flip node definition.\n * @param definition An object that we expect to be a flip node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFlipNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"flip\") {\n throw new Error(`expected node type of 'flip' for flip node at depth '${depth}'`);\n }\n\n // A flip node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for flip node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a repeat node definition.\n * @param definition An object that we expect to be a repeat node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRepeatNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"repeat\") {\n throw new Error(`expected node type of 'repeat' for repeat node at depth '${depth}'`);\n }\n\n // A repeat node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for repeat node at depth '${depth}'`);\n }\n\n // Check whether an 'iterations' property has been defined, it may not have been if this node is to repeat indefinitely.\n if (typeof definition.iterations !== \"undefined\") {\n if (Array.isArray(definition.iterations)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.iterations.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'iterations' property is an array then it MUST contain two integer values.\n if (definition.iterations.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must have a positive min and max iterations count if they are defined.\n if (definition.iterations[0] < 0 || definition.iterations[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must not have a minimum iterations count that exceeds the maximum iterations count.\n if (definition.iterations[0] > definition.iterations[1]) {\n throw new Error(\n `expected minimum iterations count that does not exceed the maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.iterations)) {\n // A repeat node must have a positive number of iterations if defined.\n if (definition.iterations < 0) {\n throw new Error(\n `expected positive iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a retry node definition.\n * @param definition An object that we expect to be a retry node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRetryNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"retry\") {\n throw new Error(`expected node type of 'retry' for retry node at depth '${depth}'`);\n }\n\n // A retry node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for retry node at depth '${depth}'`);\n }\n\n // Check whether an 'attempts' property has been defined, it may not have been if this node is to retry indefinitely.\n if (typeof definition.attempts !== \"undefined\") {\n if (Array.isArray(definition.attempts)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.attempts.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'attempts' property is an array then it MUST contain two integer values.\n if (definition.attempts.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (definition.attempts[0] < 0 || definition.attempts[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must not have a minimum attempts count that exceeds the maximum attempts count.\n if (definition.attempts[0] > definition.attempts[1]) {\n throw new Error(\n `expected minimum attempts count that does not exceed the maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.attempts)) {\n // A retry node must have a positive number of attempts if defined.\n if (definition.attempts < 0) {\n throw new Error(\n `expected positive attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a branch node definition.\n * @param definition An object that we expect to be a branch node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateBranchNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"branch\") {\n throw new Error(`expected node type of 'branch' for branch node at depth '${depth}'`);\n }\n\n // Check that the branch node 'ref' property is defined and is a non-empty string.\n if (typeof definition.ref !== \"string\" || definition.ref.length === 0) {\n throw new Error(`expected non-empty string for 'ref' property for branch node at depth '${depth}'`);\n }\n\n // It is invalid to define guard attributes for a branch node as they should be defined on the referenced root node.\n [\"while\", \"until\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `guards should not be defined for branch nodes but guard '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n\n // It is invalid to define callback attributes for a branch node as they should be defined on the referenced root node.\n [\"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `callbacks should not be defined for branch nodes but callback '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a action node definition.\n * @param definition An object that we expect to be a action node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateActionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"action\") {\n throw new Error(`expected node type of 'action' for action node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a action node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of action node at depth '${depth}'`);\n }\n\n // If any action function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for action node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a condition node definition.\n * @param definition An object that we expect to be a condition node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateConditionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"condition\") {\n throw new Error(`expected node type of 'condition' for condition node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a condition node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of condition node at depth '${depth}'`);\n }\n\n // If any condition function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for condition node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a wait node definition.\n * @param definition An object that we expect to be a wait node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateWaitNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"wait\") {\n throw new Error(`expected node type of 'wait' for wait node at depth '${depth}'`);\n }\n\n // Check whether a 'duration' property has been defined, it may not have been if this node is to wait indefinitely.\n if (typeof definition.duration !== \"undefined\") {\n if (Array.isArray(definition.duration)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.duration.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'duration' property is an array then it MUST contain two integer values.\n if (definition.duration.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must have a positive min and max duration value if they are defined.\n if (definition.duration[0] < 0 || definition.duration[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum duration for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must not have a minimum duration value that exceeds the maximum duration value.\n if (definition.duration[0] > definition.duration[1]) {\n throw new Error(\n `expected minimum duration value that does not exceed the maximum duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.duration)) {\n // A wait node must have a positive duration value if defined.\n if (definition.duration < 0) {\n throw new Error(\n `expected positive duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a sequence node definition.\n * @param definition An object that we expect to be a sequence node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSequenceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"sequence\") {\n throw new Error(`expected node type of 'sequence' for sequence node at depth '${depth}'`);\n }\n\n // A sequence node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for sequence node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a selector node definition.\n * @param definition An object that we expect to be a selector node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSelectorNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"selector\") {\n throw new Error(`expected node type of 'selector' for selector node at depth '${depth}'`);\n }\n\n // A selector node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for selector node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a parallel node definition.\n * @param definition An object that we expect to be a parallel node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateParallelNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"parallel\") {\n throw new Error(`expected node type of 'parallel' for parallel node at depth '${depth}'`);\n }\n\n // A parallel node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for parallel node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a race node definition.\n * @param definition An object that we expect to be a race node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRaceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"race\") {\n throw new Error(`expected node type of 'race' for race node at depth '${depth}'`);\n }\n\n // A race node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for race node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be an all node definition.\n * @param definition An object that we expect to be an all node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateAllNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"all\") {\n throw new Error(`expected node type of 'all' for all node at depth '${depth}'`);\n }\n\n // A all node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for all node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a lotto node definition.\n * @param definition An object that we expect to be a lotto node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateLottoNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"lotto\") {\n throw new Error(`expected node type of 'lotto' for lotto node at depth '${depth}'`);\n }\n\n // A lotto node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for lotto node at depth '${depth}'`);\n }\n\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (\n !Array.isArray(definition.weights) ||\n definition.weights.length !== definition.children.length ||\n definition.weights.filter((value: unknown) => !isInteger(value)).length ||\n definition.weights.filter((value: number) => value < 0).length\n ) {\n throw new Error(\n `expected an array of positive integer weight values with a length matching the number of child nodes for 'weights' property if defined for lotto node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * A helper function to create a failure validation result with the given error message.\n * @param errorMessage The validation failure error message.\n * @returns A failure validation result with the given error message.\n */\nfunction createValidationFailureResult(errorMessage: string): DefinitionValidationResult {\n return { succeeded: false, errorMessage };\n}\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nexport function createUid(): string {\n var S4 = function () {\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n };\n return S4() + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + S4() + S4();\n}\n", "import { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport State, { AnyState } from \"../State\";\nimport { Agent } from \"../Agent\";\nimport Leaf from \"./leaf/Leaf\";\nimport Attribute from \"../attributes/Attribute\";\nimport Entry from \"../attributes/callbacks/Entry\";\nimport Exit from \"../attributes/callbacks/Exit\";\nimport Step from \"../attributes/callbacks/Step\";\nimport While from \"../attributes/guards/While\";\nimport Until from \"../attributes/guards/Until\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\nimport { GuardAttributeDetails } from \"../attributes/guards/Guard\";\nimport { CallbackAttributeDetails } from \"../attributes/callbacks/Callback\";\nimport { createUid } from \"../Utilities\";\n\n/**\n * Details of a tree node instance.\n */\nexport type NodeDetails = {\n /**\n * The tree node identifier.\n */\n id: string;\n /**\n * The tree node type.\n */\n type: string;\n /**\n * The tree node name.\n */\n name: string;\n /**\n * The current state of the tree node.\n */\n state: AnyState;\n /**\n * The array of agent or globally registered function arguments, defined if this is an action or condition node.\n */\n args?: any[];\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: GuardAttributeDetails;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: GuardAttributeDetails;\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: CallbackAttributeDetails;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: CallbackAttributeDetails;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: CallbackAttributeDetails;\n /**\n * The array of the child nodes of this node, defined if this node is a composite or decorator node.\n */\n children?: NodeDetails[];\n};\n\n/**\n * A mapping of attribute names to attributes configured for a node.\n */\ntype Attributes = {\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: Entry;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: Step;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: Exit;\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: While;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: Until;\n};\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node unique identifier.\n */\n protected readonly uid: string;\n /**\n * The node attributes.\n */\n protected readonly attributes: Attributes;\n /**\n * The node state.\n */\n private _state: AnyState = State.READY;\n /**\n * The guard path to evaluate as part of a node update.\n */\n private _guardPath: GuardPath | undefined;\n\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n */\n constructor(private type: string, attributes: Attribute[], protected options: BehaviourTreeOptions) {\n // Create a unique identifier for this node.\n this.uid = createUid();\n\n // Create our attribute mapping.\n this.attributes = {\n entry: attributes.find(({ type }) => type === \"entry\") as Entry,\n step: attributes.find(({ type }) => type === \"step\") as Step,\n exit: attributes.find(({ type }) => type === \"exit\") as Exit,\n while: attributes.find(({ type }) => type === \"while\") as While,\n until: attributes.find(({ type }) => type === \"until\") as Until\n };\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected abstract onUpdate(agent: Agent): void;\n\n /**\n * Gets the name of the node.\n */\n public abstract getName(): string;\n\n /**\n * Gets whether this node is a leaf node.\n */\n public abstract isLeafNode: () => this is Leaf;\n\n /**\n * Gets/Sets the state of the node.\n */\n getState = (): AnyState => this._state;\n setState = (value: AnyState): void => {\n // Grab the original state of this node.\n const previousState = this._state;\n\n // Set the new node state.\n this._state = value;\n\n // If the state actually changed we should handle it.\n if (previousState !== value) {\n this.onStateChanged(previousState);\n }\n };\n\n /**\n * Gets the unique id of the node.\n */\n getUid = () => this.uid;\n\n /**\n * Gets the type of the node.\n */\n getType = () => this.type;\n\n /**\n * Gets the node attributes.\n */\n getAttributes = () => Object.values(this.attributes).filter((attribute) => !!attribute);\n\n /**\n * Sets the guard path to evaluate as part of a node update.\n */\n setGuardPath = (value: GuardPath) => (this._guardPath = value);\n\n /**\n * Gets whether a guard path is assigned to this node.\n */\n hasGuardPath = () => !!this._guardPath;\n\n /**\n * Gets whether this node is in the specified state.\n * @param value The value to compare to the node state.\n */\n public is(value: AnyState): boolean {\n return this._state === value;\n }\n\n /**\n * Reset the state of the node.\n */\n public reset(): void {\n this.setState(State.READY);\n }\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n public abort(agent: Agent): void {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @returns The result of the update.\n */\n public update(agent: Agent): void {\n // If this node is already in a 'SUCCEEDED' or 'FAILED' state then there is nothing to do.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n return;\n }\n\n try {\n // Evaluate all of the guard path conditions for the current tree path.\n this._guardPath!.evaluate(agent);\n\n // If this node is in the READY state then call the ENTRY for this node if it exists.\n if (this.is(State.READY)) {\n this.attributes.entry?.callAgentFunction(agent);\n }\n\n this.attributes.step?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent);\n\n // If this node is now in a 'SUCCEEDED' or 'FAILED' state then call the EXIT for this node if it exists.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n this.attributes.exit?.callAgentFunction(agent, this.is(State.SUCCEEDED), false);\n }\n } catch (error) {\n // If the error is a GuardUnsatisfiedException then we need to determine if this node is the source.\n if (error instanceof GuardUnsatisifedException && error.isSourceNode(this)) {\n // Abort the current node.\n this.abort(agent);\n\n // Any node that is the source of an abort will be a failed node.\n this.setState(State.FAILED);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n id: this.uid,\n name: this.getName(),\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n state: this._state\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n // We should call the onNodeStateChange callback if it was defined.\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this._state\n });\n }\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A composite node that wraps child nodes.\n */\nexport default abstract class Composite extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => this.children;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of any child nodes.\n this.children.forEach((child) => child.reset());\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort any child nodes.\n this.children.forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: this.children.map((child) => child.getDetails())\n };\n }\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A PARALLEL node.\n * The child nodes are executed concurrently until one fails or all succeed.\n */\nexport default class Parallel extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"parallel\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have failed then this node has also failed.\n if (this.children.find((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A parallel node will move into the succeeded state if all child nodes move into the succeeded state.\n if (this.children.every((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RACE node.\n * The child nodes are executed concurrently until one succeeds or all fail.\n */\nexport default class Race extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"race\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have succeeded then this node has also succeeded.\n if (this.children.find((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A race node will move into the failed state if all child nodes move into the failed state as none can succeed.\n if (this.children.every((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"RACE\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * An ALL node.\n * The child nodes are executed concurrently until all child nodes move to a completed state.\n */\nexport default class All extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"all\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // An all node will move into a completed state if all child nodes move into a completed state.\n if (this.children.every((child) => child.is(State.SUCCEEDED) || child.is(State.FAILED))) {\n // If any of our child nodes have succeeded then this node has also succeeded, otherwise it has failed.\n this.setState(this.children.find((child) => child.is(State.SUCCEEDED)) ? State.SUCCEEDED : State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ALL\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SELECTOR node.\n * The child nodes are executed in sequence until one succeeds or all fail.\n */\nexport default class Selector extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"selector\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then this node is also a 'SUCCEEDED' node.\n if (child.getState() === State.SUCCEEDED) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the selector nodes.\n return;\n }\n\n // If the current child has a state of 'FAILED' then we should move on to the next child.\n if (child.getState() === State.FAILED) {\n // Find out if the current child is the last one in the selector.\n // If it is then this sequence node has also failed.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the selector as we have completed it.\n return;\n } else {\n // The child node failed, try the next one.\n continue;\n }\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the selector as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SELECTOR\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SEQUENCE node.\n * The child nodes are executed in sequence until one fails or all succeed.\n */\nexport default class Sequence extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"sequence\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then we should move on to the next child.\n if (child.getState() === State.SUCCEEDED) {\n // Find out if the current child is the last one in the sequence.\n // If it is then this sequence node has also succeeded.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the sequence as we have completed it.\n return;\n } else {\n // The child node succeeded, but we have not finished the sequence yet.\n continue;\n }\n }\n\n // If the current child has a state of 'FAILED' then this node is also a 'FAILED' node.\n if (child.getState() === State.FAILED) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the sequence.\n return;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the sequence as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SEQUENCE\";\n}\n", "import createLotto from \"lotto-draw\";\n\nimport Node from \"../Node\";\nimport Composite from \"./Composite\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A LOTTO node.\n * A winning child is picked on the initial update of this node, based on ticket weighting.\n * The state of this node will match the state of the winning child.\n */\nexport default class Lotto extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param weights The child node weights.\n * @param children The child nodes.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private weights: number[] | undefined,\n children: Node[]\n ) {\n super(\"lotto\", attributes, options, children);\n }\n\n /**\n * The child node selected to be the active one.\n */\n private selectedChild: Node | undefined;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to pick a winning child node.\n if (this.is(State.READY)) {\n // Create a lotto draw with which to randomly pick a child node to become the active one.\n const lottoDraw = createLotto({\n // Hook up the optional 'random' behaviour tree function option to the one used by 'lotto-draw'.\n random: this.options.random,\n // Pass in each child node as a participant in the lotto draw with their respective ticket count.\n participants: this.children.map((child, index) => [child, this.weights?.[index] || 1])\n });\n\n // Randomly pick a child based on ticket weighting, this will become the active child for this composite node.\n this.selectedChild = lottoDraw.draw() || undefined;\n }\n\n // If something went wrong and we don't have an active child then we should throw an error.\n if (!this.selectedChild) {\n throw new Error(\"failed to update lotto node as it has no active child\");\n }\n\n // If the selected child has never been updated or is running then we will need to update it now.\n if (this.selectedChild.getState() === State.READY || this.selectedChild.getState() === State.RUNNING) {\n this.selectedChild.update(agent);\n }\n\n // The state of the lotto node is the state of its selected child.\n this.setState(this.selectedChild.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => (this.weights ? `LOTTO [${this.weights.join(\",\")}]` : \"LOTTO\");\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A decorator node that wraps a single child node.\n */\nexport default abstract class Decorator extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected child: Node) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => [this.child];\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of the child node.\n this.child.reset();\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort the child node.\n this.child.abort(agent);\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: [this.child.getDetails()]\n };\n }\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Fail node.\n * This node wraps a single child and will always move to the 'FAILED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Fail extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"fail\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.FAILED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FAIL\";\n}\n", "import Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Flip node.\n * This node wraps a single child and will flip the state of the child state.\n */\nexport default class Flip extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"flip\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n this.setState(State.FAILED);\n break;\n\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FLIP\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A REPEAT node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The REPEAT node will stop and have a 'FAILED' state if its child is ever in a 'FAILED' state after an update.\n * The REPEAT node will attempt to move on to the next iteration if its child is ever in a 'SUCCEEDED' state.\n */\nexport default class Repeat extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param iterations The number of iterations to repeat the child node.\n * @param iterationsMin The minimum possible number of iterations to repeat the child node.\n * @param iterationsMax The maximum possible number of iterations to repeat the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, options, child);\n }\n\n /**\n * The number of target iterations to make.\n */\n private targetIterationCount: number | null = null;\n\n /**\n * The current iteration count.\n */\n private currentIterationCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target iteration count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the FAILED state when we updated it then there is nothing left to do and this node has also failed.\n // If it has moved into the SUCCEEDED state then we have completed the current iteration.\n if (this.child.getState() === State.FAILED) {\n // The child has failed, meaning that this node has failed.\n this.setState(State.FAILED);\n\n return;\n } else if (this.child.getState() === State.SUCCEEDED) {\n // We have completed an iteration.\n this.currentIterationCount += 1;\n }\n } else {\n // This node is in the 'SUCCEEDED' state as we cannot iterate any more.\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.iterations !== null) {\n return `REPEAT ${this.iterations}x`;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n return `REPEAT ${this.iterationsMin}x-${this.iterationsMax}x`;\n } else {\n return \"REPEAT\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with an explicit iteration count or will we be randomly picking a iteration count between the min and max iteration count.\n if (this.iterations !== null) {\n this.targetIterationCount = this.iterations;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n // We will be picking a random iteration count between a min and max iteration count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random iteration count between a min and max iteration count.\n this.targetIterationCount = Math.floor(\n random() * (this.iterationsMax - this.iterationsMin + 1) + this.iterationsMin\n );\n } else {\n this.targetIterationCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RETRY node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The RETRY node will stop and have a 'SUCCEEDED' state if its child is ever in a 'SUCCEEDED' state after an update.\n * The RETRY node will attempt to move on to the next iteration if its child is ever in a 'FAILED' state.\n */\nexport default class Retry extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param attempts The number of attempts to retry the child node.\n * @param attemptsMin The minimum possible number of attempts to retry the child node.\n * @param attemptsMax The maximum possible number of attempts to retry the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, options, child);\n }\n\n /**\n * The number of target attempts to make.\n */\n private targetAttemptCount: number | null = null;\n\n /**\n * The current attempt count.\n */\n private currentAttemptCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target attempt count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Set the target attempt count.\n this.setTargetAttemptCount();\n }\n\n // Do a check to see if we can attempt. If we can then this node will move into the 'RUNNING' state.\n // If we cannot attempt then we have hit our target attempt count, which means that the node has succeeded.\n if (this.canAttempt()) {\n // This node is in the running state and can do its initial attempt.\n this.setState(State.RUNNING);\n\n // We may have already completed an attempt, meaning that the child node will be in the FAILED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.FAILED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the SUCCEEDED state when we updated it then there is nothing left to do and this node has also succeeded.\n // If it has moved into the FAILED state then we have completed the current attempt.\n if (this.child.getState() === State.SUCCEEDED) {\n // The child has succeeded, meaning that this node has succeeded.\n this.setState(State.SUCCEEDED);\n\n return;\n } else if (this.child.getState() === State.FAILED) {\n // We have completed an attempt.\n this.currentAttemptCount += 1;\n }\n } else {\n // This node is in the 'FAILED' state as we cannot iterate any more.\n this.setState(State.FAILED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.attempts !== null) {\n return `RETRY ${this.attempts}x`;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n return `RETRY ${this.attemptsMin}x-${this.attemptsMax}x`;\n } else {\n return \"RETRY\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an attempt can be made.\n * @returns Whether an attempt can be made.\n */\n canAttempt = () => {\n if (this.targetAttemptCount !== null) {\n // We can attempt as long as we have not reached our target attempt count.\n return this.currentAttemptCount < this.targetAttemptCount;\n }\n\n // If neither an attempt count or a condition function were defined then we can attempt indefinitely.\n return true;\n };\n\n /**\n * Sets the target attempt count.\n */\n setTargetAttemptCount = () => {\n // Are we dealing with an explicit attempt count or will we be randomly picking an attempt count between the min and max attempt count.\n if (this.attempts !== null) {\n this.targetAttemptCount = this.attempts;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n // We will be picking a random attempt count between a min and max attempt count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random attempt count between a min and max attempt count.\n this.targetAttemptCount = Math.floor(\n random() * (this.attemptsMax - this.attemptsMin + 1) + this.attemptsMin\n );\n } else {\n this.targetAttemptCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Root node.\n * The root node will have a single child.\n */\nexport default class Root extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"root\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n // Update the child of this node.\n this.child.update(agent);\n }\n\n // The state of the root node is the state of its child.\n this.setState(this.child.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ROOT\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Succeed node.\n * This node wraps a single child and will always move to the 'SUCCEEDED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Succeed extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"succeed\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SUCCEED\";\n}\n", "import Node from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => true;\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State, { CompleteState } from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * The type representing a resolved/rejected update promise.\n */\ntype UpdatePromiseResult = {\n /**\n * Whether the promise was resolved rather than rejected.\n */\n isResolved: boolean;\n\n /**\n * The promise resolved value or rejection reason.\n */\n value: any;\n};\n\n/**\n * An Action leaf node.\n * This represents an immediate or ongoing state of behaviour.\n */\nexport default class Action extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param actionName The action name.\n * @param actionArguments The array of action arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private actionName: string,\n public actionArguments: any[]\n ) {\n super(\"action\", attributes, options);\n }\n\n /**\n * Whether there is a pending update promise.\n */\n private isUsingUpdatePromise = false;\n\n /**\n * The finished state result of an update promise.\n */\n private updatePromiseResult: UpdatePromiseResult | null = null;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the result of this action depends on an update promise then there is nothing to do until it settles.\n if (this.isUsingUpdatePromise) {\n // Are we still waiting for our update promise to settle?\n if (!this.updatePromiseResult) {\n return;\n }\n\n const { isResolved, value } = this.updatePromiseResult;\n\n // Our update promise settled, was it resolved or rejected?\n if (isResolved) {\n // Our promise resolved so check to make sure the result is a valid finished state.\n if (value !== State.SUCCEEDED && value !== State.FAILED) {\n throw new Error(\n \"action node promise resolved with an invalid value, expected a State.SUCCEEDED or State.FAILED value to be returned\"\n );\n }\n\n // Set the state of this node to match the state returned by the promise.\n this.setState(value);\n\n return;\n } else {\n // The promise was rejected, which isn't great.\n throw new Error(`action function '${this.actionName}' promise rejected with '${value}'`);\n }\n }\n\n // Attempt to get the invoker for the action function.\n const actionFuncInvoker = Lookup.getFuncInvoker(agent, this.actionName);\n\n // The action function should be defined.\n if (actionFuncInvoker === null) {\n throw new Error(\n `cannot update action node as the action '${this.actionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let actionFunctionResult;\n\n try {\n // Call the action function, the result of which may be:\n // - The finished state of this action node.\n // - A promise to return a finished node state.\n // - Undefined if the node should remain in the running state.\n actionFunctionResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`action function '${this.actionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`action function '${this.actionName}' threw: ${error}`);\n }\n }\n\n if (actionFunctionResult instanceof Promise) {\n actionFunctionResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the resolved update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: true,\n value: result\n };\n },\n (reason) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort or reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the rejected update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: false,\n value: reason\n };\n }\n );\n\n // This node will be in the 'RUNNING' state until the update promise resolves.\n this.setState(State.RUNNING);\n\n // We are now waiting for the promise returned by the use to resolve before we know what state this node is in.\n this.isUsingUpdatePromise = true;\n } else {\n // Validate the returned value.\n this.validateUpdateResult(actionFunctionResult);\n\n // Set the state of this node, this may be undefined, which just means that the node is still in the 'RUNNING' state.\n this.setState(actionFunctionResult || State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.actionName;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // There is no longer an update promise that we care about.\n this.isUsingUpdatePromise = false;\n this.updatePromiseResult = null;\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.actionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.actionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n\n /**\n * Validate the result of an update function call.\n * @param result The result of an update function call.\n */\n private validateUpdateResult = (result: CompleteState | State.RUNNING) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case State.RUNNING:\n case undefined:\n return;\n default:\n throw new Error(\n `expected action function '${this.actionName}' to return an optional State.SUCCEEDED or State.FAILED value but returned '${result}'`\n );\n }\n };\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * A Condition leaf node.\n * This will succeed or fail immediately based on an agent predicate, without moving to the 'RUNNING' state.\n */\nexport default class Condition extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param conditionName The name of the condition function.\n * @param conditionArguments The array of condition arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private conditionName: string,\n public conditionArguments: any[]\n ) {\n super(\"condition\", attributes, options);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.conditionName);\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot update condition node as the condition '${this.conditionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.conditionArguments);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`condition function '${this.conditionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`condition function '${this.conditionName}' threw: ${error}`);\n }\n }\n\n // The result of calling the condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected condition function '${this.conditionName}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Set the state of this node based on the result of calling the condition function.\n this.setState(!!conditionFunctionResult ? State.SUCCEEDED : State.FAILED);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.conditionName;\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.conditionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.conditionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { Agent } from \"../../Agent\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A WAIT node.\n * The state of this node will change to SUCCEEDED after a duration of time\n */\nexport default class Wait extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param duration The duration that this node will wait to succeed in milliseconds.\n * @param durationMin The minimum possible duration in milliseconds that this node will wait to succeed.\n * @param durationMax The maximum possible duration in milliseconds that this node will wait to succeed.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, options);\n }\n\n /**\n * The time in milliseconds at which this node was first updated.\n */\n private initialUpdateTime: number = 0;\n\n /**\n * The total duration in milliseconds that this node will be waiting for.\n */\n private totalDuration: number | null = null;\n\n /**\n * The duration in milliseconds that this node has been waiting for.\n */\n private waitedDuration: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to set the initial update time.\n if (this.is(State.READY)) {\n // Set the initial update time.\n this.initialUpdateTime = new Date().getTime();\n\n // Set the initial waited duration.\n this.waitedDuration = 0;\n\n // Are we dealing with an explicit duration or will we be randomly picking a duration between the min and max duration.\n if (this.duration !== null) {\n this.totalDuration = this.duration;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // We will be picking a random duration between a min and max duration, if the optional 'random' behaviour tree\n // function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random duration between a min and max duration.\n this.totalDuration = Math.floor(\n random() * (this.durationMax - this.durationMin + 1) + this.durationMin\n );\n } else {\n this.totalDuration = null;\n }\n\n // The node is now running until we finish waiting.\n this.setState(State.RUNNING);\n }\n\n // If we have no total duration then this wait node will wait indefinitely until it is aborted.\n if (this.totalDuration === null) {\n return;\n }\n\n // If we have a 'getDeltaTime' function defined as part of our options then we will use it to figure out how long we have waited for.\n if (typeof this.options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = this.options.getDeltaTime();\n\n // Our delta time must be a valid number and cannot be NaN.\n if (typeof deltaTime !== \"number\" || isNaN(deltaTime)) {\n throw new Error(\"The delta time must be a valid number and not NaN.\");\n }\n\n // Update the amount of time that this node has been waiting for based on the delta time.\n this.waitedDuration += deltaTime * 1000;\n } else {\n // We are not using a delta time, so we will just work out hom much time has passed since the first update.\n this.waitedDuration = new Date().getTime() - this.initialUpdateTime;\n }\n\n // Have we waited long enough?\n if (this.waitedDuration >= this.totalDuration) {\n // We have finished waiting!\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.duration !== null) {\n return `WAIT ${this.duration}ms`;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n return `WAIT ${this.durationMin}ms-${this.durationMax}ms`;\n } else {\n return \"WAIT\";\n }\n };\n}\n", "import Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: any[];\n};\n\n/**\n * A base node attribute.\n */\nexport default abstract class Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of attribute arguments.\n */\n constructor(public type: string, public args: any[]) {}\n\n /**\n * Gets the attribute details.\n */\n abstract getDetails(): TAttributeDetails;\n\n /**\n * Gets whether this attribute is a guard.\n */\n abstract isGuard: () => this is Guard;\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node guard attribute.\n */\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node guard attribute.\n */\nexport default abstract class Guard extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n */\n constructor(type: string, args: any[], private condition: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the condition function that determines whether the guard is satisfied.\n */\n getCondition = () => this.condition;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => true;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): GuardAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getCondition()\n };\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n abstract isSatisfied(agent: Agent): boolean;\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A WHILE guard which is satisfied as long as the given condition remains true.\n */\nexport default class While extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"while\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return conditionFunctionResult;\n };\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An UNTIL guard which is satisfied as long as the given condition remains false.\n */\nexport default class Until extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"until\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return !conditionFunctionResult;\n };\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node callback attribute.\n */\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node callback attribute.\n */\nexport default abstract class Callback extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param functionName The name of the agent function to call.\n */\n constructor(type: string, args: any[], private functionName: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the agent function to call.\n */\n getFunctionName = () => this.functionName;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => false;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): CallbackAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getFunctionName()\n };\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n abstract callAgentFunction: (agent: Agent, isSuccess: boolean, isAborted: boolean) => void;\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An ENTRY callback which defines an agent function to call when the associated node is updated and moves out of running state.\n */\nexport default class Entry extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"entry\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call entry function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A STEP callback which defines an agent function to call when the associated node is updated.\n */\nexport default class Step extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"step\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call step function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An EXIT callback which defines an agent function to call when the associated node is updated and moves to a finished state or is aborted.\n */\nexport default class Exit extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"exit\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n * @param isSuccess Whether the decorated node was left with a success state.\n * @param isAborted Whether the decorated node was aborted.\n */\n callAgentFunction = (agent: Agent, isSuccess: boolean, isAborted: boolean) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call exit function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function\n callbackFuncInvoker([{ succeeded: isSuccess, aborted: isAborted }, ...this.args]);\n };\n}\n", "import { AnyNodeDefinition, RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport { validateBranchSubtreeLinks } from \"./BehaviourTreeDefinitionValidator\";\nimport { isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport Node from \"./nodes/Node\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Race from \"./nodes/composite/Race\";\nimport All from \"./nodes/composite/All\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Root from \"./nodes/decorator/Root\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Lookup from \"./Lookup\";\nimport Attribute from \"./attributes/Attribute\";\nimport Guard from \"./attributes/guards/Guard\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\n/**\n * A type representing any node instance in a behaviour tree.\n */\ntype AnyNode =\n | Root\n | Action\n | Condition\n | Wait\n | Sequence\n | Selector\n | Lotto\n | Parallel\n | Race\n | All\n | Repeat\n | Retry\n | Flip\n | Succeed\n | Fail;\n\n/**\n * A type defining a mapping of root node identifiers to root node definitions.\n */\ntype RootNodeDefinitionMap = { [key: string | symbol]: RootNodeDefinition };\n\n/**\n * A symbol to use as the main root key in any root node mappings.\n */\nconst MAIN_ROOT_NODE_KEY = Symbol(\"__root__\");\n\n/**\n * Build and populate the root nodes based on the provided definition, assuming that the definition has been validated.\n * @param definition The root node definitions.\n * @param options The behaviour tree options.\n * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[], options: BehaviourTreeOptions): Root {\n // Create a mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n const rootNodeDefinitionMap = createRootNodeDefinitionMap(definition);\n\n // Now that we have all of our root node definitions (those part of the tree definition and those globally registered)\n // we should validate the branch-subtree links. This will also double-check that we dont have any circular dependencies\n // in our branch-subtree references and that we have no broken branch-subtree links.\n validateBranchSubtreeLinks(\n [rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], ...Object.values(rootNodeDefinitionMap)],\n true\n );\n\n // Create our populated tree of node instances, starting with our main root node.\n const rootNode = nodeFactory(rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], rootNodeDefinitionMap, options) as Root;\n\n // Set a guard path on every leaf of the tree to evaluate as part of each update.\n applyLeafNodeGuardPaths(rootNode);\n\n // We only need to return the main root node.\n return rootNode;\n}\n\n/**\n * A factory function which creates a node instance based on the specified definition.\n * @param definition The node definition.\n * @param rootNodeDefinitionMap The mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n * @param options The behaviour tree options.\n * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(\n definition: AnyNodeDefinition,\n rootNodeDefinitionMap: RootNodeDefinitionMap,\n options: BehaviourTreeOptions\n): AnyNode {\n // Get the attributes for the node.\n const attributes = nodeAttributesFactory(definition);\n\n // Create the node instance based on the definition type.\n switch (definition.type) {\n case \"root\":\n return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"repeat\":\n let iterations: number | null = null;\n let iterationsMin: number | null = null;\n let iterationsMax: number | null = null;\n\n if (Array.isArray(definition.iterations)) {\n iterationsMin = definition.iterations[0];\n iterationsMax = definition.iterations[1];\n } else if (isInteger(definition.iterations)) {\n iterations = definition.iterations!;\n }\n\n return new Repeat(\n attributes,\n options,\n iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"retry\":\n let attempts: number | null = null;\n let attemptsMin: number | null = null;\n let attemptsMax: number | null = null;\n\n if (Array.isArray(definition.attempts)) {\n attemptsMin = definition.attempts[0];\n attemptsMax = definition.attempts[1];\n } else if (isInteger(definition.attempts)) {\n attempts = definition.attempts!;\n }\n\n return new Retry(\n attributes,\n options,\n attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"flip\":\n return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"succeed\":\n return new Succeed(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"fail\":\n return new Fail(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"race\":\n return new Race(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"all\":\n return new All(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n options,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap, options);\n\n case \"action\":\n return new Action(attributes, options, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, options, definition.call, definition.args || []);\n\n case \"wait\":\n let duration: number | null = null;\n let durationMin: number | null = null;\n let durationMax: number | null = null;\n\n if (Array.isArray(definition.duration)) {\n durationMin = definition.duration[0];\n durationMax = definition.duration[1];\n } else if (isInteger(definition.duration)) {\n duration = definition.duration!;\n }\n\n return new Wait(attributes, options, duration, durationMin, durationMax);\n }\n}\n\n/**\n * Creates an array of node attribute instances based on the specified node definition.\n * @param definition The node definition.\n * @returns An array of node attribute instances based on the specified node definition.\n */\nfunction nodeAttributesFactory(definition: AnyNodeDefinition): Attribute[] {\n const attributes: Attribute[] = [];\n\n if (definition.while) {\n attributes.push(new While(definition.while.call, definition.while.args ?? []));\n }\n\n if (definition.until) {\n attributes.push(new Until(definition.until.call, definition.until.args ?? []));\n }\n\n if (definition.entry) {\n attributes.push(new Entry(definition.entry.call, definition.entry.args ?? []));\n }\n\n if (definition.step) {\n attributes.push(new Step(definition.step.call, definition.step.args ?? []));\n }\n\n if (definition.exit) {\n attributes.push(new Exit(definition.exit.call, definition.exit.args ?? []));\n }\n\n return attributes;\n}\n\n/**\n * Creates a mapping of root node identifers to root node definitions, mixing in globally registered subtree root node definitions.\n * @param definition The root node definitions.\n * @returns A mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n */\nfunction createRootNodeDefinitionMap(definition: RootNodeDefinition[]): RootNodeDefinitionMap {\n // Create a mapping of root node identifers to root node definitions.\n const rootNodeMap: RootNodeDefinitionMap = {};\n\n // Add in any registered subtree root node definitions.\n for (const [name, rootNodeDefinition] of Object.entries(Lookup.getSubtrees())) {\n // The name used when registering the subtree will be used as the root node identifier.\n rootNodeMap[name] = { ...rootNodeDefinition, id: name };\n }\n\n // Populate the map with the root node definitions that were included with the tree definition.\n // We do this after adding any registered subtrees as we want these to take presedence.\n for (const rootNodeDefinition of definition) {\n rootNodeMap[rootNodeDefinition.id ?? MAIN_ROOT_NODE_KEY] = rootNodeDefinition;\n }\n\n return rootNodeMap;\n}\n\n/**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param root The main root tree node.\n */\nfunction applyLeafNodeGuardPaths(root: Root) {\n const nodePaths: Node[][] = [];\n\n const findLeafNodes = (path: Node[], node: Node) => {\n // Add the current node to the path.\n path = path.concat(node);\n\n // Check whether the current node is a leaf node.\n if (node.isLeafNode()) {\n nodePaths.push(path);\n } else {\n (node as Composite | Decorator).getChildren().forEach((child) => findLeafNodes(path, child));\n }\n };\n\n // Find all leaf node paths, starting from the root.\n findLeafNodes([], root);\n\n nodePaths.forEach((path) => {\n // Each node in the current path will have to be assigned a guard path, working from the root outwards.\n for (let depth = 0; depth < path.length; depth++) {\n // Get the node in the path at the current depth.\n const currentNode = path[depth];\n\n // The node may already have been assigned a guard path, if so just skip it.\n if (currentNode.hasGuardPath()) {\n continue;\n }\n\n // Create the guard path for the current node.\n const guardPath = new GuardPath(\n path\n .slice(0, depth + 1)\n .map((node) => ({\n node,\n guards: node.getAttributes().filter((attribute) => attribute.isGuard()) as Guard[]\n }))\n .filter((details) => details.guards.length > 0)\n );\n\n // Assign the guard path to the current node.\n currentNode.setGuardPath(guardPath);\n }\n });\n}\n", "import State, { AnyState } from \"./State\";\nimport Lookup from \"./Lookup\";\nimport Node, { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport { Agent, GlobalFunction } from \"./Agent\";\nimport { CallbackAttributeDetails } from \"./attributes/callbacks/Callback\";\nimport { GuardAttributeDetails } from \"./attributes/guards/Guard\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { validateDefinition, validateJSONDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport buildRootNode from \"./BehaviourTreeBuilder\";\nimport { isNullOrUndefined } from \"./BehaviourTreeDefinitionUtilities\";\n\n/**\n * A representation of a behaviour tree.\n */\nexport class BehaviourTree {\n /**\n * The main root tree node.\n */\n private readonly _rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition as either an MDSL string, root node definition object or array of root node definition objects.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param options The behaviour tree options object.\n */\n constructor(\n definition: string | RootNodeDefinition | RootNodeDefinition[],\n private agent: Agent,\n private options: BehaviourTreeOptions = {}\n ) {\n // The tree definition must be defined.\n if (isNullOrUndefined(definition)) {\n throw new Error(\"tree definition not defined\");\n }\n\n // The agent must be defined and not null.\n if (typeof agent !== \"object\" || agent === null) {\n throw new Error(\"the agent must be an object and not null\");\n }\n\n // We should validate the definition before we try to build the tree nodes.\n const { succeeded, errorMessage, json } = validateDefinition(definition);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(`invalid definition: ${errorMessage}`);\n }\n\n // Double check that we did actually get our json definition as part of our definition validtion.\n if (!json) {\n throw new Error(\n \"expected json definition to be returned as part of successful definition validation response\"\n );\n }\n\n try {\n // Create the populated tree of behaviour tree nodes and get the root node.\n this._rootNode = buildRootNode(json, options);\n } catch (exception) {\n // There was an issue in trying build and populate the behaviour tree.\n throw new Error(`error building tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Gets whether the tree is in the RUNNING state.\n * @returns true if the tree is in the RUNNING state, otherwise false.\n */\n public isRunning(): boolean {\n return this._rootNode.getState() === State.RUNNING;\n }\n\n /**\n * Gets the current tree state of SUCCEEDED, FAILED, READY or RUNNING.\n * @returns The current tree state.\n */\n public getState(): State {\n return this._rootNode.getState();\n }\n\n /**\n * Step the tree.\n * 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.\n * 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\n * 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.\n *\n * 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.\n */\n public step(): void {\n // If the root node has already been stepped to completion then we need to reset it.\n if (this._rootNode.getState() === State.SUCCEEDED || this._rootNode.getState() === State.FAILED) {\n this._rootNode.reset();\n }\n\n try {\n this._rootNode.update(this.agent);\n } catch (exception) {\n throw new Error(`error stepping tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Resets the tree from the root node outwards to each nested node, giving each a state of READY.\n */\n public reset(): void {\n this._rootNode.reset();\n }\n\n /**\n * Gets the details of every node in the tree, starting from the root.\n * @returns The details of every node in the tree, starting from the root.\n */\n public getTreeNodeDetails(): NodeDetails {\n return this._rootNode.getDetails();\n }\n\n /**\n * Registers the action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the function or subtree to register.\n * @param value The function or subtree definition to register.\n */\n static register(name: string, value: GlobalFunction | string | RootNodeDefinition) {\n // Are we going to register a action/condition/guard/callback function?\n if (typeof value === \"function\") {\n Lookup.setFunc(name, value);\n return;\n }\n\n // We are not registering an action/condition/guard/callback function, so we must be registering a subtree.\n if (typeof value === \"string\") {\n let rootNodeDefinitions: RootNodeDefinition[];\n\n // We will assume that any string passed in will be a mdsl definition.\n try {\n rootNodeDefinitions = convertMDSLToJSON(value);\n } catch (exception) {\n throw new Error(`error registering definition, invalid MDSL: ${(exception as Error).message}`);\n }\n\n // This function should only ever be called with a definition containing a single unnamed root node.\n if (rootNodeDefinitions.length != 1 || typeof rootNodeDefinitions[0].id !== \"undefined\") {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(rootNodeDefinitions[0]);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, rootNodeDefinitions[0]);\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // We will assume that any object passed in is a root node definition.\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(value);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, value);\n } else {\n throw new Error(\"unexpected value, expected string mdsl definition, root node json definition or function\");\n }\n }\n\n /**\n * Unregisters the registered action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the registered action/condition/guard/callback function or subtree to unregister.\n */\n static unregister(name: string): void {\n Lookup.remove(name);\n }\n\n /**\n * Unregister all registered action/condition/guard/callback functions and subtrees.\n */\n static unregisterAll(): void {\n Lookup.empty();\n }\n}\n"], + "mappings": "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", "names": ["Participant", "isNullOrUndefined", "Lotto", "createLotto", "State", "type", "createLotto"] } diff --git a/dist/mistreevous.js b/dist/mistreevous.js index c1423e8..66a10eb 100644 --- a/dist/mistreevous.js +++ b/dist/mistreevous.js @@ -317,7 +317,7 @@ var mistreevous = (() => { return ["root", "repeat", "retry", "flip", "succeed", "fail"].includes(node.type); } function isCompositeNode(node) { - return ["sequence", "selector", "lotto", "parallel", "race"].includes(node.type); + return ["sequence", "selector", "lotto", "parallel", "race", "all"].includes(node.type); } function flattenDefinition(nodeDefinition) { const nodes = []; @@ -563,6 +563,10 @@ var mistreevous = (() => { pushNode(createRaceNode(tokens, stringLiteralPlaceholders)); break; } + case "ALL": { + pushNode(createAllNode(tokens, stringLiteralPlaceholders)); + break; + } case "LOTTO": { pushNode(createLottoNode(tokens, stringLiteralPlaceholders)); break; @@ -729,6 +733,14 @@ var mistreevous = (() => { popAndCheck(tokens, "{"); return node; } + function createAllNode(tokens, stringLiteralPlaceholders) { + const node = { + type: "all", + ...parseAttributeTokens(tokens, stringLiteralPlaceholders) + }; + popAndCheck(tokens, "{"); + return node; + } function createLottoNode(tokens, stringLiteralPlaceholders) { const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders); nodeArguments.filter((arg) => arg.type !== "number" || !arg.isInteger || arg.value < 0).forEach(() => { @@ -987,6 +999,9 @@ var mistreevous = (() => { case "race": validateRaceNode(definition, depth); break; + case "all": + validateAllNode(definition, depth); + break; case "lotto": validateLottoNode(definition, depth); break; @@ -1265,6 +1280,16 @@ var mistreevous = (() => { validateNodeAttributes(definition, depth); definition.children.forEach((child) => validateNode(child, depth + 1)); } + function validateAllNode(definition, depth) { + if (definition.type !== "all") { + throw new Error(`expected node type of 'all' for all node at depth '${depth}'`); + } + if (!Array.isArray(definition.children) || definition.children.length === 0) { + throw new Error(`expected non-empty 'children' array to be defined for all node at depth '${depth}'`); + } + validateNodeAttributes(definition, depth); + definition.children.forEach((child) => validateNode(child, depth + 1)); + } function validateLottoNode(definition, depth) { if (definition.type !== "lotto") { throw new Error(`expected node type of 'lotto' for lotto node at depth '${depth}'`); @@ -1500,6 +1525,26 @@ var mistreevous = (() => { getName = () => "RACE"; }; + // src/nodes/composite/All.ts + var All = class extends Composite { + constructor(attributes, options, children) { + super("all", attributes, options, children); + } + onUpdate(agent) { + for (const child of this.children) { + if (child.getState() === "mistreevous.ready" /* READY */ || child.getState() === "mistreevous.running" /* RUNNING */) { + child.update(agent); + } + } + if (this.children.every((child) => child.is("mistreevous.succeeded" /* SUCCEEDED */) || child.is("mistreevous.failed" /* FAILED */))) { + this.setState(this.children.find((child) => child.is("mistreevous.succeeded" /* SUCCEEDED */)) ? "mistreevous.succeeded" /* SUCCEEDED */ : "mistreevous.failed" /* FAILED */); + return; + } + this.setState("mistreevous.running" /* RUNNING */); + } + getName = () => "ALL"; + }; + // src/nodes/composite/Selector.ts var Selector = class extends Composite { constructor(attributes, options, children) { @@ -2301,6 +2346,12 @@ var mistreevous = (() => { options, definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options)) ); + case "all": + return new All( + attributes, + options, + definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options)) + ); case "lotto": return new Lotto( attributes, diff --git a/dist/mistreevous.js.map b/dist/mistreevous.js.map index f201499..e8a3fd9 100644 --- a/dist/mistreevous.js.map +++ b/dist/mistreevous.js.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../node_modules/lotto-draw/dist/Participant.js", "../node_modules/lotto-draw/dist/Utilities.js", "../node_modules/lotto-draw/dist/Lotto.js", "../node_modules/lotto-draw/dist/createLotto.js", "../node_modules/lotto-draw/dist/index.js", "../src/index.ts", "../src/State.ts", "../src/Lookup.ts", "../src/BehaviourTreeDefinitionUtilities.ts", "../src/mdsl/MDSLUtilities.ts", "../src/mdsl/MDSLNodeArgumentParser.ts", "../src/mdsl/MDSLNodeAttributeParser.ts", "../src/mdsl/MDSLDefinitionParser.ts", "../src/BehaviourTreeDefinitionValidator.ts", "../src/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/Utilities.ts", "../src/nodes/Node.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Parallel.ts", "../src/nodes/composite/Race.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/leaf/Leaf.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/attributes/Attribute.ts", "../src/attributes/guards/Guard.ts", "../src/attributes/guards/While.ts", "../src/attributes/guards/Until.ts", "../src/attributes/callbacks/Callback.ts", "../src/attributes/callbacks/Entry.ts", "../src/attributes/callbacks/Step.ts", "../src/attributes/callbacks/Exit.ts", "../src/BehaviourTreeBuilder.ts", "../src/BehaviourTree.ts"], - "sourcesContent": ["\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Participant = void 0;\r\n/**\r\n * A participant that holds a number of tickets.\r\n */\r\nvar Participant = /** @class */ (function () {\r\n /**\r\n * Creates an instance of the Participant class.\r\n * @param participant The actual participant.\r\n * @param tickets The number of tickets held by the participant.\r\n */\r\n function Participant(participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n this._participant = participant;\r\n this._tickets = tickets;\r\n }\r\n Object.defineProperty(Participant.prototype, \"participant\", {\r\n /** Gets the actual participant. */\r\n get: function () {\r\n return this._participant;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(Participant.prototype, \"tickets\", {\r\n /** Gets or sets the number of tickets held by the participant. */\r\n get: function () {\r\n return this._tickets;\r\n },\r\n set: function (value) {\r\n this._tickets = value;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n return Participant;\r\n}());\r\nexports.Participant = Participant;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.isNaturalNumber = exports.isNullOrUndefined = void 0;\r\n/**\r\n * Gets whether the value provided is null or undefined.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is null or undefined.\r\n */\r\nfunction isNullOrUndefined(value) {\r\n return value === null || value === undefined;\r\n}\r\nexports.isNullOrUndefined = isNullOrUndefined;\r\n/**\r\n * Gets whether the value provided is a natural number.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is a natural number.\r\n */\r\nfunction isNaturalNumber(value) {\r\n return typeof value === \"number\" && value >= 1 && Math.floor(value) === value;\r\n}\r\nexports.isNaturalNumber = isNaturalNumber;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Lotto = void 0;\r\nvar Participant_1 = require(\"./Participant\");\r\nvar Utilities_1 = require(\"./Utilities\");\r\n/**\r\n * Represents a lotto consisting of a number of pickable ticket-holding participants.\r\n */\r\nvar Lotto = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of Lotto.\r\n * @param customRandom The custom RNG to use in place of Math.random().\r\n */\r\n function Lotto(customRandom) {\r\n /** The array of participants that are holding tickets in the lotto. */\r\n this._participants = [];\r\n this._customRandom = customRandom;\r\n }\r\n /**\r\n * Adds a participant with the specified number of tickets, or adds to the participant ticket count if the participant already holds tickets.\r\n * @param participant The participant to add or to increase the ticket count for if they already hold tickets.\r\n * @param tickets The number of tickets, defaults to 1.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.add = function (participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n // Check whether this participant has already been added.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n if (existingParticipant) {\r\n // The participant has already been added to the lotto so just add to their ticket count.\r\n existingParticipant.tickets += tickets;\r\n }\r\n else {\r\n // The participant is not part of the lotto so we should add them.\r\n this._participants.push(new Participant_1.Participant(participant, tickets));\r\n }\r\n return this;\r\n };\r\n /**\r\n * Removes the specified number of tickets for the given participant from the draw, or all tickets if a ticket number is not defined.\r\n * @param participant The participant to remove tickets for.\r\n * @param tickets The number of tickets to remove, or undefined if all tickets are to be removed.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.remove = function (participant, tickets) {\r\n // Attempt to get the existing participant.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n // There is nothing to do if the specified participant isn't even part of the lotto.\r\n if (!existingParticipant) {\r\n return this;\r\n }\r\n // Check whether a tickets value was given.\r\n if (tickets !== undefined) {\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n existingParticipant.tickets -= tickets;\r\n // If the participant no longer holds any tickets then they should be removed.\r\n if (existingParticipant.tickets < 1) {\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n }\r\n else {\r\n // We are removing all tickets for the participant so just remove them from the lotto.\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n return this;\r\n };\r\n /**\r\n * Draw a winning ticket and return the participant that holds the ticket.\r\n * @param options The draw options.\r\n * @returns The participant that holds the winning ticket.\r\n */\r\n Lotto.prototype.draw = function (options) {\r\n if (options === void 0) { options = {}; }\r\n // If we have no participants then just return null.\r\n if (this._participants.length === 0) {\r\n return null;\r\n }\r\n var redrawable = (0, Utilities_1.isNullOrUndefined)(options.redrawable) ? true : options.redrawable;\r\n var pickable = [];\r\n this._participants.forEach(function (_a) {\r\n var participant = _a.participant, tickets = _a.tickets;\r\n for (var ticketCount = 0; ticketCount < tickets; ticketCount++) {\r\n pickable.push(participant);\r\n }\r\n });\r\n var random;\r\n // We need a random floating-point number between 0 (inclusive) and 1 to scale up to pick our winner.\r\n // If a custom random function exists then we should use that or fall back to Math.random().\r\n if (this._customRandom) {\r\n // Call our custom random function to get a random floating-point number.\r\n random = this._customRandom();\r\n // Verify that the result of calling our custom random function is a number between 0 (inclusive) and 1.\r\n if (typeof random !== \"number\" || random < 0 || random >= 1) {\r\n throw new Error(\"the 'random' function provided did not return a number between 0 (inclusive) and 1\");\r\n }\r\n }\r\n else {\r\n // No custom random function was defined so just use good ol' Math.random().\r\n random = Math.random();\r\n }\r\n // Pick a winning participant.\r\n var winner = pickable[Math.floor(random * pickable.length)];\r\n // If the ticket isn't redrawable then we should remove a ticket from the winning participants ticket count.\r\n if (!redrawable) {\r\n this.remove(winner, 1);\r\n }\r\n // Return the winning participant.\r\n return winner;\r\n };\r\n /**\r\n * Draws multiple winning tickets and return an array of the participants that hold the winning tickets.\r\n * @param tickets The number of winning tickets to draw.\r\n * @param options The draw multiple options.\r\n * @returns An array of the participants that hold the winning tickets.\r\n */\r\n Lotto.prototype.drawMultiple = function (tickets, options) {\r\n if (options === void 0) { options = {}; }\r\n var uniqueResults = (0, Utilities_1.isNullOrUndefined)(options.unique) ? false : options.unique;\r\n // Handle cases where the user has asked for zero tickets (no idea why they would do this be we should trust them).\r\n if (tickets === 0) {\r\n return [];\r\n }\r\n // Now that we know out tickets value is not zero we should check that it is a valid natural number.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n var result = [];\r\n // Keep drawing tickets until we either reach the number of required tickets or we simply run out of tickets to draw.\r\n // We can run out of tickets to draw if 'options.redrawable' is explicity 'false' or we just had no participants when 'drawMultiple' was called.\r\n while (result.length < tickets && this._participants.length > 0) {\r\n result.push(this.draw(options));\r\n }\r\n // If the 'unique' draw option is set then we need to remove duplicates from the result list.\r\n if (uniqueResults) {\r\n // Create an array to store our unique results.\r\n var unique = [];\r\n // Iterate over all of our participants (with potential duplicates) and populate our array of unique values.\r\n for (var _i = 0, result_1 = result; _i < result_1.length; _i++) {\r\n var participant = result_1[_i];\r\n if (unique.indexOf(participant) === -1) {\r\n unique.push(participant);\r\n }\r\n }\r\n result = unique;\r\n }\r\n return result;\r\n };\r\n return Lotto;\r\n}());\r\nexports.Lotto = Lotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.createLotto = void 0;\r\nvar Lotto_1 = require(\"./Lotto\");\r\n/**\r\n * A function that creates and returns a Lotto instance.\r\n * @param participantsOrOptions An array of initial participants or options relating to the creation of a Lotto instance.\r\n * @returns A new Lotto instance.\r\n */\r\nfunction createLotto(participantsOrOptions) {\r\n // If no initial participants or lotto options were provided as an argument then we can just return a new lotto instance now.\r\n if (!participantsOrOptions) {\r\n return new Lotto_1.Lotto();\r\n }\r\n // Check whether we were provided with an array of initial participants or a lotto options object.\r\n if (Array.isArray(participantsOrOptions)) {\r\n // We are dealing with a pre-defined array of participants.\r\n var participants = participantsOrOptions;\r\n var lotto_1 = new Lotto_1.Lotto();\r\n // If the lotto participants have been defined upfront then we will need to add them all to our lotto instance now.\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_1.add(participant, tokens);\r\n });\r\n // Return the Lotto instance.\r\n return lotto_1;\r\n }\r\n else {\r\n // We are dealing with some lotto options.\r\n var random = participantsOrOptions.random, participants = participantsOrOptions.participants;\r\n // Create a Lotto instance passing the custom RNG function to use in place of Math.random() (which could be undefined).\r\n var lotto_2 = new Lotto_1.Lotto(random);\r\n // If the lotto participants have been defined upfront as part of the options then we will need to add them all to our lotto instance now.\r\n if (participants) {\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_2.add(participant, tokens);\r\n });\r\n }\r\n // Return the Lotto instance.\r\n return lotto_2;\r\n }\r\n}\r\nexports.createLotto = createLotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar createLotto_1 = require(\"./createLotto\");\r\nexports.default = createLotto_1.createLotto;\r\n", "import State from \"./State\";\nimport { BehaviourTree } from \"./BehaviourTree\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { NodeDetails, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n /**\n * The state that a node will be in when it has not been visited yet in the execution of the tree.\n */\n READY = \"mistreevous.ready\",\n /**\n * The state that a node will be in when it is still being processed and will usually represent or encompass a long-running action.\n */\n RUNNING = \"mistreevous.running\",\n /**\n * The state that a node will be in when it is no longer being processed and has succeeded.\n */\n SUCCEEDED = \"mistreevous.succeeded\",\n /**\n * The state that a node will be in when it is no longer being processed but has failed.\n */\n FAILED = \"mistreevous.failed\"\n}\n\nexport { State as default };\n\nexport type CompleteState = State.SUCCEEDED | State.FAILED;\nexport type AnyState = State.READY | State.RUNNING | CompleteState;\n", "import { ActionResult, Agent, GlobalFunction } from \"./Agent\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\n\nexport type InvokerFunction = (args: any[]) => ActionResult | boolean;\n\n/**\n * A singleton used to store and lookup registered functions and subtrees.\n */\nexport default class Lookup {\n /**\n * The object holding any registered functions keyed on function name.\n */\n private static registeredFunctions: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered subtree root node definitions keyed on tree name.\n */\n private static registeredSubtrees: { [key: string]: RootNodeDefinition } = {};\n\n /**\n * Gets the function with the specified name.\n * @param name The name of the function.\n * @returns The function with the specified name.\n */\n public static getFunc(name: string): GlobalFunction {\n return this.registeredFunctions[name];\n }\n\n /**\n * Sets the function with the specified name for later lookup.\n * @param name The name of the function.\n * @param func The function.\n */\n public static setFunc(name: string, func: GlobalFunction): void {\n this.registeredFunctions[name] = func;\n }\n\n /**\n * Gets the function invoker for the specified agent and function name.\n * If a function with the specified name exists on the agent object then it will\n * be returned, otherwise we will then check the registered functions for a match.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param name The function name.\n * @returns The function invoker for the specified agent and function name.\n */\n static getFuncInvoker(agent: Agent, name: string): InvokerFunction | null {\n // Check whether the agent contains the specified function.\n const agentFunction = agent[name];\n if (agentFunction && typeof agentFunction === \"function\") {\n return (args: any[]) => agentFunction.apply(agent, args);\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.registeredFunctions[name] && typeof this.registeredFunctions[name] === \"function\") {\n const registeredFunction = this.registeredFunctions[name];\n return (args: any[]) => registeredFunction(agent, ...args);\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets all registered subtree root node definitions.\n */\n static getSubtrees(): { [key: string]: RootNodeDefinition } {\n return this.registeredSubtrees;\n }\n\n /**\n * Sets the subtree with the specified name for later lookup.\n * @param name The name of the subtree.\n * @param subtree The subtree.\n */\n static setSubtree(name: string, subtree: RootNodeDefinition) {\n this.registeredSubtrees[name] = subtree;\n }\n\n /**\n * Removes the registered function or subtree with the specified name.\n * @param name The name of the registered function or subtree.\n */\n static remove(name: string) {\n delete this.registeredFunctions[name];\n delete this.registeredSubtrees[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.registeredFunctions = {};\n this.registeredSubtrees = {};\n }\n}\n", "import {\n NodeDefinition,\n RootNodeDefinition,\n DecoratorNodeDefinition,\n CompositeNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition\n} from \"./BehaviourTreeDefinition\";\n\n/**\n * A type guard function that returns true if the specified node satisfies the RootNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the RootNodeDefinition type.\n */\nexport function isRootNode(node: NodeDefinition): node is RootNodeDefinition {\n return node.type === \"root\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the BranchNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the BranchNodeDefinition type.\n */\nexport function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition {\n return node.type === \"branch\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the NodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the NodeDefinition type.\n */\nexport function isLeafNode(node: NodeDefinition): node is NodeDefinition {\n return [\"branch\", \"action\", \"condition\", \"wait\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the DecoratorNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the DecoratorNodeDefinition type.\n */\nexport function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefinition {\n return [\"root\", \"repeat\", \"retry\", \"flip\", \"succeed\", \"fail\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the CompositeNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type.\n */\nexport function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition {\n return [\"sequence\", \"selector\", \"lotto\", \"parallel\", \"race\"].includes(node.type);\n}\n\n/**\n * Flatten a node definition into an array of all of its nested node definitions.\n * @param nodeDefinition The node definition to flatten.\n * @returns An array of all of nested node definitions.\n */\nexport function flattenDefinition(nodeDefinition: AnyNodeDefinition): AnyNodeDefinition[] {\n const nodes: AnyNodeDefinition[] = [];\n\n const processNode = (currentNodeDefinition: AnyNodeDefinition) => {\n nodes.push(currentNodeDefinition);\n\n if (isCompositeNode(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNode(currentNodeDefinition)) {\n processNode(currentNodeDefinition.child);\n }\n };\n\n processNode(nodeDefinition);\n\n return nodes;\n}\n\n/**\n * Determines whether the passed value is an integer.\n * @param value The value to check.\n * @returns Whether the passed value is an integer.\n */\nexport function isInteger(value: unknown): boolean {\n return typeof value === \"number\" && Math.floor(value) === value;\n}\n\n/**\n * Determines whether the passed value is null or undefined.\n * @param value The value to check.\n * @returns Whether the passed value is null or undefined.\n */\nexport function isNullOrUndefined(value: unknown): boolean {\n return typeof value === \"undefined\" || value === null;\n}\n", "/**\n * A type defining an object that holds a reference to substitued string literals parsed from the definition.\n */\nexport type StringLiteralPlaceholders = { [key: string]: string };\n\n/**\n * Pop the next raw token from the specified array of tokens and throw an error if it wasn't the expected one.\n * @param tokens The array of tokens.\n * @param expected An optional string or array or items, one of which must match the next popped token.\n * @returns The popped token.\n */\nexport function popAndCheck(tokens: string[], expected?: string | string[]): string {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token but there aren't any.\n if (popped === undefined) {\n throw new Error(\"unexpected end of definition\");\n }\n\n // Do we have an expected token/tokens array?\n if (expected != undefined) {\n // Get an array of expected values, if the popped token matches any then we are all good.\n const expectedValues = typeof expected === \"string\" ? [expected] : expected;\n\n // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase());\n\n // Throw an error if the popped token didn't match any of our expected items.\n if (!tokenMatchesExpectation) {\n const expectationString = expectedValues.map((item) => \"'\" + item + \"'\").join(\" or \");\n throw new Error(\"unexpected token found. Expected \" + expectationString + \" but got '\" + popped + \"'\");\n }\n }\n\n // Return the popped token.\n return popped;\n}\n\n/**\n * Swaps out any node/attribute argument string literals with placeholders.\n * @param definition The definition.\n * @returns An object containing a mapping of placeholders to original string values as well as the processed definition string.\n */\nexport function substituteStringLiterals(definition: string): {\n placeholders: StringLiteralPlaceholders;\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: StringLiteralPlaceholders = {};\n\n // Replace any string literals wrapped with double quotes in our definition with placeholders to be processed later.\n const processedDefinition = definition.replace(/\\\"(\\\\.|[^\"\\\\])*\\\"/g, (match) => {\n var strippedMatch = match.substring(1, match.length - 1);\n var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch);\n\n // If we have no existing string literal match then create a new placeholder.\n if (!placeholder) {\n placeholder = `@@${Object.keys(placeholders).length}@@`;\n placeholders[placeholder] = strippedMatch;\n }\n\n return placeholder;\n });\n\n return { placeholders, processedDefinition };\n}\n\n/**\n * Parse the tree definition into an array of raw tokens.\n * @param definition The definition.\n * @returns An array of tokens parsed from the definition.\n */\nexport function parseTokensFromDefinition(definition: string): string[] {\n // Add some space around various important characters so that they can be plucked out easier as individual tokens.\n definition = definition.replace(/\\(/g, \" ( \");\n definition = definition.replace(/\\)/g, \" ) \");\n definition = definition.replace(/\\{/g, \" { \");\n definition = definition.replace(/\\}/g, \" } \");\n definition = definition.replace(/\\]/g, \" ] \");\n definition = definition.replace(/\\[/g, \" [ \");\n definition = definition.replace(/\\,/g, \" , \");\n\n // Split the definition into raw token form and return it.\n return definition.replace(/\\s+/g, \" \").trim().split(\" \");\n}\n", "import { StringLiteralPlaceholders, popAndCheck } from \"./MDSLUtilities\";\n\n/**\n * A type representing any node function argument.\n */\ntype Argument = {\n /**\n * The argument value.\n */\n value: T;\n /**\n * The argument type, used for validation.\n */\n type: string;\n};\n\ntype NullArgument = Argument & {\n type: \"null\";\n};\n\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\n\ntype NumberArgument = Argument & {\n type: \"number\";\n /**\n * A flag defining whether the number argument value is a valid integer. (used for validation)\n */\n isInteger: boolean;\n};\n\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\n\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\n\n/**\n * A type representing a reference to any node function argument.\n */\ntype AnyArgument = NullArgument | BooleanArgument | NumberArgument | StringPlaceholderArgument | IdentifierArgument;\n\n/**\n * Parse an array of argument definitions from the specified tokens array.\n * @param tokens The array tokens to parse the argument definitions from.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @param argumentValidator The argument validator function.\n * @param validationFailedMessage The exception message to throw if argument validation fails.\n * @returns An array of argument definitions parsed from the specified tokens array.\n */\nexport function parseArgumentTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): AnyArgument[] {\n const argumentList: AnyArgument[] = [];\n\n // If the next token is not a '[' or '(' then we have no arguments to parse.\n if (![\"[\", \"(\"].includes(tokens[0])) {\n return argumentList;\n }\n\n // Any lists of arguments will always be wrapped in '[]' for node arguments or '()' for attribute arguments.\n // We are looking for a '[' or '(' opener that wraps the argument tokens and the relevant closer.\n const closingToken = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closingToken) {\n // The next token is part of our arguments list.\n argumentListTokens.push(tokens.shift()!);\n }\n\n // Validate the order of the argument tokens. Each token must either be a ',' or a single argument that satisfies the validator.\n argumentListTokens.forEach((token, index) => {\n // Get whether this token should be an actual argument.\n const shouldBeArgumentToken = !(index & 1);\n\n // If the current token should be an actual argument then validate it, otherwise it should be a ',' token.\n if (shouldBeArgumentToken) {\n // Get the argument definition.\n const argumentDefinition = getArgumentDefinition(token, stringArgumentPlaceholders);\n\n // This is a valid argument!\n argumentList.push(argumentDefinition);\n } else {\n // The current token should be a ',' token.\n if (token !== \",\") {\n throw new Error(`invalid argument list, expected ',' or ']' but got '${token}'`);\n }\n }\n });\n\n // The arguments list should terminate with a ']' or ')' token, depending on the opener.\n popAndCheck(tokens, closingToken);\n\n // Return the arguments.\n return argumentList;\n}\n\n/**\n * Gets an argument value definition.\n * @param token The argument token.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An argument value definition.\n */\nfunction getArgumentDefinition(token: string, stringArgumentPlaceholders: StringLiteralPlaceholders): AnyArgument {\n // Check whether the token represents a null value.\n if (token === \"null\") {\n return {\n value: null,\n type: \"null\"\n } as NullArgument;\n }\n\n // Check whether the token represents a boolean value.\n if (token === \"true\" || token === \"false\") {\n return {\n value: token === \"true\",\n type: \"boolean\"\n } as BooleanArgument;\n }\n\n // Check whether the token represents a number value.\n // TODO: Relies on broken isNaN - see MDN.\n // if (!Number.isNaN(token)) {\n if (!isNaN(token as any)) {\n return {\n value: parseFloat(token),\n isInteger: parseFloat(token) === parseInt(token, 10),\n type: \"number\"\n } as NumberArgument;\n }\n\n // Check whether the token is a placeholder (e.g. @@0@@) representing a string literal.\n if (token.match(/^@@\\d+@@$/g)) {\n return {\n value: stringArgumentPlaceholders[token].replace('\\\\\"', '\"'),\n type: \"string\"\n } as StringPlaceholderArgument;\n }\n\n // The only remaining option is that the argument value is an identifier.\n return {\n value: token,\n type: \"identifier\"\n } as IdentifierArgument;\n}\n", "import { NodeAttributeDefinition } from \"../BehaviourTreeDefinition\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { StringLiteralPlaceholders } from \"./MDSLUtilities\";\n\n/**\n * A type defining the attribute definitions of a node.\n */\ntype NodeAttributes = {\n while?: NodeAttributeDefinition;\n until?: NodeAttributeDefinition;\n entry?: NodeAttributeDefinition;\n exit?: NodeAttributeDefinition;\n step?: NodeAttributeDefinition;\n};\n\n/**\n * Parse any node attribute definitions from the specified tokens array.\n * @param tokens The array of remaining tokens.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An object of attribute definitions defined by any directly following tokens.\n */\nexport function parseAttributeTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): NodeAttributes {\n const nodeAttributeNames: (keyof NodeAttributes)[] = [\"while\", \"until\", \"entry\", \"exit\", \"step\"];\n\n // Create an object to hold any attributes found.\n const attributes: NodeAttributes = {};\n\n // Try to get the name of the attribute for the next token.\n let nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n\n // Pull attribute tokens as well as their arguments off of the tokens stack until we have no more.\n while (nodeAttributeNames.includes(nextAttributeName)) {\n // Check to make sure that we have not already created an attribute definition of this type.\n if (attributes[nextAttributeName]) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Remove the attribute name token from the array of tokens.\n tokens.shift();\n\n // Grab the attribute arguments, assuming the first to be an identifier.\n const [attributeCallIdentifier, ...attributeArguments] = parseArgumentTokens(\n tokens,\n stringArgumentPlaceholders\n );\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeCallIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected agent function or registered function name identifier argument for attribute\");\n }\n\n // Any attribute arguments (other than the expected call identifier) must have a type of string, number, boolean or null.\n attributeArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid attribute argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Create the attribute definition and add it to the object of attribute definitions found.\n attributes[nextAttributeName] = {\n call: attributeCallIdentifier.value,\n args: attributeArguments.map(({ value }) => value)\n };\n\n // Try to get the next attribute name token, as there could be multiple.\n nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n }\n\n return attributes;\n}\n", "import {\n ActionNodeDefinition,\n AnyChildNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition,\n ConditionNodeDefinition,\n FailNodeDefinition,\n FlipNodeDefinition,\n LottoNodeDefinition,\n ParallelNodeDefinition,\n RaceNodeDefinition,\n RepeatNodeDefinition,\n RetryNodeDefinition,\n RootNodeDefinition,\n SelectorNodeDefinition,\n SequenceNodeDefinition,\n SucceedNodeDefinition,\n WaitNodeDefinition\n} from \"../BehaviourTreeDefinition\";\nimport {\n isCompositeNode,\n isDecoratorNode,\n isLeafNode,\n isNullOrUndefined,\n isRootNode\n} from \"../BehaviourTreeDefinitionUtilities\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { parseAttributeTokens } from \"./MDSLNodeAttributeParser\";\nimport {\n StringLiteralPlaceholders,\n parseTokensFromDefinition,\n popAndCheck,\n substituteStringLiterals\n} from \"./MDSLUtilities\";\n\n/**\n * Convert the MDSL tree definition string into an equivalent JSON definition.\n * @param definition The tree definition string as MDSL.\n * @returns The root node JSON definitions.\n */\nexport function convertMDSLToJSON(definition: string): RootNodeDefinition[] {\n // Swap out any node/attribute argument string literals with a placeholder and get a mapping of placeholders to original values as well as the processed definition.\n const { placeholders, processedDefinition } = substituteStringLiterals(definition);\n\n // Parse our definition definition string into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\n return convertTokensToJSONDefinition(tokens, placeholders);\n}\n\n/**\n * Converts the specified tree definition tokens into a JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definitions.\n */\nfunction convertTokensToJSONDefinition(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RootNodeDefinition[] {\n // There must be at least 3 tokens for the tree definition to be valid. 'ROOT', '{' and '}'.\n if (tokens.length < 3) {\n throw new Error(\"invalid token count\");\n }\n\n // We should have a matching number of '{' and '}' tokens. If not, then there are scopes that have not been properly closed.\n if (tokens.filter((token) => token === \"{\").length !== tokens.filter((token) => token === \"}\").length) {\n throw new Error(\"scope character mismatch\");\n }\n\n // Create an array of tree stack arrays where root nodes will always be at the botton and the current composite/decorator node at the top.\n // There should be an element in this array for every root node defined and every element should be an array with a root note as the first element.\n // E.g. A definition with two root nodes defined:\n // [\n // [root, lotto, sequence],\n // [root, selector]\n // ]\n const treeStacks: [Partial, ...Partial[]][] = [];\n\n // Create an array of all root node definitions that we create.\n const rootNodes: Partial[] = [];\n\n // A helper function used to push node definitions onto the tree stack.\n const pushNode = (node: AnyNodeDefinition) => {\n // If the node is a root node then we need to create a new tree stack array with the root node at the root.\n if (isRootNode(node)) {\n // We need to double-check that this root node is not the child of another node.\n // We can do this by checking whether the top tree stack is not empty (contains an existing node)\n if (treeStacks[treeStacks.length - 1]?.length) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Add the root node definition to our array of all parsed root node definitions.\n rootNodes.push(node);\n\n // Add the root node definition to the root of a new tree stack.\n treeStacks.push([node]);\n\n return;\n }\n\n // All non-root nodes should be pushed after their root nodes so handle cases\n // where we may not have any tree stacks or our top-most tree stack is empty.\n if (!treeStacks.length || !treeStacks[treeStacks.length - 1].length) {\n throw new Error(\"expected root node at base of definition\");\n }\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Get the top-most node in the current tree stack, this will be a composite/decorator node\n // for which we will populate its children array if composite or setting its child if a decorator.\n const topTreeStackTopNode = topTreeStack[topTreeStack.length - 1] as AnyNodeDefinition;\n\n // If the top-most node in the current root stack is a composite or decorator\n // node then the current node should be added as a child of the top-most node.\n if (isCompositeNode(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNode(topTreeStackTopNode)) {\n // If the top node already has a child node set then throw an error as a decorator should only have a single child.\n if (topTreeStackTopNode.child) {\n throw new Error(\"a decorator node must only have a single child node\");\n }\n\n topTreeStackTopNode.child = node;\n }\n\n // If the node we are adding is also a composite or decorator node, then we should push it\n // onto the current tree stack, as subsequent nodes will be added as its child/children.\n if (!isLeafNode(node)) {\n topTreeStack.push(node);\n }\n };\n\n // A helper function used to pop the top-most node definition off of the tree stack and return it.\n const popNode = (): AnyNodeDefinition | null => {\n let poppedNode: AnyNodeDefinition | null = null;\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Pop the top-most node in the current tree stack if there is one.\n if (topTreeStack.length) {\n poppedNode = topTreeStack.pop() as AnyNodeDefinition;\n }\n\n // We don't want any empty tree stacks in our stack of tree stacks.\n if (!topTreeStack.length) {\n treeStacks.pop();\n }\n\n return poppedNode;\n };\n\n // We should keep processing the raw tokens until we run out of them.\n while (tokens.length) {\n // Grab the next token.\n const token = tokens.shift()!;\n\n // How we create the next node depends on the current raw token value.\n switch (token.toUpperCase()) {\n case \"ROOT\": {\n pushNode(createRootNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SUCCEED\": {\n pushNode(createSucceedNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FAIL\": {\n pushNode(createFailNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FLIP\": {\n pushNode(createFlipNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"REPEAT\": {\n pushNode(createRepeatNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RETRY\": {\n pushNode(createRetryNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SEQUENCE\": {\n pushNode(createSequenceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SELECTOR\": {\n pushNode(createSelectorNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"PARALLEL\": {\n pushNode(createParallelNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RACE\": {\n pushNode(createRaceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"LOTTO\": {\n pushNode(createLottoNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ACTION\": {\n pushNode(createActionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"CONDITION\": {\n pushNode(createConditionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"WAIT\": {\n pushNode(createWaitNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"BRANCH\": {\n pushNode(createBranchNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope and means that we have to pop a node off of the current stack.\n const poppedNode = popNode();\n\n // Now that we have a node definition we can carry out any validation that may require the node to be fully populated.\n if (poppedNode) {\n validatePoppedNode(poppedNode);\n }\n\n break;\n }\n\n default: {\n throw new Error(`unexpected token: ${token}`);\n }\n }\n }\n\n return rootNodes as RootNodeDefinition[];\n}\n\n/**\n * Creates a root node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definition.\n */\nfunction createRootNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RootNodeDefinition {\n // Create the root node definition.\n let node = {\n type: \"root\"\n } as Partial;\n\n // Parse any node arguments, we should only have one if any which will be an identifier argument for the root identifier.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Check whether any node arguments were defined.\n if (nodeArguments.length) {\n // We should only have one argument, if any, which will be an identifier argument for the root identifier.\n if (nodeArguments.length === 1 && nodeArguments[0].type === \"identifier\") {\n // The root node identifier will be the first and only node argument value.\n node.id = nodeArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the root node definition.\n return node as RootNodeDefinition;\n}\n\n/**\n * Creates a succeed node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The succeed node JSON definition.\n */\nfunction createSucceedNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SucceedNodeDefinition {\n const node = {\n type: \"succeed\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SucceedNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the succeed node definition.\n return node;\n}\n\n/**\n * Creates a fail node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The fail node JSON definition.\n */\nfunction createFailNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FailNodeDefinition {\n const node = {\n type: \"fail\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FailNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the fail node definition.\n return node;\n}\n\n/**\n * Creates a flip node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The flip node JSON definition.\n */\nfunction createFlipNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FlipNodeDefinition {\n const node = {\n type: \"flip\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FlipNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the flip node definition.\n return node;\n}\n\n/**\n * Creates a repeat node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The repeat node JSON definition.\n */\nfunction createRepeatNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RepeatNodeDefinition {\n let node = { type: \"repeat\" } as RepeatNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a repeat node are optional. We may have:\n // - No node arguments, in which case the repeat note will iterate indefinitely.\n // - One node argument which will be the explicit number of iterations to make.\n // - Two node arguments which define the min and max iteration bounds from which a random iteration count will be picked.\n if (nodeArguments.length) {\n // All repeat node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`repeat node iteration counts must be integer values`);\n });\n\n // We should have got one or two iteration counts.\n if (nodeArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = nodeArguments[0].value as number;\n\n // A repeat node must have a positive number of iterations if defined.\n if (node.iterations < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A repeat node must have a positive min and max iteration count if they are defined.\n if (node.iterations[0] < 0 || node.iterations[1] < 0) {\n throw new Error(\"a repeat node must have a positive minimum and maximum iteration count if defined\");\n }\n\n // A repeat node must not have an minimum iteration count that exceeds the maximum iteration count.\n if (node.iterations[0] > node.iterations[1]) {\n throw new Error(\n \"a repeat node must not have a minimum iteration count that exceeds the maximum iteration count\"\n );\n }\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of repeat node iteration count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the repeat node definition.\n return node;\n}\n\n/**\n * Creates a retry node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The retry node JSON definition.\n */\nfunction createRetryNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RetryNodeDefinition {\n let node = { type: \"retry\" } as RetryNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a retry node are optional. We may have:\n // - No node arguments, in which case the retry note will attempt indefinitely.\n // - One node argument which will be the explicit number of attempts to make.\n // - Two node arguments which define the min and max attempt bounds from which a random attempt count will be picked.\n if (nodeArguments.length) {\n // All retry node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`retry node attempt counts must be integer values`);\n });\n\n // We should have got one or two attempt counts.\n if (nodeArguments.length === 1) {\n // A static attempt count was defined.\n node.attempts = nodeArguments[0].value as number;\n\n // A retry node must have a positive number of attempts if defined.\n if (node.attempts < 0) {\n throw new Error(\"a retry node must have a positive number of attempts if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum attempt count was defined.\n node.attempts = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (node.attempts[0] < 0 || node.attempts[1] < 0) {\n throw new Error(\"a retry node must have a positive minimum and maximum attempt count if defined\");\n }\n\n // A retry node must not have a minimum attempt count that exceeds the maximum attempt count.\n if (node.attempts[0] > node.attempts[1]) {\n throw new Error(\n \"a retry node must not have a minimum attempt count that exceeds the maximum attempt count\"\n );\n }\n } else {\n // An incorrect number of attempt counts was defined.\n throw new Error(\"invalid number of retry node attempt count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the retry node definition.\n return node;\n}\n\n/**\n * Creates a sequence node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The sequence node JSON definition.\n */\nfunction createSequenceNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SequenceNodeDefinition {\n const node = {\n type: \"sequence\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SequenceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the sequence node definition.\n return node;\n}\n\n/**\n * Creates a selector node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The selector node JSON definition.\n */\nfunction createSelectorNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SelectorNodeDefinition {\n const node = {\n type: \"selector\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SelectorNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the selector node definition.\n return node;\n}\n\n/**\n * Creates a parallel node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The parallel node JSON definition.\n */\nfunction createParallelNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ParallelNodeDefinition {\n const node = {\n type: \"parallel\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as ParallelNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the parallel node definition.\n return node;\n}\n\n/**\n * Creates a race node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The race node JSON definition.\n */\nfunction createRaceNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RaceNodeDefinition {\n const node = {\n type: \"race\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as RaceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the race node definition.\n return node;\n}\n\n/**\n * Creates a lotto node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The lotto node JSON definition.\n */\nfunction createLottoNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): LottoNodeDefinition {\n // If any node arguments have been defined then they must be our weights.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // All lotto node arguments MUST be of type number and must be positive integers.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger || arg.value < 0)\n .forEach(() => {\n throw new Error(`lotto node weight arguments must be positive integer values`);\n });\n\n const node = {\n type: \"lotto\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as LottoNodeDefinition;\n\n // Apply the weights if any were defined.\n if (nodeArguments.length) {\n node.weights = nodeArguments.map(({ value }) => value) as number[];\n }\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the lotto node definition.\n return node;\n}\n\n/**\n * Creates an action node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The action node JSON definition.\n */\nfunction createActionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ActionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the action name\n // and agent function to invoke for the action, all other arguments are to be passed as arguments to that function.\n const [actionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require an action name argument.\n if (actionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid action node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the action node definition.\n return {\n type: \"action\",\n call: actionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a condition node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The condition node JSON definition.\n */\nfunction createConditionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ConditionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the condition name\n // and agent function to invoke for the condition, all other arguments are to be passed as arguments to that function.\n const [conditionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require a condition name argument.\n if (conditionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid condition node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the condition node definition.\n return {\n type: \"condition\",\n call: conditionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a wait node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The wait node JSON definition.\n */\nfunction createWaitNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): WaitNodeDefinition {\n let node = { type: \"wait\" } as WaitNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a wait node are optional. We may have:\n // - No node arguments, in which case the wait will be indefinite until it is aborted.\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n if (nodeArguments.length) {\n // All wait node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`wait node durations must be integer values`);\n });\n\n // We may have:\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n // - Too many arguments, which is not valid.\n if (nodeArguments.length === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0].value as number;\n\n // If an explict duration was defined then it must be a positive number.\n if (node.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.duration = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A wait node must have a positive min and max duration.\n if (node.duration[0] < 0 || node.duration[1] < 0) {\n throw new Error(\"a wait node must have a positive minimum and maximum duration\");\n }\n\n // A wait node must not have a minimum duration that exceeds the maximum duration.\n if (node.duration[0] > node.duration[1]) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else if (nodeArguments.length > 2) {\n // An incorrect number of duration arguments were defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n }\n\n // Return the wait node definition.\n return { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n}\n\n/**\n * Creates a branch node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The branch node JSON definition.\n */\nfunction createBranchNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): BranchNodeDefinition {\n // Parse any node arguments, we should have one which will be an identifier argument for the root ref.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // We should have only a single identifer argument for a branch node, which is the root ref.\n if (nodeArguments.length !== 1 || nodeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // Return the branch node definition.\n return { type: \"branch\", ref: nodeArguments[0].value };\n}\n\n/**\n * Validate a fully-populated node definition that was popped off of the tree stack.\n * @param definition The popped node to validate.\n */\nfunction validatePoppedNode(definition: AnyNodeDefinition): void {\n // Decorators MUST have a child defined.\n if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) {\n throw new Error(`a ${definition.type} node must have a single child node defined`);\n }\n\n // Composites MUST have at least one child defined.\n if (isCompositeNode(definition) && !definition.children?.length) {\n throw new Error(`a ${definition.type} node must have at least a single child node defined`);\n }\n\n // We need to make sure that lotto nodes that have weights defined have a number of weights matching the number of child nodes.\n if (definition.type === \"lotto\") {\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (definition.weights.length !== definition.children.length) {\n throw new Error(\n \"expected a number of weight arguments matching the number of child nodes for lotto node\"\n );\n }\n }\n }\n}\n", "import { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { flattenDefinition, isBranchNode, isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\n/**\n * An object representing the result of validating a tree definition.\n */\nexport type DefinitionValidationResult = {\n /**\n * A flag defining whether validation succeeded.\n */\n succeeded: boolean;\n /**\n * A string containing the error message if validation did not succeed.\n */\n errorMessage?: string;\n /**\n * The definition as json if the validation was successful, or undefined if validation did not succeed.\n */\n json?: RootNodeDefinition[];\n};\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON or MDSL, not taking any globally registered subtrees into consideration.\n * @param definition The behaviour tree definition in the form of JSON or MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateDefinition(definition: any): DefinitionValidationResult {\n // The definition must be defined.\n if (definition === null || typeof definition === \"undefined\") {\n return createValidationFailureResult(\"definition is null or undefined\");\n }\n\n // We are expecting a definition in one of three different forms:\n // - A string which we will assume is MDSL and we will parse this to JSON before validation.\n // - An array which we will assume is an array of root node definitions with at least one being the primary root node (no 'id' property)\n // - An object which we will assume is the primary root node and should not have an 'id' property.\n if (typeof definition === \"string\") {\n // The definition is a string which we can assume is MDSL, so attempt to validate it.\n return validateMDSLDefinition(definition);\n } else if (typeof definition === \"object\") {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n return validateJSONDefinition(definition);\n } else {\n return createValidationFailureResult(`unexpected definition type of '${typeof definition}'`);\n }\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of MDSL.\n * @param definition The behaviour tree definition in the form of MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nfunction validateMDSLDefinition(definition: string): DefinitionValidationResult {\n let rootNodeDefinitions;\n\n // The first thing the we need to do is to attempt to convert our MDSL into JSON.\n try {\n // The definition is a string which we can assume is MDSL, so attempt to parse it to a JSON definition in the form of an array of root node definitions.\n rootNodeDefinitions = convertMDSLToJSON(definition);\n } catch (exception) {\n // We failed to parse the JSON from the MDSL, this is likely to be the result of it not being a valid MDSL string.\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single unnamed root node at base of definition to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(`multiple root nodes found with duplicate name '${id}'`);\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON.\n * @param definition The behaviour tree definition in the form of JSON.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateJSONDefinition(\n definition: RootNodeDefinition | RootNodeDefinition[]\n): DefinitionValidationResult {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n const rootNodeDefinitions = Array.isArray(definition) ? definition : [definition];\n\n // Iterate over our array of root nodes and call validateNode for each, passing an initial depth of 0, wrapped in a try catch to handle validation failures.\n try {\n rootNodeDefinitions.forEach((rootNodeDefinition) => validateNode(rootNodeDefinition, 0));\n } catch (error) {\n // Handle cases where we have caught a thrown Error and return a failure result with the error message.\n if (error instanceof Error) {\n return createValidationFailureResult(error.message);\n }\n\n // No idea what happened here!\n return createValidationFailureResult(`unexpected error: ${error}`);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single root node without 'id' property defined to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(\n `multiple root nodes found with duplicate 'id' property value of '${id}'`\n );\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the branch -> subtree links across all provided root node definitions.\n * This will not consider branch nodes that reference any globally registered subtrees unless includesGlobalSubtrees\n * is set to true, in which case we will also verify that there are no broken branch -> subtree links.\n * @param rootNodeDefinitions The array of root node definitions.\n * @param includesGlobalSubtrees A flag defining whether the array includes all global subtree root node definitions.\n */\nexport function validateBranchSubtreeLinks(rootNodeDefinitions: RootNodeDefinition[], includesGlobalSubtrees: boolean) {\n // Create a mapping of root node identifiers to other root nodes that they reference via branch nodes.\n // Below is an example of a mapping that includes a circular dependency (root => a => b => c => a)\n // [{ refs: [\"a\", \"b\"] }, { id: \"a\", refs: [\"b\"] }, { id: \"b\", refs: [\"c\"] }, { id: \"c\", refs: [\"a\"] }]\n const rootNodeMappings: { id: string | undefined; refs: string[] }[] = rootNodeDefinitions.map(\n (rootNodeDefinition) => ({\n id: rootNodeDefinition.id,\n refs: flattenDefinition(rootNodeDefinition)\n .filter(isBranchNode)\n .map(({ ref }) => ref)\n })\n );\n\n // A recursive function to walk through the mappings, keeping track of which root nodes we have visited in the form of a path of root node identifiers.\n const followRefs = (mapping: { id: string | undefined; refs: string[] }, path: (string | undefined)[] = []) => {\n // Have we found a circular dependency?\n if (path.includes(mapping.id)) {\n // We found a circular dependency! Get the bad path of root node identifiers.\n const badPath = [...path, mapping.id];\n\n // Create the formatted path value. [undefined, \"a\", \"b\", \"c\", \"a\"] would be formatted as \"a -> b -> c -> a\".\n const badPathFormatted = badPath.filter((element) => !!element).join(\" => \");\n\n // No need to continue, we found a circular dependency.\n throw new Error(`circular dependency found in branch node references: ${badPathFormatted}`);\n }\n\n for (const ref of mapping.refs) {\n // Find the mapping for the root node with an identifer matching the current ref.\n const subMapping = rootNodeMappings.find(({ id }) => id === ref);\n\n // We may not have a mapping for this ref, which is normal when we aren't considering all globally registered subtrees.\n if (subMapping) {\n followRefs(subMapping, [...path, mapping.id]);\n } else if (includesGlobalSubtrees) {\n // We found a reference to a root node that doesn't exist, which is a problem seeing as the root node definitons includes all globally registered subtrees.\n throw new Error(\n mapping.id\n ? `subtree '${mapping.id}' has branch node that references root node '${ref}' which has not been defined`\n : `primary tree has branch node that references root node '${ref}' which has not been defined`\n );\n }\n }\n };\n\n // Start looking for circular dependencies and broken references from the primary root node definition.\n followRefs(rootNodeMappings.find((mapping) => typeof mapping.id === \"undefined\")!);\n}\n\n/**\n * Validate an object that we expect to be a node definition.\n * @param definition An object that we expect to be a node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateNode(definition: any, depth: number): void {\n // Every node must be valid object and have a non-empty 'type' string property.\n if (typeof definition !== \"object\" || typeof definition.type !== \"string\" || definition.type.length === 0) {\n throw new Error(\n `node definition is not an object or 'type' property is not a non-empty string at depth '${depth}'`\n );\n }\n\n // If this node is at the very base of the definition then it MUST be a root node.\n if (depth === 0 && definition.type !== \"root\") {\n throw new Error(`expected root node at base of definition but got node of type '${definition.type}'`);\n }\n\n // How we validate this node definition will depend on its type.\n switch (definition.type) {\n case \"action\":\n validateActionNode(definition, depth);\n break;\n\n case \"condition\":\n validateConditionNode(definition, depth);\n break;\n\n case \"wait\":\n validateWaitNode(definition, depth);\n break;\n\n case \"branch\":\n validateBranchNode(definition, depth);\n break;\n\n case \"root\":\n validateRootNode(definition, depth);\n break;\n\n case \"succeed\":\n validateSucceedNode(definition, depth);\n break;\n\n case \"fail\":\n validateFailNode(definition, depth);\n break;\n\n case \"flip\":\n validateFlipNode(definition, depth);\n break;\n\n case \"repeat\":\n validateRepeatNode(definition, depth);\n break;\n\n case \"retry\":\n validateRetryNode(definition, depth);\n break;\n\n case \"sequence\":\n validateSequenceNode(definition, depth);\n break;\n\n case \"selector\":\n validateSelectorNode(definition, depth);\n break;\n\n case \"parallel\":\n validateParallelNode(definition, depth);\n break;\n\n case \"race\":\n validateRaceNode(definition, depth);\n break;\n\n case \"lotto\":\n validateLottoNode(definition, depth);\n break;\n\n default:\n throw new Error(`unexpected node type of '${definition.type}' at depth '${depth}'`);\n }\n}\n\n/**\n * Validate any attributes for a given node definition.\n * @param definition The node definition.\n * @param depth The depth of the node in the behaviour tree definition.\n */\nfunction validateNodeAttributes(definition: any, depth: number): void {\n // Validate each of the attribute types for this node.\n [\"while\", \"until\", \"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n // Attempt to grab the definition for the current attribute from the node definition.\n const attributeDefinition = definition[attributeName];\n\n // All node attributes are optional, so there is nothing to do if the current attribute is not defined.\n if (typeof attributeDefinition === \"undefined\") {\n return;\n }\n\n // The attribute definition must be an object.\n if (typeof attributeDefinition !== \"object\") {\n throw new Error(\n `expected attribute '${attributeName}' to be an object for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // The 'call' property must be defined for any attribute definition.\n if (typeof attributeDefinition.call !== \"string\" || attributeDefinition.call.length === 0) {\n throw new Error(\n `expected 'call' property for attribute '${attributeName}' to be a non-empty string for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // If any node attribute arguments have been defined then they must have been defined in an array.\n if (typeof attributeDefinition.args !== \"undefined\" && !Array.isArray(attributeDefinition.args)) {\n throw new Error(\n `expected 'args' property for attribute '${attributeName}' to be an array for '${definition.type}' node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a root node definition.\n * @param definition An object that we expect to be a root node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRootNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"root\") {\n throw new Error(\"expected node type of 'root' for root node\");\n }\n\n // A root node cannot be the child of another node.\n if (depth > 0) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Check that, if the root node 'id' property is defined, it is a non-empty string.\n if (typeof definition.id !== \"undefined\" && (typeof definition.id !== \"string\" || definition.id.length === 0)) {\n throw new Error(\"expected non-empty string for 'id' property if defined for root node\");\n }\n\n // A root node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(\"expected property 'child' to be defined for root node\");\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a succeed node definition.\n * @param definition An object that we expect to be a succeed node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSucceedNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"succeed\") {\n throw new Error(`expected node type of 'succeed' for succeed node at depth '${depth}'`);\n }\n\n // A succeed node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for succeed node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a fail node definition.\n * @param definition An object that we expect to be a fail node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFailNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"fail\") {\n throw new Error(`expected node type of 'fail' for fail node at depth '${depth}'`);\n }\n\n // A fail node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for fail node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a flip node definition.\n * @param definition An object that we expect to be a flip node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFlipNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"flip\") {\n throw new Error(`expected node type of 'flip' for flip node at depth '${depth}'`);\n }\n\n // A flip node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for flip node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a repeat node definition.\n * @param definition An object that we expect to be a repeat node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRepeatNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"repeat\") {\n throw new Error(`expected node type of 'repeat' for repeat node at depth '${depth}'`);\n }\n\n // A repeat node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for repeat node at depth '${depth}'`);\n }\n\n // Check whether an 'iterations' property has been defined, it may not have been if this node is to repeat indefinitely.\n if (typeof definition.iterations !== \"undefined\") {\n if (Array.isArray(definition.iterations)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.iterations.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'iterations' property is an array then it MUST contain two integer values.\n if (definition.iterations.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must have a positive min and max iterations count if they are defined.\n if (definition.iterations[0] < 0 || definition.iterations[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must not have a minimum iterations count that exceeds the maximum iterations count.\n if (definition.iterations[0] > definition.iterations[1]) {\n throw new Error(\n `expected minimum iterations count that does not exceed the maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.iterations)) {\n // A repeat node must have a positive number of iterations if defined.\n if (definition.iterations < 0) {\n throw new Error(\n `expected positive iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a retry node definition.\n * @param definition An object that we expect to be a retry node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRetryNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"retry\") {\n throw new Error(`expected node type of 'retry' for retry node at depth '${depth}'`);\n }\n\n // A retry node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for retry node at depth '${depth}'`);\n }\n\n // Check whether an 'attempts' property has been defined, it may not have been if this node is to retry indefinitely.\n if (typeof definition.attempts !== \"undefined\") {\n if (Array.isArray(definition.attempts)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.attempts.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'attempts' property is an array then it MUST contain two integer values.\n if (definition.attempts.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (definition.attempts[0] < 0 || definition.attempts[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must not have a minimum attempts count that exceeds the maximum attempts count.\n if (definition.attempts[0] > definition.attempts[1]) {\n throw new Error(\n `expected minimum attempts count that does not exceed the maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.attempts)) {\n // A retry node must have a positive number of attempts if defined.\n if (definition.attempts < 0) {\n throw new Error(\n `expected positive attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a branch node definition.\n * @param definition An object that we expect to be a branch node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateBranchNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"branch\") {\n throw new Error(`expected node type of 'branch' for branch node at depth '${depth}'`);\n }\n\n // Check that the branch node 'ref' property is defined and is a non-empty string.\n if (typeof definition.ref !== \"string\" || definition.ref.length === 0) {\n throw new Error(`expected non-empty string for 'ref' property for branch node at depth '${depth}'`);\n }\n\n // It is invalid to define guard attributes for a branch node as they should be defined on the referenced root node.\n [\"while\", \"until\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `guards should not be defined for branch nodes but guard '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n\n // It is invalid to define callback attributes for a branch node as they should be defined on the referenced root node.\n [\"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `callbacks should not be defined for branch nodes but callback '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a action node definition.\n * @param definition An object that we expect to be a action node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateActionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"action\") {\n throw new Error(`expected node type of 'action' for action node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a action node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of action node at depth '${depth}'`);\n }\n\n // If any action function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for action node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a condition node definition.\n * @param definition An object that we expect to be a condition node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateConditionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"condition\") {\n throw new Error(`expected node type of 'condition' for condition node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a condition node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of condition node at depth '${depth}'`);\n }\n\n // If any condition function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for condition node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a wait node definition.\n * @param definition An object that we expect to be a wait node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateWaitNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"wait\") {\n throw new Error(`expected node type of 'wait' for wait node at depth '${depth}'`);\n }\n\n // Check whether a 'duration' property has been defined, it may not have been if this node is to wait indefinitely.\n if (typeof definition.duration !== \"undefined\") {\n if (Array.isArray(definition.duration)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.duration.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'duration' property is an array then it MUST contain two integer values.\n if (definition.duration.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must have a positive min and max duration value if they are defined.\n if (definition.duration[0] < 0 || definition.duration[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum duration for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must not have a minimum duration value that exceeds the maximum duration value.\n if (definition.duration[0] > definition.duration[1]) {\n throw new Error(\n `expected minimum duration value that does not exceed the maximum duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.duration)) {\n // A wait node must have a positive duration value if defined.\n if (definition.duration < 0) {\n throw new Error(\n `expected positive duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a sequence node definition.\n * @param definition An object that we expect to be a sequence node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSequenceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"sequence\") {\n throw new Error(`expected node type of 'sequence' for sequence node at depth '${depth}'`);\n }\n\n // A sequence node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for sequence node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a selector node definition.\n * @param definition An object that we expect to be a selector node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSelectorNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"selector\") {\n throw new Error(`expected node type of 'selector' for selector node at depth '${depth}'`);\n }\n\n // A selector node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for selector node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a parallel node definition.\n * @param definition An object that we expect to be a parallel node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateParallelNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"parallel\") {\n throw new Error(`expected node type of 'parallel' for parallel node at depth '${depth}'`);\n }\n\n // A parallel node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for parallel node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a race node definition.\n * @param definition An object that we expect to be a race node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRaceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"race\") {\n throw new Error(`expected node type of 'race' for race node at depth '${depth}'`);\n }\n\n // A race node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for race node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a lotto node definition.\n * @param definition An object that we expect to be a lotto node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateLottoNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"lotto\") {\n throw new Error(`expected node type of 'lotto' for lotto node at depth '${depth}'`);\n }\n\n // A lotto node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for lotto node at depth '${depth}'`);\n }\n\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (\n !Array.isArray(definition.weights) ||\n definition.weights.length !== definition.children.length ||\n definition.weights.filter((value: unknown) => !isInteger(value)).length ||\n definition.weights.filter((value: number) => value < 0).length\n ) {\n throw new Error(\n `expected an array of positive integer weight values with a length matching the number of child nodes for 'weights' property if defined for lotto node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * A helper function to create a failure validation result with the given error message.\n * @param errorMessage The validation failure error message.\n * @returns A failure validation result with the given error message.\n */\nfunction createValidationFailureResult(errorMessage: string): DefinitionValidationResult {\n return { succeeded: false, errorMessage };\n}\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nexport function createUid(): string {\n var S4 = function () {\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n };\n return S4() + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + S4() + S4();\n}\n", "import { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport State, { AnyState } from \"../State\";\nimport { Agent } from \"../Agent\";\nimport Leaf from \"./leaf/Leaf\";\nimport Attribute from \"../attributes/Attribute\";\nimport Entry from \"../attributes/callbacks/Entry\";\nimport Exit from \"../attributes/callbacks/Exit\";\nimport Step from \"../attributes/callbacks/Step\";\nimport While from \"../attributes/guards/While\";\nimport Until from \"../attributes/guards/Until\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\nimport { GuardAttributeDetails } from \"../attributes/guards/Guard\";\nimport { CallbackAttributeDetails } from \"../attributes/callbacks/Callback\";\nimport { createUid } from \"../Utilities\";\n\n/**\n * Details of a tree node instance.\n */\nexport type NodeDetails = {\n /**\n * The tree node identifier.\n */\n id: string;\n /**\n * The tree node type.\n */\n type: string;\n /**\n * The tree node name.\n */\n name: string;\n /**\n * The current state of the tree node.\n */\n state: AnyState;\n /**\n * The array of agent or globally registered function arguments, defined if this is an action or condition node.\n */\n args?: any[];\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: GuardAttributeDetails;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: GuardAttributeDetails;\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: CallbackAttributeDetails;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: CallbackAttributeDetails;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: CallbackAttributeDetails;\n /**\n * The array of the child nodes of this node, defined if this node is a composite or decorator node.\n */\n children?: NodeDetails[];\n};\n\n/**\n * A mapping of attribute names to attributes configured for a node.\n */\ntype Attributes = {\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: Entry;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: Step;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: Exit;\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: While;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: Until;\n};\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node unique identifier.\n */\n protected readonly uid: string;\n /**\n * The node attributes.\n */\n protected readonly attributes: Attributes;\n /**\n * The node state.\n */\n private _state: AnyState = State.READY;\n /**\n * The guard path to evaluate as part of a node update.\n */\n private _guardPath: GuardPath | undefined;\n\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n */\n constructor(private type: string, attributes: Attribute[], protected options: BehaviourTreeOptions) {\n // Create a unique identifier for this node.\n this.uid = createUid();\n\n // Create our attribute mapping.\n this.attributes = {\n entry: attributes.find(({ type }) => type === \"entry\") as Entry,\n step: attributes.find(({ type }) => type === \"step\") as Step,\n exit: attributes.find(({ type }) => type === \"exit\") as Exit,\n while: attributes.find(({ type }) => type === \"while\") as While,\n until: attributes.find(({ type }) => type === \"until\") as Until\n };\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected abstract onUpdate(agent: Agent): void;\n\n /**\n * Gets the name of the node.\n */\n public abstract getName(): string;\n\n /**\n * Gets whether this node is a leaf node.\n */\n public abstract isLeafNode: () => this is Leaf;\n\n /**\n * Gets/Sets the state of the node.\n */\n getState = (): AnyState => this._state;\n setState = (value: AnyState): void => {\n // Grab the original state of this node.\n const previousState = this._state;\n\n // Set the new node state.\n this._state = value;\n\n // If the state actually changed we should handle it.\n if (previousState !== value) {\n this.onStateChanged(previousState);\n }\n };\n\n /**\n * Gets the unique id of the node.\n */\n getUid = () => this.uid;\n\n /**\n * Gets the type of the node.\n */\n getType = () => this.type;\n\n /**\n * Gets the node attributes.\n */\n getAttributes = () => Object.values(this.attributes).filter((attribute) => !!attribute);\n\n /**\n * Sets the guard path to evaluate as part of a node update.\n */\n setGuardPath = (value: GuardPath) => (this._guardPath = value);\n\n /**\n * Gets whether a guard path is assigned to this node.\n */\n hasGuardPath = () => !!this._guardPath;\n\n /**\n * Gets whether this node is in the specified state.\n * @param value The value to compare to the node state.\n */\n public is(value: AnyState): boolean {\n return this._state === value;\n }\n\n /**\n * Reset the state of the node.\n */\n public reset(): void {\n this.setState(State.READY);\n }\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n public abort(agent: Agent): void {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @returns The result of the update.\n */\n public update(agent: Agent): void {\n // If this node is already in a 'SUCCEEDED' or 'FAILED' state then there is nothing to do.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n return;\n }\n\n try {\n // Evaluate all of the guard path conditions for the current tree path.\n this._guardPath!.evaluate(agent);\n\n // If this node is in the READY state then call the ENTRY for this node if it exists.\n if (this.is(State.READY)) {\n this.attributes.entry?.callAgentFunction(agent);\n }\n\n this.attributes.step?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent);\n\n // If this node is now in a 'SUCCEEDED' or 'FAILED' state then call the EXIT for this node if it exists.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n this.attributes.exit?.callAgentFunction(agent, this.is(State.SUCCEEDED), false);\n }\n } catch (error) {\n // If the error is a GuardUnsatisfiedException then we need to determine if this node is the source.\n if (error instanceof GuardUnsatisifedException && error.isSourceNode(this)) {\n // Abort the current node.\n this.abort(agent);\n\n // Any node that is the source of an abort will be a failed node.\n this.setState(State.FAILED);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n id: this.uid,\n name: this.getName(),\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n state: this._state\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n // We should call the onNodeStateChange callback if it was defined.\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this._state\n });\n }\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A composite node that wraps child nodes.\n */\nexport default abstract class Composite extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => this.children;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of any child nodes.\n this.children.forEach((child) => child.reset());\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort any child nodes.\n this.children.forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: this.children.map((child) => child.getDetails())\n };\n }\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A PARALLEL node.\n * The child nodes are executed concurrently until one fails or all succeed.\n */\nexport default class Parallel extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"parallel\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have failed then this node has also failed.\n if (this.children.find((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A parallel node will move into the succeeded state if all child nodes move into the succeeded state.\n if (this.children.every((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RACE node.\n * The child nodes are executed concurrently until one succeeds or all fail.\n */\nexport default class Race extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"race\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have succeeded then this node has also succeeded\n if (this.children.find((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A race node will move into the failed state if all child nodes move into the failed state as none can succeed.\n if (this.children.every((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"RACE\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SELECTOR node.\n * The child nodes are executed in sequence until one succeeds or all fail.\n */\nexport default class Selector extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"selector\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then this node is also a 'SUCCEEDED' node.\n if (child.getState() === State.SUCCEEDED) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the selector nodes.\n return;\n }\n\n // If the current child has a state of 'FAILED' then we should move on to the next child.\n if (child.getState() === State.FAILED) {\n // Find out if the current child is the last one in the selector.\n // If it is then this sequence node has also failed.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the selector as we have completed it.\n return;\n } else {\n // The child node failed, try the next one.\n continue;\n }\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the selector as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SELECTOR\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SEQUENCE node.\n * The child nodes are executed in sequence until one fails or all succeed.\n */\nexport default class Sequence extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"sequence\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then we should move on to the next child.\n if (child.getState() === State.SUCCEEDED) {\n // Find out if the current child is the last one in the sequence.\n // If it is then this sequence node has also succeeded.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the sequence as we have completed it.\n return;\n } else {\n // The child node succeeded, but we have not finished the sequence yet.\n continue;\n }\n }\n\n // If the current child has a state of 'FAILED' then this node is also a 'FAILED' node.\n if (child.getState() === State.FAILED) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the sequence.\n return;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the sequence as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SEQUENCE\";\n}\n", "import createLotto from \"lotto-draw\";\n\nimport Node from \"../Node\";\nimport Composite from \"./Composite\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A LOTTO node.\n * A winning child is picked on the initial update of this node, based on ticket weighting.\n * The state of this node will match the state of the winning child.\n */\nexport default class Lotto extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param weights The child node weights.\n * @param children The child nodes.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private weights: number[] | undefined,\n children: Node[]\n ) {\n super(\"lotto\", attributes, options, children);\n }\n\n /**\n * The child node selected to be the active one.\n */\n private selectedChild: Node | undefined;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to pick a winning child node.\n if (this.is(State.READY)) {\n // Create a lotto draw with which to randomly pick a child node to become the active one.\n const lottoDraw = createLotto({\n // Hook up the optional 'random' behaviour tree function option to the one used by 'lotto-draw'.\n random: this.options.random,\n // Pass in each child node as a participant in the lotto draw with their respective ticket count.\n participants: this.children.map((child, index) => [child, this.weights?.[index] || 1])\n });\n\n // Randomly pick a child based on ticket weighting, this will become the active child for this composite node.\n this.selectedChild = lottoDraw.draw() || undefined;\n }\n\n // If something went wrong and we don't have an active child then we should throw an error.\n if (!this.selectedChild) {\n throw new Error(\"failed to update lotto node as it has no active child\");\n }\n\n // If the selected child has never been updated or is running then we will need to update it now.\n if (this.selectedChild.getState() === State.READY || this.selectedChild.getState() === State.RUNNING) {\n this.selectedChild.update(agent);\n }\n\n // The state of the lotto node is the state of its selected child.\n this.setState(this.selectedChild.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => (this.weights ? `LOTTO [${this.weights.join(\",\")}]` : \"LOTTO\");\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A decorator node that wraps a single child node.\n */\nexport default abstract class Decorator extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected child: Node) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => [this.child];\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of the child node.\n this.child.reset();\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort the child node.\n this.child.abort(agent);\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: [this.child.getDetails()]\n };\n }\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Fail node.\n * This node wraps a single child and will always move to the 'FAILED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Fail extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"fail\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.FAILED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FAIL\";\n}\n", "import Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Flip node.\n * This node wraps a single child and will flip the state of the child state.\n */\nexport default class Flip extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"flip\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n this.setState(State.FAILED);\n break;\n\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FLIP\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A REPEAT node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The REPEAT node will stop and have a 'FAILED' state if its child is ever in a 'FAILED' state after an update.\n * The REPEAT node will attempt to move on to the next iteration if its child is ever in a 'SUCCEEDED' state.\n */\nexport default class Repeat extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param iterations The number of iterations to repeat the child node.\n * @param iterationsMin The minimum possible number of iterations to repeat the child node.\n * @param iterationsMax The maximum possible number of iterations to repeat the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, options, child);\n }\n\n /**\n * The number of target iterations to make.\n */\n private targetIterationCount: number | null = null;\n\n /**\n * The current iteration count.\n */\n private currentIterationCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target iteration count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the FAILED state when we updated it then there is nothing left to do and this node has also failed.\n // If it has moved into the SUCCEEDED state then we have completed the current iteration.\n if (this.child.getState() === State.FAILED) {\n // The child has failed, meaning that this node has failed.\n this.setState(State.FAILED);\n\n return;\n } else if (this.child.getState() === State.SUCCEEDED) {\n // We have completed an iteration.\n this.currentIterationCount += 1;\n }\n } else {\n // This node is in the 'SUCCEEDED' state as we cannot iterate any more.\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.iterations !== null) {\n return `REPEAT ${this.iterations}x`;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n return `REPEAT ${this.iterationsMin}x-${this.iterationsMax}x`;\n } else {\n return \"REPEAT\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with an explicit iteration count or will we be randomly picking a iteration count between the min and max iteration count.\n if (this.iterations !== null) {\n this.targetIterationCount = this.iterations;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n // We will be picking a random iteration count between a min and max iteration count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random iteration count between a min and max iteration count.\n this.targetIterationCount = Math.floor(\n random() * (this.iterationsMax - this.iterationsMin + 1) + this.iterationsMin\n );\n } else {\n this.targetIterationCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RETRY node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The RETRY node will stop and have a 'SUCCEEDED' state if its child is ever in a 'SUCCEEDED' state after an update.\n * The RETRY node will attempt to move on to the next iteration if its child is ever in a 'FAILED' state.\n */\nexport default class Retry extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param attempts The number of attempts to retry the child node.\n * @param attemptsMin The minimum possible number of attempts to retry the child node.\n * @param attemptsMax The maximum possible number of attempts to retry the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, options, child);\n }\n\n /**\n * The number of target attempts to make.\n */\n private targetAttemptCount: number | null = null;\n\n /**\n * The current attempt count.\n */\n private currentAttemptCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target attempt count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Set the target attempt count.\n this.setTargetAttemptCount();\n }\n\n // Do a check to see if we can attempt. If we can then this node will move into the 'RUNNING' state.\n // If we cannot attempt then we have hit our target attempt count, which means that the node has succeeded.\n if (this.canAttempt()) {\n // This node is in the running state and can do its initial attempt.\n this.setState(State.RUNNING);\n\n // We may have already completed an attempt, meaning that the child node will be in the FAILED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.FAILED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the SUCCEEDED state when we updated it then there is nothing left to do and this node has also succeeded.\n // If it has moved into the FAILED state then we have completed the current attempt.\n if (this.child.getState() === State.SUCCEEDED) {\n // The child has succeeded, meaning that this node has succeeded.\n this.setState(State.SUCCEEDED);\n\n return;\n } else if (this.child.getState() === State.FAILED) {\n // We have completed an attempt.\n this.currentAttemptCount += 1;\n }\n } else {\n // This node is in the 'FAILED' state as we cannot iterate any more.\n this.setState(State.FAILED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.attempts !== null) {\n return `RETRY ${this.attempts}x`;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n return `RETRY ${this.attemptsMin}x-${this.attemptsMax}x`;\n } else {\n return \"RETRY\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an attempt can be made.\n * @returns Whether an attempt can be made.\n */\n canAttempt = () => {\n if (this.targetAttemptCount !== null) {\n // We can attempt as long as we have not reached our target attempt count.\n return this.currentAttemptCount < this.targetAttemptCount;\n }\n\n // If neither an attempt count or a condition function were defined then we can attempt indefinitely.\n return true;\n };\n\n /**\n * Sets the target attempt count.\n */\n setTargetAttemptCount = () => {\n // Are we dealing with an explicit attempt count or will we be randomly picking an attempt count between the min and max attempt count.\n if (this.attempts !== null) {\n this.targetAttemptCount = this.attempts;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n // We will be picking a random attempt count between a min and max attempt count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random attempt count between a min and max attempt count.\n this.targetAttemptCount = Math.floor(\n random() * (this.attemptsMax - this.attemptsMin + 1) + this.attemptsMin\n );\n } else {\n this.targetAttemptCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Root node.\n * The root node will have a single child.\n */\nexport default class Root extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"root\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n // Update the child of this node.\n this.child.update(agent);\n }\n\n // The state of the root node is the state of its child.\n this.setState(this.child.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ROOT\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Succeed node.\n * This node wraps a single child and will always move to the 'SUCCEEDED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Succeed extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"succeed\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SUCCEED\";\n}\n", "import Node from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => true;\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State, { CompleteState } from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * The type representing a resolved/rejected update promise.\n */\ntype UpdatePromiseResult = {\n /**\n * Whether the promise was resolved rather than rejected.\n */\n isResolved: boolean;\n\n /**\n * The promise resolved value or rejection reason.\n */\n value: any;\n};\n\n/**\n * An Action leaf node.\n * This represents an immediate or ongoing state of behaviour.\n */\nexport default class Action extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param actionName The action name.\n * @param actionArguments The array of action arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private actionName: string,\n public actionArguments: any[]\n ) {\n super(\"action\", attributes, options);\n }\n\n /**\n * Whether there is a pending update promise.\n */\n private isUsingUpdatePromise = false;\n\n /**\n * The finished state result of an update promise.\n */\n private updatePromiseResult: UpdatePromiseResult | null = null;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the result of this action depends on an update promise then there is nothing to do until it settles.\n if (this.isUsingUpdatePromise) {\n // Are we still waiting for our update promise to settle?\n if (!this.updatePromiseResult) {\n return;\n }\n\n const { isResolved, value } = this.updatePromiseResult;\n\n // Our update promise settled, was it resolved or rejected?\n if (isResolved) {\n // Our promise resolved so check to make sure the result is a valid finished state.\n if (value !== State.SUCCEEDED && value !== State.FAILED) {\n throw new Error(\n \"action node promise resolved with an invalid value, expected a State.SUCCEEDED or State.FAILED value to be returned\"\n );\n }\n\n // Set the state of this node to match the state returned by the promise.\n this.setState(value);\n\n return;\n } else {\n // The promise was rejected, which isn't great.\n throw new Error(`action function '${this.actionName}' promise rejected with '${value}'`);\n }\n }\n\n // Attempt to get the invoker for the action function.\n const actionFuncInvoker = Lookup.getFuncInvoker(agent, this.actionName);\n\n // The action function should be defined.\n if (actionFuncInvoker === null) {\n throw new Error(\n `cannot update action node as the action '${this.actionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let actionFunctionResult;\n\n try {\n // Call the action function, the result of which may be:\n // - The finished state of this action node.\n // - A promise to return a finished node state.\n // - Undefined if the node should remain in the running state.\n actionFunctionResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`action function '${this.actionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`action function '${this.actionName}' threw: ${error}`);\n }\n }\n\n if (actionFunctionResult instanceof Promise) {\n actionFunctionResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the resolved update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: true,\n value: result\n };\n },\n (reason) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort or reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the rejected update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: false,\n value: reason\n };\n }\n );\n\n // This node will be in the 'RUNNING' state until the update promise resolves.\n this.setState(State.RUNNING);\n\n // We are now waiting for the promise returned by the use to resolve before we know what state this node is in.\n this.isUsingUpdatePromise = true;\n } else {\n // Validate the returned value.\n this.validateUpdateResult(actionFunctionResult);\n\n // Set the state of this node, this may be undefined, which just means that the node is still in the 'RUNNING' state.\n this.setState(actionFunctionResult || State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.actionName;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // There is no longer an update promise that we care about.\n this.isUsingUpdatePromise = false;\n this.updatePromiseResult = null;\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.actionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.actionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n\n /**\n * Validate the result of an update function call.\n * @param result The result of an update function call.\n */\n private validateUpdateResult = (result: CompleteState | State.RUNNING) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case State.RUNNING:\n case undefined:\n return;\n default:\n throw new Error(\n `expected action function '${this.actionName}' to return an optional State.SUCCEEDED or State.FAILED value but returned '${result}'`\n );\n }\n };\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * A Condition leaf node.\n * This will succeed or fail immediately based on an agent predicate, without moving to the 'RUNNING' state.\n */\nexport default class Condition extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param conditionName The name of the condition function.\n * @param conditionArguments The array of condition arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private conditionName: string,\n public conditionArguments: any[]\n ) {\n super(\"condition\", attributes, options);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.conditionName);\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot update condition node as the condition '${this.conditionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.conditionArguments);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`condition function '${this.conditionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`condition function '${this.conditionName}' threw: ${error}`);\n }\n }\n\n // The result of calling the condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected condition function '${this.conditionName}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Set the state of this node based on the result of calling the condition function.\n this.setState(!!conditionFunctionResult ? State.SUCCEEDED : State.FAILED);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.conditionName;\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.conditionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.conditionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { Agent } from \"../../Agent\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A WAIT node.\n * The state of this node will change to SUCCEEDED after a duration of time\n */\nexport default class Wait extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param duration The duration that this node will wait to succeed in milliseconds.\n * @param durationMin The minimum possible duration in milliseconds that this node will wait to succeed.\n * @param durationMax The maximum possible duration in milliseconds that this node will wait to succeed.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, options);\n }\n\n /**\n * The time in milliseconds at which this node was first updated.\n */\n private initialUpdateTime: number = 0;\n\n /**\n * The total duration in milliseconds that this node will be waiting for.\n */\n private totalDuration: number | null = null;\n\n /**\n * The duration in milliseconds that this node has been waiting for.\n */\n private waitedDuration: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to set the initial update time.\n if (this.is(State.READY)) {\n // Set the initial update time.\n this.initialUpdateTime = new Date().getTime();\n\n // Set the initial waited duration.\n this.waitedDuration = 0;\n\n // Are we dealing with an explicit duration or will we be randomly picking a duration between the min and max duration.\n if (this.duration !== null) {\n this.totalDuration = this.duration;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // We will be picking a random duration between a min and max duration, if the optional 'random' behaviour tree\n // function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random duration between a min and max duration.\n this.totalDuration = Math.floor(\n random() * (this.durationMax - this.durationMin + 1) + this.durationMin\n );\n } else {\n this.totalDuration = null;\n }\n\n // The node is now running until we finish waiting.\n this.setState(State.RUNNING);\n }\n\n // If we have no total duration then this wait node will wait indefinitely until it is aborted.\n if (this.totalDuration === null) {\n return;\n }\n\n // If we have a 'getDeltaTime' function defined as part of our options then we will use it to figure out how long we have waited for.\n if (typeof this.options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = this.options.getDeltaTime();\n\n // Our delta time must be a valid number and cannot be NaN.\n if (typeof deltaTime !== \"number\" || isNaN(deltaTime)) {\n throw new Error(\"The delta time must be a valid number and not NaN.\");\n }\n\n // Update the amount of time that this node has been waiting for based on the delta time.\n this.waitedDuration += deltaTime * 1000;\n } else {\n // We are not using a delta time, so we will just work out hom much time has passed since the first update.\n this.waitedDuration = new Date().getTime() - this.initialUpdateTime;\n }\n\n // Have we waited long enough?\n if (this.waitedDuration >= this.totalDuration) {\n // We have finished waiting!\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.duration !== null) {\n return `WAIT ${this.duration}ms`;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n return `WAIT ${this.durationMin}ms-${this.durationMax}ms`;\n } else {\n return \"WAIT\";\n }\n };\n}\n", "import Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: any[];\n};\n\n/**\n * A base node attribute.\n */\nexport default abstract class Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of attribute arguments.\n */\n constructor(public type: string, public args: any[]) {}\n\n /**\n * Gets the attribute details.\n */\n abstract getDetails(): TAttributeDetails;\n\n /**\n * Gets whether this attribute is a guard.\n */\n abstract isGuard: () => this is Guard;\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node guard attribute.\n */\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node guard attribute.\n */\nexport default abstract class Guard extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n */\n constructor(type: string, args: any[], private condition: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the condition function that determines whether the guard is satisfied.\n */\n getCondition = () => this.condition;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => true;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): GuardAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getCondition()\n };\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n abstract isSatisfied(agent: Agent): boolean;\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A WHILE guard which is satisfied as long as the given condition remains true.\n */\nexport default class While extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"while\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return conditionFunctionResult;\n };\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An UNTIL guard which is satisfied as long as the given condition remains false.\n */\nexport default class Until extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"until\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return !conditionFunctionResult;\n };\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node callback attribute.\n */\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node callback attribute.\n */\nexport default abstract class Callback extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param functionName The name of the agent function to call.\n */\n constructor(type: string, args: any[], private functionName: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the agent function to call.\n */\n getFunctionName = () => this.functionName;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => false;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): CallbackAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getFunctionName()\n };\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n abstract callAgentFunction: (agent: Agent, isSuccess: boolean, isAborted: boolean) => void;\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An ENTRY callback which defines an agent function to call when the associated node is updated and moves out of running state.\n */\nexport default class Entry extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"entry\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call entry function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A STEP callback which defines an agent function to call when the associated node is updated.\n */\nexport default class Step extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"step\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call step function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An EXIT callback which defines an agent function to call when the associated node is updated and moves to a finished state or is aborted.\n */\nexport default class Exit extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"exit\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n * @param isSuccess Whether the decorated node was left with a success state.\n * @param isAborted Whether the decorated node was aborted.\n */\n callAgentFunction = (agent: Agent, isSuccess: boolean, isAborted: boolean) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call exit function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function\n callbackFuncInvoker([{ succeeded: isSuccess, aborted: isAborted }, ...this.args]);\n };\n}\n", "import { AnyNodeDefinition, RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport { validateBranchSubtreeLinks } from \"./BehaviourTreeDefinitionValidator\";\nimport { isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport Node from \"./nodes/Node\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Race from \"./nodes/composite/Race\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Root from \"./nodes/decorator/Root\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Lookup from \"./Lookup\";\nimport Attribute from \"./attributes/Attribute\";\nimport Guard from \"./attributes/guards/Guard\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\n/**\n * A type representing any node instance in a behaviour tree.\n */\ntype AnyNode =\n | Root\n | Action\n | Condition\n | Wait\n | Sequence\n | Selector\n | Lotto\n | Parallel\n | Race\n | Repeat\n | Retry\n | Flip\n | Succeed\n | Fail;\n\n/**\n * A type defining a mapping of root node identifiers to root node definitions.\n */\ntype RootNodeDefinitionMap = { [key: string | symbol]: RootNodeDefinition };\n\n/**\n * A symbol to use as the main root key in any root node mappings.\n */\nconst MAIN_ROOT_NODE_KEY = Symbol(\"__root__\");\n\n/**\n * Build and populate the root nodes based on the provided definition, assuming that the definition has been validated.\n * @param definition The root node definitions.\n * @param options The behaviour tree options.\n * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[], options: BehaviourTreeOptions): Root {\n // Create a mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n const rootNodeDefinitionMap = createRootNodeDefinitionMap(definition);\n\n // Now that we have all of our root node definitions (those part of the tree definition and those globally registered)\n // we should validate the branch-subtree links. This will also double-check that we dont have any circular dependencies\n // in our branch-subtree references and that we have no broken branch-subtree links.\n validateBranchSubtreeLinks(\n [rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], ...Object.values(rootNodeDefinitionMap)],\n true\n );\n\n // Create our populated tree of node instances, starting with our main root node.\n const rootNode = nodeFactory(rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], rootNodeDefinitionMap, options) as Root;\n\n // Set a guard path on every leaf of the tree to evaluate as part of each update.\n applyLeafNodeGuardPaths(rootNode);\n\n // We only need to return the main root node.\n return rootNode;\n}\n\n/**\n * A factory function which creates a node instance based on the specified definition.\n * @param definition The node definition.\n * @param rootNodeDefinitionMap The mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n * @param options The behaviour tree options.\n * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(\n definition: AnyNodeDefinition,\n rootNodeDefinitionMap: RootNodeDefinitionMap,\n options: BehaviourTreeOptions\n): AnyNode {\n // Get the attributes for the node.\n const attributes = nodeAttributesFactory(definition);\n\n // Create the node instance based on the definition type.\n switch (definition.type) {\n case \"root\":\n return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"repeat\":\n let iterations: number | null = null;\n let iterationsMin: number | null = null;\n let iterationsMax: number | null = null;\n\n if (Array.isArray(definition.iterations)) {\n iterationsMin = definition.iterations[0];\n iterationsMax = definition.iterations[1];\n } else if (isInteger(definition.iterations)) {\n iterations = definition.iterations!;\n }\n\n return new Repeat(\n attributes,\n options,\n iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"retry\":\n let attempts: number | null = null;\n let attemptsMin: number | null = null;\n let attemptsMax: number | null = null;\n\n if (Array.isArray(definition.attempts)) {\n attemptsMin = definition.attempts[0];\n attemptsMax = definition.attempts[1];\n } else if (isInteger(definition.attempts)) {\n attempts = definition.attempts!;\n }\n\n return new Retry(\n attributes,\n options,\n attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"flip\":\n return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"succeed\":\n return new Succeed(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"fail\":\n return new Fail(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"race\":\n return new Race(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n options,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap, options);\n\n case \"action\":\n return new Action(attributes, options, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, options, definition.call, definition.args || []);\n\n case \"wait\":\n let duration: number | null = null;\n let durationMin: number | null = null;\n let durationMax: number | null = null;\n\n if (Array.isArray(definition.duration)) {\n durationMin = definition.duration[0];\n durationMax = definition.duration[1];\n } else if (isInteger(definition.duration)) {\n duration = definition.duration!;\n }\n\n return new Wait(attributes, options, duration, durationMin, durationMax);\n }\n}\n\n/**\n * Creates an array of node attribute instances based on the specified node definition.\n * @param definition The node definition.\n * @returns An array of node attribute instances based on the specified node definition.\n */\nfunction nodeAttributesFactory(definition: AnyNodeDefinition): Attribute[] {\n const attributes: Attribute[] = [];\n\n if (definition.while) {\n attributes.push(new While(definition.while.call, definition.while.args ?? []));\n }\n\n if (definition.until) {\n attributes.push(new Until(definition.until.call, definition.until.args ?? []));\n }\n\n if (definition.entry) {\n attributes.push(new Entry(definition.entry.call, definition.entry.args ?? []));\n }\n\n if (definition.step) {\n attributes.push(new Step(definition.step.call, definition.step.args ?? []));\n }\n\n if (definition.exit) {\n attributes.push(new Exit(definition.exit.call, definition.exit.args ?? []));\n }\n\n return attributes;\n}\n\n/**\n * Creates a mapping of root node identifers to root node definitions, mixing in globally registered subtree root node definitions.\n * @param definition The root node definitions.\n * @returns A mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n */\nfunction createRootNodeDefinitionMap(definition: RootNodeDefinition[]): RootNodeDefinitionMap {\n // Create a mapping of root node identifers to root node definitions.\n const rootNodeMap: RootNodeDefinitionMap = {};\n\n // Add in any registered subtree root node definitions.\n for (const [name, rootNodeDefinition] of Object.entries(Lookup.getSubtrees())) {\n // The name used when registering the subtree will be used as the root node identifier.\n rootNodeMap[name] = { ...rootNodeDefinition, id: name };\n }\n\n // Populate the map with the root node definitions that were included with the tree definition.\n // We do this after adding any registered subtrees as we want these to take presedence.\n for (const rootNodeDefinition of definition) {\n rootNodeMap[rootNodeDefinition.id ?? MAIN_ROOT_NODE_KEY] = rootNodeDefinition;\n }\n\n return rootNodeMap;\n}\n\n/**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param root The main root tree node.\n */\nfunction applyLeafNodeGuardPaths(root: Root) {\n const nodePaths: Node[][] = [];\n\n const findLeafNodes = (path: Node[], node: Node) => {\n // Add the current node to the path.\n path = path.concat(node);\n\n // Check whether the current node is a leaf node.\n if (node.isLeafNode()) {\n nodePaths.push(path);\n } else {\n (node as Composite | Decorator).getChildren().forEach((child) => findLeafNodes(path, child));\n }\n };\n\n // Find all leaf node paths, starting from the root.\n findLeafNodes([], root);\n\n nodePaths.forEach((path) => {\n // Each node in the current path will have to be assigned a guard path, working from the root outwards.\n for (let depth = 0; depth < path.length; depth++) {\n // Get the node in the path at the current depth.\n const currentNode = path[depth];\n\n // The node may already have been assigned a guard path, if so just skip it.\n if (currentNode.hasGuardPath()) {\n continue;\n }\n\n // Create the guard path for the current node.\n const guardPath = new GuardPath(\n path\n .slice(0, depth + 1)\n .map((node) => ({\n node,\n guards: node.getAttributes().filter((attribute) => attribute.isGuard()) as Guard[]\n }))\n .filter((details) => details.guards.length > 0)\n );\n\n // Assign the guard path to the current node.\n currentNode.setGuardPath(guardPath);\n }\n });\n}\n", "import State, { AnyState } from \"./State\";\nimport Lookup from \"./Lookup\";\nimport Node, { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport { Agent, GlobalFunction } from \"./Agent\";\nimport { CallbackAttributeDetails } from \"./attributes/callbacks/Callback\";\nimport { GuardAttributeDetails } from \"./attributes/guards/Guard\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { validateDefinition, validateJSONDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport buildRootNode from \"./BehaviourTreeBuilder\";\nimport { isNullOrUndefined } from \"./BehaviourTreeDefinitionUtilities\";\n\n/**\n * A representation of a behaviour tree.\n */\nexport class BehaviourTree {\n /**\n * The main root tree node.\n */\n private readonly _rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition as either an MDSL string, root node definition object or array of root node definition objects.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param options The behaviour tree options object.\n */\n constructor(\n definition: string | RootNodeDefinition | RootNodeDefinition[],\n private agent: Agent,\n private options: BehaviourTreeOptions = {}\n ) {\n // The tree definition must be defined.\n if (isNullOrUndefined(definition)) {\n throw new Error(\"tree definition not defined\");\n }\n\n // The agent must be defined and not null.\n if (typeof agent !== \"object\" || agent === null) {\n throw new Error(\"the agent must be an object and not null\");\n }\n\n // We should validate the definition before we try to build the tree nodes.\n const { succeeded, errorMessage, json } = validateDefinition(definition);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(`invalid definition: ${errorMessage}`);\n }\n\n // Double check that we did actually get our json definition as part of our definition validtion.\n if (!json) {\n throw new Error(\n \"expected json definition to be returned as part of successful definition validation response\"\n );\n }\n\n try {\n // Create the populated tree of behaviour tree nodes and get the root node.\n this._rootNode = buildRootNode(json, options);\n } catch (exception) {\n // There was an issue in trying build and populate the behaviour tree.\n throw new Error(`error building tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Gets whether the tree is in the RUNNING state.\n * @returns true if the tree is in the RUNNING state, otherwise false.\n */\n public isRunning(): boolean {\n return this._rootNode.getState() === State.RUNNING;\n }\n\n /**\n * Gets the current tree state of SUCCEEDED, FAILED, READY or RUNNING.\n * @returns The current tree state.\n */\n public getState(): State {\n return this._rootNode.getState();\n }\n\n /**\n * Step the tree.\n * 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.\n * 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\n * 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.\n *\n * 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.\n */\n public step(): void {\n // If the root node has already been stepped to completion then we need to reset it.\n if (this._rootNode.getState() === State.SUCCEEDED || this._rootNode.getState() === State.FAILED) {\n this._rootNode.reset();\n }\n\n try {\n this._rootNode.update(this.agent);\n } catch (exception) {\n throw new Error(`error stepping tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Resets the tree from the root node outwards to each nested node, giving each a state of READY.\n */\n public reset(): void {\n this._rootNode.reset();\n }\n\n /**\n * Gets the details of every node in the tree, starting from the root.\n * @returns The details of every node in the tree, starting from the root.\n */\n public getTreeNodeDetails(): NodeDetails {\n return this._rootNode.getDetails();\n }\n\n /**\n * Registers the action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the function or subtree to register.\n * @param value The function or subtree definition to register.\n */\n static register(name: string, value: GlobalFunction | string | RootNodeDefinition) {\n // Are we going to register a action/condition/guard/callback function?\n if (typeof value === \"function\") {\n Lookup.setFunc(name, value);\n return;\n }\n\n // We are not registering an action/condition/guard/callback function, so we must be registering a subtree.\n if (typeof value === \"string\") {\n let rootNodeDefinitions: RootNodeDefinition[];\n\n // We will assume that any string passed in will be a mdsl definition.\n try {\n rootNodeDefinitions = convertMDSLToJSON(value);\n } catch (exception) {\n throw new Error(`error registering definition, invalid MDSL: ${(exception as Error).message}`);\n }\n\n // This function should only ever be called with a definition containing a single unnamed root node.\n if (rootNodeDefinitions.length != 1 || typeof rootNodeDefinitions[0].id !== \"undefined\") {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(rootNodeDefinitions[0]);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, rootNodeDefinitions[0]);\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // We will assume that any object passed in is a root node definition.\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(value);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, value);\n } else {\n throw new Error(\"unexpected value, expected string mdsl definition, root node json definition or function\");\n }\n }\n\n /**\n * Unregisters the registered action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the registered action/condition/guard/callback function or subtree to unregister.\n */\n static unregister(name: string): void {\n Lookup.remove(name);\n }\n\n /**\n * Unregister all registered action/condition/guard/callback functions and subtrees.\n */\n static unregisterAll(): void {\n Lookup.empty();\n }\n}\n"], - "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AACA,aAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,cAAQ,cAAc;AAItB,UAAI,cAA6B,WAAY;AAMzC,iBAASA,aAAY,aAAa,SAAS;AACvC,cAAI,YAAY,QAAQ;AAAE,sBAAU;AAAA,UAAG;AACvC,eAAK,eAAe;AACpB,eAAK,WAAW;AAAA,QACpB;AACA,eAAO,eAAeA,aAAY,WAAW,eAAe;AAAA,UAExD,KAAK,WAAY;AACb,mBAAO,KAAK;AAAA,UAChB;AAAA,UACA,YAAY;AAAA,UACZ,cAAc;AAAA,QAClB,CAAC;AACD,eAAO,eAAeA,aAAY,WAAW,WAAW;AAAA,UAEpD,KAAK,WAAY;AACb,mBAAO,KAAK;AAAA,UAChB;AAAA,UACA,KAAK,SAAU,OAAO;AAClB,iBAAK,WAAW;AAAA,UACpB;AAAA,UACA,YAAY;AAAA,UACZ,cAAc;AAAA,QAClB,CAAC;AACD,eAAOA;AAAA,MACX,EAAE;AACF,cAAQ,cAAc;AAAA;AAAA;;;ACtCtB;AAAA;AAAA;AACA,aAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,cAAQ,kBAAkB,QAAQ,oBAAoB;AAMtD,eAASC,mBAAkB,OAAO;AAC9B,eAAO,UAAU,QAAQ,UAAU;AAAA,MACvC;AACA,cAAQ,oBAAoBA;AAM5B,eAAS,gBAAgB,OAAO;AAC5B,eAAO,OAAO,UAAU,YAAY,SAAS,KAAK,KAAK,MAAM,KAAK,MAAM;AAAA,MAC5E;AACA,cAAQ,kBAAkB;AAAA;AAAA;;;ACpB1B;AAAA;AAAA;AACA,aAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,cAAQ,QAAQ;AAChB,UAAI,gBAAgB;AACpB,UAAI,cAAc;AAIlB,UAAIC,SAAuB,WAAY;AAKnC,iBAASA,OAAM,cAAc;AAEzB,eAAK,gBAAgB,CAAC;AACtB,eAAK,gBAAgB;AAAA,QACzB;AAOA,QAAAA,OAAM,UAAU,MAAM,SAAU,aAAa,SAAS;AAClD,cAAI,YAAY,QAAQ;AAAE,sBAAU;AAAA,UAAG;AAEvC,cAAI,EAAE,GAAG,YAAY,iBAAiB,OAAO,GAAG;AAC5C,kBAAM,IAAI,MAAM,wCAAwC;AAAA,UAC5D;AAEA,cAAI,sBAAsB,KAAK,cAAc,KAAK,SAAU,MAAM;AAAE,mBAAO,KAAK,gBAAgB;AAAA,UAAa,CAAC;AAC9G,cAAI,qBAAqB;AAErB,gCAAoB,WAAW;AAAA,UACnC,OACK;AAED,iBAAK,cAAc,KAAK,IAAI,cAAc,YAAY,aAAa,OAAO,CAAC;AAAA,UAC/E;AACA,iBAAO;AAAA,QACX;AAOA,QAAAA,OAAM,UAAU,SAAS,SAAU,aAAa,SAAS;AAErD,cAAI,sBAAsB,KAAK,cAAc,KAAK,SAAU,MAAM;AAAE,mBAAO,KAAK,gBAAgB;AAAA,UAAa,CAAC;AAE9G,cAAI,CAAC,qBAAqB;AACtB,mBAAO;AAAA,UACX;AAEA,cAAI,YAAY,QAAW;AAEvB,gBAAI,EAAE,GAAG,YAAY,iBAAiB,OAAO,GAAG;AAC5C,oBAAM,IAAI,MAAM,wCAAwC;AAAA,YAC5D;AACA,gCAAoB,WAAW;AAE/B,gBAAI,oBAAoB,UAAU,GAAG;AACjC,mBAAK,gBAAgB,KAAK,cAAc,OAAO,SAAU,MAAM;AAAE,uBAAO,SAAS;AAAA,cAAqB,CAAC;AAAA,YAC3G;AAAA,UACJ,OACK;AAED,iBAAK,gBAAgB,KAAK,cAAc,OAAO,SAAU,MAAM;AAAE,qBAAO,SAAS;AAAA,YAAqB,CAAC;AAAA,UAC3G;AACA,iBAAO;AAAA,QACX;AAMA,QAAAA,OAAM,UAAU,OAAO,SAAU,SAAS;AACtC,cAAI,YAAY,QAAQ;AAAE,sBAAU,CAAC;AAAA,UAAG;AAExC,cAAI,KAAK,cAAc,WAAW,GAAG;AACjC,mBAAO;AAAA,UACX;AACA,cAAI,cAAc,GAAG,YAAY,mBAAmB,QAAQ,UAAU,IAAI,OAAO,QAAQ;AACzF,cAAI,WAAW,CAAC;AAChB,eAAK,cAAc,QAAQ,SAAU,IAAI;AACrC,gBAAI,cAAc,GAAG,aAAa,UAAU,GAAG;AAC/C,qBAAS,cAAc,GAAG,cAAc,SAAS,eAAe;AAC5D,uBAAS,KAAK,WAAW;AAAA,YAC7B;AAAA,UACJ,CAAC;AACD,cAAI;AAGJ,cAAI,KAAK,eAAe;AAEpB,qBAAS,KAAK,cAAc;AAE5B,gBAAI,OAAO,WAAW,YAAY,SAAS,KAAK,UAAU,GAAG;AACzD,oBAAM,IAAI,MAAM,oFAAoF;AAAA,YACxG;AAAA,UACJ,OACK;AAED,qBAAS,KAAK,OAAO;AAAA,UACzB;AAEA,cAAI,SAAS,SAAS,KAAK,MAAM,SAAS,SAAS,MAAM;AAEzD,cAAI,CAAC,YAAY;AACb,iBAAK,OAAO,QAAQ,CAAC;AAAA,UACzB;AAEA,iBAAO;AAAA,QACX;AAOA,QAAAA,OAAM,UAAU,eAAe,SAAU,SAAS,SAAS;AACvD,cAAI,YAAY,QAAQ;AAAE,sBAAU,CAAC;AAAA,UAAG;AACxC,cAAI,iBAAiB,GAAG,YAAY,mBAAmB,QAAQ,MAAM,IAAI,QAAQ,QAAQ;AAEzF,cAAI,YAAY,GAAG;AACf,mBAAO,CAAC;AAAA,UACZ;AAEA,cAAI,EAAE,GAAG,YAAY,iBAAiB,OAAO,GAAG;AAC5C,kBAAM,IAAI,MAAM,wCAAwC;AAAA,UAC5D;AACA,cAAI,SAAS,CAAC;AAGd,iBAAO,OAAO,SAAS,WAAW,KAAK,cAAc,SAAS,GAAG;AAC7D,mBAAO,KAAK,KAAK,KAAK,OAAO,CAAC;AAAA,UAClC;AAEA,cAAI,eAAe;AAEf,gBAAI,SAAS,CAAC;AAEd,qBAAS,KAAK,GAAG,WAAW,QAAQ,KAAK,SAAS,QAAQ,MAAM;AAC5D,kBAAI,cAAc,SAAS;AAC3B,kBAAI,OAAO,QAAQ,WAAW,MAAM,IAAI;AACpC,uBAAO,KAAK,WAAW;AAAA,cAC3B;AAAA,YACJ;AACA,qBAAS;AAAA,UACb;AACA,iBAAO;AAAA,QACX;AACA,eAAOA;AAAA,MACX,EAAE;AACF,cAAQ,QAAQA;AAAA;AAAA;;;AC5JhB;AAAA;AAAA;AACA,aAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,cAAQ,cAAc;AACtB,UAAI,UAAU;AAMd,eAASC,aAAY,uBAAuB;AAExC,YAAI,CAAC,uBAAuB;AACxB,iBAAO,IAAI,QAAQ,MAAM;AAAA,QAC7B;AAEA,YAAI,MAAM,QAAQ,qBAAqB,GAAG;AAEtC,cAAI,eAAe;AACnB,cAAI,UAAU,IAAI,QAAQ,MAAM;AAEhC,uBAAa,QAAQ,SAAU,IAAI;AAC/B,gBAAI,cAAc,GAAG,IAAI,SAAS,GAAG;AACrC,mBAAO,QAAQ,IAAI,aAAa,MAAM;AAAA,UAC1C,CAAC;AAED,iBAAO;AAAA,QACX,OACK;AAED,cAAI,SAAS,sBAAsB,QAAQ,eAAe,sBAAsB;AAEhF,cAAI,UAAU,IAAI,QAAQ,MAAM,MAAM;AAEtC,cAAI,cAAc;AACd,yBAAa,QAAQ,SAAU,IAAI;AAC/B,kBAAI,cAAc,GAAG,IAAI,SAAS,GAAG;AACrC,qBAAO,QAAQ,IAAI,aAAa,MAAM;AAAA,YAC1C,CAAC;AAAA,UACL;AAEA,iBAAO;AAAA,QACX;AAAA,MACJ;AACA,cAAQ,cAAcA;AAAA;AAAA;;;AC3CtB;AAAA;AAAA;AACA,aAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,UAAI,gBAAgB;AACpB,cAAQ,UAAU,cAAc;AAAA;AAAA;;;ACHhC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,MAAK,QAAL,kBAAKC,WAAL;AAIH,IAAAA,OAAA,WAAQ;AAIR,IAAAA,OAAA,aAAU;AAIV,IAAAA,OAAA,eAAY;AAIZ,IAAAA,OAAA,YAAS;AAhBD,WAAAA;AAAA,KAAA;;;ACKZ,MAAqB,SAArB,MAA4B;AAAA,IAexB,OAAc,QAAQ,MAA8B;AAChD,aAAO,KAAK,oBAAoB;AAAA,IACpC;AAAA,IAOA,OAAc,QAAQ,MAAc,MAA4B;AAC5D,WAAK,oBAAoB,QAAQ;AAAA,IACrC;AAAA,IAUA,OAAO,eAAe,OAAc,MAAsC;AAEtE,YAAM,gBAAgB,MAAM;AAC5B,UAAI,iBAAiB,OAAO,kBAAkB,YAAY;AACtD,eAAO,CAAC,SAAgB,cAAc,MAAM,OAAO,IAAI;AAAA,MAC3D;AAGA,UAAI,KAAK,oBAAoB,SAAS,OAAO,KAAK,oBAAoB,UAAU,YAAY;AACxF,cAAM,qBAAqB,KAAK,oBAAoB;AACpD,eAAO,CAAC,SAAgB,mBAAmB,OAAO,GAAG,IAAI;AAAA,MAC7D;AAGA,aAAO;AAAA,IACX;AAAA,IAKA,OAAO,cAAqD;AACxD,aAAO,KAAK;AAAA,IAChB;AAAA,IAOA,OAAO,WAAW,MAAc,SAA6B;AACzD,WAAK,mBAAmB,QAAQ;AAAA,IACpC;AAAA,IAMA,OAAO,OAAO,MAAc;AACxB,aAAO,KAAK,oBAAoB;AAChC,aAAO,KAAK,mBAAmB;AAAA,IACnC;AAAA,IAKA,OAAO,QAAQ;AACX,WAAK,sBAAsB,CAAC;AAC5B,WAAK,qBAAqB,CAAC;AAAA,IAC/B;AAAA,EACJ;AAjFI,gBAJiB,QAIF,uBAAyD,CAAC;AAIzE,gBARiB,QAQF,sBAA4D,CAAC;;;ACFzE,WAAS,WAAW,MAAkD;AACzE,WAAO,KAAK,SAAS;AAAA,EACzB;AAOO,WAAS,aAAa,MAAoD;AAC7E,WAAO,KAAK,SAAS;AAAA,EACzB;AAOO,WAAS,WAAW,MAA8C;AACrE,WAAO,CAAC,UAAU,UAAU,aAAa,MAAM,EAAE,SAAS,KAAK,IAAI;AAAA,EACvE;AAOO,WAAS,gBAAgB,MAAuD;AACnF,WAAO,CAAC,QAAQ,UAAU,SAAS,QAAQ,WAAW,MAAM,EAAE,SAAS,KAAK,IAAI;AAAA,EACpF;AAOO,WAAS,gBAAgB,MAAuD;AACnF,WAAO,CAAC,YAAY,YAAY,SAAS,YAAY,MAAM,EAAE,SAAS,KAAK,IAAI;AAAA,EACnF;AAOO,WAAS,kBAAkB,gBAAwD;AACtF,UAAM,QAA6B,CAAC;AAEpC,UAAM,cAAc,CAAC,0BAA6C;AAC9D,YAAM,KAAK,qBAAqB;AAEhC,UAAI,gBAAgB,qBAAqB,GAAG;AACxC,8BAAsB,SAAS,QAAQ,WAAW;AAAA,MACtD,WAAW,gBAAgB,qBAAqB,GAAG;AAC/C,oBAAY,sBAAsB,KAAK;AAAA,MAC3C;AAAA,IACJ;AAEA,gBAAY,cAAc;AAE1B,WAAO;AAAA,EACX;AAOO,WAAS,UAAU,OAAyB;AAC/C,WAAO,OAAO,UAAU,YAAY,KAAK,MAAM,KAAK,MAAM;AAAA,EAC9D;AAOO,WAAS,kBAAkB,OAAyB;AACvD,WAAO,OAAO,UAAU,eAAe,UAAU;AAAA,EACrD;;;AClFO,WAAS,YAAY,QAAkB,UAAsC;AAEhF,UAAM,SAAS,OAAO,MAAM;AAG5B,QAAI,WAAW,QAAW;AACtB,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAClD;AAGA,QAAI,YAAY,QAAW;AAEvB,YAAM,iBAAiB,OAAO,aAAa,WAAW,CAAC,QAAQ,IAAI;AAGnE,UAAI,0BAA0B,eAAe,KAAK,CAAC,SAAS,OAAO,YAAY,MAAM,KAAK,YAAY,CAAC;AAGvG,UAAI,CAAC,yBAAyB;AAC1B,cAAM,oBAAoB,eAAe,IAAI,CAAC,SAAS,MAAM,OAAO,GAAG,EAAE,KAAK,MAAM;AACpF,cAAM,IAAI,MAAM,sCAAsC,oBAAoB,eAAe,SAAS,GAAG;AAAA,MACzG;AAAA,IACJ;AAGA,WAAO;AAAA,EACX;AAOO,WAAS,yBAAyB,YAGvC;AAEE,UAAM,eAA0C,CAAC;AAGjD,UAAM,sBAAsB,WAAW,QAAQ,sBAAsB,CAAC,UAAU;AAC5E,UAAI,gBAAgB,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC;AACvD,UAAI,cAAc,OAAO,KAAK,YAAY,EAAE,KAAK,CAAC,QAAQ,aAAa,SAAS,aAAa;AAG7F,UAAI,CAAC,aAAa;AACd,sBAAc,KAAK,OAAO,KAAK,YAAY,EAAE;AAC7C,qBAAa,eAAe;AAAA,MAChC;AAEA,aAAO;AAAA,IACX,CAAC;AAED,WAAO,EAAE,cAAc,oBAAoB;AAAA,EAC/C;AAOO,WAAS,0BAA0B,YAA8B;AAEpE,iBAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,iBAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,iBAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,iBAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,iBAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,iBAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,iBAAa,WAAW,QAAQ,OAAO,KAAK;AAG5C,WAAO,WAAW,QAAQ,QAAQ,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG;AAAA,EAC3D;;;AChCO,WAAS,oBACZ,QACA,4BACa;AACb,UAAM,eAA8B,CAAC;AAGrC,QAAI,CAAC,CAAC,KAAK,GAAG,EAAE,SAAS,OAAO,EAAE,GAAG;AACjC,aAAO;AAAA,IACX;AAIA,UAAM,eAAe,YAAY,QAAQ,CAAC,KAAK,GAAG,CAAC,MAAM,MAAM,MAAM;AAErE,UAAM,qBAA+B,CAAC;AAGtC,WAAO,OAAO,UAAU,OAAO,OAAO,cAAc;AAEhD,yBAAmB,KAAK,OAAO,MAAM,CAAE;AAAA,IAC3C;AAGA,uBAAmB,QAAQ,CAAC,OAAO,UAAU;AAEzC,YAAM,wBAAwB,EAAE,QAAQ;AAGxC,UAAI,uBAAuB;AAEvB,cAAM,qBAAqB,sBAAsB,OAAO,0BAA0B;AAGlF,qBAAa,KAAK,kBAAkB;AAAA,MACxC,OAAO;AAEH,YAAI,UAAU,KAAK;AACf,gBAAM,IAAI,MAAM,uDAAuD,QAAQ;AAAA,QACnF;AAAA,MACJ;AAAA,IACJ,CAAC;AAGD,gBAAY,QAAQ,YAAY;AAGhC,WAAO;AAAA,EACX;AAQA,WAAS,sBAAsB,OAAe,4BAAoE;AAE9G,QAAI,UAAU,QAAQ;AAClB,aAAO;AAAA,QACH,OAAO;AAAA,QACP,MAAM;AAAA,MACV;AAAA,IACJ;AAGA,QAAI,UAAU,UAAU,UAAU,SAAS;AACvC,aAAO;AAAA,QACH,OAAO,UAAU;AAAA,QACjB,MAAM;AAAA,MACV;AAAA,IACJ;AAKA,QAAI,CAAC,MAAM,KAAY,GAAG;AACtB,aAAO;AAAA,QACH,OAAO,WAAW,KAAK;AAAA,QACvB,WAAW,WAAW,KAAK,MAAM,SAAS,OAAO,EAAE;AAAA,QACnD,MAAM;AAAA,MACV;AAAA,IACJ;AAGA,QAAI,MAAM,MAAM,YAAY,GAAG;AAC3B,aAAO;AAAA,QACH,OAAO,2BAA2B,OAAO,QAAQ,OAAO,GAAG;AAAA,QAC3D,MAAM;AAAA,MACV;AAAA,IACJ;AAGA,WAAO;AAAA,MACH,OAAO;AAAA,MACP,MAAM;AAAA,IACV;AAAA,EACJ;;;ACjIO,WAAS,qBACZ,QACA,4BACc;AACd,UAAM,qBAA+C,CAAC,SAAS,SAAS,SAAS,QAAQ,MAAM;AAG/F,UAAM,aAA6B,CAAC;AAGpC,QAAI,oBAAoB,OAAO,IAAI,YAAY;AAG/C,WAAO,mBAAmB,SAAS,iBAAiB,GAAG;AAEnD,UAAI,WAAW,oBAAoB;AAC/B,cAAM,IAAI,MAAM,wBAAwB,OAAO,GAAG,YAAY,mBAAmB;AAAA,MACrF;AAGA,aAAO,MAAM;AAGb,YAAM,CAAC,4BAA4B,kBAAkB,IAAI;AAAA,QACrD;AAAA,QACA;AAAA,MACJ;AAGA,UAAI,yBAAyB,SAAS,cAAc;AAChD,cAAM,IAAI,MAAM,uFAAuF;AAAA,MAC3G;AAGA,yBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,EACzC,QAAQ,CAAC,QAAQ;AACd,cAAM,IAAI;AAAA,UACN,qCAAqC,IAAI;AAAA,QAC7C;AAAA,MACJ,CAAC;AAGL,iBAAW,qBAAqB;AAAA,QAC5B,MAAM,wBAAwB;AAAA,QAC9B,MAAM,mBAAmB,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK;AAAA,MACrD;AAGA,0BAAoB,OAAO,IAAI,YAAY;AAAA,IAC/C;AAEA,WAAO;AAAA,EACX;;;AClCO,WAAS,kBAAkB,YAA0C;AAExE,UAAM,EAAE,cAAc,oBAAoB,IAAI,yBAAyB,UAAU;AAGjF,UAAM,SAAS,0BAA0B,mBAAmB;AAE5D,WAAO,8BAA8B,QAAQ,YAAY;AAAA,EAC7D;AAQA,WAAS,8BACL,QACA,2BACoB;AAEpB,QAAI,OAAO,SAAS,GAAG;AACnB,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACzC;AAGA,QAAI,OAAO,OAAO,CAAC,UAAU,UAAU,GAAG,EAAE,WAAW,OAAO,OAAO,CAAC,UAAU,UAAU,GAAG,EAAE,QAAQ;AACnG,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC9C;AASA,UAAM,aAAoF,CAAC;AAG3F,UAAM,YAA2C,CAAC;AAGlD,UAAM,WAAW,CAAC,SAA4B;AAE1C,UAAI,WAAW,IAAI,GAAG;AAGlB,YAAI,WAAW,WAAW,SAAS,IAAI,QAAQ;AAC3C,gBAAM,IAAI,MAAM,iDAAiD;AAAA,QACrE;AAGA,kBAAU,KAAK,IAAI;AAGnB,mBAAW,KAAK,CAAC,IAAI,CAAC;AAEtB;AAAA,MACJ;AAIA,UAAI,CAAC,WAAW,UAAU,CAAC,WAAW,WAAW,SAAS,GAAG,QAAQ;AACjE,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC9D;AAGA,YAAM,eAAe,WAAW,WAAW,SAAS;AAIpD,YAAM,sBAAsB,aAAa,aAAa,SAAS;AAI/D,UAAI,gBAAgB,mBAAmB,GAAG;AACtC,4BAAoB,WAAW,oBAAoB,YAAY,CAAC;AAChE,4BAAoB,SAAS,KAAK,IAAI;AAAA,MAC1C,WAAW,gBAAgB,mBAAmB,GAAG;AAE7C,YAAI,oBAAoB,OAAO;AAC3B,gBAAM,IAAI,MAAM,qDAAqD;AAAA,QACzE;AAEA,4BAAoB,QAAQ;AAAA,MAChC;AAIA,UAAI,CAAC,WAAW,IAAI,GAAG;AACnB,qBAAa,KAAK,IAAI;AAAA,MAC1B;AAAA,IACJ;AAGA,UAAM,UAAU,MAAgC;AAC5C,UAAI,aAAuC;AAG3C,YAAM,eAAe,WAAW,WAAW,SAAS;AAGpD,UAAI,aAAa,QAAQ;AACrB,qBAAa,aAAa,IAAI;AAAA,MAClC;AAGA,UAAI,CAAC,aAAa,QAAQ;AACtB,mBAAW,IAAI;AAAA,MACnB;AAEA,aAAO;AAAA,IACX;AAGA,WAAO,OAAO,QAAQ;AAElB,YAAM,QAAQ,OAAO,MAAM;AAG3B,cAAQ,MAAM,YAAY,GAAG;AAAA,QACzB,KAAK,QAAQ;AACT,mBAAS,eAAe,QAAQ,yBAAyB,CAAC;AAC1D;AAAA,QACJ;AAAA,QAEA,KAAK,WAAW;AACZ,mBAAS,kBAAkB,QAAQ,yBAAyB,CAAC;AAC7D;AAAA,QACJ;AAAA,QAEA,KAAK,QAAQ;AACT,mBAAS,eAAe,QAAQ,yBAAyB,CAAC;AAC1D;AAAA,QACJ;AAAA,QAEA,KAAK,QAAQ;AACT,mBAAS,eAAe,QAAQ,yBAAyB,CAAC;AAC1D;AAAA,QACJ;AAAA,QAEA,KAAK,UAAU;AACX,mBAAS,iBAAiB,QAAQ,yBAAyB,CAAC;AAC5D;AAAA,QACJ;AAAA,QAEA,KAAK,SAAS;AACV,mBAAS,gBAAgB,QAAQ,yBAAyB,CAAC;AAC3D;AAAA,QACJ;AAAA,QAEA,KAAK,YAAY;AACb,mBAAS,mBAAmB,QAAQ,yBAAyB,CAAC;AAC9D;AAAA,QACJ;AAAA,QAEA,KAAK,YAAY;AACb,mBAAS,mBAAmB,QAAQ,yBAAyB,CAAC;AAC9D;AAAA,QACJ;AAAA,QAEA,KAAK,YAAY;AACb,mBAAS,mBAAmB,QAAQ,yBAAyB,CAAC;AAC9D;AAAA,QACJ;AAAA,QAEA,KAAK,QAAQ;AACT,mBAAS,eAAe,QAAQ,yBAAyB,CAAC;AAC1D;AAAA,QACJ;AAAA,QAEA,KAAK,SAAS;AACV,mBAAS,gBAAgB,QAAQ,yBAAyB,CAAC;AAC3D;AAAA,QACJ;AAAA,QAEA,KAAK,UAAU;AACX,mBAAS,iBAAiB,QAAQ,yBAAyB,CAAC;AAC5D;AAAA,QACJ;AAAA,QAEA,KAAK,aAAa;AACd,mBAAS,oBAAoB,QAAQ,yBAAyB,CAAC;AAC/D;AAAA,QACJ;AAAA,QAEA,KAAK,QAAQ;AACT,mBAAS,eAAe,QAAQ,yBAAyB,CAAC;AAC1D;AAAA,QACJ;AAAA,QAEA,KAAK,UAAU;AACX,mBAAS,iBAAiB,QAAQ,yBAAyB,CAAC;AAC5D;AAAA,QACJ;AAAA,QAEA,KAAK,KAAK;AAEN,gBAAM,aAAa,QAAQ;AAG3B,cAAI,YAAY;AACZ,+BAAmB,UAAU;AAAA,UACjC;AAEA;AAAA,QACJ;AAAA,QAEA,SAAS;AACL,gBAAM,IAAI,MAAM,qBAAqB,OAAO;AAAA,QAChD;AAAA,MACJ;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAQA,WAAS,eAAe,QAAkB,2BAA0E;AAEhH,QAAI,OAAO;AAAA,MACP,MAAM;AAAA,IACV;AAGA,UAAM,gBAAgB,oBAAoB,QAAQ,yBAAyB;AAG3E,QAAI,cAAc,QAAQ;AAEtB,UAAI,cAAc,WAAW,KAAK,cAAc,GAAG,SAAS,cAAc;AAEtE,aAAK,KAAK,cAAc,GAAG;AAAA,MAC/B,OAAO;AACH,cAAM,IAAI,MAAM,oCAAoC;AAAA,MACxD;AAAA,IACJ;AAGA,WAAO,EAAE,GAAG,MAAM,GAAG,qBAAqB,QAAQ,yBAAyB,EAAE;AAG7E,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,kBACL,QACA,2BACqB;AACrB,UAAM,OAAO;AAAA,MACT,MAAM;AAAA,MACN,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAGA,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,eAAe,QAAkB,2BAA0E;AAChH,UAAM,OAAO;AAAA,MACT,MAAM;AAAA,MACN,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAGA,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,eAAe,QAAkB,2BAA0E;AAChH,UAAM,OAAO;AAAA,MACT,MAAM;AAAA,MACN,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAGA,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,iBACL,QACA,2BACoB;AACpB,QAAI,OAAO,EAAE,MAAM,SAAS;AAG5B,UAAM,gBAAgB,oBAAoB,QAAQ,yBAAyB;AAM3E,QAAI,cAAc,QAAQ;AAEtB,oBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,CAAC,IAAI,SAAS,EACvD,QAAQ,MAAM;AACX,cAAM,IAAI,MAAM,qDAAqD;AAAA,MACzE,CAAC;AAGL,UAAI,cAAc,WAAW,GAAG;AAE5B,aAAK,aAAa,cAAc,GAAG;AAGnC,YAAI,KAAK,aAAa,GAAG;AACrB,gBAAM,IAAI,MAAM,oEAAoE;AAAA,QACxF;AAAA,MACJ,WAAW,cAAc,WAAW,GAAG;AAEnC,aAAK,aAAa,CAAC,cAAc,GAAG,OAAiB,cAAc,GAAG,KAAe;AAGrF,YAAI,KAAK,WAAW,KAAK,KAAK,KAAK,WAAW,KAAK,GAAG;AAClD,gBAAM,IAAI,MAAM,mFAAmF;AAAA,QACvG;AAGA,YAAI,KAAK,WAAW,KAAK,KAAK,WAAW,IAAI;AACzC,gBAAM,IAAI;AAAA,YACN;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ,OAAO;AAEH,cAAM,IAAI,MAAM,iEAAiE;AAAA,MACrF;AAAA,IACJ;AAGA,WAAO,EAAE,GAAG,MAAM,GAAG,qBAAqB,QAAQ,yBAAyB,EAAE;AAG7E,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,gBAAgB,QAAkB,2BAA2E;AAClH,QAAI,OAAO,EAAE,MAAM,QAAQ;AAG3B,UAAM,gBAAgB,oBAAoB,QAAQ,yBAAyB;AAM3E,QAAI,cAAc,QAAQ;AAEtB,oBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,CAAC,IAAI,SAAS,EACvD,QAAQ,MAAM;AACX,cAAM,IAAI,MAAM,kDAAkD;AAAA,MACtE,CAAC;AAGL,UAAI,cAAc,WAAW,GAAG;AAE5B,aAAK,WAAW,cAAc,GAAG;AAGjC,YAAI,KAAK,WAAW,GAAG;AACnB,gBAAM,IAAI,MAAM,iEAAiE;AAAA,QACrF;AAAA,MACJ,WAAW,cAAc,WAAW,GAAG;AAEnC,aAAK,WAAW,CAAC,cAAc,GAAG,OAAiB,cAAc,GAAG,KAAe;AAGnF,YAAI,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK,GAAG;AAC9C,gBAAM,IAAI,MAAM,gFAAgF;AAAA,QACpG;AAGA,YAAI,KAAK,SAAS,KAAK,KAAK,SAAS,IAAI;AACrC,gBAAM,IAAI;AAAA,YACN;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ,OAAO;AAEH,cAAM,IAAI,MAAM,8DAA8D;AAAA,MAClF;AAAA,IACJ;AAGA,WAAO,EAAE,GAAG,MAAM,GAAG,qBAAqB,QAAQ,yBAAyB,EAAE;AAG7E,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,mBACL,QACA,2BACsB;AACtB,UAAM,OAAO;AAAA,MACT,MAAM;AAAA,MACN,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAGA,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,mBACL,QACA,2BACsB;AACtB,UAAM,OAAO;AAAA,MACT,MAAM;AAAA,MACN,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAGA,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,mBACL,QACA,2BACsB;AACtB,UAAM,OAAO;AAAA,MACT,MAAM;AAAA,MACN,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAGA,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,eAAe,QAAkB,2BAA0E;AAChH,UAAM,OAAO;AAAA,MACT,MAAM;AAAA,MACN,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAGA,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,gBAAgB,QAAkB,2BAA2E;AAElH,UAAM,gBAAgB,oBAAoB,QAAQ,yBAAyB;AAG3E,kBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,CAAC,IAAI,aAAa,IAAI,QAAQ,CAAC,EACxE,QAAQ,MAAM;AACX,YAAM,IAAI,MAAM,6DAA6D;AAAA,IACjF,CAAC;AAEL,UAAM,OAAO;AAAA,MACT,MAAM;AAAA,MACN,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAGA,QAAI,cAAc,QAAQ;AACtB,WAAK,UAAU,cAAc,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK;AAAA,IACzD;AAGA,gBAAY,QAAQ,GAAG;AAGvB,WAAO;AAAA,EACX;AAQA,WAAS,iBACL,QACA,2BACoB;AAGpB,UAAM,CAAC,yBAAyB,iBAAiB,IAAI,oBAAoB,QAAQ,yBAAyB;AAG1G,QAAI,sBAAsB,SAAS,cAAc;AAC7C,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC9D;AAGA,sBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,EACzC,QAAQ,CAAC,QAAQ;AACd,YAAM,IAAI;AAAA,QACN,uCAAuC,IAAI;AAAA,MAC/C;AAAA,IACJ,CAAC;AAGL,WAAO;AAAA,MACH,MAAM;AAAA,MACN,MAAM,qBAAqB;AAAA,MAC3B,MAAM,kBAAkB,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK;AAAA,MAChD,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAAA,EACJ;AAQA,WAAS,oBACL,QACA,2BACuB;AAGvB,UAAM,CAAC,4BAA4B,iBAAiB,IAAI,oBAAoB,QAAQ,yBAAyB;AAG7G,QAAI,yBAAyB,SAAS,cAAc;AAChD,YAAM,IAAI,MAAM,6CAA6C;AAAA,IACjE;AAGA,sBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,EACzC,QAAQ,CAAC,QAAQ;AACd,YAAM,IAAI;AAAA,QACN,0CAA0C,IAAI;AAAA,MAClD;AAAA,IACJ,CAAC;AAGL,WAAO;AAAA,MACH,MAAM;AAAA,MACN,MAAM,wBAAwB;AAAA,MAC9B,MAAM,kBAAkB,IAAI,CAAC,EAAE,MAAM,MAAM,KAAK;AAAA,MAChD,GAAG,qBAAqB,QAAQ,yBAAyB;AAAA,IAC7D;AAAA,EACJ;AAQA,WAAS,eAAe,QAAkB,2BAA0E;AAChH,QAAI,OAAO,EAAE,MAAM,OAAO;AAG1B,UAAM,gBAAgB,oBAAoB,QAAQ,yBAAyB;AAM3E,QAAI,cAAc,QAAQ;AAEtB,oBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,CAAC,IAAI,SAAS,EACvD,QAAQ,MAAM;AACX,cAAM,IAAI,MAAM,4CAA4C;AAAA,MAChE,CAAC;AAML,UAAI,cAAc,WAAW,GAAG;AAE5B,aAAK,WAAW,cAAc,GAAG;AAGjC,YAAI,KAAK,WAAW,GAAG;AACnB,gBAAM,IAAI,MAAM,2CAA2C;AAAA,QAC/D;AAAA,MACJ,WAAW,cAAc,WAAW,GAAG;AAEnC,aAAK,WAAW,CAAC,cAAc,GAAG,OAAiB,cAAc,GAAG,KAAe;AAGnF,YAAI,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK,GAAG;AAC9C,gBAAM,IAAI,MAAM,+DAA+D;AAAA,QACnF;AAGA,YAAI,KAAK,SAAS,KAAK,KAAK,SAAS,IAAI;AACrC,gBAAM,IAAI,MAAM,gFAAgF;AAAA,QACpG;AAAA,MACJ,WAAW,cAAc,SAAS,GAAG;AAEjC,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC5E;AAAA,IACJ;AAGA,WAAO,EAAE,GAAG,MAAM,GAAG,qBAAqB,QAAQ,yBAAyB,EAAE;AAAA,EACjF;AAQA,WAAS,iBACL,QACA,2BACoB;AAEpB,UAAM,gBAAgB,oBAAoB,QAAQ,yBAAyB;AAG3E,QAAI,cAAc,WAAW,KAAK,cAAc,GAAG,SAAS,cAAc;AACtE,YAAM,IAAI,MAAM,sCAAsC;AAAA,IAC1D;AAGA,WAAO,EAAE,MAAM,UAAU,KAAK,cAAc,GAAG,MAAM;AAAA,EACzD;AAMA,WAAS,mBAAmB,YAAqC;AAE7D,QAAI,gBAAgB,UAAU,KAAK,kBAAkB,WAAW,KAAK,GAAG;AACpE,YAAM,IAAI,MAAM,KAAK,WAAW,iDAAiD;AAAA,IACrF;AAGA,QAAI,gBAAgB,UAAU,KAAK,CAAC,WAAW,UAAU,QAAQ;AAC7D,YAAM,IAAI,MAAM,KAAK,WAAW,0DAA0D;AAAA,IAC9F;AAGA,QAAI,WAAW,SAAS,SAAS;AAE7B,UAAI,OAAO,WAAW,YAAY,aAAa;AAE3C,YAAI,WAAW,QAAQ,WAAW,WAAW,SAAS,QAAQ;AAC1D,gBAAM,IAAI;AAAA,YACN;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;;;ACvvBO,WAAS,mBAAmB,YAA6C;AAE5E,QAAI,eAAe,QAAQ,OAAO,eAAe,aAAa;AAC1D,aAAO,8BAA8B,iCAAiC;AAAA,IAC1E;AAMA,QAAI,OAAO,eAAe,UAAU;AAEhC,aAAO,uBAAuB,UAAU;AAAA,IAC5C,WAAW,OAAO,eAAe,UAAU;AAEvC,aAAO,uBAAuB,UAAU;AAAA,IAC5C,OAAO;AACH,aAAO,8BAA8B,kCAAkC,OAAO,aAAa;AAAA,IAC/F;AAAA,EACJ;AAOA,WAAS,uBAAuB,YAAgD;AAC5E,QAAI;AAGJ,QAAI;AAEA,4BAAsB,kBAAkB,UAAU;AAAA,IACtD,SAAS,WAAP;AAEE,aAAO,8BAA+B,UAAoB,OAAO;AAAA,IACrE;AAGA,UAAM,0BAA0B,oBAAoB,OAAO,CAAC,EAAE,GAAG,MAAM,OAAO,OAAO,WAAW;AAChG,UAAM,yBAAyB,oBAAoB,OAAO,CAAC,EAAE,GAAG,MAAM,OAAO,OAAO,YAAY,GAAG,SAAS,CAAC;AAG7G,QAAI,wBAAwB,WAAW,GAAG;AACtC,aAAO;AAAA,QACH;AAAA,MACJ;AAAA,IACJ;AAGA,UAAM,yBAAmC,CAAC;AAC1C,eAAW,EAAE,GAAG,KAAK,wBAAwB;AAEzC,UAAI,uBAAuB,SAAS,EAAG,GAAG;AACtC,eAAO,8BAA8B,kDAAkD,KAAK;AAAA,MAChG;AAEA,6BAAuB,KAAK,EAAG;AAAA,IACnC;AAEA,QAAI;AAEA,iCAA2B,qBAAqB,KAAK;AAAA,IACzD,SAAS,WAAP;AACE,aAAO,8BAA+B,UAAoB,OAAO;AAAA,IACrE;AAGA,WAAO;AAAA,MACH,WAAW;AAAA,MACX,MAAM;AAAA,IACV;AAAA,EACJ;AAOO,WAAS,uBACZ,YAC0B;AAE1B,UAAM,sBAAsB,MAAM,QAAQ,UAAU,IAAI,aAAa,CAAC,UAAU;AAGhF,QAAI;AACA,0BAAoB,QAAQ,CAAC,uBAAuB,aAAa,oBAAoB,CAAC,CAAC;AAAA,IAC3F,SAAS,OAAP;AAEE,UAAI,iBAAiB,OAAO;AACxB,eAAO,8BAA8B,MAAM,OAAO;AAAA,MACtD;AAGA,aAAO,8BAA8B,qBAAqB,OAAO;AAAA,IACrE;AAGA,UAAM,0BAA0B,oBAAoB,OAAO,CAAC,EAAE,GAAG,MAAM,OAAO,OAAO,WAAW;AAChG,UAAM,yBAAyB,oBAAoB,OAAO,CAAC,EAAE,GAAG,MAAM,OAAO,OAAO,YAAY,GAAG,SAAS,CAAC;AAG7G,QAAI,wBAAwB,WAAW,GAAG;AACtC,aAAO;AAAA,QACH;AAAA,MACJ;AAAA,IACJ;AAGA,UAAM,yBAAmC,CAAC;AAC1C,eAAW,EAAE,GAAG,KAAK,wBAAwB;AAEzC,UAAI,uBAAuB,SAAS,EAAG,GAAG;AACtC,eAAO;AAAA,UACH,oEAAoE;AAAA,QACxE;AAAA,MACJ;AAEA,6BAAuB,KAAK,EAAG;AAAA,IACnC;AAEA,QAAI;AAEA,iCAA2B,qBAAqB,KAAK;AAAA,IACzD,SAAS,WAAP;AACE,aAAO,8BAA+B,UAAoB,OAAO;AAAA,IACrE;AAGA,WAAO;AAAA,MACH,WAAW;AAAA,MACX,MAAM;AAAA,IACV;AAAA,EACJ;AASO,WAAS,2BAA2B,qBAA2C,wBAAiC;AAInH,UAAM,mBAAiE,oBAAoB;AAAA,MACvF,CAAC,wBAAwB;AAAA,QACrB,IAAI,mBAAmB;AAAA,QACvB,MAAM,kBAAkB,kBAAkB,EACrC,OAAO,YAAY,EACnB,IAAI,CAAC,EAAE,IAAI,MAAM,GAAG;AAAA,MAC7B;AAAA,IACJ;AAGA,UAAM,aAAa,CAAC,SAAqD,OAA+B,CAAC,MAAM;AAE3G,UAAI,KAAK,SAAS,QAAQ,EAAE,GAAG;AAE3B,cAAM,UAAU,CAAC,GAAG,MAAM,QAAQ,EAAE;AAGpC,cAAM,mBAAmB,QAAQ,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,KAAK,MAAM;AAG3E,cAAM,IAAI,MAAM,wDAAwD,kBAAkB;AAAA,MAC9F;AAEA,iBAAW,OAAO,QAAQ,MAAM;AAE5B,cAAM,aAAa,iBAAiB,KAAK,CAAC,EAAE,GAAG,MAAM,OAAO,GAAG;AAG/D,YAAI,YAAY;AACZ,qBAAW,YAAY,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAC;AAAA,QAChD,WAAW,wBAAwB;AAE/B,gBAAM,IAAI;AAAA,YACN,QAAQ,KACF,YAAY,QAAQ,kDAAkD,oCACtE,2DAA2D;AAAA,UACrE;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAGA,eAAW,iBAAiB,KAAK,CAAC,YAAY,OAAO,QAAQ,OAAO,WAAW,CAAE;AAAA,EACrF;AAOA,WAAS,aAAa,YAAiB,OAAqB;AAExD,QAAI,OAAO,eAAe,YAAY,OAAO,WAAW,SAAS,YAAY,WAAW,KAAK,WAAW,GAAG;AACvG,YAAM,IAAI;AAAA,QACN,2FAA2F;AAAA,MAC/F;AAAA,IACJ;AAGA,QAAI,UAAU,KAAK,WAAW,SAAS,QAAQ;AAC3C,YAAM,IAAI,MAAM,kEAAkE,WAAW,OAAO;AAAA,IACxG;AAGA,YAAQ,WAAW,MAAM;AAAA,MACrB,KAAK;AACD,2BAAmB,YAAY,KAAK;AACpC;AAAA,MAEJ,KAAK;AACD,8BAAsB,YAAY,KAAK;AACvC;AAAA,MAEJ,KAAK;AACD,yBAAiB,YAAY,KAAK;AAClC;AAAA,MAEJ,KAAK;AACD,2BAAmB,YAAY,KAAK;AACpC;AAAA,MAEJ,KAAK;AACD,yBAAiB,YAAY,KAAK;AAClC;AAAA,MAEJ,KAAK;AACD,4BAAoB,YAAY,KAAK;AACrC;AAAA,MAEJ,KAAK;AACD,yBAAiB,YAAY,KAAK;AAClC;AAAA,MAEJ,KAAK;AACD,yBAAiB,YAAY,KAAK;AAClC;AAAA,MAEJ,KAAK;AACD,2BAAmB,YAAY,KAAK;AACpC;AAAA,MAEJ,KAAK;AACD,0BAAkB,YAAY,KAAK;AACnC;AAAA,MAEJ,KAAK;AACD,6BAAqB,YAAY,KAAK;AACtC;AAAA,MAEJ,KAAK;AACD,6BAAqB,YAAY,KAAK;AACtC;AAAA,MAEJ,KAAK;AACD,6BAAqB,YAAY,KAAK;AACtC;AAAA,MAEJ,KAAK;AACD,yBAAiB,YAAY,KAAK;AAClC;AAAA,MAEJ,KAAK;AACD,0BAAkB,YAAY,KAAK;AACnC;AAAA,MAEJ;AACI,cAAM,IAAI,MAAM,4BAA4B,WAAW,mBAAmB,QAAQ;AAAA,IAC1F;AAAA,EACJ;AAOA,WAAS,uBAAuB,YAAiB,OAAqB;AAElE,KAAC,SAAS,SAAS,SAAS,QAAQ,MAAM,EAAE,QAAQ,CAAC,kBAAkB;AAEnE,YAAM,sBAAsB,WAAW;AAGvC,UAAI,OAAO,wBAAwB,aAAa;AAC5C;AAAA,MACJ;AAGA,UAAI,OAAO,wBAAwB,UAAU;AACzC,cAAM,IAAI;AAAA,UACN,uBAAuB,uCAAuC,WAAW,wBAAwB;AAAA,QACrG;AAAA,MACJ;AAGA,UAAI,OAAO,oBAAoB,SAAS,YAAY,oBAAoB,KAAK,WAAW,GAAG;AACvF,cAAM,IAAI;AAAA,UACN,2CAA2C,gDAAgD,WAAW,wBAAwB;AAAA,QAClI;AAAA,MACJ;AAGA,UAAI,OAAO,oBAAoB,SAAS,eAAe,CAAC,MAAM,QAAQ,oBAAoB,IAAI,GAAG;AAC7F,cAAM,IAAI;AAAA,UACN,2CAA2C,sCAAsC,WAAW,wBAAwB;AAAA,QACxH;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAOA,WAAS,iBAAiB,YAAiB,OAAqB;AAE5D,QAAI,WAAW,SAAS,QAAQ;AAC5B,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAChE;AAGA,QAAI,QAAQ,GAAG;AACX,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACrE;AAGA,QAAI,OAAO,WAAW,OAAO,gBAAgB,OAAO,WAAW,OAAO,YAAY,WAAW,GAAG,WAAW,IAAI;AAC3G,YAAM,IAAI,MAAM,sEAAsE;AAAA,IAC1F;AAGA,QAAI,OAAO,WAAW,UAAU,aAAa;AACzC,YAAM,IAAI,MAAM,uDAAuD;AAAA,IAC3E;AAGA,2BAAuB,YAAY,KAAK;AAGxC,iBAAa,WAAW,OAAO,QAAQ,CAAC;AAAA,EAC5C;AAOA,WAAS,oBAAoB,YAAiB,OAAqB;AAE/D,QAAI,WAAW,SAAS,WAAW;AAC/B,YAAM,IAAI,MAAM,8DAA8D,QAAQ;AAAA,IAC1F;AAGA,QAAI,OAAO,WAAW,UAAU,aAAa;AACzC,YAAM,IAAI,MAAM,sEAAsE,QAAQ;AAAA,IAClG;AAGA,2BAAuB,YAAY,KAAK;AAGxC,iBAAa,WAAW,OAAO,QAAQ,CAAC;AAAA,EAC5C;AAOA,WAAS,iBAAiB,YAAiB,OAAqB;AAE5D,QAAI,WAAW,SAAS,QAAQ;AAC5B,YAAM,IAAI,MAAM,wDAAwD,QAAQ;AAAA,IACpF;AAGA,QAAI,OAAO,WAAW,UAAU,aAAa;AACzC,YAAM,IAAI,MAAM,mEAAmE,QAAQ;AAAA,IAC/F;AAGA,2BAAuB,YAAY,KAAK;AAGxC,iBAAa,WAAW,OAAO,QAAQ,CAAC;AAAA,EAC5C;AAOA,WAAS,iBAAiB,YAAiB,OAAqB;AAE5D,QAAI,WAAW,SAAS,QAAQ;AAC5B,YAAM,IAAI,MAAM,wDAAwD,QAAQ;AAAA,IACpF;AAGA,QAAI,OAAO,WAAW,UAAU,aAAa;AACzC,YAAM,IAAI,MAAM,mEAAmE,QAAQ;AAAA,IAC/F;AAGA,2BAAuB,YAAY,KAAK;AAGxC,iBAAa,WAAW,OAAO,QAAQ,CAAC;AAAA,EAC5C;AAOA,WAAS,mBAAmB,YAAiB,OAAqB;AAE9D,QAAI,WAAW,SAAS,UAAU;AAC9B,YAAM,IAAI,MAAM,4DAA4D,QAAQ;AAAA,IACxF;AAGA,QAAI,OAAO,WAAW,UAAU,aAAa;AACzC,YAAM,IAAI,MAAM,qEAAqE,QAAQ;AAAA,IACjG;AAGA,QAAI,OAAO,WAAW,eAAe,aAAa;AAC9C,UAAI,MAAM,QAAQ,WAAW,UAAU,GAAG;AAEtC,cAAM,qBAAqB,CAAC,CAAC,WAAW,WAAW,OAAO,CAAC,UAAmB,CAAC,UAAU,KAAK,CAAC,EAAE;AAGjG,YAAI,WAAW,WAAW,WAAW,KAAK,oBAAoB;AAC1D,gBAAM,IAAI;AAAA,YACN,+GAA+G;AAAA,UACnH;AAAA,QACJ;AAGA,YAAI,WAAW,WAAW,KAAK,KAAK,WAAW,WAAW,KAAK,GAAG;AAC9D,gBAAM,IAAI;AAAA,YACN,yHAAyH;AAAA,UAC7H;AAAA,QACJ;AAGA,YAAI,WAAW,WAAW,KAAK,WAAW,WAAW,IAAI;AACrD,gBAAM,IAAI;AAAA,YACN,sJAAsJ;AAAA,UAC1J;AAAA,QACJ;AAAA,MACJ,WAAW,UAAU,WAAW,UAAU,GAAG;AAEzC,YAAI,WAAW,aAAa,GAAG;AAC3B,gBAAM,IAAI;AAAA,YACN,qGAAqG;AAAA,UACzG;AAAA,QACJ;AAAA,MACJ,OAAO;AACH,cAAM,IAAI;AAAA,UACN,gIAAgI;AAAA,QACpI;AAAA,MACJ;AAAA,IACJ;AAGA,2BAAuB,YAAY,KAAK;AAGxC,iBAAa,WAAW,OAAO,QAAQ,CAAC;AAAA,EAC5C;AAOA,WAAS,kBAAkB,YAAiB,OAAqB;AAE7D,QAAI,WAAW,SAAS,SAAS;AAC7B,YAAM,IAAI,MAAM,0DAA0D,QAAQ;AAAA,IACtF;AAGA,QAAI,OAAO,WAAW,UAAU,aAAa;AACzC,YAAM,IAAI,MAAM,oEAAoE,QAAQ;AAAA,IAChG;AAGA,QAAI,OAAO,WAAW,aAAa,aAAa;AAC5C,UAAI,MAAM,QAAQ,WAAW,QAAQ,GAAG;AAEpC,cAAM,qBAAqB,CAAC,CAAC,WAAW,SAAS,OAAO,CAAC,UAAmB,CAAC,UAAU,KAAK,CAAC,EAAE;AAG/F,YAAI,WAAW,SAAS,WAAW,KAAK,oBAAoB;AACxD,gBAAM,IAAI;AAAA,YACN,4GAA4G;AAAA,UAChH;AAAA,QACJ;AAGA,YAAI,WAAW,SAAS,KAAK,KAAK,WAAW,SAAS,KAAK,GAAG;AAC1D,gBAAM,IAAI;AAAA,YACN,oHAAoH;AAAA,UACxH;AAAA,QACJ;AAGA,YAAI,WAAW,SAAS,KAAK,WAAW,SAAS,IAAI;AACjD,gBAAM,IAAI;AAAA,YACN,+IAA+I;AAAA,UACnJ;AAAA,QACJ;AAAA,MACJ,WAAW,UAAU,WAAW,QAAQ,GAAG;AAEvC,YAAI,WAAW,WAAW,GAAG;AACzB,gBAAM,IAAI;AAAA,YACN,gGAAgG;AAAA,UACpG;AAAA,QACJ;AAAA,MACJ,OAAO;AACH,cAAM,IAAI;AAAA,UACN,6HAA6H;AAAA,QACjI;AAAA,MACJ;AAAA,IACJ;AAGA,2BAAuB,YAAY,KAAK;AAGxC,iBAAa,WAAW,OAAO,QAAQ,CAAC;AAAA,EAC5C;AAOA,WAAS,mBAAmB,YAAiB,OAAqB;AAE9D,QAAI,WAAW,SAAS,UAAU;AAC9B,YAAM,IAAI,MAAM,4DAA4D,QAAQ;AAAA,IACxF;AAGA,QAAI,OAAO,WAAW,QAAQ,YAAY,WAAW,IAAI,WAAW,GAAG;AACnE,YAAM,IAAI,MAAM,0EAA0E,QAAQ;AAAA,IACtG;AAGA,KAAC,SAAS,OAAO,EAAE,QAAQ,CAAC,kBAAkB;AAC1C,UAAI,OAAO,WAAW,mBAAmB,aAAa;AAClD,cAAM,IAAI;AAAA,UACN,4DAA4D,wDAAwD;AAAA,QACxH;AAAA,MACJ;AAAA,IACJ,CAAC;AAGD,KAAC,SAAS,QAAQ,MAAM,EAAE,QAAQ,CAAC,kBAAkB;AACjD,UAAI,OAAO,WAAW,mBAAmB,aAAa;AAClD,cAAM,IAAI;AAAA,UACN,kEAAkE,wDAAwD;AAAA,QAC9H;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAOA,WAAS,mBAAmB,YAAiB,OAAqB;AAE9D,QAAI,WAAW,SAAS,UAAU;AAC9B,YAAM,IAAI,MAAM,4DAA4D,QAAQ;AAAA,IACxF;AAGA,QAAI,OAAO,WAAW,SAAS,YAAY,WAAW,KAAK,WAAW,GAAG;AACrE,YAAM,IAAI,MAAM,0EAA0E,QAAQ;AAAA,IACtG;AAGA,QAAI,OAAO,WAAW,SAAS,eAAe,CAAC,MAAM,QAAQ,WAAW,IAAI,GAAG;AAC3E,YAAM,IAAI,MAAM,2EAA2E,QAAQ;AAAA,IACvG;AAGA,2BAAuB,YAAY,KAAK;AAAA,EAC5C;AAOA,WAAS,sBAAsB,YAAiB,OAAqB;AAEjE,QAAI,WAAW,SAAS,aAAa;AACjC,YAAM,IAAI,MAAM,kEAAkE,QAAQ;AAAA,IAC9F;AAGA,QAAI,OAAO,WAAW,SAAS,YAAY,WAAW,KAAK,WAAW,GAAG;AACrE,YAAM,IAAI,MAAM,6EAA6E,QAAQ;AAAA,IACzG;AAGA,QAAI,OAAO,WAAW,SAAS,eAAe,CAAC,MAAM,QAAQ,WAAW,IAAI,GAAG;AAC3E,YAAM,IAAI,MAAM,8EAA8E,QAAQ;AAAA,IAC1G;AAGA,2BAAuB,YAAY,KAAK;AAAA,EAC5C;AAOA,WAAS,iBAAiB,YAAiB,OAAqB;AAE5D,QAAI,WAAW,SAAS,QAAQ;AAC5B,YAAM,IAAI,MAAM,wDAAwD,QAAQ;AAAA,IACpF;AAGA,QAAI,OAAO,WAAW,aAAa,aAAa;AAC5C,UAAI,MAAM,QAAQ,WAAW,QAAQ,GAAG;AAEpC,cAAM,qBAAqB,CAAC,CAAC,WAAW,SAAS,OAAO,CAAC,UAAmB,CAAC,UAAU,KAAK,CAAC,EAAE;AAG/F,YAAI,WAAW,SAAS,WAAW,KAAK,oBAAoB;AACxD,gBAAM,IAAI;AAAA,YACN,2GAA2G;AAAA,UAC/G;AAAA,QACJ;AAGA,YAAI,WAAW,SAAS,KAAK,KAAK,WAAW,SAAS,KAAK,GAAG;AAC1D,gBAAM,IAAI;AAAA,YACN,6GAA6G;AAAA,UACjH;AAAA,QACJ;AAGA,YAAI,WAAW,SAAS,KAAK,WAAW,SAAS,IAAI;AACjD,gBAAM,IAAI;AAAA,YACN,8IAA8I;AAAA,UAClJ;AAAA,QACJ;AAAA,MACJ,WAAW,UAAU,WAAW,QAAQ,GAAG;AAEvC,YAAI,WAAW,WAAW,GAAG;AACzB,gBAAM,IAAI;AAAA,YACN,+FAA+F;AAAA,UACnG;AAAA,QACJ;AAAA,MACJ,OAAO;AACH,cAAM,IAAI;AAAA,UACN,4HAA4H;AAAA,QAChI;AAAA,MACJ;AAAA,IACJ;AAGA,2BAAuB,YAAY,KAAK;AAAA,EAC5C;AAOA,WAAS,qBAAqB,YAAiB,OAAqB;AAEhE,QAAI,WAAW,SAAS,YAAY;AAChC,YAAM,IAAI,MAAM,gEAAgE,QAAQ;AAAA,IAC5F;AAGA,QAAI,CAAC,MAAM,QAAQ,WAAW,QAAQ,KAAK,WAAW,SAAS,WAAW,GAAG;AACzE,YAAM,IAAI,MAAM,iFAAiF,QAAQ;AAAA,IAC7G;AAGA,2BAAuB,YAAY,KAAK;AAGxC,eAAW,SAAS,QAAQ,CAAC,UAAe,aAAa,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9E;AAOA,WAAS,qBAAqB,YAAiB,OAAqB;AAEhE,QAAI,WAAW,SAAS,YAAY;AAChC,YAAM,IAAI,MAAM,gEAAgE,QAAQ;AAAA,IAC5F;AAGA,QAAI,CAAC,MAAM,QAAQ,WAAW,QAAQ,KAAK,WAAW,SAAS,WAAW,GAAG;AACzE,YAAM,IAAI,MAAM,iFAAiF,QAAQ;AAAA,IAC7G;AAGA,2BAAuB,YAAY,KAAK;AAGxC,eAAW,SAAS,QAAQ,CAAC,UAAe,aAAa,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9E;AAOA,WAAS,qBAAqB,YAAiB,OAAqB;AAEhE,QAAI,WAAW,SAAS,YAAY;AAChC,YAAM,IAAI,MAAM,gEAAgE,QAAQ;AAAA,IAC5F;AAGA,QAAI,CAAC,MAAM,QAAQ,WAAW,QAAQ,KAAK,WAAW,SAAS,WAAW,GAAG;AACzE,YAAM,IAAI,MAAM,iFAAiF,QAAQ;AAAA,IAC7G;AAGA,2BAAuB,YAAY,KAAK;AAGxC,eAAW,SAAS,QAAQ,CAAC,UAAe,aAAa,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9E;AAOA,WAAS,iBAAiB,YAAiB,OAAqB;AAE5D,QAAI,WAAW,SAAS,QAAQ;AAC5B,YAAM,IAAI,MAAM,wDAAwD,QAAQ;AAAA,IACpF;AAGA,QAAI,CAAC,MAAM,QAAQ,WAAW,QAAQ,KAAK,WAAW,SAAS,WAAW,GAAG;AACzE,YAAM,IAAI,MAAM,6EAA6E,QAAQ;AAAA,IACzG;AAGA,2BAAuB,YAAY,KAAK;AAGxC,eAAW,SAAS,QAAQ,CAAC,UAAe,aAAa,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9E;AAOA,WAAS,kBAAkB,YAAiB,OAAqB;AAE7D,QAAI,WAAW,SAAS,SAAS;AAC7B,YAAM,IAAI,MAAM,0DAA0D,QAAQ;AAAA,IACtF;AAGA,QAAI,CAAC,MAAM,QAAQ,WAAW,QAAQ,KAAK,WAAW,SAAS,WAAW,GAAG;AACzE,YAAM,IAAI,MAAM,8EAA8E,QAAQ;AAAA,IAC1G;AAGA,QAAI,OAAO,WAAW,YAAY,aAAa;AAE3C,UACI,CAAC,MAAM,QAAQ,WAAW,OAAO,KACjC,WAAW,QAAQ,WAAW,WAAW,SAAS,UAClD,WAAW,QAAQ,OAAO,CAAC,UAAmB,CAAC,UAAU,KAAK,CAAC,EAAE,UACjE,WAAW,QAAQ,OAAO,CAAC,UAAkB,QAAQ,CAAC,EAAE,QAC1D;AACE,cAAM,IAAI;AAAA,UACN,mKAAmK;AAAA,QACvK;AAAA,MACJ;AAAA,IACJ;AAGA,2BAAuB,YAAY,KAAK;AAGxC,eAAW,SAAS,QAAQ,CAAC,UAAe,aAAa,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9E;AAOA,WAAS,8BAA8B,cAAkD;AACrF,WAAO,EAAE,WAAW,OAAO,aAAa;AAAA,EAC5C;;;AC30BA,MAAqB,4BAArB,cAAuD,MAAM;AAAA,IAIzD,YAAoB,QAAc;AAC9B,YAAM,mCAAmC;AADzB;AAAA,IAEpB;AAAA,IAOA,eAAe,CAAC,SAAe,SAAS,KAAK;AAAA,EACjD;;;ACNA,MAAqB,YAArB,MAA+B;AAAA,IAI3B,YAAoB,OAAwB;AAAxB;AAAA,IAAyB;AAAA,IAO7C,WAAW,CAAC,UAAiB;AAEzB,iBAAW,WAAW,KAAK,OAAO;AAE9B,mBAAW,SAAS,QAAQ,QAAQ;AAEhC,cAAI,CAAC,MAAM,YAAY,KAAK,GAAG;AAC3B,kBAAM,IAAI,0BAA0B,QAAQ,IAAI;AAAA,UACpD;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;;;AChCO,WAAS,YAAoB;AAChC,QAAI,KAAK,WAAY;AACjB,eAAU,IAAI,KAAK,OAAO,KAAK,QAAW,GAAG,SAAS,EAAE,EAAE,UAAU,CAAC;AAAA,IACzE;AACA,WAAO,GAAG,IAAI,GAAG,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG;AAAA,EACvF;;;ACsFA,MAA8B,OAA9B,MAAmC;AAAA,IAuB/B,YAAoB,MAAc,YAAmC,SAA+B;AAAhF;AAAiD;AAEjE,WAAK,MAAM,UAAU;AAGrB,WAAK,aAAa;AAAA,QACd,OAAO,WAAW,KAAK,CAAC,EAAE,MAAAC,MAAK,MAAMA,UAAS,OAAO;AAAA,QACrD,MAAM,WAAW,KAAK,CAAC,EAAE,MAAAA,MAAK,MAAMA,UAAS,MAAM;AAAA,QACnD,MAAM,WAAW,KAAK,CAAC,EAAE,MAAAA,MAAK,MAAMA,UAAS,MAAM;AAAA,QACnD,OAAO,WAAW,KAAK,CAAC,EAAE,MAAAA,MAAK,MAAMA,UAAS,OAAO;AAAA,QACrD,OAAO,WAAW,KAAK,CAAC,EAAE,MAAAA,MAAK,MAAMA,UAAS,OAAO;AAAA,MACzD;AAAA,IACJ;AAAA,IA/BmB;AAAA,IAIA;AAAA,IAIX;AAAA,IAIA;AAAA,IAwCR,WAAW,MAAgB,KAAK;AAAA,IAChC,WAAW,CAAC,UAA0B;AAElC,YAAM,gBAAgB,KAAK;AAG3B,WAAK,SAAS;AAGd,UAAI,kBAAkB,OAAO;AACzB,aAAK,eAAe,aAAa;AAAA,MACrC;AAAA,IACJ;AAAA,IAKA,SAAS,MAAM,KAAK;AAAA,IAKpB,UAAU,MAAM,KAAK;AAAA,IAKrB,gBAAgB,MAAM,OAAO,OAAO,KAAK,UAAU,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,SAAS;AAAA,IAKtF,eAAe,CAAC,UAAsB,KAAK,aAAa;AAAA,IAKxD,eAAe,MAAM,CAAC,CAAC,KAAK;AAAA,IAMrB,GAAG,OAA0B;AAChC,aAAO,KAAK,WAAW;AAAA,IAC3B;AAAA,IAKO,QAAc;AACjB,WAAK,wCAAoB;AAAA,IAC7B;AAAA,IAMO,MAAM,OAAoB;AAE7B,UAAI,CAAC,KAAK,sCAAgB,GAAG;AACzB;AAAA,MACJ;AAGA,WAAK,MAAM;AAEX,WAAK,WAAW,MAAM,kBAAkB,OAAO,OAAO,IAAI;AAAA,IAC9D;AAAA,IAOO,OAAO,OAAoB;AAE9B,UAAI,KAAK,0CAAkB,KAAK,KAAK,oCAAe,GAAG;AACnD;AAAA,MACJ;AAEA,UAAI;AAEA,aAAK,WAAY,SAAS,KAAK;AAG/B,YAAI,KAAK,kCAAc,GAAG;AACtB,eAAK,WAAW,OAAO,kBAAkB,KAAK;AAAA,QAClD;AAEA,aAAK,WAAW,MAAM,kBAAkB,KAAK;AAG7C,aAAK,SAAS,KAAK;AAGnB,YAAI,KAAK,0CAAkB,KAAK,KAAK,oCAAe,GAAG;AACnD,eAAK,WAAW,MAAM,kBAAkB,OAAO,KAAK,0CAAkB,GAAG,KAAK;AAAA,QAClF;AAAA,MACJ,SAAS,OAAP;AAEE,YAAI,iBAAiB,6BAA6B,MAAM,aAAa,IAAI,GAAG;AAExE,eAAK,MAAM,KAAK;AAGhB,eAAK,0CAAqB;AAAA,QAC9B,OAAO;AACH,gBAAM;AAAA,QACV;AAAA,MACJ;AAAA,IACJ;AAAA,IAMO,aAA0B;AAC7B,aAAO;AAAA,QACH,IAAI,KAAK;AAAA,QACT,MAAM,KAAK,QAAQ;AAAA,QACnB,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,MAAM,KAAK,WAAW,MAAM,WAAW;AAAA,QACvC,MAAM,KAAK,WAAW,MAAM,WAAW;AAAA,QACvC,OAAO,KAAK;AAAA,MAChB;AAAA,IACJ;AAAA,IAMU,eAAe,eAA4B;AAEjD,WAAK,QAAQ,oBAAoB;AAAA,QAC7B,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,MAAM,KAAK,WAAW,MAAM,WAAW;AAAA,QACvC,MAAM,KAAK,WAAW,MAAM,WAAW;AAAA,QACvC;AAAA,QACA,OAAO,KAAK;AAAA,MAChB,CAAC;AAAA,IACL;AAAA,EACJ;;;ACnSA,MAA8B,YAA9B,cAAgD,KAAK;AAAA,IAOjD,YAAY,MAAc,YAAyB,SAAyC,UAAkB;AAC1G,YAAM,MAAM,YAAY,OAAO;AADyD;AAAA,IAE5F;AAAA,IAKA,aAAa,MAAM;AAAA,IAKnB,cAAc,MAAM,KAAK;AAAA,IAKzB,QAAQ,MAAM;AAEV,WAAK,wCAAoB;AAGzB,WAAK,SAAS,QAAQ,CAAC,UAAU,MAAM,MAAM,CAAC;AAAA,IAClD;AAAA,IAMA,QAAQ,CAAC,UAAiB;AAEtB,UAAI,CAAC,KAAK,sCAAgB,GAAG;AACzB;AAAA,MACJ;AAGA,WAAK,SAAS,QAAQ,CAAC,UAAU,MAAM,MAAM,KAAK,CAAC;AAGnD,WAAK,MAAM;AAEX,WAAK,WAAW,MAAM,kBAAkB,OAAO,OAAO,IAAI;AAAA,IAC9D;AAAA,IAMO,aAA0B;AAC7B,aAAO;AAAA,QACH,GAAG,MAAM,WAAW;AAAA,QACpB,UAAU,KAAK,SAAS,IAAI,CAAC,UAAU,MAAM,WAAW,CAAC;AAAA,MAC7D;AAAA,IACJ;AAAA,EACJ;;;AC3DA,MAAqB,WAArB,cAAsC,UAAU;AAAA,IAM5C,YAAY,YAAyB,SAA+B,UAAkB;AAClF,YAAM,YAAY,YAAY,SAAS,QAAQ;AAAA,IACnD;AAAA,IAMU,SAAS,OAAoB;AAEnC,iBAAW,SAAS,KAAK,UAAU;AAE/B,YAAI,MAAM,SAAS,yCAAqB,MAAM,SAAS,2CAAqB;AAExE,gBAAM,OAAO,KAAK;AAAA,QACtB;AAAA,MACJ;AAGA,UAAI,KAAK,SAAS,KAAK,CAAC,UAAU,MAAM,oCAAe,CAAC,GAAG;AAEvD,aAAK,0CAAqB;AAG1B,mBAAW,SAAS,KAAK,UAAU;AAC/B,cAAI,MAAM,SAAS,2CAAqB;AACpC,kBAAM,MAAM,KAAK;AAAA,UACrB;AAAA,QACJ;AAEA;AAAA,MACJ;AAGA,UAAI,KAAK,SAAS,MAAM,CAAC,UAAU,MAAM,0CAAkB,CAAC,GAAG;AAE3D,aAAK,gDAAwB;AAE7B;AAAA,MACJ;AAGA,WAAK,4CAAsB;AAAA,IAC/B;AAAA,IAKA,UAAU,MAAM;AAAA,EACpB;;;ACvDA,MAAqB,OAArB,cAAkC,UAAU;AAAA,IAMxC,YAAY,YAAyB,SAA+B,UAAkB;AAClF,YAAM,QAAQ,YAAY,SAAS,QAAQ;AAAA,IAC/C;AAAA,IAMU,SAAS,OAAoB;AAEnC,iBAAW,SAAS,KAAK,UAAU;AAE/B,YAAI,MAAM,SAAS,yCAAqB,MAAM,SAAS,2CAAqB;AAExE,gBAAM,OAAO,KAAK;AAAA,QACtB;AAAA,MACJ;AAGA,UAAI,KAAK,SAAS,KAAK,CAAC,UAAU,MAAM,0CAAkB,CAAC,GAAG;AAE1D,aAAK,gDAAwB;AAG7B,mBAAW,SAAS,KAAK,UAAU;AAC/B,cAAI,MAAM,SAAS,2CAAqB;AACpC,kBAAM,MAAM,KAAK;AAAA,UACrB;AAAA,QACJ;AAEA;AAAA,MACJ;AAGA,UAAI,KAAK,SAAS,MAAM,CAAC,UAAU,MAAM,oCAAe,CAAC,GAAG;AAExD,aAAK,0CAAqB;AAE1B;AAAA,MACJ;AAGA,WAAK,4CAAsB;AAAA,IAC/B;AAAA,IAKA,UAAU,MAAM;AAAA,EACpB;;;ACvDA,MAAqB,WAArB,cAAsC,UAAU;AAAA,IAM5C,YAAY,YAAyB,SAAyC,UAAkB;AAC5F,YAAM,YAAY,YAAY,SAAS,QAAQ;AAD2B;AAAA,IAE9E;AAAA,IAMU,SAAS,OAAoB;AAEnC,iBAAW,SAAS,KAAK,UAAU;AAE/B,YAAI,MAAM,SAAS,yCAAqB,MAAM,SAAS,2CAAqB;AAExE,gBAAM,OAAO,KAAK;AAAA,QACtB;AAGA,YAAI,MAAM,SAAS,+CAAuB;AAEtC,eAAK,gDAAwB;AAG7B;AAAA,QACJ;AAGA,YAAI,MAAM,SAAS,yCAAoB;AAGnC,cAAI,KAAK,SAAS,QAAQ,KAAK,MAAM,KAAK,SAAS,SAAS,GAAG;AAE3D,iBAAK,0CAAqB;AAG1B;AAAA,UACJ,OAAO;AAEH;AAAA,UACJ;AAAA,QACJ;AAGA,YAAI,MAAM,SAAS,2CAAqB;AAEpC,eAAK,4CAAsB;AAG3B;AAAA,QACJ;AAGA,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC9D;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM;AAAA,EACpB;;;AClEA,MAAqB,WAArB,cAAsC,UAAU;AAAA,IAM5C,YAAY,YAAyB,SAAyC,UAAkB;AAC5F,YAAM,YAAY,YAAY,SAAS,QAAQ;AAD2B;AAAA,IAE9E;AAAA,IAMU,SAAS,OAAoB;AAEnC,iBAAW,SAAS,KAAK,UAAU;AAE/B,YAAI,MAAM,SAAS,yCAAqB,MAAM,SAAS,2CAAqB;AAExE,gBAAM,OAAO,KAAK;AAAA,QACtB;AAGA,YAAI,MAAM,SAAS,+CAAuB;AAGtC,cAAI,KAAK,SAAS,QAAQ,KAAK,MAAM,KAAK,SAAS,SAAS,GAAG;AAE3D,iBAAK,gDAAwB;AAG7B;AAAA,UACJ,OAAO;AAEH;AAAA,UACJ;AAAA,QACJ;AAGA,YAAI,MAAM,SAAS,yCAAoB;AAEnC,eAAK,0CAAqB;AAG1B;AAAA,QACJ;AAGA,YAAI,MAAM,SAAS,2CAAqB;AAEpC,eAAK,4CAAsB;AAG3B;AAAA,QACJ;AAGA,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC9D;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM;AAAA,EACpB;;;AC7EA,0BAAwB;AAcxB,MAAqB,QAArB,cAAmC,UAAU;AAAA,IAOzC,YACI,YACA,SACQ,SACR,UACF;AACE,YAAM,SAAS,YAAY,SAAS,QAAQ;AAHpC;AAAA,IAIZ;AAAA,IAKQ;AAAA,IAME,SAAS,OAAoB;AAEnC,UAAI,KAAK,kCAAc,GAAG;AAEtB,cAAM,gBAAY,kBAAAC,SAAkB;AAAA,UAEhC,QAAQ,KAAK,QAAQ;AAAA,UAErB,cAAc,KAAK,SAAS,IAAI,CAAC,OAAO,UAAU,CAAC,OAAO,KAAK,UAAU,UAAU,CAAC,CAAC;AAAA,QACzF,CAAC;AAGD,aAAK,gBAAgB,UAAU,KAAK,KAAK;AAAA,MAC7C;AAGA,UAAI,CAAC,KAAK,eAAe;AACrB,cAAM,IAAI,MAAM,uDAAuD;AAAA,MAC3E;AAGA,UAAI,KAAK,cAAc,SAAS,yCAAqB,KAAK,cAAc,SAAS,2CAAqB;AAClG,aAAK,cAAc,OAAO,KAAK;AAAA,MACnC;AAGA,WAAK,SAAS,KAAK,cAAc,SAAS,CAAC;AAAA,IAC/C;AAAA,IAKA,UAAU,MAAO,KAAK,UAAU,UAAU,KAAK,QAAQ,KAAK,GAAG,OAAO;AAAA,EAC1E;;;AC/DA,MAA8B,YAA9B,cAAgD,KAAK;AAAA,IAOjD,YAAY,MAAc,YAAyB,SAAyC,OAAa;AACrG,YAAM,MAAM,YAAY,OAAO;AADyD;AAAA,IAE5F;AAAA,IAKA,aAAa,MAAM;AAAA,IAKnB,cAAc,MAAM,CAAC,KAAK,KAAK;AAAA,IAK/B,QAAQ,MAAM;AAEV,WAAK,wCAAoB;AAGzB,WAAK,MAAM,MAAM;AAAA,IACrB;AAAA,IAMA,QAAQ,CAAC,UAAiB;AAEtB,UAAI,CAAC,KAAK,sCAAgB,GAAG;AACzB;AAAA,MACJ;AAGA,WAAK,MAAM,MAAM,KAAK;AAGtB,WAAK,MAAM;AAEX,WAAK,WAAW,MAAM,kBAAkB,OAAO,OAAO,IAAI;AAAA,IAC9D;AAAA,IAMO,aAA0B;AAC7B,aAAO;AAAA,QACH,GAAG,MAAM,WAAW;AAAA,QACpB,UAAU,CAAC,KAAK,MAAM,WAAW,CAAC;AAAA,MACtC;AAAA,IACJ;AAAA,EACJ;;;AC3DA,MAAqB,OAArB,cAAkC,UAAU;AAAA,IAMxC,YAAY,YAAyB,SAA+B,OAAa;AAC7E,YAAM,QAAQ,YAAY,SAAS,KAAK;AAAA,IAC5C;AAAA,IAMU,SAAS,OAAoB;AAEnC,UAAI,KAAK,MAAM,SAAS,yCAAqB,KAAK,MAAM,SAAS,2CAAqB;AAClF,aAAK,MAAM,OAAO,KAAK;AAAA,MAC3B;AAGA,cAAQ,KAAK,MAAM,SAAS,GAAG;AAAA,QAC3B;AACI,eAAK,4CAAsB;AAC3B;AAAA,QAEJ;AAAA,QACA;AACI,eAAK,0CAAqB;AAC1B;AAAA,QAEJ;AACI,eAAK,wCAAoB;AAAA,MACjC;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM;AAAA,EACpB;;;ACxCA,MAAqB,OAArB,cAAkC,UAAU;AAAA,IAMxC,YAAY,YAAyB,SAA+B,OAAa;AAC7E,YAAM,QAAQ,YAAY,SAAS,KAAK;AAAA,IAC5C;AAAA,IAMU,SAAS,OAAoB;AAEnC,UAAI,KAAK,MAAM,SAAS,yCAAqB,KAAK,MAAM,SAAS,2CAAqB;AAClF,aAAK,MAAM,OAAO,KAAK;AAAA,MAC3B;AAGA,cAAQ,KAAK,MAAM,SAAS,GAAG;AAAA,QAC3B;AACI,eAAK,4CAAsB;AAC3B;AAAA,QAEJ;AACI,eAAK,0CAAqB;AAC1B;AAAA,QAEJ;AACI,eAAK,gDAAwB;AAC7B;AAAA,QAEJ;AACI,eAAK,wCAAoB;AAAA,MACjC;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM;AAAA,EACpB;;;ACvCA,MAAqB,SAArB,cAAoC,UAAU;AAAA,IAS1C,YACI,YACA,SACQ,YACA,eACA,eACR,OACF;AACE,YAAM,UAAU,YAAY,SAAS,KAAK;AALlC;AACA;AACA;AAAA,IAIZ;AAAA,IAKQ,uBAAsC;AAAA,IAKtC,wBAAgC;AAAA,IAM9B,SAAS,OAAoB;AAEnC,UAAI,KAAK,kCAAc,GAAG;AAEtB,aAAK,MAAM,MAAM;AAGjB,aAAK,wBAAwB;AAG7B,aAAK,wBAAwB;AAAA,MACjC;AAIA,UAAI,KAAK,WAAW,GAAG;AAEnB,aAAK,4CAAsB;AAI3B,YAAI,KAAK,MAAM,SAAS,+CAAuB;AAC3C,eAAK,MAAM,MAAM;AAAA,QACrB;AAGA,aAAK,MAAM,OAAO,KAAK;AAIvB,YAAI,KAAK,MAAM,SAAS,yCAAoB;AAExC,eAAK,0CAAqB;AAE1B;AAAA,QACJ,WAAW,KAAK,MAAM,SAAS,+CAAuB;AAElD,eAAK,yBAAyB;AAAA,QAClC;AAAA,MACJ,OAAO;AAEH,aAAK,gDAAwB;AAAA,MACjC;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM;AACZ,UAAI,KAAK,eAAe,MAAM;AAC1B,eAAO,UAAU,KAAK;AAAA,MAC1B,WAAW,KAAK,kBAAkB,QAAQ,KAAK,kBAAkB,MAAM;AACnE,eAAO,UAAU,KAAK,kBAAkB,KAAK;AAAA,MACjD,OAAO;AACH,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,IAKA,QAAQ,MAAM;AAEV,WAAK,wCAAoB;AAGzB,WAAK,wBAAwB;AAG7B,WAAK,MAAM,MAAM;AAAA,IACrB;AAAA,IAMQ,aAAa,MAAM;AACvB,UAAI,KAAK,yBAAyB,MAAM;AAEpC,eAAO,KAAK,wBAAwB,KAAK;AAAA,MAC7C;AAGA,aAAO;AAAA,IACX;AAAA,IAKQ,0BAA0B,MAAM;AAEpC,UAAI,KAAK,eAAe,MAAM;AAC1B,aAAK,uBAAuB,KAAK;AAAA,MACrC,WAAW,KAAK,kBAAkB,QAAQ,KAAK,kBAAkB,MAAM;AAGnE,cAAM,SAAS,OAAO,KAAK,QAAQ,WAAW,aAAa,KAAK,QAAQ,SAAS,KAAK;AAGtF,aAAK,uBAAuB,KAAK;AAAA,UAC7B,OAAO,KAAK,KAAK,gBAAgB,KAAK,gBAAgB,KAAK,KAAK;AAAA,QACpE;AAAA,MACJ,OAAO;AACH,aAAK,uBAAuB;AAAA,MAChC;AAAA,IACJ;AAAA,EACJ;;;AC5IA,MAAqB,QAArB,cAAmC,UAAU;AAAA,IASzC,YACI,YACA,SACQ,UACA,aACA,aACR,OACF;AACE,YAAM,SAAS,YAAY,SAAS,KAAK;AALjC;AACA;AACA;AAAA,IAIZ;AAAA,IAKQ,qBAAoC;AAAA,IAKpC,sBAA8B;AAAA,IAM5B,SAAS,OAAoB;AAEnC,UAAI,KAAK,kCAAc,GAAG;AAEtB,aAAK,MAAM,MAAM;AAGjB,aAAK,sBAAsB;AAG3B,aAAK,sBAAsB;AAAA,MAC/B;AAIA,UAAI,KAAK,WAAW,GAAG;AAEnB,aAAK,4CAAsB;AAI3B,YAAI,KAAK,MAAM,SAAS,yCAAoB;AACxC,eAAK,MAAM,MAAM;AAAA,QACrB;AAGA,aAAK,MAAM,OAAO,KAAK;AAIvB,YAAI,KAAK,MAAM,SAAS,+CAAuB;AAE3C,eAAK,gDAAwB;AAE7B;AAAA,QACJ,WAAW,KAAK,MAAM,SAAS,yCAAoB;AAE/C,eAAK,uBAAuB;AAAA,QAChC;AAAA,MACJ,OAAO;AAEH,aAAK,0CAAqB;AAAA,MAC9B;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM;AACZ,UAAI,KAAK,aAAa,MAAM;AACxB,eAAO,SAAS,KAAK;AAAA,MACzB,WAAW,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,MAAM;AAC/D,eAAO,SAAS,KAAK,gBAAgB,KAAK;AAAA,MAC9C,OAAO;AACH,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,IAKA,QAAQ,MAAM;AAEV,WAAK,wCAAoB;AAGzB,WAAK,sBAAsB;AAG3B,WAAK,MAAM,MAAM;AAAA,IACrB;AAAA,IAMA,aAAa,MAAM;AACf,UAAI,KAAK,uBAAuB,MAAM;AAElC,eAAO,KAAK,sBAAsB,KAAK;AAAA,MAC3C;AAGA,aAAO;AAAA,IACX;AAAA,IAKA,wBAAwB,MAAM;AAE1B,UAAI,KAAK,aAAa,MAAM;AACxB,aAAK,qBAAqB,KAAK;AAAA,MACnC,WAAW,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,MAAM;AAG/D,cAAM,SAAS,OAAO,KAAK,QAAQ,WAAW,aAAa,KAAK,QAAQ,SAAS,KAAK;AAGtF,aAAK,qBAAqB,KAAK;AAAA,UAC3B,OAAO,KAAK,KAAK,cAAc,KAAK,cAAc,KAAK,KAAK;AAAA,QAChE;AAAA,MACJ,OAAO;AACH,aAAK,qBAAqB;AAAA,MAC9B;AAAA,IACJ;AAAA,EACJ;;;AChJA,MAAqB,OAArB,cAAkC,UAAU;AAAA,IAMxC,YAAY,YAAyB,SAA+B,OAAa;AAC7E,YAAM,QAAQ,YAAY,SAAS,KAAK;AAAA,IAC5C;AAAA,IAMU,SAAS,OAAoB;AAEnC,UAAI,KAAK,MAAM,SAAS,yCAAqB,KAAK,MAAM,SAAS,2CAAqB;AAElF,aAAK,MAAM,OAAO,KAAK;AAAA,MAC3B;AAGA,WAAK,SAAS,KAAK,MAAM,SAAS,CAAC;AAAA,IACvC;AAAA,IAKA,UAAU,MAAM;AAAA,EACpB;;;AC7BA,MAAqB,UAArB,cAAqC,UAAU;AAAA,IAM3C,YAAY,YAAyB,SAA+B,OAAa;AAC7E,YAAM,WAAW,YAAY,SAAS,KAAK;AAAA,IAC/C;AAAA,IAMU,SAAS,OAAoB;AAEnC,UAAI,KAAK,MAAM,SAAS,yCAAqB,KAAK,MAAM,SAAS,2CAAqB;AAClF,aAAK,MAAM,OAAO,KAAK;AAAA,MAC3B;AAGA,cAAQ,KAAK,MAAM,SAAS,GAAG;AAAA,QAC3B;AACI,eAAK,4CAAsB;AAC3B;AAAA,QAEJ;AAAA,QACA;AACI,eAAK,gDAAwB;AAC7B;AAAA,QAEJ;AACI,eAAK,wCAAoB;AAAA,MACjC;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM;AAAA,EACpB;;;AC9CA,MAA8B,OAA9B,cAA2C,KAAK;AAAA,IAI5C,aAAa,MAAM;AAAA,EACvB;;;ACiBA,MAAqB,SAArB,cAAoC,KAAK;AAAA,IAOrC,YACI,YACA,SACQ,YACD,iBACT;AACE,YAAM,UAAU,YAAY,OAAO;AAH3B;AACD;AAAA,IAGX;AAAA,IAKQ,uBAAuB;AAAA,IAKvB,sBAAkD;AAAA,IAMhD,SAAS,OAAoB;AAEnC,UAAI,KAAK,sBAAsB;AAE3B,YAAI,CAAC,KAAK,qBAAqB;AAC3B;AAAA,QACJ;AAEA,cAAM,EAAE,YAAY,MAAM,IAAI,KAAK;AAGnC,YAAI,YAAY;AAEZ,cAAI,qDAA6B,6CAAwB;AACrD,kBAAM,IAAI;AAAA,cACN;AAAA,YACJ;AAAA,UACJ;AAGA,eAAK,SAAS,KAAK;AAEnB;AAAA,QACJ,OAAO;AAEH,gBAAM,IAAI,MAAM,oBAAoB,KAAK,sCAAsC,QAAQ;AAAA,QAC3F;AAAA,MACJ;AAGA,YAAM,oBAAoB,OAAO,eAAe,OAAO,KAAK,UAAU;AAGtE,UAAI,sBAAsB,MAAM;AAC5B,cAAM,IAAI;AAAA,UACN,4CAA4C,KAAK;AAAA,QACrD;AAAA,MACJ;AAEA,UAAI;AAEJ,UAAI;AAKA,+BAAuB,kBAAkB,KAAK,eAAe;AAAA,MACjE,SAAS,OAAP;AAEE,YAAI,iBAAiB,OAAO;AACxB,gBAAM,IAAI,MAAM,oBAAoB,KAAK,sBAAsB,MAAM,OAAO;AAAA,QAChF,OAAO;AACH,gBAAM,IAAI,MAAM,oBAAoB,KAAK,sBAAsB,OAAO;AAAA,QAC1E;AAAA,MACJ;AAEA,UAAI,gCAAgC,SAAS;AACzC,6BAAqB;AAAA,UACjB,CAAC,WAAW;AAER,gBAAI,CAAC,KAAK,sBAAsB;AAC5B;AAAA,YACJ;AAGA,iBAAK,sBAAsB;AAAA,cACvB,YAAY;AAAA,cACZ,OAAO;AAAA,YACX;AAAA,UACJ;AAAA,UACA,CAAC,WAAW;AAER,gBAAI,CAAC,KAAK,sBAAsB;AAC5B;AAAA,YACJ;AAGA,iBAAK,sBAAsB;AAAA,cACvB,YAAY;AAAA,cACZ,OAAO;AAAA,YACX;AAAA,UACJ;AAAA,QACJ;AAGA,aAAK,4CAAsB;AAG3B,aAAK,uBAAuB;AAAA,MAChC,OAAO;AAEH,aAAK,qBAAqB,oBAAoB;AAG9C,aAAK,SAAS,2DAAqC;AAAA,MACvD;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM,KAAK;AAAA,IAKrB,QAAQ,MAAM;AAEV,WAAK,wCAAoB;AAGzB,WAAK,uBAAuB;AAC5B,WAAK,sBAAsB;AAAA,IAC/B;AAAA,IAMO,aAA0B;AAC7B,aAAO;AAAA,QACH,GAAG,MAAM,WAAW;AAAA,QACpB,MAAM,KAAK;AAAA,MACf;AAAA,IACJ;AAAA,IAMU,eAAe,eAA4B;AACjD,WAAK,QAAQ,oBAAoB;AAAA,QAC7B,IAAI,KAAK;AAAA,QACT,MAAM,KAAK,QAAQ;AAAA,QACnB,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,MAAM,KAAK,WAAW,MAAM,WAAW;AAAA,QACvC,MAAM,KAAK,WAAW,MAAM,WAAW;AAAA,QACvC;AAAA,QACA,OAAO,KAAK,SAAS;AAAA,MACzB,CAAC;AAAA,IACL;AAAA,IAMQ,uBAAuB,CAAC,WAA0C;AACtE,cAAQ,QAAQ;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AACD;AAAA,QACJ;AACI,gBAAM,IAAI;AAAA,YACN,6BAA6B,KAAK,yFAAyF;AAAA,UAC/H;AAAA,MACR;AAAA,IACJ;AAAA,EACJ;;;AC/MA,MAAqB,YAArB,cAAuC,KAAK;AAAA,IAOxC,YACI,YACA,SACQ,eACD,oBACT;AACE,YAAM,aAAa,YAAY,OAAO;AAH9B;AACD;AAAA,IAGX;AAAA,IAMU,SAAS,OAAoB;AAEnC,YAAM,uBAAuB,OAAO,eAAe,OAAO,KAAK,aAAa;AAG5E,UAAI,yBAAyB,MAAM;AAC/B,cAAM,IAAI;AAAA,UACN,kDAAkD,KAAK;AAAA,QAC3D;AAAA,MACJ;AAEA,UAAI;AAEJ,UAAI;AAEA,kCAA0B,qBAAqB,KAAK,kBAAkB;AAAA,MAC1E,SAAS,OAAP;AAEE,YAAI,iBAAiB,OAAO;AACxB,gBAAM,IAAI,MAAM,uBAAuB,KAAK,yBAAyB,MAAM,OAAO;AAAA,QACtF,OAAO;AACH,gBAAM,IAAI,MAAM,uBAAuB,KAAK,yBAAyB,OAAO;AAAA,QAChF;AAAA,MACJ;AAGA,UAAI,OAAO,4BAA4B,WAAW;AAC9C,cAAM,IAAI;AAAA,UACN,gCAAgC,KAAK,oDAAoD;AAAA,QAC7F;AAAA,MACJ;AAGA,WAAK,SAAS,CAAC,CAAC,qGAAwD;AAAA,IAC5E;AAAA,IAKA,UAAU,MAAM,KAAK;AAAA,IAMd,aAA0B;AAC7B,aAAO;AAAA,QACH,GAAG,MAAM,WAAW;AAAA,QACpB,MAAM,KAAK;AAAA,MACf;AAAA,IACJ;AAAA,IAMU,eAAe,eAA4B;AACjD,WAAK,QAAQ,oBAAoB;AAAA,QAC7B,IAAI,KAAK;AAAA,QACT,MAAM,KAAK,QAAQ;AAAA,QACnB,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,OAAO,KAAK,WAAW,OAAO,WAAW;AAAA,QACzC,MAAM,KAAK,WAAW,MAAM,WAAW;AAAA,QACvC,MAAM,KAAK,WAAW,MAAM,WAAW;AAAA,QACvC;AAAA,QACA,OAAO,KAAK,SAAS;AAAA,MACzB,CAAC;AAAA,IACL;AAAA,EACJ;;;AC5FA,MAAqB,OAArB,cAAkC,KAAK;AAAA,IAQnC,YACI,YACA,SACQ,UACA,aACA,aACV;AACE,YAAM,QAAQ,YAAY,OAAO;AAJzB;AACA;AACA;AAAA,IAGZ;AAAA,IAKQ,oBAA4B;AAAA,IAK5B,gBAA+B;AAAA,IAK/B,iBAAyB;AAAA,IAMvB,SAAS,OAAoB;AAEnC,UAAI,KAAK,kCAAc,GAAG;AAEtB,aAAK,oBAAoB,IAAI,KAAK,EAAE,QAAQ;AAG5C,aAAK,iBAAiB;AAGtB,YAAI,KAAK,aAAa,MAAM;AACxB,eAAK,gBAAgB,KAAK;AAAA,QAC9B,WAAW,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,MAAM;AAG/D,gBAAM,SAAS,OAAO,KAAK,QAAQ,WAAW,aAAa,KAAK,QAAQ,SAAS,KAAK;AAGtF,eAAK,gBAAgB,KAAK;AAAA,YACtB,OAAO,KAAK,KAAK,cAAc,KAAK,cAAc,KAAK,KAAK;AAAA,UAChE;AAAA,QACJ,OAAO;AACH,eAAK,gBAAgB;AAAA,QACzB;AAGA,aAAK,4CAAsB;AAAA,MAC/B;AAGA,UAAI,KAAK,kBAAkB,MAAM;AAC7B;AAAA,MACJ;AAGA,UAAI,OAAO,KAAK,QAAQ,iBAAiB,YAAY;AAEjD,cAAM,YAAY,KAAK,QAAQ,aAAa;AAG5C,YAAI,OAAO,cAAc,YAAY,MAAM,SAAS,GAAG;AACnD,gBAAM,IAAI,MAAM,oDAAoD;AAAA,QACxE;AAGA,aAAK,kBAAkB,YAAY;AAAA,MACvC,OAAO;AAEH,aAAK,iBAAiB,IAAI,KAAK,EAAE,QAAQ,IAAI,KAAK;AAAA,MACtD;AAGA,UAAI,KAAK,kBAAkB,KAAK,eAAe;AAE3C,aAAK,gDAAwB;AAAA,MACjC;AAAA,IACJ;AAAA,IAKA,UAAU,MAAM;AACZ,UAAI,KAAK,aAAa,MAAM;AACxB,eAAO,QAAQ,KAAK;AAAA,MACxB,WAAW,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,MAAM;AAC/D,eAAO,QAAQ,KAAK,iBAAiB,KAAK;AAAA,MAC9C,OAAO;AACH,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ;;;ACxGA,MAA8B,YAA9B,MAAuG;AAAA,IAKnG,YAAmB,MAAqB,MAAa;AAAlC;AAAqB;AAAA,IAAc;AAAA,EAW1D;;;ACfA,MAA8B,QAA9B,cAA4C,UAAiC;AAAA,IAMzE,YAAY,MAAc,MAAqB,WAAmB;AAC9D,YAAM,MAAM,IAAI;AAD2B;AAAA,IAE/C;AAAA,IAKA,eAAe,MAAM,KAAK;AAAA,IAK1B,UAAU,MAAM;AAAA,IAKhB,aAAoC;AAChC,aAAO;AAAA,QACH,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,aAAa;AAAA,MAC7B;AAAA,IACJ;AAAA,EAQJ;;;AC5CA,MAAqB,QAArB,cAAmC,MAAM;AAAA,IAKrC,YAAY,WAAmB,MAAa;AACxC,YAAM,SAAS,MAAM,SAAS;AAAA,IAClC;AAAA,IAOA,cAAc,CAAC,UAAiB;AAE5B,YAAM,uBAAuB,OAAO,eAAe,OAAO,KAAK,aAAa,CAAC;AAG7E,UAAI,yBAAyB,MAAM;AAC/B,cAAM,IAAI;AAAA,UACN,gDAAgD,KAAK,aAAa;AAAA,QACtE;AAAA,MACJ;AAEA,UAAI;AAEJ,UAAI;AAEA,kCAA0B,qBAAqB,KAAK,IAAI;AAAA,MAC5D,SAAS,OAAP;AAEE,YAAI,iBAAiB,OAAO;AACxB,gBAAM,IAAI,MAAM,6BAA6B,KAAK,aAAa,aAAa,MAAM,OAAO;AAAA,QAC7F,OAAO;AACH,gBAAM,IAAI,MAAM,6BAA6B,KAAK,aAAa,aAAa,OAAO;AAAA,QACvF;AAAA,MACJ;AAGA,UAAI,OAAO,4BAA4B,WAAW;AAC9C,cAAM,IAAI;AAAA,UACN,sCAAsC,KAAK,aAAa,wCAAwC;AAAA,QACpG;AAAA,MACJ;AAGA,aAAO;AAAA,IACX;AAAA,EACJ;;;ACjDA,MAAqB,QAArB,cAAmC,MAAM;AAAA,IAKrC,YAAY,WAAmB,MAAa;AACxC,YAAM,SAAS,MAAM,SAAS;AAAA,IAClC;AAAA,IAOA,cAAc,CAAC,UAAiB;AAE5B,YAAM,uBAAuB,OAAO,eAAe,OAAO,KAAK,aAAa,CAAC;AAG7E,UAAI,yBAAyB,MAAM;AAC/B,cAAM,IAAI;AAAA,UACN,gDAAgD,KAAK,aAAa;AAAA,QACtE;AAAA,MACJ;AAEA,UAAI;AAEJ,UAAI;AAEA,kCAA0B,qBAAqB,KAAK,IAAI;AAAA,MAC5D,SAAS,OAAP;AAEE,YAAI,iBAAiB,OAAO;AACxB,gBAAM,IAAI,MAAM,6BAA6B,KAAK,aAAa,aAAa,MAAM,OAAO;AAAA,QAC7F,OAAO;AACH,gBAAM,IAAI,MAAM,6BAA6B,KAAK,aAAa,aAAa,OAAO;AAAA,QACvF;AAAA,MACJ;AAGA,UAAI,OAAO,4BAA4B,WAAW;AAC9C,cAAM,IAAI;AAAA,UACN,sCAAsC,KAAK,aAAa,wCAAwC;AAAA,QACpG;AAAA,MACJ;AAGA,aAAO,CAAC;AAAA,IACZ;AAAA,EACJ;;;AC1CA,MAA8B,WAA9B,cAA+C,UAAoC;AAAA,IAM/E,YAAY,MAAc,MAAqB,cAAsB;AACjE,YAAM,MAAM,IAAI;AAD2B;AAAA,IAE/C;AAAA,IAKA,kBAAkB,MAAM,KAAK;AAAA,IAK7B,UAAU,MAAM;AAAA,IAKhB,aAAuC;AACnC,aAAO;AAAA,QACH,MAAM,KAAK;AAAA,QACX,MAAM,KAAK;AAAA,QACX,OAAO,KAAK,gBAAgB;AAAA,MAChC;AAAA,IACJ;AAAA,EAOJ;;;AC3CA,MAAqB,QAArB,cAAmC,SAAS;AAAA,IAKxC,YAAY,cAAsB,MAAa;AAC3C,YAAM,SAAS,MAAM,YAAY;AAAA,IACrC;AAAA,IAMA,oBAAoB,CAAC,UAAiB;AAElC,YAAM,sBAAsB,OAAO,eAAe,OAAO,KAAK,gBAAgB,CAAC;AAG/E,UAAI,wBAAwB,MAAM;AAC9B,cAAM,IAAI;AAAA,UACN,+BAA+B,KAAK,gBAAgB;AAAA,QACxD;AAAA,MACJ;AAGA,0BAAoB,KAAK,IAAI;AAAA,IACjC;AAAA,EACJ;;;AC3BA,MAAqB,OAArB,cAAkC,SAAS;AAAA,IAKvC,YAAY,cAAsB,MAAa;AAC3C,YAAM,QAAQ,MAAM,YAAY;AAAA,IACpC;AAAA,IAMA,oBAAoB,CAAC,UAAiB;AAElC,YAAM,sBAAsB,OAAO,eAAe,OAAO,KAAK,gBAAgB,CAAC;AAG/E,UAAI,wBAAwB,MAAM;AAC9B,cAAM,IAAI;AAAA,UACN,8BAA8B,KAAK,gBAAgB;AAAA,QACvD;AAAA,MACJ;AAGA,0BAAoB,KAAK,IAAI;AAAA,IACjC;AAAA,EACJ;;;AC3BA,MAAqB,OAArB,cAAkC,SAAS;AAAA,IAKvC,YAAY,cAAsB,MAAa;AAC3C,YAAM,QAAQ,MAAM,YAAY;AAAA,IACpC;AAAA,IAQA,oBAAoB,CAAC,OAAc,WAAoB,cAAuB;AAE1E,YAAM,sBAAsB,OAAO,eAAe,OAAO,KAAK,gBAAgB,CAAC;AAG/E,UAAI,wBAAwB,MAAM;AAC9B,cAAM,IAAI;AAAA,UACN,8BAA8B,KAAK,gBAAgB;AAAA,QACvD;AAAA,MACJ;AAGA,0BAAoB,CAAC,EAAE,WAAW,WAAW,SAAS,UAAU,GAAG,GAAG,KAAK,IAAI,CAAC;AAAA,IACpF;AAAA,EACJ;;;ACsBA,MAAM,qBAAqB,OAAO,UAAU;AAQ7B,WAAR,cAA+B,YAAkC,SAAqC;AAEzG,UAAM,wBAAwB,4BAA4B,UAAU;AAKpE;AAAA,MACI,CAAC,sBAAsB,qBAAqB,GAAG,OAAO,OAAO,qBAAqB,CAAC;AAAA,MACnF;AAAA,IACJ;AAGA,UAAM,WAAW,YAAY,sBAAsB,qBAAqB,uBAAuB,OAAO;AAGtG,4BAAwB,QAAQ;AAGhC,WAAO;AAAA,EACX;AASA,WAAS,YACL,YACA,uBACA,SACO;AAEP,UAAM,aAAa,sBAAsB,UAAU;AAGnD,YAAQ,WAAW,MAAM;AAAA,MACrB,KAAK;AACD,eAAO,IAAI,KAAK,YAAY,SAAS,YAAY,WAAW,OAAO,uBAAuB,OAAO,CAAC;AAAA,MAEtG,KAAK;AACD,YAAI,aAA4B;AAChC,YAAI,gBAA+B;AACnC,YAAI,gBAA+B;AAEnC,YAAI,MAAM,QAAQ,WAAW,UAAU,GAAG;AACtC,0BAAgB,WAAW,WAAW;AACtC,0BAAgB,WAAW,WAAW;AAAA,QAC1C,WAAW,UAAU,WAAW,UAAU,GAAG;AACzC,uBAAa,WAAW;AAAA,QAC5B;AAEA,eAAO,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,YAAY,WAAW,OAAO,uBAAuB,OAAO;AAAA,QAChE;AAAA,MAEJ,KAAK;AACD,YAAI,WAA0B;AAC9B,YAAI,cAA6B;AACjC,YAAI,cAA6B;AAEjC,YAAI,MAAM,QAAQ,WAAW,QAAQ,GAAG;AACpC,wBAAc,WAAW,SAAS;AAClC,wBAAc,WAAW,SAAS;AAAA,QACtC,WAAW,UAAU,WAAW,QAAQ,GAAG;AACvC,qBAAW,WAAW;AAAA,QAC1B;AAEA,eAAO,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,YAAY,WAAW,OAAO,uBAAuB,OAAO;AAAA,QAChE;AAAA,MAEJ,KAAK;AACD,eAAO,IAAI,KAAK,YAAY,SAAS,YAAY,WAAW,OAAO,uBAAuB,OAAO,CAAC;AAAA,MAEtG,KAAK;AACD,eAAO,IAAI,QAAQ,YAAY,SAAS,YAAY,WAAW,OAAO,uBAAuB,OAAO,CAAC;AAAA,MAEzG,KAAK;AACD,eAAO,IAAI,KAAK,YAAY,SAAS,YAAY,WAAW,OAAO,uBAAuB,OAAO,CAAC;AAAA,MAEtG,KAAK;AACD,eAAO,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA,WAAW,SAAS,IAAI,CAAC,UAAU,YAAY,OAAO,uBAAuB,OAAO,CAAC;AAAA,QACzF;AAAA,MAEJ,KAAK;AACD,eAAO,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA,WAAW,SAAS,IAAI,CAAC,UAAU,YAAY,OAAO,uBAAuB,OAAO,CAAC;AAAA,QACzF;AAAA,MAEJ,KAAK;AACD,eAAO,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA,WAAW,SAAS,IAAI,CAAC,UAAU,YAAY,OAAO,uBAAuB,OAAO,CAAC;AAAA,QACzF;AAAA,MAEJ,KAAK;AACD,eAAO,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA,WAAW,SAAS,IAAI,CAAC,UAAU,YAAY,OAAO,uBAAuB,OAAO,CAAC;AAAA,QACzF;AAAA,MAEJ,KAAK;AACD,eAAO,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,WAAW,SAAS,IAAI,CAAC,UAAU,YAAY,OAAO,uBAAuB,OAAO,CAAC;AAAA,QACzF;AAAA,MAEJ,KAAK;AACD,eAAO,YAAY,sBAAsB,WAAW,KAAK,OAAO,uBAAuB,OAAO;AAAA,MAElG,KAAK;AACD,eAAO,IAAI,OAAO,YAAY,SAAS,WAAW,MAAM,WAAW,QAAQ,CAAC,CAAC;AAAA,MAEjF,KAAK;AACD,eAAO,IAAI,UAAU,YAAY,SAAS,WAAW,MAAM,WAAW,QAAQ,CAAC,CAAC;AAAA,MAEpF,KAAK;AACD,YAAI,WAA0B;AAC9B,YAAI,cAA6B;AACjC,YAAI,cAA6B;AAEjC,YAAI,MAAM,QAAQ,WAAW,QAAQ,GAAG;AACpC,wBAAc,WAAW,SAAS;AAClC,wBAAc,WAAW,SAAS;AAAA,QACtC,WAAW,UAAU,WAAW,QAAQ,GAAG;AACvC,qBAAW,WAAW;AAAA,QAC1B;AAEA,eAAO,IAAI,KAAK,YAAY,SAAS,UAAU,aAAa,WAAW;AAAA,IAC/E;AAAA,EACJ;AAOA,WAAS,sBAAsB,YAA4C;AACvE,UAAM,aAA0B,CAAC;AAEjC,QAAI,WAAW,OAAO;AAClB,iBAAW,KAAK,IAAI,MAAM,WAAW,MAAM,MAAM,WAAW,MAAM,QAAQ,CAAC,CAAC,CAAC;AAAA,IACjF;AAEA,QAAI,WAAW,OAAO;AAClB,iBAAW,KAAK,IAAI,MAAM,WAAW,MAAM,MAAM,WAAW,MAAM,QAAQ,CAAC,CAAC,CAAC;AAAA,IACjF;AAEA,QAAI,WAAW,OAAO;AAClB,iBAAW,KAAK,IAAI,MAAM,WAAW,MAAM,MAAM,WAAW,MAAM,QAAQ,CAAC,CAAC,CAAC;AAAA,IACjF;AAEA,QAAI,WAAW,MAAM;AACjB,iBAAW,KAAK,IAAI,KAAK,WAAW,KAAK,MAAM,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,IAC9E;AAEA,QAAI,WAAW,MAAM;AACjB,iBAAW,KAAK,IAAI,KAAK,WAAW,KAAK,MAAM,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC;AAAA,IAC9E;AAEA,WAAO;AAAA,EACX;AAOA,WAAS,4BAA4B,YAAyD;AAE1F,UAAM,cAAqC,CAAC;AAG5C,eAAW,CAAC,MAAM,kBAAkB,KAAK,OAAO,QAAQ,OAAO,YAAY,CAAC,GAAG;AAE3E,kBAAY,QAAQ,EAAE,GAAG,oBAAoB,IAAI,KAAK;AAAA,IAC1D;AAIA,eAAW,sBAAsB,YAAY;AACzC,kBAAY,mBAAmB,MAAM,sBAAsB;AAAA,IAC/D;AAEA,WAAO;AAAA,EACX;AAMA,WAAS,wBAAwB,MAAY;AACzC,UAAM,YAAsB,CAAC;AAE7B,UAAM,gBAAgB,CAAC,MAAc,SAAe;AAEhD,aAAO,KAAK,OAAO,IAAI;AAGvB,UAAI,KAAK,WAAW,GAAG;AACnB,kBAAU,KAAK,IAAI;AAAA,MACvB,OAAO;AACH,QAAC,KAA+B,YAAY,EAAE,QAAQ,CAAC,UAAU,cAAc,MAAM,KAAK,CAAC;AAAA,MAC/F;AAAA,IACJ;AAGA,kBAAc,CAAC,GAAG,IAAI;AAEtB,cAAU,QAAQ,CAAC,SAAS;AAExB,eAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;AAE9C,cAAM,cAAc,KAAK;AAGzB,YAAI,YAAY,aAAa,GAAG;AAC5B;AAAA,QACJ;AAGA,cAAM,YAAY,IAAI;AAAA,UAClB,KACK,MAAM,GAAG,QAAQ,CAAC,EAClB,IAAmB,CAAC,UAAU;AAAA,YAC3B;AAAA,YACA,QAAQ,KAAK,cAAc,EAAE,OAAO,CAAC,cAAc,UAAU,QAAQ,CAAC;AAAA,UAC1E,EAAE,EACD,OAAO,CAAC,YAAY,QAAQ,OAAO,SAAS,CAAC;AAAA,QACtD;AAGA,oBAAY,aAAa,SAAS;AAAA,MACtC;AAAA,IACJ,CAAC;AAAA,EACL;;;AC9SO,MAAM,gBAAN,MAAoB;AAAA,IAYvB,YACI,YACQ,OACA,UAAgC,CAAC,GAC3C;AAFU;AACA;AAGR,UAAI,kBAAkB,UAAU,GAAG;AAC/B,cAAM,IAAI,MAAM,6BAA6B;AAAA,MACjD;AAGA,UAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC7C,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC9D;AAGA,YAAM,EAAE,WAAW,cAAc,KAAK,IAAI,mBAAmB,UAAU;AAGvE,UAAI,CAAC,WAAW;AACZ,cAAM,IAAI,MAAM,uBAAuB,cAAc;AAAA,MACzD;AAGA,UAAI,CAAC,MAAM;AACP,cAAM,IAAI;AAAA,UACN;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI;AAEA,aAAK,YAAY,cAAc,MAAM,OAAO;AAAA,MAChD,SAAS,WAAP;AAEE,cAAM,IAAI,MAAM,wBAAyB,UAAoB,SAAS;AAAA,MAC1E;AAAA,IACJ;AAAA,IA7CiB;AAAA,IAmDV,YAAqB;AACxB,aAAO,KAAK,UAAU,SAAS;AAAA,IACnC;AAAA,IAMO,WAAkB;AACrB,aAAO,KAAK,UAAU,SAAS;AAAA,IACnC;AAAA,IAUO,OAAa;AAEhB,UAAI,KAAK,UAAU,SAAS,iDAAyB,KAAK,UAAU,SAAS,yCAAoB;AAC7F,aAAK,UAAU,MAAM;AAAA,MACzB;AAEA,UAAI;AACA,aAAK,UAAU,OAAO,KAAK,KAAK;AAAA,MACpC,SAAS,WAAP;AACE,cAAM,IAAI,MAAM,wBAAyB,UAAoB,SAAS;AAAA,MAC1E;AAAA,IACJ;AAAA,IAKO,QAAc;AACjB,WAAK,UAAU,MAAM;AAAA,IACzB;AAAA,IAMO,qBAAkC;AACrC,aAAO,KAAK,UAAU,WAAW;AAAA,IACrC;AAAA,IAOA,OAAO,SAAS,MAAc,OAAqD;AAE/E,UAAI,OAAO,UAAU,YAAY;AAC7B,eAAO,QAAQ,MAAM,KAAK;AAC1B;AAAA,MACJ;AAGA,UAAI,OAAO,UAAU,UAAU;AAC3B,YAAI;AAGJ,YAAI;AACA,gCAAsB,kBAAkB,KAAK;AAAA,QACjD,SAAS,WAAP;AACE,gBAAM,IAAI,MAAM,+CAAgD,UAAoB,SAAS;AAAA,QACjG;AAGA,YAAI,oBAAoB,UAAU,KAAK,OAAO,oBAAoB,GAAG,OAAO,aAAa;AACrF,gBAAM,IAAI,MAAM,mEAAmE;AAAA,QACvF;AAEA,YAAI;AAEA,gBAAM,EAAE,WAAW,aAAa,IAAI,uBAAuB,oBAAoB,EAAE;AAGjF,cAAI,CAAC,WAAW;AACZ,kBAAM,IAAI,MAAM,YAAY;AAAA,UAChC;AAAA,QACJ,SAAS,WAAP;AACE,gBAAM,IAAI,MAAM,iCAAkC,UAAoB,SAAS;AAAA,QACnF;AAGA,eAAO,WAAW,MAAM,oBAAoB,EAAE;AAAA,MAClD,WAAW,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AAG3D,YAAI;AAEA,gBAAM,EAAE,WAAW,aAAa,IAAI,uBAAuB,KAAK;AAGhE,cAAI,CAAC,WAAW;AACZ,kBAAM,IAAI,MAAM,YAAY;AAAA,UAChC;AAAA,QACJ,SAAS,WAAP;AACE,gBAAM,IAAI,MAAM,iCAAkC,UAAoB,SAAS;AAAA,QACnF;AAGA,eAAO,WAAW,MAAM,KAAK;AAAA,MACjC,OAAO;AACH,cAAM,IAAI,MAAM,0FAA0F;AAAA,MAC9G;AAAA,IACJ;AAAA,IAMA,OAAO,WAAW,MAAoB;AAClC,aAAO,OAAO,IAAI;AAAA,IACtB;AAAA,IAKA,OAAO,gBAAsB;AACzB,aAAO,MAAM;AAAA,IACjB;AAAA,EACJ;", + "sources": ["../node_modules/lotto-draw/dist/Participant.js", "../node_modules/lotto-draw/dist/Utilities.js", "../node_modules/lotto-draw/dist/Lotto.js", "../node_modules/lotto-draw/dist/createLotto.js", "../node_modules/lotto-draw/dist/index.js", "../src/index.ts", "../src/State.ts", "../src/Lookup.ts", "../src/BehaviourTreeDefinitionUtilities.ts", "../src/mdsl/MDSLUtilities.ts", "../src/mdsl/MDSLNodeArgumentParser.ts", "../src/mdsl/MDSLNodeAttributeParser.ts", "../src/mdsl/MDSLDefinitionParser.ts", "../src/BehaviourTreeDefinitionValidator.ts", "../src/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/Utilities.ts", "../src/nodes/Node.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Parallel.ts", "../src/nodes/composite/Race.ts", "../src/nodes/composite/All.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/leaf/Leaf.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/attributes/Attribute.ts", "../src/attributes/guards/Guard.ts", "../src/attributes/guards/While.ts", "../src/attributes/guards/Until.ts", "../src/attributes/callbacks/Callback.ts", "../src/attributes/callbacks/Entry.ts", "../src/attributes/callbacks/Step.ts", "../src/attributes/callbacks/Exit.ts", "../src/BehaviourTreeBuilder.ts", "../src/BehaviourTree.ts"], + "sourcesContent": ["\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Participant = void 0;\r\n/**\r\n * A participant that holds a number of tickets.\r\n */\r\nvar Participant = /** @class */ (function () {\r\n /**\r\n * Creates an instance of the Participant class.\r\n * @param participant The actual participant.\r\n * @param tickets The number of tickets held by the participant.\r\n */\r\n function Participant(participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n this._participant = participant;\r\n this._tickets = tickets;\r\n }\r\n Object.defineProperty(Participant.prototype, \"participant\", {\r\n /** Gets the actual participant. */\r\n get: function () {\r\n return this._participant;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(Participant.prototype, \"tickets\", {\r\n /** Gets or sets the number of tickets held by the participant. */\r\n get: function () {\r\n return this._tickets;\r\n },\r\n set: function (value) {\r\n this._tickets = value;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n return Participant;\r\n}());\r\nexports.Participant = Participant;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.isNaturalNumber = exports.isNullOrUndefined = void 0;\r\n/**\r\n * Gets whether the value provided is null or undefined.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is null or undefined.\r\n */\r\nfunction isNullOrUndefined(value) {\r\n return value === null || value === undefined;\r\n}\r\nexports.isNullOrUndefined = isNullOrUndefined;\r\n/**\r\n * Gets whether the value provided is a natural number.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is a natural number.\r\n */\r\nfunction isNaturalNumber(value) {\r\n return typeof value === \"number\" && value >= 1 && Math.floor(value) === value;\r\n}\r\nexports.isNaturalNumber = isNaturalNumber;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Lotto = void 0;\r\nvar Participant_1 = require(\"./Participant\");\r\nvar Utilities_1 = require(\"./Utilities\");\r\n/**\r\n * Represents a lotto consisting of a number of pickable ticket-holding participants.\r\n */\r\nvar Lotto = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of Lotto.\r\n * @param customRandom The custom RNG to use in place of Math.random().\r\n */\r\n function Lotto(customRandom) {\r\n /** The array of participants that are holding tickets in the lotto. */\r\n this._participants = [];\r\n this._customRandom = customRandom;\r\n }\r\n /**\r\n * Adds a participant with the specified number of tickets, or adds to the participant ticket count if the participant already holds tickets.\r\n * @param participant The participant to add or to increase the ticket count for if they already hold tickets.\r\n * @param tickets The number of tickets, defaults to 1.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.add = function (participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n // Check whether this participant has already been added.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n if (existingParticipant) {\r\n // The participant has already been added to the lotto so just add to their ticket count.\r\n existingParticipant.tickets += tickets;\r\n }\r\n else {\r\n // The participant is not part of the lotto so we should add them.\r\n this._participants.push(new Participant_1.Participant(participant, tickets));\r\n }\r\n return this;\r\n };\r\n /**\r\n * Removes the specified number of tickets for the given participant from the draw, or all tickets if a ticket number is not defined.\r\n * @param participant The participant to remove tickets for.\r\n * @param tickets The number of tickets to remove, or undefined if all tickets are to be removed.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.remove = function (participant, tickets) {\r\n // Attempt to get the existing participant.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n // There is nothing to do if the specified participant isn't even part of the lotto.\r\n if (!existingParticipant) {\r\n return this;\r\n }\r\n // Check whether a tickets value was given.\r\n if (tickets !== undefined) {\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n existingParticipant.tickets -= tickets;\r\n // If the participant no longer holds any tickets then they should be removed.\r\n if (existingParticipant.tickets < 1) {\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n }\r\n else {\r\n // We are removing all tickets for the participant so just remove them from the lotto.\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n return this;\r\n };\r\n /**\r\n * Draw a winning ticket and return the participant that holds the ticket.\r\n * @param options The draw options.\r\n * @returns The participant that holds the winning ticket.\r\n */\r\n Lotto.prototype.draw = function (options) {\r\n if (options === void 0) { options = {}; }\r\n // If we have no participants then just return null.\r\n if (this._participants.length === 0) {\r\n return null;\r\n }\r\n var redrawable = (0, Utilities_1.isNullOrUndefined)(options.redrawable) ? true : options.redrawable;\r\n var pickable = [];\r\n this._participants.forEach(function (_a) {\r\n var participant = _a.participant, tickets = _a.tickets;\r\n for (var ticketCount = 0; ticketCount < tickets; ticketCount++) {\r\n pickable.push(participant);\r\n }\r\n });\r\n var random;\r\n // We need a random floating-point number between 0 (inclusive) and 1 to scale up to pick our winner.\r\n // If a custom random function exists then we should use that or fall back to Math.random().\r\n if (this._customRandom) {\r\n // Call our custom random function to get a random floating-point number.\r\n random = this._customRandom();\r\n // Verify that the result of calling our custom random function is a number between 0 (inclusive) and 1.\r\n if (typeof random !== \"number\" || random < 0 || random >= 1) {\r\n throw new Error(\"the 'random' function provided did not return a number between 0 (inclusive) and 1\");\r\n }\r\n }\r\n else {\r\n // No custom random function was defined so just use good ol' Math.random().\r\n random = Math.random();\r\n }\r\n // Pick a winning participant.\r\n var winner = pickable[Math.floor(random * pickable.length)];\r\n // If the ticket isn't redrawable then we should remove a ticket from the winning participants ticket count.\r\n if (!redrawable) {\r\n this.remove(winner, 1);\r\n }\r\n // Return the winning participant.\r\n return winner;\r\n };\r\n /**\r\n * Draws multiple winning tickets and return an array of the participants that hold the winning tickets.\r\n * @param tickets The number of winning tickets to draw.\r\n * @param options The draw multiple options.\r\n * @returns An array of the participants that hold the winning tickets.\r\n */\r\n Lotto.prototype.drawMultiple = function (tickets, options) {\r\n if (options === void 0) { options = {}; }\r\n var uniqueResults = (0, Utilities_1.isNullOrUndefined)(options.unique) ? false : options.unique;\r\n // Handle cases where the user has asked for zero tickets (no idea why they would do this be we should trust them).\r\n if (tickets === 0) {\r\n return [];\r\n }\r\n // Now that we know out tickets value is not zero we should check that it is a valid natural number.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n var result = [];\r\n // Keep drawing tickets until we either reach the number of required tickets or we simply run out of tickets to draw.\r\n // We can run out of tickets to draw if 'options.redrawable' is explicity 'false' or we just had no participants when 'drawMultiple' was called.\r\n while (result.length < tickets && this._participants.length > 0) {\r\n result.push(this.draw(options));\r\n }\r\n // If the 'unique' draw option is set then we need to remove duplicates from the result list.\r\n if (uniqueResults) {\r\n // Create an array to store our unique results.\r\n var unique = [];\r\n // Iterate over all of our participants (with potential duplicates) and populate our array of unique values.\r\n for (var _i = 0, result_1 = result; _i < result_1.length; _i++) {\r\n var participant = result_1[_i];\r\n if (unique.indexOf(participant) === -1) {\r\n unique.push(participant);\r\n }\r\n }\r\n result = unique;\r\n }\r\n return result;\r\n };\r\n return Lotto;\r\n}());\r\nexports.Lotto = Lotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.createLotto = void 0;\r\nvar Lotto_1 = require(\"./Lotto\");\r\n/**\r\n * A function that creates and returns a Lotto instance.\r\n * @param participantsOrOptions An array of initial participants or options relating to the creation of a Lotto instance.\r\n * @returns A new Lotto instance.\r\n */\r\nfunction createLotto(participantsOrOptions) {\r\n // If no initial participants or lotto options were provided as an argument then we can just return a new lotto instance now.\r\n if (!participantsOrOptions) {\r\n return new Lotto_1.Lotto();\r\n }\r\n // Check whether we were provided with an array of initial participants or a lotto options object.\r\n if (Array.isArray(participantsOrOptions)) {\r\n // We are dealing with a pre-defined array of participants.\r\n var participants = participantsOrOptions;\r\n var lotto_1 = new Lotto_1.Lotto();\r\n // If the lotto participants have been defined upfront then we will need to add them all to our lotto instance now.\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_1.add(participant, tokens);\r\n });\r\n // Return the Lotto instance.\r\n return lotto_1;\r\n }\r\n else {\r\n // We are dealing with some lotto options.\r\n var random = participantsOrOptions.random, participants = participantsOrOptions.participants;\r\n // Create a Lotto instance passing the custom RNG function to use in place of Math.random() (which could be undefined).\r\n var lotto_2 = new Lotto_1.Lotto(random);\r\n // If the lotto participants have been defined upfront as part of the options then we will need to add them all to our lotto instance now.\r\n if (participants) {\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_2.add(participant, tokens);\r\n });\r\n }\r\n // Return the Lotto instance.\r\n return lotto_2;\r\n }\r\n}\r\nexports.createLotto = createLotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar createLotto_1 = require(\"./createLotto\");\r\nexports.default = createLotto_1.createLotto;\r\n", "import State from \"./State\";\nimport { BehaviourTree } from \"./BehaviourTree\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { NodeDetails, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n /**\n * The state that a node will be in when it has not been visited yet in the execution of the tree.\n */\n READY = \"mistreevous.ready\",\n /**\n * The state that a node will be in when it is still being processed and will usually represent or encompass a long-running action.\n */\n RUNNING = \"mistreevous.running\",\n /**\n * The state that a node will be in when it is no longer being processed and has succeeded.\n */\n SUCCEEDED = \"mistreevous.succeeded\",\n /**\n * The state that a node will be in when it is no longer being processed but has failed.\n */\n FAILED = \"mistreevous.failed\"\n}\n\nexport { State as default };\n\nexport type CompleteState = State.SUCCEEDED | State.FAILED;\nexport type AnyState = State.READY | State.RUNNING | CompleteState;\n", "import { ActionResult, Agent, GlobalFunction } from \"./Agent\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\n\nexport type InvokerFunction = (args: any[]) => ActionResult | boolean;\n\n/**\n * A singleton used to store and lookup registered functions and subtrees.\n */\nexport default class Lookup {\n /**\n * The object holding any registered functions keyed on function name.\n */\n private static registeredFunctions: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered subtree root node definitions keyed on tree name.\n */\n private static registeredSubtrees: { [key: string]: RootNodeDefinition } = {};\n\n /**\n * Gets the function with the specified name.\n * @param name The name of the function.\n * @returns The function with the specified name.\n */\n public static getFunc(name: string): GlobalFunction {\n return this.registeredFunctions[name];\n }\n\n /**\n * Sets the function with the specified name for later lookup.\n * @param name The name of the function.\n * @param func The function.\n */\n public static setFunc(name: string, func: GlobalFunction): void {\n this.registeredFunctions[name] = func;\n }\n\n /**\n * Gets the function invoker for the specified agent and function name.\n * If a function with the specified name exists on the agent object then it will\n * be returned, otherwise we will then check the registered functions for a match.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param name The function name.\n * @returns The function invoker for the specified agent and function name.\n */\n static getFuncInvoker(agent: Agent, name: string): InvokerFunction | null {\n // Check whether the agent contains the specified function.\n const agentFunction = agent[name];\n if (agentFunction && typeof agentFunction === \"function\") {\n return (args: any[]) => agentFunction.apply(agent, args);\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.registeredFunctions[name] && typeof this.registeredFunctions[name] === \"function\") {\n const registeredFunction = this.registeredFunctions[name];\n return (args: any[]) => registeredFunction(agent, ...args);\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets all registered subtree root node definitions.\n */\n static getSubtrees(): { [key: string]: RootNodeDefinition } {\n return this.registeredSubtrees;\n }\n\n /**\n * Sets the subtree with the specified name for later lookup.\n * @param name The name of the subtree.\n * @param subtree The subtree.\n */\n static setSubtree(name: string, subtree: RootNodeDefinition) {\n this.registeredSubtrees[name] = subtree;\n }\n\n /**\n * Removes the registered function or subtree with the specified name.\n * @param name The name of the registered function or subtree.\n */\n static remove(name: string) {\n delete this.registeredFunctions[name];\n delete this.registeredSubtrees[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.registeredFunctions = {};\n this.registeredSubtrees = {};\n }\n}\n", "import {\n NodeDefinition,\n RootNodeDefinition,\n DecoratorNodeDefinition,\n CompositeNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition\n} from \"./BehaviourTreeDefinition\";\n\n/**\n * A type guard function that returns true if the specified node satisfies the RootNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the RootNodeDefinition type.\n */\nexport function isRootNode(node: NodeDefinition): node is RootNodeDefinition {\n return node.type === \"root\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the BranchNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the BranchNodeDefinition type.\n */\nexport function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition {\n return node.type === \"branch\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the NodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the NodeDefinition type.\n */\nexport function isLeafNode(node: NodeDefinition): node is NodeDefinition {\n return [\"branch\", \"action\", \"condition\", \"wait\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the DecoratorNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the DecoratorNodeDefinition type.\n */\nexport function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefinition {\n return [\"root\", \"repeat\", \"retry\", \"flip\", \"succeed\", \"fail\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the CompositeNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type.\n */\nexport function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition {\n return [\"sequence\", \"selector\", \"lotto\", \"parallel\", \"race\", \"all\"].includes(node.type);\n}\n\n/**\n * Flatten a node definition into an array of all of its nested node definitions.\n * @param nodeDefinition The node definition to flatten.\n * @returns An array of all of nested node definitions.\n */\nexport function flattenDefinition(nodeDefinition: AnyNodeDefinition): AnyNodeDefinition[] {\n const nodes: AnyNodeDefinition[] = [];\n\n const processNode = (currentNodeDefinition: AnyNodeDefinition) => {\n nodes.push(currentNodeDefinition);\n\n if (isCompositeNode(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNode(currentNodeDefinition)) {\n processNode(currentNodeDefinition.child);\n }\n };\n\n processNode(nodeDefinition);\n\n return nodes;\n}\n\n/**\n * Determines whether the passed value is an integer.\n * @param value The value to check.\n * @returns Whether the passed value is an integer.\n */\nexport function isInteger(value: unknown): boolean {\n return typeof value === \"number\" && Math.floor(value) === value;\n}\n\n/**\n * Determines whether the passed value is null or undefined.\n * @param value The value to check.\n * @returns Whether the passed value is null or undefined.\n */\nexport function isNullOrUndefined(value: unknown): boolean {\n return typeof value === \"undefined\" || value === null;\n}\n", "/**\n * A type defining an object that holds a reference to substitued string literals parsed from the definition.\n */\nexport type StringLiteralPlaceholders = { [key: string]: string };\n\n/**\n * Pop the next raw token from the specified array of tokens and throw an error if it wasn't the expected one.\n * @param tokens The array of tokens.\n * @param expected An optional string or array or items, one of which must match the next popped token.\n * @returns The popped token.\n */\nexport function popAndCheck(tokens: string[], expected?: string | string[]): string {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token but there aren't any.\n if (popped === undefined) {\n throw new Error(\"unexpected end of definition\");\n }\n\n // Do we have an expected token/tokens array?\n if (expected != undefined) {\n // Get an array of expected values, if the popped token matches any then we are all good.\n const expectedValues = typeof expected === \"string\" ? [expected] : expected;\n\n // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase());\n\n // Throw an error if the popped token didn't match any of our expected items.\n if (!tokenMatchesExpectation) {\n const expectationString = expectedValues.map((item) => \"'\" + item + \"'\").join(\" or \");\n throw new Error(\"unexpected token found. Expected \" + expectationString + \" but got '\" + popped + \"'\");\n }\n }\n\n // Return the popped token.\n return popped;\n}\n\n/**\n * Swaps out any node/attribute argument string literals with placeholders.\n * @param definition The definition.\n * @returns An object containing a mapping of placeholders to original string values as well as the processed definition string.\n */\nexport function substituteStringLiterals(definition: string): {\n placeholders: StringLiteralPlaceholders;\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: StringLiteralPlaceholders = {};\n\n // Replace any string literals wrapped with double quotes in our definition with placeholders to be processed later.\n const processedDefinition = definition.replace(/\\\"(\\\\.|[^\"\\\\])*\\\"/g, (match) => {\n var strippedMatch = match.substring(1, match.length - 1);\n var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch);\n\n // If we have no existing string literal match then create a new placeholder.\n if (!placeholder) {\n placeholder = `@@${Object.keys(placeholders).length}@@`;\n placeholders[placeholder] = strippedMatch;\n }\n\n return placeholder;\n });\n\n return { placeholders, processedDefinition };\n}\n\n/**\n * Parse the tree definition into an array of raw tokens.\n * @param definition The definition.\n * @returns An array of tokens parsed from the definition.\n */\nexport function parseTokensFromDefinition(definition: string): string[] {\n // Add some space around various important characters so that they can be plucked out easier as individual tokens.\n definition = definition.replace(/\\(/g, \" ( \");\n definition = definition.replace(/\\)/g, \" ) \");\n definition = definition.replace(/\\{/g, \" { \");\n definition = definition.replace(/\\}/g, \" } \");\n definition = definition.replace(/\\]/g, \" ] \");\n definition = definition.replace(/\\[/g, \" [ \");\n definition = definition.replace(/\\,/g, \" , \");\n\n // Split the definition into raw token form and return it.\n return definition.replace(/\\s+/g, \" \").trim().split(\" \");\n}\n", "import { StringLiteralPlaceholders, popAndCheck } from \"./MDSLUtilities\";\n\n/**\n * A type representing any node function argument.\n */\ntype Argument = {\n /**\n * The argument value.\n */\n value: T;\n /**\n * The argument type, used for validation.\n */\n type: string;\n};\n\ntype NullArgument = Argument & {\n type: \"null\";\n};\n\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\n\ntype NumberArgument = Argument & {\n type: \"number\";\n /**\n * A flag defining whether the number argument value is a valid integer. (used for validation)\n */\n isInteger: boolean;\n};\n\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\n\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\n\n/**\n * A type representing a reference to any node function argument.\n */\ntype AnyArgument = NullArgument | BooleanArgument | NumberArgument | StringPlaceholderArgument | IdentifierArgument;\n\n/**\n * Parse an array of argument definitions from the specified tokens array.\n * @param tokens The array tokens to parse the argument definitions from.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @param argumentValidator The argument validator function.\n * @param validationFailedMessage The exception message to throw if argument validation fails.\n * @returns An array of argument definitions parsed from the specified tokens array.\n */\nexport function parseArgumentTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): AnyArgument[] {\n const argumentList: AnyArgument[] = [];\n\n // If the next token is not a '[' or '(' then we have no arguments to parse.\n if (![\"[\", \"(\"].includes(tokens[0])) {\n return argumentList;\n }\n\n // Any lists of arguments will always be wrapped in '[]' for node arguments or '()' for attribute arguments.\n // We are looking for a '[' or '(' opener that wraps the argument tokens and the relevant closer.\n const closingToken = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closingToken) {\n // The next token is part of our arguments list.\n argumentListTokens.push(tokens.shift()!);\n }\n\n // Validate the order of the argument tokens. Each token must either be a ',' or a single argument that satisfies the validator.\n argumentListTokens.forEach((token, index) => {\n // Get whether this token should be an actual argument.\n const shouldBeArgumentToken = !(index & 1);\n\n // If the current token should be an actual argument then validate it, otherwise it should be a ',' token.\n if (shouldBeArgumentToken) {\n // Get the argument definition.\n const argumentDefinition = getArgumentDefinition(token, stringArgumentPlaceholders);\n\n // This is a valid argument!\n argumentList.push(argumentDefinition);\n } else {\n // The current token should be a ',' token.\n if (token !== \",\") {\n throw new Error(`invalid argument list, expected ',' or ']' but got '${token}'`);\n }\n }\n });\n\n // The arguments list should terminate with a ']' or ')' token, depending on the opener.\n popAndCheck(tokens, closingToken);\n\n // Return the arguments.\n return argumentList;\n}\n\n/**\n * Gets an argument value definition.\n * @param token The argument token.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An argument value definition.\n */\nfunction getArgumentDefinition(token: string, stringArgumentPlaceholders: StringLiteralPlaceholders): AnyArgument {\n // Check whether the token represents a null value.\n if (token === \"null\") {\n return {\n value: null,\n type: \"null\"\n } as NullArgument;\n }\n\n // Check whether the token represents a boolean value.\n if (token === \"true\" || token === \"false\") {\n return {\n value: token === \"true\",\n type: \"boolean\"\n } as BooleanArgument;\n }\n\n // Check whether the token represents a number value.\n // TODO: Relies on broken isNaN - see MDN.\n // if (!Number.isNaN(token)) {\n if (!isNaN(token as any)) {\n return {\n value: parseFloat(token),\n isInteger: parseFloat(token) === parseInt(token, 10),\n type: \"number\"\n } as NumberArgument;\n }\n\n // Check whether the token is a placeholder (e.g. @@0@@) representing a string literal.\n if (token.match(/^@@\\d+@@$/g)) {\n return {\n value: stringArgumentPlaceholders[token].replace('\\\\\"', '\"'),\n type: \"string\"\n } as StringPlaceholderArgument;\n }\n\n // The only remaining option is that the argument value is an identifier.\n return {\n value: token,\n type: \"identifier\"\n } as IdentifierArgument;\n}\n", "import { NodeAttributeDefinition } from \"../BehaviourTreeDefinition\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { StringLiteralPlaceholders } from \"./MDSLUtilities\";\n\n/**\n * A type defining the attribute definitions of a node.\n */\ntype NodeAttributes = {\n while?: NodeAttributeDefinition;\n until?: NodeAttributeDefinition;\n entry?: NodeAttributeDefinition;\n exit?: NodeAttributeDefinition;\n step?: NodeAttributeDefinition;\n};\n\n/**\n * Parse any node attribute definitions from the specified tokens array.\n * @param tokens The array of remaining tokens.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An object of attribute definitions defined by any directly following tokens.\n */\nexport function parseAttributeTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): NodeAttributes {\n const nodeAttributeNames: (keyof NodeAttributes)[] = [\"while\", \"until\", \"entry\", \"exit\", \"step\"];\n\n // Create an object to hold any attributes found.\n const attributes: NodeAttributes = {};\n\n // Try to get the name of the attribute for the next token.\n let nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n\n // Pull attribute tokens as well as their arguments off of the tokens stack until we have no more.\n while (nodeAttributeNames.includes(nextAttributeName)) {\n // Check to make sure that we have not already created an attribute definition of this type.\n if (attributes[nextAttributeName]) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Remove the attribute name token from the array of tokens.\n tokens.shift();\n\n // Grab the attribute arguments, assuming the first to be an identifier.\n const [attributeCallIdentifier, ...attributeArguments] = parseArgumentTokens(\n tokens,\n stringArgumentPlaceholders\n );\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeCallIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected agent function or registered function name identifier argument for attribute\");\n }\n\n // Any attribute arguments (other than the expected call identifier) must have a type of string, number, boolean or null.\n attributeArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid attribute argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Create the attribute definition and add it to the object of attribute definitions found.\n attributes[nextAttributeName] = {\n call: attributeCallIdentifier.value,\n args: attributeArguments.map(({ value }) => value)\n };\n\n // Try to get the next attribute name token, as there could be multiple.\n nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n }\n\n return attributes;\n}\n", "import {\n ActionNodeDefinition,\n AnyChildNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition,\n ConditionNodeDefinition,\n FailNodeDefinition,\n FlipNodeDefinition,\n LottoNodeDefinition,\n ParallelNodeDefinition,\n RaceNodeDefinition,\n AllNodeDefinition,\n RepeatNodeDefinition,\n RetryNodeDefinition,\n RootNodeDefinition,\n SelectorNodeDefinition,\n SequenceNodeDefinition,\n SucceedNodeDefinition,\n WaitNodeDefinition\n} from \"../BehaviourTreeDefinition\";\nimport {\n isCompositeNode,\n isDecoratorNode,\n isLeafNode,\n isNullOrUndefined,\n isRootNode\n} from \"../BehaviourTreeDefinitionUtilities\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { parseAttributeTokens } from \"./MDSLNodeAttributeParser\";\nimport {\n StringLiteralPlaceholders,\n parseTokensFromDefinition,\n popAndCheck,\n substituteStringLiterals\n} from \"./MDSLUtilities\";\n\n/**\n * Convert the MDSL tree definition string into an equivalent JSON definition.\n * @param definition The tree definition string as MDSL.\n * @returns The root node JSON definitions.\n */\nexport function convertMDSLToJSON(definition: string): RootNodeDefinition[] {\n // Swap out any node/attribute argument string literals with a placeholder and get a mapping of placeholders to original values as well as the processed definition.\n const { placeholders, processedDefinition } = substituteStringLiterals(definition);\n\n // Parse our definition definition string into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\n return convertTokensToJSONDefinition(tokens, placeholders);\n}\n\n/**\n * Converts the specified tree definition tokens into a JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definitions.\n */\nfunction convertTokensToJSONDefinition(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RootNodeDefinition[] {\n // There must be at least 3 tokens for the tree definition to be valid. 'ROOT', '{' and '}'.\n if (tokens.length < 3) {\n throw new Error(\"invalid token count\");\n }\n\n // We should have a matching number of '{' and '}' tokens. If not, then there are scopes that have not been properly closed.\n if (tokens.filter((token) => token === \"{\").length !== tokens.filter((token) => token === \"}\").length) {\n throw new Error(\"scope character mismatch\");\n }\n\n // Create an array of tree stack arrays where root nodes will always be at the botton and the current composite/decorator node at the top.\n // There should be an element in this array for every root node defined and every element should be an array with a root note as the first element.\n // E.g. A definition with two root nodes defined:\n // [\n // [root, lotto, sequence],\n // [root, selector]\n // ]\n const treeStacks: [Partial, ...Partial[]][] = [];\n\n // Create an array of all root node definitions that we create.\n const rootNodes: Partial[] = [];\n\n // A helper function used to push node definitions onto the tree stack.\n const pushNode = (node: AnyNodeDefinition) => {\n // If the node is a root node then we need to create a new tree stack array with the root node at the root.\n if (isRootNode(node)) {\n // We need to double-check that this root node is not the child of another node.\n // We can do this by checking whether the top tree stack is not empty (contains an existing node)\n if (treeStacks[treeStacks.length - 1]?.length) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Add the root node definition to our array of all parsed root node definitions.\n rootNodes.push(node);\n\n // Add the root node definition to the root of a new tree stack.\n treeStacks.push([node]);\n\n return;\n }\n\n // All non-root nodes should be pushed after their root nodes so handle cases\n // where we may not have any tree stacks or our top-most tree stack is empty.\n if (!treeStacks.length || !treeStacks[treeStacks.length - 1].length) {\n throw new Error(\"expected root node at base of definition\");\n }\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Get the top-most node in the current tree stack, this will be a composite/decorator node\n // for which we will populate its children array if composite or setting its child if a decorator.\n const topTreeStackTopNode = topTreeStack[topTreeStack.length - 1] as AnyNodeDefinition;\n\n // If the top-most node in the current root stack is a composite or decorator\n // node then the current node should be added as a child of the top-most node.\n if (isCompositeNode(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNode(topTreeStackTopNode)) {\n // If the top node already has a child node set then throw an error as a decorator should only have a single child.\n if (topTreeStackTopNode.child) {\n throw new Error(\"a decorator node must only have a single child node\");\n }\n\n topTreeStackTopNode.child = node;\n }\n\n // If the node we are adding is also a composite or decorator node, then we should push it\n // onto the current tree stack, as subsequent nodes will be added as its child/children.\n if (!isLeafNode(node)) {\n topTreeStack.push(node);\n }\n };\n\n // A helper function used to pop the top-most node definition off of the tree stack and return it.\n const popNode = (): AnyNodeDefinition | null => {\n let poppedNode: AnyNodeDefinition | null = null;\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Pop the top-most node in the current tree stack if there is one.\n if (topTreeStack.length) {\n poppedNode = topTreeStack.pop() as AnyNodeDefinition;\n }\n\n // We don't want any empty tree stacks in our stack of tree stacks.\n if (!topTreeStack.length) {\n treeStacks.pop();\n }\n\n return poppedNode;\n };\n\n // We should keep processing the raw tokens until we run out of them.\n while (tokens.length) {\n // Grab the next token.\n const token = tokens.shift()!;\n\n // How we create the next node depends on the current raw token value.\n switch (token.toUpperCase()) {\n case \"ROOT\": {\n pushNode(createRootNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SUCCEED\": {\n pushNode(createSucceedNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FAIL\": {\n pushNode(createFailNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FLIP\": {\n pushNode(createFlipNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"REPEAT\": {\n pushNode(createRepeatNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RETRY\": {\n pushNode(createRetryNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SEQUENCE\": {\n pushNode(createSequenceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SELECTOR\": {\n pushNode(createSelectorNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"PARALLEL\": {\n pushNode(createParallelNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RACE\": {\n pushNode(createRaceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ALL\": {\n pushNode(createAllNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"LOTTO\": {\n pushNode(createLottoNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ACTION\": {\n pushNode(createActionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"CONDITION\": {\n pushNode(createConditionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"WAIT\": {\n pushNode(createWaitNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"BRANCH\": {\n pushNode(createBranchNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope and means that we have to pop a node off of the current stack.\n const poppedNode = popNode();\n\n // Now that we have a node definition we can carry out any validation that may require the node to be fully populated.\n if (poppedNode) {\n validatePoppedNode(poppedNode);\n }\n\n break;\n }\n\n default: {\n throw new Error(`unexpected token: ${token}`);\n }\n }\n }\n\n return rootNodes as RootNodeDefinition[];\n}\n\n/**\n * Creates a root node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definition.\n */\nfunction createRootNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RootNodeDefinition {\n // Create the root node definition.\n let node = {\n type: \"root\"\n } as Partial;\n\n // Parse any node arguments, we should only have one if any which will be an identifier argument for the root identifier.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Check whether any node arguments were defined.\n if (nodeArguments.length) {\n // We should only have one argument, if any, which will be an identifier argument for the root identifier.\n if (nodeArguments.length === 1 && nodeArguments[0].type === \"identifier\") {\n // The root node identifier will be the first and only node argument value.\n node.id = nodeArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the root node definition.\n return node as RootNodeDefinition;\n}\n\n/**\n * Creates a succeed node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The succeed node JSON definition.\n */\nfunction createSucceedNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SucceedNodeDefinition {\n const node = {\n type: \"succeed\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SucceedNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the succeed node definition.\n return node;\n}\n\n/**\n * Creates a fail node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The fail node JSON definition.\n */\nfunction createFailNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FailNodeDefinition {\n const node = {\n type: \"fail\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FailNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the fail node definition.\n return node;\n}\n\n/**\n * Creates a flip node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The flip node JSON definition.\n */\nfunction createFlipNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FlipNodeDefinition {\n const node = {\n type: \"flip\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FlipNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the flip node definition.\n return node;\n}\n\n/**\n * Creates a repeat node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The repeat node JSON definition.\n */\nfunction createRepeatNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RepeatNodeDefinition {\n let node = { type: \"repeat\" } as RepeatNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a repeat node are optional. We may have:\n // - No node arguments, in which case the repeat note will iterate indefinitely.\n // - One node argument which will be the explicit number of iterations to make.\n // - Two node arguments which define the min and max iteration bounds from which a random iteration count will be picked.\n if (nodeArguments.length) {\n // All repeat node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`repeat node iteration counts must be integer values`);\n });\n\n // We should have got one or two iteration counts.\n if (nodeArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = nodeArguments[0].value as number;\n\n // A repeat node must have a positive number of iterations if defined.\n if (node.iterations < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A repeat node must have a positive min and max iteration count if they are defined.\n if (node.iterations[0] < 0 || node.iterations[1] < 0) {\n throw new Error(\"a repeat node must have a positive minimum and maximum iteration count if defined\");\n }\n\n // A repeat node must not have an minimum iteration count that exceeds the maximum iteration count.\n if (node.iterations[0] > node.iterations[1]) {\n throw new Error(\n \"a repeat node must not have a minimum iteration count that exceeds the maximum iteration count\"\n );\n }\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of repeat node iteration count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the repeat node definition.\n return node;\n}\n\n/**\n * Creates a retry node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The retry node JSON definition.\n */\nfunction createRetryNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RetryNodeDefinition {\n let node = { type: \"retry\" } as RetryNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a retry node are optional. We may have:\n // - No node arguments, in which case the retry note will attempt indefinitely.\n // - One node argument which will be the explicit number of attempts to make.\n // - Two node arguments which define the min and max attempt bounds from which a random attempt count will be picked.\n if (nodeArguments.length) {\n // All retry node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`retry node attempt counts must be integer values`);\n });\n\n // We should have got one or two attempt counts.\n if (nodeArguments.length === 1) {\n // A static attempt count was defined.\n node.attempts = nodeArguments[0].value as number;\n\n // A retry node must have a positive number of attempts if defined.\n if (node.attempts < 0) {\n throw new Error(\"a retry node must have a positive number of attempts if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum attempt count was defined.\n node.attempts = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (node.attempts[0] < 0 || node.attempts[1] < 0) {\n throw new Error(\"a retry node must have a positive minimum and maximum attempt count if defined\");\n }\n\n // A retry node must not have a minimum attempt count that exceeds the maximum attempt count.\n if (node.attempts[0] > node.attempts[1]) {\n throw new Error(\n \"a retry node must not have a minimum attempt count that exceeds the maximum attempt count\"\n );\n }\n } else {\n // An incorrect number of attempt counts was defined.\n throw new Error(\"invalid number of retry node attempt count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the retry node definition.\n return node;\n}\n\n/**\n * Creates a sequence node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The sequence node JSON definition.\n */\nfunction createSequenceNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SequenceNodeDefinition {\n const node = {\n type: \"sequence\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SequenceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the sequence node definition.\n return node;\n}\n\n/**\n * Creates a selector node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The selector node JSON definition.\n */\nfunction createSelectorNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SelectorNodeDefinition {\n const node = {\n type: \"selector\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SelectorNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the selector node definition.\n return node;\n}\n\n/**\n * Creates a parallel node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The parallel node JSON definition.\n */\nfunction createParallelNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ParallelNodeDefinition {\n const node = {\n type: \"parallel\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as ParallelNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the parallel node definition.\n return node;\n}\n\n/**\n * Creates a race node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The race node JSON definition.\n */\nfunction createRaceNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RaceNodeDefinition {\n const node = {\n type: \"race\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as RaceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the race node definition.\n return node;\n}\n\n/**\n * Creates an all node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The all node JSON definition.\n */\nfunction createAllNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): AllNodeDefinition {\n const node = {\n type: \"all\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as AllNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the all node definition.\n return node;\n}\n\n/**\n * Creates a lotto node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The lotto node JSON definition.\n */\nfunction createLottoNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): LottoNodeDefinition {\n // If any node arguments have been defined then they must be our weights.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // All lotto node arguments MUST be of type number and must be positive integers.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger || arg.value < 0)\n .forEach(() => {\n throw new Error(`lotto node weight arguments must be positive integer values`);\n });\n\n const node = {\n type: \"lotto\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as LottoNodeDefinition;\n\n // Apply the weights if any were defined.\n if (nodeArguments.length) {\n node.weights = nodeArguments.map(({ value }) => value) as number[];\n }\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the lotto node definition.\n return node;\n}\n\n/**\n * Creates an action node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The action node JSON definition.\n */\nfunction createActionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ActionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the action name\n // and agent function to invoke for the action, all other arguments are to be passed as arguments to that function.\n const [actionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require an action name argument.\n if (actionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid action node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the action node definition.\n return {\n type: \"action\",\n call: actionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a condition node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The condition node JSON definition.\n */\nfunction createConditionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ConditionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the condition name\n // and agent function to invoke for the condition, all other arguments are to be passed as arguments to that function.\n const [conditionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require a condition name argument.\n if (conditionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid condition node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the condition node definition.\n return {\n type: \"condition\",\n call: conditionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a wait node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The wait node JSON definition.\n */\nfunction createWaitNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): WaitNodeDefinition {\n let node = { type: \"wait\" } as WaitNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a wait node are optional. We may have:\n // - No node arguments, in which case the wait will be indefinite until it is aborted.\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n if (nodeArguments.length) {\n // All wait node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`wait node durations must be integer values`);\n });\n\n // We may have:\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n // - Too many arguments, which is not valid.\n if (nodeArguments.length === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0].value as number;\n\n // If an explict duration was defined then it must be a positive number.\n if (node.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.duration = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A wait node must have a positive min and max duration.\n if (node.duration[0] < 0 || node.duration[1] < 0) {\n throw new Error(\"a wait node must have a positive minimum and maximum duration\");\n }\n\n // A wait node must not have a minimum duration that exceeds the maximum duration.\n if (node.duration[0] > node.duration[1]) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else if (nodeArguments.length > 2) {\n // An incorrect number of duration arguments were defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n }\n\n // Return the wait node definition.\n return { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n}\n\n/**\n * Creates a branch node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The branch node JSON definition.\n */\nfunction createBranchNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): BranchNodeDefinition {\n // Parse any node arguments, we should have one which will be an identifier argument for the root ref.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // We should have only a single identifer argument for a branch node, which is the root ref.\n if (nodeArguments.length !== 1 || nodeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // Return the branch node definition.\n return { type: \"branch\", ref: nodeArguments[0].value };\n}\n\n/**\n * Validate a fully-populated node definition that was popped off of the tree stack.\n * @param definition The popped node to validate.\n */\nfunction validatePoppedNode(definition: AnyNodeDefinition): void {\n // Decorators MUST have a child defined.\n if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) {\n throw new Error(`a ${definition.type} node must have a single child node defined`);\n }\n\n // Composites MUST have at least one child defined.\n if (isCompositeNode(definition) && !definition.children?.length) {\n throw new Error(`a ${definition.type} node must have at least a single child node defined`);\n }\n\n // We need to make sure that lotto nodes that have weights defined have a number of weights matching the number of child nodes.\n if (definition.type === \"lotto\") {\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (definition.weights.length !== definition.children.length) {\n throw new Error(\n \"expected a number of weight arguments matching the number of child nodes for lotto node\"\n );\n }\n }\n }\n}\n", "import { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { flattenDefinition, isBranchNode, isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\n/**\n * An object representing the result of validating a tree definition.\n */\nexport type DefinitionValidationResult = {\n /**\n * A flag defining whether validation succeeded.\n */\n succeeded: boolean;\n /**\n * A string containing the error message if validation did not succeed.\n */\n errorMessage?: string;\n /**\n * The definition as json if the validation was successful, or undefined if validation did not succeed.\n */\n json?: RootNodeDefinition[];\n};\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON or MDSL, not taking any globally registered subtrees into consideration.\n * @param definition The behaviour tree definition in the form of JSON or MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateDefinition(definition: any): DefinitionValidationResult {\n // The definition must be defined.\n if (definition === null || typeof definition === \"undefined\") {\n return createValidationFailureResult(\"definition is null or undefined\");\n }\n\n // We are expecting a definition in one of three different forms:\n // - A string which we will assume is MDSL and we will parse this to JSON before validation.\n // - An array which we will assume is an array of root node definitions with at least one being the primary root node (no 'id' property)\n // - An object which we will assume is the primary root node and should not have an 'id' property.\n if (typeof definition === \"string\") {\n // The definition is a string which we can assume is MDSL, so attempt to validate it.\n return validateMDSLDefinition(definition);\n } else if (typeof definition === \"object\") {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n return validateJSONDefinition(definition);\n } else {\n return createValidationFailureResult(`unexpected definition type of '${typeof definition}'`);\n }\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of MDSL.\n * @param definition The behaviour tree definition in the form of MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nfunction validateMDSLDefinition(definition: string): DefinitionValidationResult {\n let rootNodeDefinitions;\n\n // The first thing the we need to do is to attempt to convert our MDSL into JSON.\n try {\n // The definition is a string which we can assume is MDSL, so attempt to parse it to a JSON definition in the form of an array of root node definitions.\n rootNodeDefinitions = convertMDSLToJSON(definition);\n } catch (exception) {\n // We failed to parse the JSON from the MDSL, this is likely to be the result of it not being a valid MDSL string.\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single unnamed root node at base of definition to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(`multiple root nodes found with duplicate name '${id}'`);\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON.\n * @param definition The behaviour tree definition in the form of JSON.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateJSONDefinition(\n definition: RootNodeDefinition | RootNodeDefinition[]\n): DefinitionValidationResult {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n const rootNodeDefinitions = Array.isArray(definition) ? definition : [definition];\n\n // Iterate over our array of root nodes and call validateNode for each, passing an initial depth of 0, wrapped in a try catch to handle validation failures.\n try {\n rootNodeDefinitions.forEach((rootNodeDefinition) => validateNode(rootNodeDefinition, 0));\n } catch (error) {\n // Handle cases where we have caught a thrown Error and return a failure result with the error message.\n if (error instanceof Error) {\n return createValidationFailureResult(error.message);\n }\n\n // No idea what happened here!\n return createValidationFailureResult(`unexpected error: ${error}`);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single root node without 'id' property defined to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(\n `multiple root nodes found with duplicate 'id' property value of '${id}'`\n );\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the branch -> subtree links across all provided root node definitions.\n * This will not consider branch nodes that reference any globally registered subtrees unless includesGlobalSubtrees\n * is set to true, in which case we will also verify that there are no broken branch -> subtree links.\n * @param rootNodeDefinitions The array of root node definitions.\n * @param includesGlobalSubtrees A flag defining whether the array includes all global subtree root node definitions.\n */\nexport function validateBranchSubtreeLinks(rootNodeDefinitions: RootNodeDefinition[], includesGlobalSubtrees: boolean) {\n // Create a mapping of root node identifiers to other root nodes that they reference via branch nodes.\n // Below is an example of a mapping that includes a circular dependency (root => a => b => c => a)\n // [{ refs: [\"a\", \"b\"] }, { id: \"a\", refs: [\"b\"] }, { id: \"b\", refs: [\"c\"] }, { id: \"c\", refs: [\"a\"] }]\n const rootNodeMappings: { id: string | undefined; refs: string[] }[] = rootNodeDefinitions.map(\n (rootNodeDefinition) => ({\n id: rootNodeDefinition.id,\n refs: flattenDefinition(rootNodeDefinition)\n .filter(isBranchNode)\n .map(({ ref }) => ref)\n })\n );\n\n // A recursive function to walk through the mappings, keeping track of which root nodes we have visited in the form of a path of root node identifiers.\n const followRefs = (mapping: { id: string | undefined; refs: string[] }, path: (string | undefined)[] = []) => {\n // Have we found a circular dependency?\n if (path.includes(mapping.id)) {\n // We found a circular dependency! Get the bad path of root node identifiers.\n const badPath = [...path, mapping.id];\n\n // Create the formatted path value. [undefined, \"a\", \"b\", \"c\", \"a\"] would be formatted as \"a -> b -> c -> a\".\n const badPathFormatted = badPath.filter((element) => !!element).join(\" => \");\n\n // No need to continue, we found a circular dependency.\n throw new Error(`circular dependency found in branch node references: ${badPathFormatted}`);\n }\n\n for (const ref of mapping.refs) {\n // Find the mapping for the root node with an identifer matching the current ref.\n const subMapping = rootNodeMappings.find(({ id }) => id === ref);\n\n // We may not have a mapping for this ref, which is normal when we aren't considering all globally registered subtrees.\n if (subMapping) {\n followRefs(subMapping, [...path, mapping.id]);\n } else if (includesGlobalSubtrees) {\n // We found a reference to a root node that doesn't exist, which is a problem seeing as the root node definitons includes all globally registered subtrees.\n throw new Error(\n mapping.id\n ? `subtree '${mapping.id}' has branch node that references root node '${ref}' which has not been defined`\n : `primary tree has branch node that references root node '${ref}' which has not been defined`\n );\n }\n }\n };\n\n // Start looking for circular dependencies and broken references from the primary root node definition.\n followRefs(rootNodeMappings.find((mapping) => typeof mapping.id === \"undefined\")!);\n}\n\n/**\n * Validate an object that we expect to be a node definition.\n * @param definition An object that we expect to be a node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateNode(definition: any, depth: number): void {\n // Every node must be valid object and have a non-empty 'type' string property.\n if (typeof definition !== \"object\" || typeof definition.type !== \"string\" || definition.type.length === 0) {\n throw new Error(\n `node definition is not an object or 'type' property is not a non-empty string at depth '${depth}'`\n );\n }\n\n // If this node is at the very base of the definition then it MUST be a root node.\n if (depth === 0 && definition.type !== \"root\") {\n throw new Error(`expected root node at base of definition but got node of type '${definition.type}'`);\n }\n\n // How we validate this node definition will depend on its type.\n switch (definition.type) {\n case \"action\":\n validateActionNode(definition, depth);\n break;\n\n case \"condition\":\n validateConditionNode(definition, depth);\n break;\n\n case \"wait\":\n validateWaitNode(definition, depth);\n break;\n\n case \"branch\":\n validateBranchNode(definition, depth);\n break;\n\n case \"root\":\n validateRootNode(definition, depth);\n break;\n\n case \"succeed\":\n validateSucceedNode(definition, depth);\n break;\n\n case \"fail\":\n validateFailNode(definition, depth);\n break;\n\n case \"flip\":\n validateFlipNode(definition, depth);\n break;\n\n case \"repeat\":\n validateRepeatNode(definition, depth);\n break;\n\n case \"retry\":\n validateRetryNode(definition, depth);\n break;\n\n case \"sequence\":\n validateSequenceNode(definition, depth);\n break;\n\n case \"selector\":\n validateSelectorNode(definition, depth);\n break;\n\n case \"parallel\":\n validateParallelNode(definition, depth);\n break;\n\n case \"race\":\n validateRaceNode(definition, depth);\n break;\n\n case \"all\":\n validateAllNode(definition, depth);\n break;\n\n case \"lotto\":\n validateLottoNode(definition, depth);\n break;\n\n default:\n throw new Error(`unexpected node type of '${definition.type}' at depth '${depth}'`);\n }\n}\n\n/**\n * Validate any attributes for a given node definition.\n * @param definition The node definition.\n * @param depth The depth of the node in the behaviour tree definition.\n */\nfunction validateNodeAttributes(definition: any, depth: number): void {\n // Validate each of the attribute types for this node.\n [\"while\", \"until\", \"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n // Attempt to grab the definition for the current attribute from the node definition.\n const attributeDefinition = definition[attributeName];\n\n // All node attributes are optional, so there is nothing to do if the current attribute is not defined.\n if (typeof attributeDefinition === \"undefined\") {\n return;\n }\n\n // The attribute definition must be an object.\n if (typeof attributeDefinition !== \"object\") {\n throw new Error(\n `expected attribute '${attributeName}' to be an object for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // The 'call' property must be defined for any attribute definition.\n if (typeof attributeDefinition.call !== \"string\" || attributeDefinition.call.length === 0) {\n throw new Error(\n `expected 'call' property for attribute '${attributeName}' to be a non-empty string for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // If any node attribute arguments have been defined then they must have been defined in an array.\n if (typeof attributeDefinition.args !== \"undefined\" && !Array.isArray(attributeDefinition.args)) {\n throw new Error(\n `expected 'args' property for attribute '${attributeName}' to be an array for '${definition.type}' node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a root node definition.\n * @param definition An object that we expect to be a root node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRootNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"root\") {\n throw new Error(\"expected node type of 'root' for root node\");\n }\n\n // A root node cannot be the child of another node.\n if (depth > 0) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Check that, if the root node 'id' property is defined, it is a non-empty string.\n if (typeof definition.id !== \"undefined\" && (typeof definition.id !== \"string\" || definition.id.length === 0)) {\n throw new Error(\"expected non-empty string for 'id' property if defined for root node\");\n }\n\n // A root node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(\"expected property 'child' to be defined for root node\");\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a succeed node definition.\n * @param definition An object that we expect to be a succeed node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSucceedNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"succeed\") {\n throw new Error(`expected node type of 'succeed' for succeed node at depth '${depth}'`);\n }\n\n // A succeed node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for succeed node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a fail node definition.\n * @param definition An object that we expect to be a fail node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFailNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"fail\") {\n throw new Error(`expected node type of 'fail' for fail node at depth '${depth}'`);\n }\n\n // A fail node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for fail node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a flip node definition.\n * @param definition An object that we expect to be a flip node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFlipNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"flip\") {\n throw new Error(`expected node type of 'flip' for flip node at depth '${depth}'`);\n }\n\n // A flip node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for flip node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a repeat node definition.\n * @param definition An object that we expect to be a repeat node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRepeatNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"repeat\") {\n throw new Error(`expected node type of 'repeat' for repeat node at depth '${depth}'`);\n }\n\n // A repeat node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for repeat node at depth '${depth}'`);\n }\n\n // Check whether an 'iterations' property has been defined, it may not have been if this node is to repeat indefinitely.\n if (typeof definition.iterations !== \"undefined\") {\n if (Array.isArray(definition.iterations)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.iterations.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'iterations' property is an array then it MUST contain two integer values.\n if (definition.iterations.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must have a positive min and max iterations count if they are defined.\n if (definition.iterations[0] < 0 || definition.iterations[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must not have a minimum iterations count that exceeds the maximum iterations count.\n if (definition.iterations[0] > definition.iterations[1]) {\n throw new Error(\n `expected minimum iterations count that does not exceed the maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.iterations)) {\n // A repeat node must have a positive number of iterations if defined.\n if (definition.iterations < 0) {\n throw new Error(\n `expected positive iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a retry node definition.\n * @param definition An object that we expect to be a retry node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRetryNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"retry\") {\n throw new Error(`expected node type of 'retry' for retry node at depth '${depth}'`);\n }\n\n // A retry node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for retry node at depth '${depth}'`);\n }\n\n // Check whether an 'attempts' property has been defined, it may not have been if this node is to retry indefinitely.\n if (typeof definition.attempts !== \"undefined\") {\n if (Array.isArray(definition.attempts)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.attempts.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'attempts' property is an array then it MUST contain two integer values.\n if (definition.attempts.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (definition.attempts[0] < 0 || definition.attempts[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must not have a minimum attempts count that exceeds the maximum attempts count.\n if (definition.attempts[0] > definition.attempts[1]) {\n throw new Error(\n `expected minimum attempts count that does not exceed the maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.attempts)) {\n // A retry node must have a positive number of attempts if defined.\n if (definition.attempts < 0) {\n throw new Error(\n `expected positive attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a branch node definition.\n * @param definition An object that we expect to be a branch node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateBranchNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"branch\") {\n throw new Error(`expected node type of 'branch' for branch node at depth '${depth}'`);\n }\n\n // Check that the branch node 'ref' property is defined and is a non-empty string.\n if (typeof definition.ref !== \"string\" || definition.ref.length === 0) {\n throw new Error(`expected non-empty string for 'ref' property for branch node at depth '${depth}'`);\n }\n\n // It is invalid to define guard attributes for a branch node as they should be defined on the referenced root node.\n [\"while\", \"until\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `guards should not be defined for branch nodes but guard '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n\n // It is invalid to define callback attributes for a branch node as they should be defined on the referenced root node.\n [\"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `callbacks should not be defined for branch nodes but callback '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a action node definition.\n * @param definition An object that we expect to be a action node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateActionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"action\") {\n throw new Error(`expected node type of 'action' for action node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a action node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of action node at depth '${depth}'`);\n }\n\n // If any action function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for action node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a condition node definition.\n * @param definition An object that we expect to be a condition node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateConditionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"condition\") {\n throw new Error(`expected node type of 'condition' for condition node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a condition node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of condition node at depth '${depth}'`);\n }\n\n // If any condition function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for condition node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a wait node definition.\n * @param definition An object that we expect to be a wait node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateWaitNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"wait\") {\n throw new Error(`expected node type of 'wait' for wait node at depth '${depth}'`);\n }\n\n // Check whether a 'duration' property has been defined, it may not have been if this node is to wait indefinitely.\n if (typeof definition.duration !== \"undefined\") {\n if (Array.isArray(definition.duration)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.duration.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'duration' property is an array then it MUST contain two integer values.\n if (definition.duration.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must have a positive min and max duration value if they are defined.\n if (definition.duration[0] < 0 || definition.duration[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum duration for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must not have a minimum duration value that exceeds the maximum duration value.\n if (definition.duration[0] > definition.duration[1]) {\n throw new Error(\n `expected minimum duration value that does not exceed the maximum duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.duration)) {\n // A wait node must have a positive duration value if defined.\n if (definition.duration < 0) {\n throw new Error(\n `expected positive duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a sequence node definition.\n * @param definition An object that we expect to be a sequence node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSequenceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"sequence\") {\n throw new Error(`expected node type of 'sequence' for sequence node at depth '${depth}'`);\n }\n\n // A sequence node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for sequence node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a selector node definition.\n * @param definition An object that we expect to be a selector node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSelectorNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"selector\") {\n throw new Error(`expected node type of 'selector' for selector node at depth '${depth}'`);\n }\n\n // A selector node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for selector node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a parallel node definition.\n * @param definition An object that we expect to be a parallel node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateParallelNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"parallel\") {\n throw new Error(`expected node type of 'parallel' for parallel node at depth '${depth}'`);\n }\n\n // A parallel node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for parallel node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a race node definition.\n * @param definition An object that we expect to be a race node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRaceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"race\") {\n throw new Error(`expected node type of 'race' for race node at depth '${depth}'`);\n }\n\n // A race node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for race node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be an all node definition.\n * @param definition An object that we expect to be an all node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateAllNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"all\") {\n throw new Error(`expected node type of 'all' for all node at depth '${depth}'`);\n }\n\n // A all node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for all node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a lotto node definition.\n * @param definition An object that we expect to be a lotto node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateLottoNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"lotto\") {\n throw new Error(`expected node type of 'lotto' for lotto node at depth '${depth}'`);\n }\n\n // A lotto node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for lotto node at depth '${depth}'`);\n }\n\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (\n !Array.isArray(definition.weights) ||\n definition.weights.length !== definition.children.length ||\n definition.weights.filter((value: unknown) => !isInteger(value)).length ||\n definition.weights.filter((value: number) => value < 0).length\n ) {\n throw new Error(\n `expected an array of positive integer weight values with a length matching the number of child nodes for 'weights' property if defined for lotto node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * A helper function to create a failure validation result with the given error message.\n * @param errorMessage The validation failure error message.\n * @returns A failure validation result with the given error message.\n */\nfunction createValidationFailureResult(errorMessage: string): DefinitionValidationResult {\n return { succeeded: false, errorMessage };\n}\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nexport function createUid(): string {\n var S4 = function () {\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n };\n return S4() + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + S4() + S4();\n}\n", "import { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport State, { AnyState } from \"../State\";\nimport { Agent } from \"../Agent\";\nimport Leaf from \"./leaf/Leaf\";\nimport Attribute from \"../attributes/Attribute\";\nimport Entry from \"../attributes/callbacks/Entry\";\nimport Exit from \"../attributes/callbacks/Exit\";\nimport Step from \"../attributes/callbacks/Step\";\nimport While from \"../attributes/guards/While\";\nimport Until from \"../attributes/guards/Until\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\nimport { GuardAttributeDetails } from \"../attributes/guards/Guard\";\nimport { CallbackAttributeDetails } from \"../attributes/callbacks/Callback\";\nimport { createUid } from \"../Utilities\";\n\n/**\n * Details of a tree node instance.\n */\nexport type NodeDetails = {\n /**\n * The tree node identifier.\n */\n id: string;\n /**\n * The tree node type.\n */\n type: string;\n /**\n * The tree node name.\n */\n name: string;\n /**\n * The current state of the tree node.\n */\n state: AnyState;\n /**\n * The array of agent or globally registered function arguments, defined if this is an action or condition node.\n */\n args?: any[];\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: GuardAttributeDetails;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: GuardAttributeDetails;\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: CallbackAttributeDetails;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: CallbackAttributeDetails;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: CallbackAttributeDetails;\n /**\n * The array of the child nodes of this node, defined if this node is a composite or decorator node.\n */\n children?: NodeDetails[];\n};\n\n/**\n * A mapping of attribute names to attributes configured for a node.\n */\ntype Attributes = {\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: Entry;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: Step;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: Exit;\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: While;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: Until;\n};\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node unique identifier.\n */\n protected readonly uid: string;\n /**\n * The node attributes.\n */\n protected readonly attributes: Attributes;\n /**\n * The node state.\n */\n private _state: AnyState = State.READY;\n /**\n * The guard path to evaluate as part of a node update.\n */\n private _guardPath: GuardPath | undefined;\n\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n */\n constructor(private type: string, attributes: Attribute[], protected options: BehaviourTreeOptions) {\n // Create a unique identifier for this node.\n this.uid = createUid();\n\n // Create our attribute mapping.\n this.attributes = {\n entry: attributes.find(({ type }) => type === \"entry\") as Entry,\n step: attributes.find(({ type }) => type === \"step\") as Step,\n exit: attributes.find(({ type }) => type === \"exit\") as Exit,\n while: attributes.find(({ type }) => type === \"while\") as While,\n until: attributes.find(({ type }) => type === \"until\") as Until\n };\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected abstract onUpdate(agent: Agent): void;\n\n /**\n * Gets the name of the node.\n */\n public abstract getName(): string;\n\n /**\n * Gets whether this node is a leaf node.\n */\n public abstract isLeafNode: () => this is Leaf;\n\n /**\n * Gets/Sets the state of the node.\n */\n getState = (): AnyState => this._state;\n setState = (value: AnyState): void => {\n // Grab the original state of this node.\n const previousState = this._state;\n\n // Set the new node state.\n this._state = value;\n\n // If the state actually changed we should handle it.\n if (previousState !== value) {\n this.onStateChanged(previousState);\n }\n };\n\n /**\n * Gets the unique id of the node.\n */\n getUid = () => this.uid;\n\n /**\n * Gets the type of the node.\n */\n getType = () => this.type;\n\n /**\n * Gets the node attributes.\n */\n getAttributes = () => Object.values(this.attributes).filter((attribute) => !!attribute);\n\n /**\n * Sets the guard path to evaluate as part of a node update.\n */\n setGuardPath = (value: GuardPath) => (this._guardPath = value);\n\n /**\n * Gets whether a guard path is assigned to this node.\n */\n hasGuardPath = () => !!this._guardPath;\n\n /**\n * Gets whether this node is in the specified state.\n * @param value The value to compare to the node state.\n */\n public is(value: AnyState): boolean {\n return this._state === value;\n }\n\n /**\n * Reset the state of the node.\n */\n public reset(): void {\n this.setState(State.READY);\n }\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n public abort(agent: Agent): void {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @returns The result of the update.\n */\n public update(agent: Agent): void {\n // If this node is already in a 'SUCCEEDED' or 'FAILED' state then there is nothing to do.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n return;\n }\n\n try {\n // Evaluate all of the guard path conditions for the current tree path.\n this._guardPath!.evaluate(agent);\n\n // If this node is in the READY state then call the ENTRY for this node if it exists.\n if (this.is(State.READY)) {\n this.attributes.entry?.callAgentFunction(agent);\n }\n\n this.attributes.step?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent);\n\n // If this node is now in a 'SUCCEEDED' or 'FAILED' state then call the EXIT for this node if it exists.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n this.attributes.exit?.callAgentFunction(agent, this.is(State.SUCCEEDED), false);\n }\n } catch (error) {\n // If the error is a GuardUnsatisfiedException then we need to determine if this node is the source.\n if (error instanceof GuardUnsatisifedException && error.isSourceNode(this)) {\n // Abort the current node.\n this.abort(agent);\n\n // Any node that is the source of an abort will be a failed node.\n this.setState(State.FAILED);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n id: this.uid,\n name: this.getName(),\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n state: this._state\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n // We should call the onNodeStateChange callback if it was defined.\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this._state\n });\n }\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A composite node that wraps child nodes.\n */\nexport default abstract class Composite extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => this.children;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of any child nodes.\n this.children.forEach((child) => child.reset());\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort any child nodes.\n this.children.forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: this.children.map((child) => child.getDetails())\n };\n }\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A PARALLEL node.\n * The child nodes are executed concurrently until one fails or all succeed.\n */\nexport default class Parallel extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"parallel\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have failed then this node has also failed.\n if (this.children.find((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A parallel node will move into the succeeded state if all child nodes move into the succeeded state.\n if (this.children.every((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RACE node.\n * The child nodes are executed concurrently until one succeeds or all fail.\n */\nexport default class Race extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"race\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have succeeded then this node has also succeeded.\n if (this.children.find((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A race node will move into the failed state if all child nodes move into the failed state as none can succeed.\n if (this.children.every((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"RACE\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * An ALL node.\n * The child nodes are executed concurrently until all child nodes move to a completed state.\n */\nexport default class All extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"all\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // An all node will move into a completed state if all child nodes move into a completed state.\n if (this.children.every((child) => child.is(State.SUCCEEDED) || child.is(State.FAILED))) {\n // If any of our child nodes have succeeded then this node has also succeeded, otherwise it has failed.\n this.setState(this.children.find((child) => child.is(State.SUCCEEDED)) ? State.SUCCEEDED : State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ALL\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SELECTOR node.\n * The child nodes are executed in sequence until one succeeds or all fail.\n */\nexport default class Selector extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"selector\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then this node is also a 'SUCCEEDED' node.\n if (child.getState() === State.SUCCEEDED) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the selector nodes.\n return;\n }\n\n // If the current child has a state of 'FAILED' then we should move on to the next child.\n if (child.getState() === State.FAILED) {\n // Find out if the current child is the last one in the selector.\n // If it is then this sequence node has also failed.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the selector as we have completed it.\n return;\n } else {\n // The child node failed, try the next one.\n continue;\n }\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the selector as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SELECTOR\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SEQUENCE node.\n * The child nodes are executed in sequence until one fails or all succeed.\n */\nexport default class Sequence extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"sequence\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then we should move on to the next child.\n if (child.getState() === State.SUCCEEDED) {\n // Find out if the current child is the last one in the sequence.\n // If it is then this sequence node has also succeeded.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the sequence as we have completed it.\n return;\n } else {\n // The child node succeeded, but we have not finished the sequence yet.\n continue;\n }\n }\n\n // If the current child has a state of 'FAILED' then this node is also a 'FAILED' node.\n if (child.getState() === State.FAILED) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the sequence.\n return;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the sequence as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SEQUENCE\";\n}\n", "import createLotto from \"lotto-draw\";\n\nimport Node from \"../Node\";\nimport Composite from \"./Composite\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A LOTTO node.\n * A winning child is picked on the initial update of this node, based on ticket weighting.\n * The state of this node will match the state of the winning child.\n */\nexport default class Lotto extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param weights The child node weights.\n * @param children The child nodes.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private weights: number[] | undefined,\n children: Node[]\n ) {\n super(\"lotto\", attributes, options, children);\n }\n\n /**\n * The child node selected to be the active one.\n */\n private selectedChild: Node | undefined;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to pick a winning child node.\n if (this.is(State.READY)) {\n // Create a lotto draw with which to randomly pick a child node to become the active one.\n const lottoDraw = createLotto({\n // Hook up the optional 'random' behaviour tree function option to the one used by 'lotto-draw'.\n random: this.options.random,\n // Pass in each child node as a participant in the lotto draw with their respective ticket count.\n participants: this.children.map((child, index) => [child, this.weights?.[index] || 1])\n });\n\n // Randomly pick a child based on ticket weighting, this will become the active child for this composite node.\n this.selectedChild = lottoDraw.draw() || undefined;\n }\n\n // If something went wrong and we don't have an active child then we should throw an error.\n if (!this.selectedChild) {\n throw new Error(\"failed to update lotto node as it has no active child\");\n }\n\n // If the selected child has never been updated or is running then we will need to update it now.\n if (this.selectedChild.getState() === State.READY || this.selectedChild.getState() === State.RUNNING) {\n this.selectedChild.update(agent);\n }\n\n // The state of the lotto node is the state of its selected child.\n this.setState(this.selectedChild.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => (this.weights ? `LOTTO [${this.weights.join(\",\")}]` : \"LOTTO\");\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A decorator node that wraps a single child node.\n */\nexport default abstract class Decorator extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected child: Node) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => [this.child];\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of the child node.\n this.child.reset();\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort the child node.\n this.child.abort(agent);\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: [this.child.getDetails()]\n };\n }\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Fail node.\n * This node wraps a single child and will always move to the 'FAILED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Fail extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"fail\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.FAILED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FAIL\";\n}\n", "import Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Flip node.\n * This node wraps a single child and will flip the state of the child state.\n */\nexport default class Flip extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"flip\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n this.setState(State.FAILED);\n break;\n\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FLIP\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A REPEAT node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The REPEAT node will stop and have a 'FAILED' state if its child is ever in a 'FAILED' state after an update.\n * The REPEAT node will attempt to move on to the next iteration if its child is ever in a 'SUCCEEDED' state.\n */\nexport default class Repeat extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param iterations The number of iterations to repeat the child node.\n * @param iterationsMin The minimum possible number of iterations to repeat the child node.\n * @param iterationsMax The maximum possible number of iterations to repeat the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, options, child);\n }\n\n /**\n * The number of target iterations to make.\n */\n private targetIterationCount: number | null = null;\n\n /**\n * The current iteration count.\n */\n private currentIterationCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target iteration count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the FAILED state when we updated it then there is nothing left to do and this node has also failed.\n // If it has moved into the SUCCEEDED state then we have completed the current iteration.\n if (this.child.getState() === State.FAILED) {\n // The child has failed, meaning that this node has failed.\n this.setState(State.FAILED);\n\n return;\n } else if (this.child.getState() === State.SUCCEEDED) {\n // We have completed an iteration.\n this.currentIterationCount += 1;\n }\n } else {\n // This node is in the 'SUCCEEDED' state as we cannot iterate any more.\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.iterations !== null) {\n return `REPEAT ${this.iterations}x`;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n return `REPEAT ${this.iterationsMin}x-${this.iterationsMax}x`;\n } else {\n return \"REPEAT\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with an explicit iteration count or will we be randomly picking a iteration count between the min and max iteration count.\n if (this.iterations !== null) {\n this.targetIterationCount = this.iterations;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n // We will be picking a random iteration count between a min and max iteration count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random iteration count between a min and max iteration count.\n this.targetIterationCount = Math.floor(\n random() * (this.iterationsMax - this.iterationsMin + 1) + this.iterationsMin\n );\n } else {\n this.targetIterationCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RETRY node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The RETRY node will stop and have a 'SUCCEEDED' state if its child is ever in a 'SUCCEEDED' state after an update.\n * The RETRY node will attempt to move on to the next iteration if its child is ever in a 'FAILED' state.\n */\nexport default class Retry extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param attempts The number of attempts to retry the child node.\n * @param attemptsMin The minimum possible number of attempts to retry the child node.\n * @param attemptsMax The maximum possible number of attempts to retry the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, options, child);\n }\n\n /**\n * The number of target attempts to make.\n */\n private targetAttemptCount: number | null = null;\n\n /**\n * The current attempt count.\n */\n private currentAttemptCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target attempt count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Set the target attempt count.\n this.setTargetAttemptCount();\n }\n\n // Do a check to see if we can attempt. If we can then this node will move into the 'RUNNING' state.\n // If we cannot attempt then we have hit our target attempt count, which means that the node has succeeded.\n if (this.canAttempt()) {\n // This node is in the running state and can do its initial attempt.\n this.setState(State.RUNNING);\n\n // We may have already completed an attempt, meaning that the child node will be in the FAILED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.FAILED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the SUCCEEDED state when we updated it then there is nothing left to do and this node has also succeeded.\n // If it has moved into the FAILED state then we have completed the current attempt.\n if (this.child.getState() === State.SUCCEEDED) {\n // The child has succeeded, meaning that this node has succeeded.\n this.setState(State.SUCCEEDED);\n\n return;\n } else if (this.child.getState() === State.FAILED) {\n // We have completed an attempt.\n this.currentAttemptCount += 1;\n }\n } else {\n // This node is in the 'FAILED' state as we cannot iterate any more.\n this.setState(State.FAILED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.attempts !== null) {\n return `RETRY ${this.attempts}x`;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n return `RETRY ${this.attemptsMin}x-${this.attemptsMax}x`;\n } else {\n return \"RETRY\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an attempt can be made.\n * @returns Whether an attempt can be made.\n */\n canAttempt = () => {\n if (this.targetAttemptCount !== null) {\n // We can attempt as long as we have not reached our target attempt count.\n return this.currentAttemptCount < this.targetAttemptCount;\n }\n\n // If neither an attempt count or a condition function were defined then we can attempt indefinitely.\n return true;\n };\n\n /**\n * Sets the target attempt count.\n */\n setTargetAttemptCount = () => {\n // Are we dealing with an explicit attempt count or will we be randomly picking an attempt count between the min and max attempt count.\n if (this.attempts !== null) {\n this.targetAttemptCount = this.attempts;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n // We will be picking a random attempt count between a min and max attempt count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random attempt count between a min and max attempt count.\n this.targetAttemptCount = Math.floor(\n random() * (this.attemptsMax - this.attemptsMin + 1) + this.attemptsMin\n );\n } else {\n this.targetAttemptCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Root node.\n * The root node will have a single child.\n */\nexport default class Root extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"root\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n // Update the child of this node.\n this.child.update(agent);\n }\n\n // The state of the root node is the state of its child.\n this.setState(this.child.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ROOT\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Succeed node.\n * This node wraps a single child and will always move to the 'SUCCEEDED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Succeed extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"succeed\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SUCCEED\";\n}\n", "import Node from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => true;\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State, { CompleteState } from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * The type representing a resolved/rejected update promise.\n */\ntype UpdatePromiseResult = {\n /**\n * Whether the promise was resolved rather than rejected.\n */\n isResolved: boolean;\n\n /**\n * The promise resolved value or rejection reason.\n */\n value: any;\n};\n\n/**\n * An Action leaf node.\n * This represents an immediate or ongoing state of behaviour.\n */\nexport default class Action extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param actionName The action name.\n * @param actionArguments The array of action arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private actionName: string,\n public actionArguments: any[]\n ) {\n super(\"action\", attributes, options);\n }\n\n /**\n * Whether there is a pending update promise.\n */\n private isUsingUpdatePromise = false;\n\n /**\n * The finished state result of an update promise.\n */\n private updatePromiseResult: UpdatePromiseResult | null = null;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the result of this action depends on an update promise then there is nothing to do until it settles.\n if (this.isUsingUpdatePromise) {\n // Are we still waiting for our update promise to settle?\n if (!this.updatePromiseResult) {\n return;\n }\n\n const { isResolved, value } = this.updatePromiseResult;\n\n // Our update promise settled, was it resolved or rejected?\n if (isResolved) {\n // Our promise resolved so check to make sure the result is a valid finished state.\n if (value !== State.SUCCEEDED && value !== State.FAILED) {\n throw new Error(\n \"action node promise resolved with an invalid value, expected a State.SUCCEEDED or State.FAILED value to be returned\"\n );\n }\n\n // Set the state of this node to match the state returned by the promise.\n this.setState(value);\n\n return;\n } else {\n // The promise was rejected, which isn't great.\n throw new Error(`action function '${this.actionName}' promise rejected with '${value}'`);\n }\n }\n\n // Attempt to get the invoker for the action function.\n const actionFuncInvoker = Lookup.getFuncInvoker(agent, this.actionName);\n\n // The action function should be defined.\n if (actionFuncInvoker === null) {\n throw new Error(\n `cannot update action node as the action '${this.actionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let actionFunctionResult;\n\n try {\n // Call the action function, the result of which may be:\n // - The finished state of this action node.\n // - A promise to return a finished node state.\n // - Undefined if the node should remain in the running state.\n actionFunctionResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`action function '${this.actionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`action function '${this.actionName}' threw: ${error}`);\n }\n }\n\n if (actionFunctionResult instanceof Promise) {\n actionFunctionResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the resolved update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: true,\n value: result\n };\n },\n (reason) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort or reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the rejected update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: false,\n value: reason\n };\n }\n );\n\n // This node will be in the 'RUNNING' state until the update promise resolves.\n this.setState(State.RUNNING);\n\n // We are now waiting for the promise returned by the use to resolve before we know what state this node is in.\n this.isUsingUpdatePromise = true;\n } else {\n // Validate the returned value.\n this.validateUpdateResult(actionFunctionResult);\n\n // Set the state of this node, this may be undefined, which just means that the node is still in the 'RUNNING' state.\n this.setState(actionFunctionResult || State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.actionName;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // There is no longer an update promise that we care about.\n this.isUsingUpdatePromise = false;\n this.updatePromiseResult = null;\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.actionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.actionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n\n /**\n * Validate the result of an update function call.\n * @param result The result of an update function call.\n */\n private validateUpdateResult = (result: CompleteState | State.RUNNING) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case State.RUNNING:\n case undefined:\n return;\n default:\n throw new Error(\n `expected action function '${this.actionName}' to return an optional State.SUCCEEDED or State.FAILED value but returned '${result}'`\n );\n }\n };\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * A Condition leaf node.\n * This will succeed or fail immediately based on an agent predicate, without moving to the 'RUNNING' state.\n */\nexport default class Condition extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param conditionName The name of the condition function.\n * @param conditionArguments The array of condition arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private conditionName: string,\n public conditionArguments: any[]\n ) {\n super(\"condition\", attributes, options);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.conditionName);\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot update condition node as the condition '${this.conditionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.conditionArguments);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`condition function '${this.conditionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`condition function '${this.conditionName}' threw: ${error}`);\n }\n }\n\n // The result of calling the condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected condition function '${this.conditionName}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Set the state of this node based on the result of calling the condition function.\n this.setState(!!conditionFunctionResult ? State.SUCCEEDED : State.FAILED);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.conditionName;\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.conditionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.conditionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { Agent } from \"../../Agent\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A WAIT node.\n * The state of this node will change to SUCCEEDED after a duration of time\n */\nexport default class Wait extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param duration The duration that this node will wait to succeed in milliseconds.\n * @param durationMin The minimum possible duration in milliseconds that this node will wait to succeed.\n * @param durationMax The maximum possible duration in milliseconds that this node will wait to succeed.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, options);\n }\n\n /**\n * The time in milliseconds at which this node was first updated.\n */\n private initialUpdateTime: number = 0;\n\n /**\n * The total duration in milliseconds that this node will be waiting for.\n */\n private totalDuration: number | null = null;\n\n /**\n * The duration in milliseconds that this node has been waiting for.\n */\n private waitedDuration: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to set the initial update time.\n if (this.is(State.READY)) {\n // Set the initial update time.\n this.initialUpdateTime = new Date().getTime();\n\n // Set the initial waited duration.\n this.waitedDuration = 0;\n\n // Are we dealing with an explicit duration or will we be randomly picking a duration between the min and max duration.\n if (this.duration !== null) {\n this.totalDuration = this.duration;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // We will be picking a random duration between a min and max duration, if the optional 'random' behaviour tree\n // function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random duration between a min and max duration.\n this.totalDuration = Math.floor(\n random() * (this.durationMax - this.durationMin + 1) + this.durationMin\n );\n } else {\n this.totalDuration = null;\n }\n\n // The node is now running until we finish waiting.\n this.setState(State.RUNNING);\n }\n\n // If we have no total duration then this wait node will wait indefinitely until it is aborted.\n if (this.totalDuration === null) {\n return;\n }\n\n // If we have a 'getDeltaTime' function defined as part of our options then we will use it to figure out how long we have waited for.\n if (typeof this.options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = this.options.getDeltaTime();\n\n // Our delta time must be a valid number and cannot be NaN.\n if (typeof deltaTime !== \"number\" || isNaN(deltaTime)) {\n throw new Error(\"The delta time must be a valid number and not NaN.\");\n }\n\n // Update the amount of time that this node has been waiting for based on the delta time.\n this.waitedDuration += deltaTime * 1000;\n } else {\n // We are not using a delta time, so we will just work out hom much time has passed since the first update.\n this.waitedDuration = new Date().getTime() - this.initialUpdateTime;\n }\n\n // Have we waited long enough?\n if (this.waitedDuration >= this.totalDuration) {\n // We have finished waiting!\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.duration !== null) {\n return `WAIT ${this.duration}ms`;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n return `WAIT ${this.durationMin}ms-${this.durationMax}ms`;\n } else {\n return \"WAIT\";\n }\n };\n}\n", "import Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: any[];\n};\n\n/**\n * A base node attribute.\n */\nexport default abstract class Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of attribute arguments.\n */\n constructor(public type: string, public args: any[]) {}\n\n /**\n * Gets the attribute details.\n */\n abstract getDetails(): TAttributeDetails;\n\n /**\n * Gets whether this attribute is a guard.\n */\n abstract isGuard: () => this is Guard;\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node guard attribute.\n */\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node guard attribute.\n */\nexport default abstract class Guard extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n */\n constructor(type: string, args: any[], private condition: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the condition function that determines whether the guard is satisfied.\n */\n getCondition = () => this.condition;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => true;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): GuardAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getCondition()\n };\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n abstract isSatisfied(agent: Agent): boolean;\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A WHILE guard which is satisfied as long as the given condition remains true.\n */\nexport default class While extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"while\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return conditionFunctionResult;\n };\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An UNTIL guard which is satisfied as long as the given condition remains false.\n */\nexport default class Until extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"until\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return !conditionFunctionResult;\n };\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node callback attribute.\n */\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node callback attribute.\n */\nexport default abstract class Callback extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param functionName The name of the agent function to call.\n */\n constructor(type: string, args: any[], private functionName: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the agent function to call.\n */\n getFunctionName = () => this.functionName;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => false;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): CallbackAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getFunctionName()\n };\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n abstract callAgentFunction: (agent: Agent, isSuccess: boolean, isAborted: boolean) => void;\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An ENTRY callback which defines an agent function to call when the associated node is updated and moves out of running state.\n */\nexport default class Entry extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"entry\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call entry function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A STEP callback which defines an agent function to call when the associated node is updated.\n */\nexport default class Step extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"step\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call step function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An EXIT callback which defines an agent function to call when the associated node is updated and moves to a finished state or is aborted.\n */\nexport default class Exit extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"exit\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n * @param isSuccess Whether the decorated node was left with a success state.\n * @param isAborted Whether the decorated node was aborted.\n */\n callAgentFunction = (agent: Agent, isSuccess: boolean, isAborted: boolean) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call exit function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function\n callbackFuncInvoker([{ succeeded: isSuccess, aborted: isAborted }, ...this.args]);\n };\n}\n", "import { AnyNodeDefinition, RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport { validateBranchSubtreeLinks } from \"./BehaviourTreeDefinitionValidator\";\nimport { isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport Node from \"./nodes/Node\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Race from \"./nodes/composite/Race\";\nimport All from \"./nodes/composite/All\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Root from \"./nodes/decorator/Root\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Lookup from \"./Lookup\";\nimport Attribute from \"./attributes/Attribute\";\nimport Guard from \"./attributes/guards/Guard\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\n/**\n * A type representing any node instance in a behaviour tree.\n */\ntype AnyNode =\n | Root\n | Action\n | Condition\n | Wait\n | Sequence\n | Selector\n | Lotto\n | Parallel\n | Race\n | All\n | Repeat\n | Retry\n | Flip\n | Succeed\n | Fail;\n\n/**\n * A type defining a mapping of root node identifiers to root node definitions.\n */\ntype RootNodeDefinitionMap = { [key: string | symbol]: RootNodeDefinition };\n\n/**\n * A symbol to use as the main root key in any root node mappings.\n */\nconst MAIN_ROOT_NODE_KEY = Symbol(\"__root__\");\n\n/**\n * Build and populate the root nodes based on the provided definition, assuming that the definition has been validated.\n * @param definition The root node definitions.\n * @param options The behaviour tree options.\n * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[], options: BehaviourTreeOptions): Root {\n // Create a mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n const rootNodeDefinitionMap = createRootNodeDefinitionMap(definition);\n\n // Now that we have all of our root node definitions (those part of the tree definition and those globally registered)\n // we should validate the branch-subtree links. This will also double-check that we dont have any circular dependencies\n // in our branch-subtree references and that we have no broken branch-subtree links.\n validateBranchSubtreeLinks(\n [rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], ...Object.values(rootNodeDefinitionMap)],\n true\n );\n\n // Create our populated tree of node instances, starting with our main root node.\n const rootNode = nodeFactory(rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], rootNodeDefinitionMap, options) as Root;\n\n // Set a guard path on every leaf of the tree to evaluate as part of each update.\n applyLeafNodeGuardPaths(rootNode);\n\n // We only need to return the main root node.\n return rootNode;\n}\n\n/**\n * A factory function which creates a node instance based on the specified definition.\n * @param definition The node definition.\n * @param rootNodeDefinitionMap The mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n * @param options The behaviour tree options.\n * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(\n definition: AnyNodeDefinition,\n rootNodeDefinitionMap: RootNodeDefinitionMap,\n options: BehaviourTreeOptions\n): AnyNode {\n // Get the attributes for the node.\n const attributes = nodeAttributesFactory(definition);\n\n // Create the node instance based on the definition type.\n switch (definition.type) {\n case \"root\":\n return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"repeat\":\n let iterations: number | null = null;\n let iterationsMin: number | null = null;\n let iterationsMax: number | null = null;\n\n if (Array.isArray(definition.iterations)) {\n iterationsMin = definition.iterations[0];\n iterationsMax = definition.iterations[1];\n } else if (isInteger(definition.iterations)) {\n iterations = definition.iterations!;\n }\n\n return new Repeat(\n attributes,\n options,\n iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"retry\":\n let attempts: number | null = null;\n let attemptsMin: number | null = null;\n let attemptsMax: number | null = null;\n\n if (Array.isArray(definition.attempts)) {\n attemptsMin = definition.attempts[0];\n attemptsMax = definition.attempts[1];\n } else if (isInteger(definition.attempts)) {\n attempts = definition.attempts!;\n }\n\n return new Retry(\n attributes,\n options,\n attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"flip\":\n return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"succeed\":\n return new Succeed(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"fail\":\n return new Fail(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"race\":\n return new Race(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"all\":\n return new All(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n options,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap, options);\n\n case \"action\":\n return new Action(attributes, options, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, options, definition.call, definition.args || []);\n\n case \"wait\":\n let duration: number | null = null;\n let durationMin: number | null = null;\n let durationMax: number | null = null;\n\n if (Array.isArray(definition.duration)) {\n durationMin = definition.duration[0];\n durationMax = definition.duration[1];\n } else if (isInteger(definition.duration)) {\n duration = definition.duration!;\n }\n\n return new Wait(attributes, options, duration, durationMin, durationMax);\n }\n}\n\n/**\n * Creates an array of node attribute instances based on the specified node definition.\n * @param definition The node definition.\n * @returns An array of node attribute instances based on the specified node definition.\n */\nfunction nodeAttributesFactory(definition: AnyNodeDefinition): Attribute[] {\n const attributes: Attribute[] = [];\n\n if (definition.while) {\n attributes.push(new While(definition.while.call, definition.while.args ?? []));\n }\n\n if (definition.until) {\n attributes.push(new Until(definition.until.call, definition.until.args ?? []));\n }\n\n if (definition.entry) {\n attributes.push(new Entry(definition.entry.call, definition.entry.args ?? []));\n }\n\n if (definition.step) {\n attributes.push(new Step(definition.step.call, definition.step.args ?? []));\n }\n\n if (definition.exit) {\n attributes.push(new Exit(definition.exit.call, definition.exit.args ?? []));\n }\n\n return attributes;\n}\n\n/**\n * Creates a mapping of root node identifers to root node definitions, mixing in globally registered subtree root node definitions.\n * @param definition The root node definitions.\n * @returns A mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n */\nfunction createRootNodeDefinitionMap(definition: RootNodeDefinition[]): RootNodeDefinitionMap {\n // Create a mapping of root node identifers to root node definitions.\n const rootNodeMap: RootNodeDefinitionMap = {};\n\n // Add in any registered subtree root node definitions.\n for (const [name, rootNodeDefinition] of Object.entries(Lookup.getSubtrees())) {\n // The name used when registering the subtree will be used as the root node identifier.\n rootNodeMap[name] = { ...rootNodeDefinition, id: name };\n }\n\n // Populate the map with the root node definitions that were included with the tree definition.\n // We do this after adding any registered subtrees as we want these to take presedence.\n for (const rootNodeDefinition of definition) {\n rootNodeMap[rootNodeDefinition.id ?? MAIN_ROOT_NODE_KEY] = rootNodeDefinition;\n }\n\n return rootNodeMap;\n}\n\n/**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param root The main root tree node.\n */\nfunction applyLeafNodeGuardPaths(root: Root) {\n const nodePaths: Node[][] = [];\n\n const findLeafNodes = (path: Node[], node: Node) => {\n // Add the current node to the path.\n path = path.concat(node);\n\n // Check whether the current node is a leaf node.\n if (node.isLeafNode()) {\n nodePaths.push(path);\n } else {\n (node as Composite | Decorator).getChildren().forEach((child) => findLeafNodes(path, child));\n }\n };\n\n // Find all leaf node paths, starting from the root.\n findLeafNodes([], root);\n\n nodePaths.forEach((path) => {\n // Each node in the current path will have to be assigned a guard path, working from the root outwards.\n for (let depth = 0; depth < path.length; depth++) {\n // Get the node in the path at the current depth.\n const currentNode = path[depth];\n\n // The node may already have been assigned a guard path, if so just skip it.\n if (currentNode.hasGuardPath()) {\n continue;\n }\n\n // Create the guard path for the current node.\n const guardPath = new GuardPath(\n path\n .slice(0, depth + 1)\n .map((node) => ({\n node,\n guards: node.getAttributes().filter((attribute) => attribute.isGuard()) as Guard[]\n }))\n .filter((details) => details.guards.length > 0)\n );\n\n // Assign the guard path to the current node.\n currentNode.setGuardPath(guardPath);\n }\n });\n}\n", "import State, { AnyState } from \"./State\";\nimport Lookup from \"./Lookup\";\nimport Node, { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport { Agent, GlobalFunction } from \"./Agent\";\nimport { CallbackAttributeDetails } from \"./attributes/callbacks/Callback\";\nimport { GuardAttributeDetails } from \"./attributes/guards/Guard\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { validateDefinition, validateJSONDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport buildRootNode from \"./BehaviourTreeBuilder\";\nimport { isNullOrUndefined } from \"./BehaviourTreeDefinitionUtilities\";\n\n/**\n * A representation of a behaviour tree.\n */\nexport class BehaviourTree {\n /**\n * The main root tree node.\n */\n private readonly _rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition as either an MDSL string, root node definition object or array of root node definition objects.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param options The behaviour tree options object.\n */\n constructor(\n definition: string | RootNodeDefinition | RootNodeDefinition[],\n private agent: Agent,\n private options: BehaviourTreeOptions = {}\n ) {\n // The tree definition must be defined.\n if (isNullOrUndefined(definition)) {\n throw new Error(\"tree definition not defined\");\n }\n\n // The agent must be defined and not null.\n if (typeof agent !== \"object\" || agent === null) {\n throw new Error(\"the agent must be an object and not null\");\n }\n\n // We should validate the definition before we try to build the tree nodes.\n const { succeeded, errorMessage, json } = validateDefinition(definition);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(`invalid definition: ${errorMessage}`);\n }\n\n // Double check that we did actually get our json definition as part of our definition validtion.\n if (!json) {\n throw new Error(\n \"expected json definition to be returned as part of successful definition validation response\"\n );\n }\n\n try {\n // Create the populated tree of behaviour tree nodes and get the root node.\n this._rootNode = buildRootNode(json, options);\n } catch (exception) {\n // There was an issue in trying build and populate the behaviour tree.\n throw new Error(`error building tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Gets whether the tree is in the RUNNING state.\n * @returns true if the tree is in the RUNNING state, otherwise false.\n */\n public isRunning(): boolean {\n return this._rootNode.getState() === State.RUNNING;\n }\n\n /**\n * Gets the current tree state of SUCCEEDED, FAILED, READY or RUNNING.\n * @returns The current tree state.\n */\n public getState(): State {\n return this._rootNode.getState();\n }\n\n /**\n * Step the tree.\n * 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.\n * 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\n * 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.\n *\n * 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.\n */\n public step(): void {\n // If the root node has already been stepped to completion then we need to reset it.\n if (this._rootNode.getState() === State.SUCCEEDED || this._rootNode.getState() === State.FAILED) {\n this._rootNode.reset();\n }\n\n try {\n this._rootNode.update(this.agent);\n } catch (exception) {\n throw new Error(`error stepping tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Resets the tree from the root node outwards to each nested node, giving each a state of READY.\n */\n public reset(): void {\n this._rootNode.reset();\n }\n\n /**\n * Gets the details of every node in the tree, starting from the root.\n * @returns The details of every node in the tree, starting from the root.\n */\n public getTreeNodeDetails(): NodeDetails {\n return this._rootNode.getDetails();\n }\n\n /**\n * Registers the action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the function or subtree to register.\n * @param value The function or subtree definition to register.\n */\n static register(name: string, value: GlobalFunction | string | RootNodeDefinition) {\n // Are we going to register a action/condition/guard/callback function?\n if (typeof value === \"function\") {\n Lookup.setFunc(name, value);\n return;\n }\n\n // We are not registering an action/condition/guard/callback function, so we must be registering a subtree.\n if (typeof value === \"string\") {\n let rootNodeDefinitions: RootNodeDefinition[];\n\n // We will assume that any string passed in will be a mdsl definition.\n try {\n rootNodeDefinitions = convertMDSLToJSON(value);\n } catch (exception) {\n throw new Error(`error registering definition, invalid MDSL: ${(exception as Error).message}`);\n }\n\n // This function should only ever be called with a definition containing a single unnamed root node.\n if (rootNodeDefinitions.length != 1 || typeof rootNodeDefinitions[0].id !== \"undefined\") {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(rootNodeDefinitions[0]);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, rootNodeDefinitions[0]);\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // We will assume that any object passed in is a root node definition.\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(value);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, value);\n } else {\n throw new Error(\"unexpected value, expected string mdsl definition, root node json definition or function\");\n }\n }\n\n /**\n * Unregisters the registered action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the registered action/condition/guard/callback function or subtree to unregister.\n */\n static unregister(name: string): void {\n Lookup.remove(name);\n }\n\n /**\n * Unregister all registered action/condition/guard/callback functions and subtrees.\n */\n static unregisterAll(): void {\n Lookup.empty();\n }\n}\n"], + "mappings": "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", "names": ["Participant", "isNullOrUndefined", "Lotto", "createLotto", "State", "type", "createLotto"] } diff --git a/dist/mistreevous.min.js b/dist/mistreevous.min.js index 3d0ae45..dced975 100644 --- a/dist/mistreevous.min.js +++ b/dist/mistreevous.min.js @@ -1,2 +1,2 @@ -"use strict";var mistreevous=(()=>{var Ft=Object.create;var U=Object.defineProperty;var Tt=Object.getOwnPropertyDescriptor;var Lt=Object.getOwnPropertyNames;var Pt=Object.getPrototypeOf,Ot=Object.prototype.hasOwnProperty;var Gt=(t,e,r)=>e in t?U(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var F=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),kt=(t,e)=>{for(var r in e)U(t,r,{get:e[r],enumerable:!0})},yt=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Lt(e))!Ot.call(t,i)&&i!==r&&U(t,i,{get:()=>e[i],enumerable:!(o=Tt(e,i))||o.enumerable});return t};var Mt=(t,e,r)=>(r=t!=null?Ft(Pt(t)):{},yt(e||!t||!t.__esModule?U(r,"default",{value:t,enumerable:!0}):r,t)),Bt=t=>yt(U({},"__esModule",{value:!0}),t);var ct=(t,e,r)=>(Gt(t,typeof e!="symbol"?e+"":e,r),r);var xt=F(at=>{"use strict";Object.defineProperty(at,"__esModule",{value:!0});at.Participant=void 0;var Ae=function(){function t(e,r){r===void 0&&(r=1),this._participant=e,this._tickets=r}return Object.defineProperty(t.prototype,"participant",{get:function(){return this._participant},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"tickets",{get:function(){return this._tickets},set:function(e){this._tickets=e},enumerable:!1,configurable:!0}),t}();at.Participant=Ae});var Rt=F(I=>{"use strict";Object.defineProperty(I,"__esModule",{value:!0});I.isNaturalNumber=I.isNullOrUndefined=void 0;function Ee(t){return t==null}I.isNullOrUndefined=Ee;function De(t){return typeof t=="number"&&t>=1&&Math.floor(t)===t}I.isNaturalNumber=De});var Ct=F(st=>{"use strict";Object.defineProperty(st,"__esModule",{value:!0});st.Lotto=void 0;var ve=xt(),k=Rt(),Se=function(){function t(e){this._participants=[],this._customRandom=e}return t.prototype.add=function(e,r){if(r===void 0&&(r=1),!(0,k.isNaturalNumber)(r))throw new Error("tickets value must be a natural number");var o=this._participants.find(function(i){return i.participant===e});return o?o.tickets+=r:this._participants.push(new ve.Participant(e,r)),this},t.prototype.remove=function(e,r){var o=this._participants.find(function(i){return i.participant===e});if(!o)return this;if(r!==void 0){if(!(0,k.isNaturalNumber)(r))throw new Error("tickets value must be a natural number");o.tickets-=r,o.tickets<1&&(this._participants=this._participants.filter(function(i){return i!==o}))}else this._participants=this._participants.filter(function(i){return i!==o});return this},t.prototype.draw=function(e){if(e===void 0&&(e={}),this._participants.length===0)return null;var r=(0,k.isNullOrUndefined)(e.redrawable)?!0:e.redrawable,o=[];this._participants.forEach(function(a){for(var s=a.participant,d=a.tickets,$=0;$=1)throw new Error("the 'random' function provided did not return a number between 0 (inclusive) and 1")}else i=Math.random();var n=o[Math.floor(i*o.length)];return r||this.remove(n,1),n},t.prototype.drawMultiple=function(e,r){r===void 0&&(r={});var o=(0,k.isNullOrUndefined)(r.unique)?!1:r.unique;if(e===0)return[];if(!(0,k.isNaturalNumber)(e))throw new Error("tickets value must be a natural number");for(var i=[];i.length0;)i.push(this.draw(r));if(o){for(var n=[],a=0,s=i;a{"use strict";Object.defineProperty(ut,"__esModule",{value:!0});ut.createLotto=void 0;var lt=Ct();function xe(t){if(!t)return new lt.Lotto;if(Array.isArray(t)){var e=t,r=new lt.Lotto;return e.forEach(function(n){var a=n[0],s=n[1];return r.add(a,s)}),r}else{var o=t.random,e=t.participants,i=new lt.Lotto(o);return e&&e.forEach(function(a){var s=a[0],d=a[1];return i.add(s,d)}),i}}ut.createLotto=xe});var $t=F(pt=>{"use strict";Object.defineProperty(pt,"__esModule",{value:!0});var Re=It();pt.default=Re.createLotto});var Ue={};kt(Ue,{BehaviourTree:()=>dt,State:()=>c,convertMDSLToJSON:()=>C,validateDefinition:()=>ot});var c=(i=>(i.READY="mistreevous.ready",i.RUNNING="mistreevous.running",i.SUCCEEDED="mistreevous.succeeded",i.FAILED="mistreevous.failed",i))(c||{});var u=class{static getFunc(e){return this.registeredFunctions[e]}static setFunc(e,r){this.registeredFunctions[e]=r}static getFuncInvoker(e,r){let o=e[r];if(o&&typeof o=="function")return i=>o.apply(e,i);if(this.registeredFunctions[r]&&typeof this.registeredFunctions[r]=="function"){let i=this.registeredFunctions[r];return n=>i(e,...n)}return null}static getSubtrees(){return this.registeredSubtrees}static setSubtree(e,r){this.registeredSubtrees[e]=r}static remove(e){delete this.registeredFunctions[e],delete this.registeredSubtrees[e]}static empty(){this.registeredFunctions={},this.registeredSubtrees={}}};ct(u,"registeredFunctions",{}),ct(u,"registeredSubtrees",{});function Nt(t){return t.type==="root"}function wt(t){return t.type==="branch"}function At(t){return["branch","action","condition","wait"].includes(t.type)}function tt(t){return["root","repeat","retry","flip","succeed","fail"].includes(t.type)}function et(t){return["sequence","selector","lotto","parallel","race"].includes(t.type)}function Et(t){let e=[],r=o=>{e.push(o),et(o)?o.children.forEach(r):tt(o)&&r(o.child)};return r(t),e}function b(t){return typeof t=="number"&&Math.floor(t)===t}function rt(t){return typeof t>"u"||t===null}function l(t,e){let r=t.shift();if(r===void 0)throw new Error("unexpected end of definition");if(e!=null){let i=typeof e=="string"?[e]:e;var o=i.some(n=>r.toUpperCase()===n.toUpperCase());if(!o){let n=i.map(a=>"'"+a+"'").join(" or ");throw new Error("unexpected token found. Expected "+n+" but got '"+r+"'")}}return r}function Dt(t){let e={},r=t.replace(/\"(\\.|[^"\\])*\"/g,o=>{var i=o.substring(1,o.length-1),n=Object.keys(e).find(a=>e[a]===i);return n||(n=`@@${Object.keys(e).length}@@`,e[n]=i),n});return{placeholders:e,processedDefinition:r}}function vt(t){return t=t.replace(/\(/g," ( "),t=t.replace(/\)/g," ) "),t=t.replace(/\{/g," { "),t=t.replace(/\}/g," } "),t=t.replace(/\]/g," ] "),t=t.replace(/\[/g," [ "),t=t.replace(/\,/g," , "),t.replace(/\s+/g," ").trim().split(" ")}function N(t,e){let r=[];if(!["[","("].includes(t[0]))return r;let o=l(t,["[","("])==="["?"]":")",i=[];for(;t.length&&t[0]!==o;)i.push(t.shift());return i.forEach((n,a)=>{if(!(a&1)){let d=_t(n,e);r.push(d)}else if(n!==",")throw new Error(`invalid argument list, expected ',' or ']' but got '${n}'`)}),l(t,o),r}function _t(t,e){return t==="null"?{value:null,type:"null"}:t==="true"||t==="false"?{value:t==="true",type:"boolean"}:isNaN(t)?t.match(/^@@\d+@@$/g)?{value:e[t].replace('\\"','"'),type:"string"}:{value:t,type:"identifier"}:{value:parseFloat(t),isInteger:parseFloat(t)===parseInt(t,10),type:"number"}}function p(t,e){let r=["while","until","entry","exit","step"],o={},i=t[0]?.toLowerCase();for(;r.includes(i);){if(o[i])throw new Error(`duplicate attribute '${t[0].toUpperCase()}' found for node`);t.shift();let[n,...a]=N(t,e);if(n?.type!=="identifier")throw new Error("expected agent function or registered function name identifier argument for attribute");a.filter(s=>s.type==="identifier").forEach(s=>{throw new Error(`invalid attribute argument value '${s.value}', must be string, number, boolean or null`)}),o[i]={call:n.value,args:a.map(({value:s})=>s)},i=t[0]?.toLowerCase()}return o}function C(t){let{placeholders:e,processedDefinition:r}=Dt(t),o=vt(r);return Yt(o,e)}function Yt(t,e){if(t.length<3)throw new Error("invalid token count");if(t.filter(a=>a==="{").length!==t.filter(a=>a==="}").length)throw new Error("scope character mismatch");let r=[],o=[],i=a=>{if(Nt(a)){if(r[r.length-1]?.length)throw new Error("a root node cannot be the child of another node");o.push(a),r.push([a]);return}if(!r.length||!r[r.length-1].length)throw new Error("expected root node at base of definition");let s=r[r.length-1],d=s[s.length-1];if(et(d))d.children=d.children||[],d.children.push(a);else if(tt(d)){if(d.child)throw new Error("a decorator node must only have a single child node");d.child=a}At(a)||s.push(a)},n=()=>{let a=null,s=r[r.length-1];return s.length&&(a=s.pop()),s.length||r.pop(),a};for(;t.length;){let a=t.shift();switch(a.toUpperCase()){case"ROOT":{i(jt(t,e));break}case"SUCCEED":{i(qt(t,e));break}case"FAIL":{i(Wt(t,e));break}case"FLIP":{i(Jt(t,e));break}case"REPEAT":{i(Vt(t,e));break}case"RETRY":{i(Qt(t,e));break}case"SEQUENCE":{i(Ht(t,e));break}case"SELECTOR":{i(Kt(t,e));break}case"PARALLEL":{i(zt(t,e));break}case"RACE":{i(Xt(t,e));break}case"LOTTO":{i(Zt(t,e));break}case"ACTION":{i(te(t,e));break}case"CONDITION":{i(ee(t,e));break}case"WAIT":{i(re(t,e));break}case"BRANCH":{i(oe(t,e));break}case"}":{let s=n();s&&ie(s);break}default:throw new Error(`unexpected token: ${a}`)}}return o}function jt(t,e){let r={type:"root"},o=N(t,e);if(o.length)if(o.length===1&&o[0].type==="identifier")r.id=o[0].value;else throw new Error("expected single root name argument");return r={...r,...p(t,e)},l(t,"{"),r}function qt(t,e){let r={type:"succeed",...p(t,e)};return l(t,"{"),r}function Wt(t,e){let r={type:"fail",...p(t,e)};return l(t,"{"),r}function Jt(t,e){let r={type:"flip",...p(t,e)};return l(t,"{"),r}function Vt(t,e){let r={type:"repeat"},o=N(t,e);if(o.length)if(o.filter(i=>i.type!=="number"||!i.isInteger).forEach(()=>{throw new Error("repeat node iteration counts must be integer values")}),o.length===1){if(r.iterations=o[0].value,r.iterations<0)throw new Error("a repeat node must have a positive number of iterations if defined")}else if(o.length===2){if(r.iterations=[o[0].value,o[1].value],r.iterations[0]<0||r.iterations[1]<0)throw new Error("a repeat node must have a positive minimum and maximum iteration count if defined");if(r.iterations[0]>r.iterations[1])throw new Error("a repeat node must not have a minimum iteration count that exceeds the maximum iteration count")}else throw new Error("invalid number of repeat node iteration count arguments defined");return r={...r,...p(t,e)},l(t,"{"),r}function Qt(t,e){let r={type:"retry"},o=N(t,e);if(o.length)if(o.filter(i=>i.type!=="number"||!i.isInteger).forEach(()=>{throw new Error("retry node attempt counts must be integer values")}),o.length===1){if(r.attempts=o[0].value,r.attempts<0)throw new Error("a retry node must have a positive number of attempts if defined")}else if(o.length===2){if(r.attempts=[o[0].value,o[1].value],r.attempts[0]<0||r.attempts[1]<0)throw new Error("a retry node must have a positive minimum and maximum attempt count if defined");if(r.attempts[0]>r.attempts[1])throw new Error("a retry node must not have a minimum attempt count that exceeds the maximum attempt count")}else throw new Error("invalid number of retry node attempt count arguments defined");return r={...r,...p(t,e)},l(t,"{"),r}function Ht(t,e){let r={type:"sequence",...p(t,e)};return l(t,"{"),r}function Kt(t,e){let r={type:"selector",...p(t,e)};return l(t,"{"),r}function zt(t,e){let r={type:"parallel",...p(t,e)};return l(t,"{"),r}function Xt(t,e){let r={type:"race",...p(t,e)};return l(t,"{"),r}function Zt(t,e){let r=N(t,e);r.filter(i=>i.type!=="number"||!i.isInteger||i.value<0).forEach(()=>{throw new Error("lotto node weight arguments must be positive integer values")});let o={type:"lotto",...p(t,e)};return r.length&&(o.weights=r.map(({value:i})=>i)),l(t,"{"),o}function te(t,e){let[r,...o]=N(t,e);if(r?.type!=="identifier")throw new Error("expected action name identifier argument");return o.filter(i=>i.type==="identifier").forEach(i=>{throw new Error(`invalid action node argument value '${i.value}', must be string, number, boolean or null`)}),{type:"action",call:r.value,args:o.map(({value:i})=>i),...p(t,e)}}function ee(t,e){let[r,...o]=N(t,e);if(r?.type!=="identifier")throw new Error("expected condition name identifier argument");return o.filter(i=>i.type==="identifier").forEach(i=>{throw new Error(`invalid condition node argument value '${i.value}', must be string, number, boolean or null`)}),{type:"condition",call:r.value,args:o.map(({value:i})=>i),...p(t,e)}}function re(t,e){let r={type:"wait"},o=N(t,e);if(o.length){if(o.filter(i=>i.type!=="number"||!i.isInteger).forEach(()=>{throw new Error("wait node durations must be integer values")}),o.length===1){if(r.duration=o[0].value,r.duration<0)throw new Error("a wait node must have a positive duration")}else if(o.length===2){if(r.duration=[o[0].value,o[1].value],r.duration[0]<0||r.duration[1]<0)throw new Error("a wait node must have a positive minimum and maximum duration");if(r.duration[0]>r.duration[1])throw new Error("a wait node must not have a minimum duration that exceeds the maximum duration")}else if(o.length>2)throw new Error("invalid number of wait node duration arguments defined")}return{...r,...p(t,e)}}function oe(t,e){let r=N(t,e);if(r.length!==1||r[0].type!=="identifier")throw new Error("expected single branch name argument");return{type:"branch",ref:r[0].value}}function ie(t){if(tt(t)&&rt(t.child))throw new Error(`a ${t.type} node must have a single child node defined`);if(et(t)&&!t.children?.length)throw new Error(`a ${t.type} node must have at least a single child node defined`);if(t.type==="lotto"&&typeof t.weights<"u"&&t.weights.length!==t.children.length)throw new Error("expected a number of weight arguments matching the number of child nodes for lotto node")}function ot(t){return t===null||typeof t>"u"?w("definition is null or undefined"):typeof t=="string"?ne(t):typeof t=="object"?it(t):w(`unexpected definition type of '${typeof t}'`)}function ne(t){let e;try{e=C(t)}catch(n){return w(n.message)}let r=e.filter(({id:n})=>typeof n>"u"),o=e.filter(({id:n})=>typeof n=="string"&&n.length>0);if(r.length!==1)return w("expected single unnamed root node at base of definition to act as main root");let i=[];for(let{id:n}of o){if(i.includes(n))return w(`multiple root nodes found with duplicate name '${n}'`);i.push(n)}try{nt(e,!1)}catch(n){return w(n.message)}return{succeeded:!0,json:e}}function it(t){let e=Array.isArray(t)?t:[t];try{e.forEach(n=>y(n,0))}catch(n){return n instanceof Error?w(n.message):w(`unexpected error: ${n}`)}let r=e.filter(({id:n})=>typeof n>"u"),o=e.filter(({id:n})=>typeof n=="string"&&n.length>0);if(r.length!==1)return w("expected single root node without 'id' property defined to act as main root");let i=[];for(let{id:n}of o){if(i.includes(n))return w(`multiple root nodes found with duplicate 'id' property value of '${n}'`);i.push(n)}try{nt(e,!1)}catch(n){return w(n.message)}return{succeeded:!0,json:e}}function nt(t,e){let r=t.map(i=>({id:i.id,refs:Et(i).filter(wt).map(({ref:n})=>n)})),o=(i,n=[])=>{if(n.includes(i.id)){let s=[...n,i.id].filter(d=>!!d).join(" => ");throw new Error(`circular dependency found in branch node references: ${s}`)}for(let a of i.refs){let s=r.find(({id:d})=>d===a);if(s)o(s,[...n,i.id]);else if(e)throw new Error(i.id?`subtree '${i.id}' has branch node that references root node '${a}' which has not been defined`:`primary tree has branch node that references root node '${a}' which has not been defined`)}};o(r.find(i=>typeof i.id>"u"))}function y(t,e){if(typeof t!="object"||typeof t.type!="string"||t.type.length===0)throw new Error(`node definition is not an object or 'type' property is not a non-empty string at depth '${e}'`);if(e===0&&t.type!=="root")throw new Error(`expected root node at base of definition but got node of type '${t.type}'`);switch(t.type){case"action":fe(t,e);break;case"condition":he(t,e);break;case"wait":me(t,e);break;case"branch":pe(t,e);break;case"root":ae(t,e);break;case"succeed":se(t,e);break;case"fail":ue(t,e);break;case"flip":de(t,e);break;case"repeat":ce(t,e);break;case"retry":le(t,e);break;case"sequence":ge(t,e);break;case"selector":be(t,e);break;case"parallel":ye(t,e);break;case"race":Ne(t,e);break;case"lotto":we(t,e);break;default:throw new Error(`unexpected node type of '${t.type}' at depth '${e}'`)}}function h(t,e){["while","until","entry","exit","step"].forEach(r=>{let o=t[r];if(!(typeof o>"u")){if(typeof o!="object")throw new Error(`expected attribute '${r}' to be an object for '${t.type}' node at depth '${e}'`);if(typeof o.call!="string"||o.call.length===0)throw new Error(`expected 'call' property for attribute '${r}' to be a non-empty string for '${t.type}' node at depth '${e}'`);if(typeof o.args<"u"&&!Array.isArray(o.args))throw new Error(`expected 'args' property for attribute '${r}' to be an array for '${t.type}' node at depth '${e}'`)}})}function ae(t,e){if(t.type!=="root")throw new Error("expected node type of 'root' for root node");if(e>0)throw new Error("a root node cannot be the child of another node");if(typeof t.id<"u"&&(typeof t.id!="string"||t.id.length===0))throw new Error("expected non-empty string for 'id' property if defined for root node");if(typeof t.child>"u")throw new Error("expected property 'child' to be defined for root node");h(t,e),y(t.child,e+1)}function se(t,e){if(t.type!=="succeed")throw new Error(`expected node type of 'succeed' for succeed node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for succeed node at depth '${e}'`);h(t,e),y(t.child,e+1)}function ue(t,e){if(t.type!=="fail")throw new Error(`expected node type of 'fail' for fail node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for fail node at depth '${e}'`);h(t,e),y(t.child,e+1)}function de(t,e){if(t.type!=="flip")throw new Error(`expected node type of 'flip' for flip node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for flip node at depth '${e}'`);h(t,e),y(t.child,e+1)}function ce(t,e){if(t.type!=="repeat")throw new Error(`expected node type of 'repeat' for repeat node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for repeat node at depth '${e}'`);if(typeof t.iterations<"u")if(Array.isArray(t.iterations)){let r=!!t.iterations.filter(o=>!b(o)).length;if(t.iterations.length!==2||r)throw new Error(`expected array containing two integer values for 'iterations' property if defined for repeat node at depth '${e}'`);if(t.iterations[0]<0||t.iterations[1]<0)throw new Error(`expected positive minimum and maximum iterations count for 'iterations' property if defined for repeat node at depth '${e}'`);if(t.iterations[0]>t.iterations[1])throw new Error(`expected minimum iterations count that does not exceed the maximum iterations count for 'iterations' property if defined for repeat node at depth '${e}'`)}else if(b(t.iterations)){if(t.iterations<0)throw new Error(`expected positive iterations count for 'iterations' property if defined for repeat node at depth '${e}'`)}else throw new Error(`expected integer value or array containing two integer values for 'iterations' property if defined for repeat node at depth '${e}'`);h(t,e),y(t.child,e+1)}function le(t,e){if(t.type!=="retry")throw new Error(`expected node type of 'retry' for retry node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for retry node at depth '${e}'`);if(typeof t.attempts<"u")if(Array.isArray(t.attempts)){let r=!!t.attempts.filter(o=>!b(o)).length;if(t.attempts.length!==2||r)throw new Error(`expected array containing two integer values for 'attempts' property if defined for retry node at depth '${e}'`);if(t.attempts[0]<0||t.attempts[1]<0)throw new Error(`expected positive minimum and maximum attempts count for 'attempts' property if defined for retry node at depth '${e}'`);if(t.attempts[0]>t.attempts[1])throw new Error(`expected minimum attempts count that does not exceed the maximum attempts count for 'attempts' property if defined for retry node at depth '${e}'`)}else if(b(t.attempts)){if(t.attempts<0)throw new Error(`expected positive attempts count for 'attempts' property if defined for retry node at depth '${e}'`)}else throw new Error(`expected integer value or array containing two integer values for 'attempts' property if defined for retry node at depth '${e}'`);h(t,e),y(t.child,e+1)}function pe(t,e){if(t.type!=="branch")throw new Error(`expected node type of 'branch' for branch node at depth '${e}'`);if(typeof t.ref!="string"||t.ref.length===0)throw new Error(`expected non-empty string for 'ref' property for branch node at depth '${e}'`);["while","until"].forEach(r=>{if(typeof t[r]<"u")throw new Error(`guards should not be defined for branch nodes but guard '${r}' was defined for branch node at depth '${e}'`)}),["entry","exit","step"].forEach(r=>{if(typeof t[r]<"u")throw new Error(`callbacks should not be defined for branch nodes but callback '${r}' was defined for branch node at depth '${e}'`)})}function fe(t,e){if(t.type!=="action")throw new Error(`expected node type of 'action' for action node at depth '${e}'`);if(typeof t.call!="string"||t.call.length===0)throw new Error(`expected non-empty string for 'call' property of action node at depth '${e}'`);if(typeof t.args<"u"&&!Array.isArray(t.args))throw new Error(`expected array for 'args' property if defined for action node at depth '${e}'`);h(t,e)}function he(t,e){if(t.type!=="condition")throw new Error(`expected node type of 'condition' for condition node at depth '${e}'`);if(typeof t.call!="string"||t.call.length===0)throw new Error(`expected non-empty string for 'call' property of condition node at depth '${e}'`);if(typeof t.args<"u"&&!Array.isArray(t.args))throw new Error(`expected array for 'args' property if defined for condition node at depth '${e}'`);h(t,e)}function me(t,e){if(t.type!=="wait")throw new Error(`expected node type of 'wait' for wait node at depth '${e}'`);if(typeof t.duration<"u")if(Array.isArray(t.duration)){let r=!!t.duration.filter(o=>!b(o)).length;if(t.duration.length!==2||r)throw new Error(`expected array containing two integer values for 'duration' property if defined for wait node at depth '${e}'`);if(t.duration[0]<0||t.duration[1]<0)throw new Error(`expected positive minimum and maximum duration for 'duration' property if defined for wait node at depth '${e}'`);if(t.duration[0]>t.duration[1])throw new Error(`expected minimum duration value that does not exceed the maximum duration value for 'duration' property if defined for wait node at depth '${e}'`)}else if(b(t.duration)){if(t.duration<0)throw new Error(`expected positive duration value for 'duration' property if defined for wait node at depth '${e}'`)}else throw new Error(`expected integer value or array containing two integer values for 'duration' property if defined for wait node at depth '${e}'`);h(t,e)}function ge(t,e){if(t.type!=="sequence")throw new Error(`expected node type of 'sequence' for sequence node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for sequence node at depth '${e}'`);h(t,e),t.children.forEach(r=>y(r,e+1))}function be(t,e){if(t.type!=="selector")throw new Error(`expected node type of 'selector' for selector node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for selector node at depth '${e}'`);h(t,e),t.children.forEach(r=>y(r,e+1))}function ye(t,e){if(t.type!=="parallel")throw new Error(`expected node type of 'parallel' for parallel node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for parallel node at depth '${e}'`);h(t,e),t.children.forEach(r=>y(r,e+1))}function Ne(t,e){if(t.type!=="race")throw new Error(`expected node type of 'race' for race node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for race node at depth '${e}'`);h(t,e),t.children.forEach(r=>y(r,e+1))}function we(t,e){if(t.type!=="lotto")throw new Error(`expected node type of 'lotto' for lotto node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for lotto node at depth '${e}'`);if(typeof t.weights<"u"&&(!Array.isArray(t.weights)||t.weights.length!==t.children.length||t.weights.filter(r=>!b(r)).length||t.weights.filter(r=>r<0).length))throw new Error(`expected an array of positive integer weight values with a length matching the number of child nodes for 'weights' property if defined for lotto node at depth '${e}'`);h(t,e),t.children.forEach(r=>y(r,e+1))}function w(t){return{succeeded:!1,errorMessage:t}}var S=class extends Error{constructor(r){super("A guard path condition has failed");this.source=r}isSourceNode=r=>r===this.source};var T=class{constructor(e){this.nodes=e}evaluate=e=>{for(let r of this.nodes)for(let o of r.guards)if(!o.isSatisfied(e))throw new S(r.node)}};function St(){var t=function(){return((1+Math.random())*65536|0).toString(16).substring(1)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}var E=class{constructor(e,r,o){this.type=e;this.options=o;this.uid=St(),this.attributes={entry:r.find(({type:i})=>i==="entry"),step:r.find(({type:i})=>i==="step"),exit:r.find(({type:i})=>i==="exit"),while:r.find(({type:i})=>i==="while"),until:r.find(({type:i})=>i==="until")}}uid;attributes;_state="mistreevous.ready";_guardPath;getState=()=>this._state;setState=e=>{let r=this._state;this._state=e,r!==e&&this.onStateChanged(r)};getUid=()=>this.uid;getType=()=>this.type;getAttributes=()=>Object.values(this.attributes).filter(e=>!!e);setGuardPath=e=>this._guardPath=e;hasGuardPath=()=>!!this._guardPath;is(e){return this._state===e}reset(){this.setState("mistreevous.ready")}abort(e){!this.is("mistreevous.running")||(this.reset(),this.attributes.exit?.callAgentFunction(e,!1,!0))}update(e){if(!(this.is("mistreevous.succeeded")||this.is("mistreevous.failed")))try{this._guardPath.evaluate(e),this.is("mistreevous.ready")&&this.attributes.entry?.callAgentFunction(e),this.attributes.step?.callAgentFunction(e),this.onUpdate(e),(this.is("mistreevous.succeeded")||this.is("mistreevous.failed"))&&this.attributes.exit?.callAgentFunction(e,this.is("mistreevous.succeeded"),!1)}catch(r){if(r instanceof S&&r.isSourceNode(this))this.abort(e),this.setState("mistreevous.failed");else throw r}}getDetails(){return{id:this.uid,name:this.getName(),type:this.type,while:this.attributes.while?.getDetails(),until:this.attributes.until?.getDetails(),entry:this.attributes.entry?.getDetails(),step:this.attributes.step?.getDetails(),exit:this.attributes.exit?.getDetails(),state:this._state}}onStateChanged(e){this.options.onNodeStateChange?.({id:this.uid,type:this.type,while:this.attributes.while?.getDetails(),until:this.attributes.until?.getDetails(),entry:this.attributes.entry?.getDetails(),step:this.attributes.step?.getDetails(),exit:this.attributes.exit?.getDetails(),previousState:e,state:this._state})}};var m=class extends E{constructor(r,o,i,n){super(r,o,i);this.children=n}isLeafNode=()=>!1;getChildren=()=>this.children;reset=()=>{this.setState("mistreevous.ready"),this.children.forEach(r=>r.reset())};abort=r=>{!this.is("mistreevous.running")||(this.children.forEach(o=>o.abort(r)),this.reset(),this.attributes.exit?.callAgentFunction(r,!1,!0))};getDetails(){return{...super.getDetails(),children:this.children.map(r=>r.getDetails())}}};var L=class extends m{constructor(e,r,o){super("parallel",e,r,o)}onUpdate(e){for(let r of this.children)(r.getState()==="mistreevous.ready"||r.getState()==="mistreevous.running")&&r.update(e);if(this.children.find(r=>r.is("mistreevous.failed"))){this.setState("mistreevous.failed");for(let r of this.children)r.getState()==="mistreevous.running"&&r.abort(e);return}if(this.children.every(r=>r.is("mistreevous.succeeded"))){this.setState("mistreevous.succeeded");return}this.setState("mistreevous.running")}getName=()=>"PARALLEL"};var P=class extends m{constructor(e,r,o){super("race",e,r,o)}onUpdate(e){for(let r of this.children)(r.getState()==="mistreevous.ready"||r.getState()==="mistreevous.running")&&r.update(e);if(this.children.find(r=>r.is("mistreevous.succeeded"))){this.setState("mistreevous.succeeded");for(let r of this.children)r.getState()==="mistreevous.running"&&r.abort(e);return}if(this.children.every(r=>r.is("mistreevous.failed"))){this.setState("mistreevous.failed");return}this.setState("mistreevous.running")}getName=()=>"RACE"};var O=class extends m{constructor(r,o,i){super("selector",r,o,i);this.children=i}onUpdate(r){for(let o of this.children){if((o.getState()==="mistreevous.ready"||o.getState()==="mistreevous.running")&&o.update(r),o.getState()==="mistreevous.succeeded"){this.setState("mistreevous.succeeded");return}if(o.getState()==="mistreevous.failed")if(this.children.indexOf(o)===this.children.length-1){this.setState("mistreevous.failed");return}else continue;if(o.getState()==="mistreevous.running"){this.setState("mistreevous.running");return}throw new Error("child node was not in an expected state.")}}getName=()=>"SELECTOR"};var G=class extends m{constructor(r,o,i){super("sequence",r,o,i);this.children=i}onUpdate(r){for(let o of this.children){if((o.getState()==="mistreevous.ready"||o.getState()==="mistreevous.running")&&o.update(r),o.getState()==="mistreevous.succeeded")if(this.children.indexOf(o)===this.children.length-1){this.setState("mistreevous.succeeded");return}else continue;if(o.getState()==="mistreevous.failed"){this.setState("mistreevous.failed");return}if(o.getState()==="mistreevous.running"){this.setState("mistreevous.running");return}throw new Error("child node was not in an expected state.")}}getName=()=>"SEQUENCE"};var Ut=Mt($t());var M=class extends m{constructor(r,o,i,n){super("lotto",r,o,n);this.weights=i}selectedChild;onUpdate(r){if(this.is("mistreevous.ready")){let o=(0,Ut.default)({random:this.options.random,participants:this.children.map((i,n)=>[i,this.weights?.[n]||1])});this.selectedChild=o.draw()||void 0}if(!this.selectedChild)throw new Error("failed to update lotto node as it has no active child");(this.selectedChild.getState()==="mistreevous.ready"||this.selectedChild.getState()==="mistreevous.running")&&this.selectedChild.update(r),this.setState(this.selectedChild.getState())}getName=()=>this.weights?`LOTTO [${this.weights.join(",")}]`:"LOTTO"};var f=class extends E{constructor(r,o,i,n){super(r,o,i);this.child=n}isLeafNode=()=>!1;getChildren=()=>[this.child];reset=()=>{this.setState("mistreevous.ready"),this.child.reset()};abort=r=>{!this.is("mistreevous.running")||(this.child.abort(r),this.reset(),this.attributes.exit?.callAgentFunction(r,!1,!0))};getDetails(){return{...super.getDetails(),children:[this.child.getDetails()]}}};var B=class extends f{constructor(e,r,o){super("fail",e,r,o)}onUpdate(e){switch((this.child.getState()==="mistreevous.ready"||this.child.getState()==="mistreevous.running")&&this.child.update(e),this.child.getState()){case"mistreevous.running":this.setState("mistreevous.running");break;case"mistreevous.succeeded":case"mistreevous.failed":this.setState("mistreevous.failed");break;default:this.setState("mistreevous.ready")}}getName=()=>"FAIL"};var _=class extends f{constructor(e,r,o){super("flip",e,r,o)}onUpdate(e){switch((this.child.getState()==="mistreevous.ready"||this.child.getState()==="mistreevous.running")&&this.child.update(e),this.child.getState()){case"mistreevous.running":this.setState("mistreevous.running");break;case"mistreevous.succeeded":this.setState("mistreevous.failed");break;case"mistreevous.failed":this.setState("mistreevous.succeeded");break;default:this.setState("mistreevous.ready")}}getName=()=>"FLIP"};var Y=class extends f{constructor(r,o,i,n,a,s){super("repeat",r,o,s);this.iterations=i;this.iterationsMin=n;this.iterationsMax=a}targetIterationCount=null;currentIterationCount=0;onUpdate(r){if(this.is("mistreevous.ready")&&(this.child.reset(),this.currentIterationCount=0,this.setTargetIterationCount()),this.canIterate())if(this.setState("mistreevous.running"),this.child.getState()==="mistreevous.succeeded"&&this.child.reset(),this.child.update(r),this.child.getState()==="mistreevous.failed"){this.setState("mistreevous.failed");return}else this.child.getState()==="mistreevous.succeeded"&&(this.currentIterationCount+=1);else this.setState("mistreevous.succeeded")}getName=()=>this.iterations!==null?`REPEAT ${this.iterations}x`:this.iterationsMin!==null&&this.iterationsMax!==null?`REPEAT ${this.iterationsMin}x-${this.iterationsMax}x`:"REPEAT";reset=()=>{this.setState("mistreevous.ready"),this.currentIterationCount=0,this.child.reset()};canIterate=()=>this.targetIterationCount!==null?this.currentIterationCount{if(this.iterations!==null)this.targetIterationCount=this.iterations;else if(this.iterationsMin!==null&&this.iterationsMax!==null){let r=typeof this.options.random=="function"?this.options.random:Math.random;this.targetIterationCount=Math.floor(r()*(this.iterationsMax-this.iterationsMin+1)+this.iterationsMin)}else this.targetIterationCount=null}};var j=class extends f{constructor(r,o,i,n,a,s){super("retry",r,o,s);this.attempts=i;this.attemptsMin=n;this.attemptsMax=a}targetAttemptCount=null;currentAttemptCount=0;onUpdate(r){if(this.is("mistreevous.ready")&&(this.child.reset(),this.currentAttemptCount=0,this.setTargetAttemptCount()),this.canAttempt())if(this.setState("mistreevous.running"),this.child.getState()==="mistreevous.failed"&&this.child.reset(),this.child.update(r),this.child.getState()==="mistreevous.succeeded"){this.setState("mistreevous.succeeded");return}else this.child.getState()==="mistreevous.failed"&&(this.currentAttemptCount+=1);else this.setState("mistreevous.failed")}getName=()=>this.attempts!==null?`RETRY ${this.attempts}x`:this.attemptsMin!==null&&this.attemptsMax!==null?`RETRY ${this.attemptsMin}x-${this.attemptsMax}x`:"RETRY";reset=()=>{this.setState("mistreevous.ready"),this.currentAttemptCount=0,this.child.reset()};canAttempt=()=>this.targetAttemptCount!==null?this.currentAttemptCount{if(this.attempts!==null)this.targetAttemptCount=this.attempts;else if(this.attemptsMin!==null&&this.attemptsMax!==null){let r=typeof this.options.random=="function"?this.options.random:Math.random;this.targetAttemptCount=Math.floor(r()*(this.attemptsMax-this.attemptsMin+1)+this.attemptsMin)}else this.targetAttemptCount=null}};var q=class extends f{constructor(e,r,o){super("root",e,r,o)}onUpdate(e){(this.child.getState()==="mistreevous.ready"||this.child.getState()==="mistreevous.running")&&this.child.update(e),this.setState(this.child.getState())}getName=()=>"ROOT"};var W=class extends f{constructor(e,r,o){super("succeed",e,r,o)}onUpdate(e){switch((this.child.getState()==="mistreevous.ready"||this.child.getState()==="mistreevous.running")&&this.child.update(e),this.child.getState()){case"mistreevous.running":this.setState("mistreevous.running");break;case"mistreevous.succeeded":case"mistreevous.failed":this.setState("mistreevous.succeeded");break;default:this.setState("mistreevous.ready")}}getName=()=>"SUCCEED"};var D=class extends E{isLeafNode=()=>!0};var J=class extends D{constructor(r,o,i,n){super("action",r,o);this.actionName=i;this.actionArguments=n}isUsingUpdatePromise=!1;updatePromiseResult=null;onUpdate(r){if(this.isUsingUpdatePromise){if(!this.updatePromiseResult)return;let{isResolved:n,value:a}=this.updatePromiseResult;if(n){if(a!=="mistreevous.succeeded"&&a!=="mistreevous.failed")throw new Error("action node promise resolved with an invalid value, expected a State.SUCCEEDED or State.FAILED value to be returned");this.setState(a);return}else throw new Error(`action function '${this.actionName}' promise rejected with '${a}'`)}let o=u.getFuncInvoker(r,this.actionName);if(o===null)throw new Error(`cannot update action node as the action '${this.actionName}' function is not defined on the agent and has not been registered`);let i;try{i=o(this.actionArguments)}catch(n){throw n instanceof Error?new Error(`action function '${this.actionName}' threw: ${n.stack}`):new Error(`action function '${this.actionName}' threw: ${n}`)}i instanceof Promise?(i.then(n=>{!this.isUsingUpdatePromise||(this.updatePromiseResult={isResolved:!0,value:n})},n=>{!this.isUsingUpdatePromise||(this.updatePromiseResult={isResolved:!1,value:n})}),this.setState("mistreevous.running"),this.isUsingUpdatePromise=!0):(this.validateUpdateResult(i),this.setState(i||"mistreevous.running"))}getName=()=>this.actionName;reset=()=>{this.setState("mistreevous.ready"),this.isUsingUpdatePromise=!1,this.updatePromiseResult=null};getDetails(){return{...super.getDetails(),args:this.actionArguments}}onStateChanged(r){this.options.onNodeStateChange?.({id:this.uid,type:this.getType(),args:this.actionArguments,while:this.attributes.while?.getDetails(),until:this.attributes.until?.getDetails(),entry:this.attributes.entry?.getDetails(),step:this.attributes.step?.getDetails(),exit:this.attributes.exit?.getDetails(),previousState:r,state:this.getState()})}validateUpdateResult=r=>{switch(r){case"mistreevous.succeeded":case"mistreevous.failed":case"mistreevous.running":case void 0:return;default:throw new Error(`expected action function '${this.actionName}' to return an optional State.SUCCEEDED or State.FAILED value but returned '${r}'`)}}};var V=class extends D{constructor(r,o,i,n){super("condition",r,o);this.conditionName=i;this.conditionArguments=n}onUpdate(r){let o=u.getFuncInvoker(r,this.conditionName);if(o===null)throw new Error(`cannot update condition node as the condition '${this.conditionName}' function is not defined on the agent and has not been registered`);let i;try{i=o(this.conditionArguments)}catch(n){throw n instanceof Error?new Error(`condition function '${this.conditionName}' threw: ${n.stack}`):new Error(`condition function '${this.conditionName}' threw: ${n}`)}if(typeof i!="boolean")throw new Error(`expected condition function '${this.conditionName}' to return a boolean but returned '${i}'`);this.setState(i?"mistreevous.succeeded":"mistreevous.failed")}getName=()=>this.conditionName;getDetails(){return{...super.getDetails(),args:this.conditionArguments}}onStateChanged(r){this.options.onNodeStateChange?.({id:this.uid,type:this.getType(),args:this.conditionArguments,while:this.attributes.while?.getDetails(),until:this.attributes.until?.getDetails(),entry:this.attributes.entry?.getDetails(),step:this.attributes.step?.getDetails(),exit:this.attributes.exit?.getDetails(),previousState:r,state:this.getState()})}};var Q=class extends D{constructor(r,o,i,n,a){super("wait",r,o);this.duration=i;this.durationMin=n;this.durationMax=a}initialUpdateTime=0;totalDuration=null;waitedDuration=0;onUpdate(r){if(this.is("mistreevous.ready")){if(this.initialUpdateTime=new Date().getTime(),this.waitedDuration=0,this.duration!==null)this.totalDuration=this.duration;else if(this.durationMin!==null&&this.durationMax!==null){let o=typeof this.options.random=="function"?this.options.random:Math.random;this.totalDuration=Math.floor(o()*(this.durationMax-this.durationMin+1)+this.durationMin)}else this.totalDuration=null;this.setState("mistreevous.running")}if(this.totalDuration!==null){if(typeof this.options.getDeltaTime=="function"){let o=this.options.getDeltaTime();if(typeof o!="number"||isNaN(o))throw new Error("The delta time must be a valid number and not NaN.");this.waitedDuration+=o*1e3}else this.waitedDuration=new Date().getTime()-this.initialUpdateTime;this.waitedDuration>=this.totalDuration&&this.setState("mistreevous.succeeded")}}getName=()=>this.duration!==null?`WAIT ${this.duration}ms`:this.durationMin!==null&&this.durationMax!==null?`WAIT ${this.durationMin}ms-${this.durationMax}ms`:"WAIT"};var x=class{constructor(e,r){this.type=e;this.args=r}};var R=class extends x{constructor(r,o,i){super(r,o);this.condition=i}getCondition=()=>this.condition;isGuard=()=>!0;getDetails(){return{type:this.type,args:this.args,calls:this.getCondition()}}};var H=class extends R{constructor(e,r){super("while",r,e)}isSatisfied=e=>{let r=u.getFuncInvoker(e,this.getCondition());if(r===null)throw new Error(`cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`);let o;try{o=r(this.args)}catch(i){throw i instanceof Error?new Error(`guard condition function '${this.getCondition()}' threw: ${i.stack}`):new Error(`guard condition function '${this.getCondition()}' threw: ${i}`)}if(typeof o!="boolean")throw new Error(`expected guard condition function '${this.getCondition()}' to return a boolean but returned '${o}'`);return o}};var K=class extends R{constructor(e,r){super("until",r,e)}isSatisfied=e=>{let r=u.getFuncInvoker(e,this.getCondition());if(r===null)throw new Error(`cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`);let o;try{o=r(this.args)}catch(i){throw i instanceof Error?new Error(`guard condition function '${this.getCondition()}' threw: ${i.stack}`):new Error(`guard condition function '${this.getCondition()}' threw: ${i}`)}if(typeof o!="boolean")throw new Error(`expected guard condition function '${this.getCondition()}' to return a boolean but returned '${o}'`);return!o}};var v=class extends x{constructor(r,o,i){super(r,o);this.functionName=i}getFunctionName=()=>this.functionName;isGuard=()=>!1;getDetails(){return{type:this.type,args:this.args,calls:this.getFunctionName()}}};var z=class extends v{constructor(e,r){super("entry",r,e)}callAgentFunction=e=>{let r=u.getFuncInvoker(e,this.getFunctionName());if(r===null)throw new Error(`cannot call entry function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`);r(this.args)}};var X=class extends v{constructor(e,r){super("step",r,e)}callAgentFunction=e=>{let r=u.getFuncInvoker(e,this.getFunctionName());if(r===null)throw new Error(`cannot call step function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`);r(this.args)}};var Z=class extends v{constructor(e,r){super("exit",r,e)}callAgentFunction=(e,r,o)=>{let i=u.getFuncInvoker(e,this.getFunctionName());if(i===null)throw new Error(`cannot call exit function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`);i([{succeeded:r,aborted:o},...this.args])}};var ft=Symbol("__root__");function ht(t,e){let r=Ie(t);nt([r[ft],...Object.values(r)],!0);let o=g(r[ft],r,e);return $e(o),o}function g(t,e,r){let o=Ce(t);switch(t.type){case"root":return new q(o,r,g(t.child,e,r));case"repeat":let i=null,n=null,a=null;return Array.isArray(t.iterations)?(n=t.iterations[0],a=t.iterations[1]):b(t.iterations)&&(i=t.iterations),new Y(o,r,i,n,a,g(t.child,e,r));case"retry":let s=null,d=null,$=null;return Array.isArray(t.attempts)?(d=t.attempts[0],$=t.attempts[1]):b(t.attempts)&&(s=t.attempts),new j(o,r,s,d,$,g(t.child,e,r));case"flip":return new _(o,r,g(t.child,e,r));case"succeed":return new W(o,r,g(t.child,e,r));case"fail":return new B(o,r,g(t.child,e,r));case"sequence":return new G(o,r,t.children.map(A=>g(A,e,r)));case"selector":return new O(o,r,t.children.map(A=>g(A,e,r)));case"parallel":return new L(o,r,t.children.map(A=>g(A,e,r)));case"race":return new P(o,r,t.children.map(A=>g(A,e,r)));case"lotto":return new M(o,r,t.weights,t.children.map(A=>g(A,e,r)));case"branch":return g(e[t.ref].child,e,r);case"action":return new J(o,r,t.call,t.args||[]);case"condition":return new V(o,r,t.call,t.args||[]);case"wait":let mt=null,gt=null,bt=null;return Array.isArray(t.duration)?(gt=t.duration[0],bt=t.duration[1]):b(t.duration)&&(mt=t.duration),new Q(o,r,mt,gt,bt)}}function Ce(t){let e=[];return t.while&&e.push(new H(t.while.call,t.while.args??[])),t.until&&e.push(new K(t.until.call,t.until.args??[])),t.entry&&e.push(new z(t.entry.call,t.entry.args??[])),t.step&&e.push(new X(t.step.call,t.step.args??[])),t.exit&&e.push(new Z(t.exit.call,t.exit.args??[])),e}function Ie(t){let e={};for(let[r,o]of Object.entries(u.getSubtrees()))e[r]={...o,id:r};for(let r of t)e[r.id??ft]=r;return e}function $e(t){let e=[],r=(o,i)=>{o=o.concat(i),i.isLeafNode()?e.push(o):i.getChildren().forEach(n=>r(o,n))};r([],t),e.forEach(o=>{for(let i=0;i({node:s,guards:s.getAttributes().filter(d=>d.isGuard())})).filter(s=>s.guards.length>0));n.setGuardPath(a)}})}var dt=class{constructor(e,r,o={}){this.agent=r;this.options=o;if(rt(e))throw new Error("tree definition not defined");if(typeof r!="object"||r===null)throw new Error("the agent must be an object and not null");let{succeeded:i,errorMessage:n,json:a}=ot(e);if(!i)throw new Error(`invalid definition: ${n}`);if(!a)throw new Error("expected json definition to be returned as part of successful definition validation response");try{this._rootNode=ht(a,o)}catch(s){throw new Error(`error building tree: ${s.message}`)}}_rootNode;isRunning(){return this._rootNode.getState()==="mistreevous.running"}getState(){return this._rootNode.getState()}step(){(this._rootNode.getState()==="mistreevous.succeeded"||this._rootNode.getState()==="mistreevous.failed")&&this._rootNode.reset();try{this._rootNode.update(this.agent)}catch(e){throw new Error(`error stepping tree: ${e.message}`)}}reset(){this._rootNode.reset()}getTreeNodeDetails(){return this._rootNode.getDetails()}static register(e,r){if(typeof r=="function"){u.setFunc(e,r);return}if(typeof r=="string"){let o;try{o=C(r)}catch(i){throw new Error(`error registering definition, invalid MDSL: ${i.message}`)}if(o.length!=1||typeof o[0].id<"u")throw new Error("error registering definition: expected a single unnamed root node");try{let{succeeded:i,errorMessage:n}=it(o[0]);if(!i)throw new Error(n)}catch(i){throw new Error(`error registering definition: ${i.message}`)}u.setSubtree(e,o[0])}else if(typeof r=="object"&&!Array.isArray(r)){try{let{succeeded:o,errorMessage:i}=it(r);if(!o)throw new Error(i)}catch(o){throw new Error(`error registering definition: ${o.message}`)}u.setSubtree(e,r)}else throw new Error("unexpected value, expected string mdsl definition, root node json definition or function")}static unregister(e){u.remove(e)}static unregisterAll(){u.empty()}};return Bt(Ue);})(); +"use strict";var mistreevous=(()=>{var Tt=Object.create;var $=Object.defineProperty;var Lt=Object.getOwnPropertyDescriptor;var Ot=Object.getOwnPropertyNames;var Pt=Object.getPrototypeOf,Gt=Object.prototype.hasOwnProperty;var kt=(t,e,r)=>e in t?$(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var F=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Mt=(t,e)=>{for(var r in e)$(t,r,{get:e[r],enumerable:!0})},Nt=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ot(e))!Gt.call(t,i)&&i!==r&&$(t,i,{get:()=>e[i],enumerable:!(o=Lt(e,i))||o.enumerable});return t};var Bt=(t,e,r)=>(r=t!=null?Tt(Pt(t)):{},Nt(e||!t||!t.__esModule?$(r,"default",{value:t,enumerable:!0}):r,t)),_t=t=>Nt($({},"__esModule",{value:!0}),t);var ct=(t,e,r)=>(kt(t,typeof e!="symbol"?e+"":e,r),r);var Rt=F(st=>{"use strict";Object.defineProperty(st,"__esModule",{value:!0});st.Participant=void 0;var ve=function(){function t(e,r){r===void 0&&(r=1),this._participant=e,this._tickets=r}return Object.defineProperty(t.prototype,"participant",{get:function(){return this._participant},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"tickets",{get:function(){return this._tickets},set:function(e){this._tickets=e},enumerable:!1,configurable:!0}),t}();st.Participant=ve});var Ct=F(I=>{"use strict";Object.defineProperty(I,"__esModule",{value:!0});I.isNaturalNumber=I.isNullOrUndefined=void 0;function Se(t){return t==null}I.isNullOrUndefined=Se;function xe(t){return typeof t=="number"&&t>=1&&Math.floor(t)===t}I.isNaturalNumber=xe});var It=F(ut=>{"use strict";Object.defineProperty(ut,"__esModule",{value:!0});ut.Lotto=void 0;var Re=Rt(),M=Ct(),Ce=function(){function t(e){this._participants=[],this._customRandom=e}return t.prototype.add=function(e,r){if(r===void 0&&(r=1),!(0,M.isNaturalNumber)(r))throw new Error("tickets value must be a natural number");var o=this._participants.find(function(i){return i.participant===e});return o?o.tickets+=r:this._participants.push(new Re.Participant(e,r)),this},t.prototype.remove=function(e,r){var o=this._participants.find(function(i){return i.participant===e});if(!o)return this;if(r!==void 0){if(!(0,M.isNaturalNumber)(r))throw new Error("tickets value must be a natural number");o.tickets-=r,o.tickets<1&&(this._participants=this._participants.filter(function(i){return i!==o}))}else this._participants=this._participants.filter(function(i){return i!==o});return this},t.prototype.draw=function(e){if(e===void 0&&(e={}),this._participants.length===0)return null;var r=(0,M.isNullOrUndefined)(e.redrawable)?!0:e.redrawable,o=[];this._participants.forEach(function(a){for(var s=a.participant,d=a.tickets,U=0;U=1)throw new Error("the 'random' function provided did not return a number between 0 (inclusive) and 1")}else i=Math.random();var n=o[Math.floor(i*o.length)];return r||this.remove(n,1),n},t.prototype.drawMultiple=function(e,r){r===void 0&&(r={});var o=(0,M.isNullOrUndefined)(r.unique)?!1:r.unique;if(e===0)return[];if(!(0,M.isNaturalNumber)(e))throw new Error("tickets value must be a natural number");for(var i=[];i.length0;)i.push(this.draw(r));if(o){for(var n=[],a=0,s=i;a{"use strict";Object.defineProperty(dt,"__esModule",{value:!0});dt.createLotto=void 0;var pt=It();function Ie(t){if(!t)return new pt.Lotto;if(Array.isArray(t)){var e=t,r=new pt.Lotto;return e.forEach(function(n){var a=n[0],s=n[1];return r.add(a,s)}),r}else{var o=t.random,e=t.participants,i=new pt.Lotto(o);return e&&e.forEach(function(a){var s=a[0],d=a[1];return i.add(s,d)}),i}}dt.createLotto=Ie});var $t=F(ft=>{"use strict";Object.defineProperty(ft,"__esModule",{value:!0});var Ue=Ut();ft.default=Ue.createLotto});var Le={};Mt(Le,{BehaviourTree:()=>lt,State:()=>l,convertMDSLToJSON:()=>C,validateDefinition:()=>it});var l=(i=>(i.READY="mistreevous.ready",i.RUNNING="mistreevous.running",i.SUCCEEDED="mistreevous.succeeded",i.FAILED="mistreevous.failed",i))(l||{});var u=class{static getFunc(e){return this.registeredFunctions[e]}static setFunc(e,r){this.registeredFunctions[e]=r}static getFuncInvoker(e,r){let o=e[r];if(o&&typeof o=="function")return i=>o.apply(e,i);if(this.registeredFunctions[r]&&typeof this.registeredFunctions[r]=="function"){let i=this.registeredFunctions[r];return n=>i(e,...n)}return null}static getSubtrees(){return this.registeredSubtrees}static setSubtree(e,r){this.registeredSubtrees[e]=r}static remove(e){delete this.registeredFunctions[e],delete this.registeredSubtrees[e]}static empty(){this.registeredFunctions={},this.registeredSubtrees={}}};ct(u,"registeredFunctions",{}),ct(u,"registeredSubtrees",{});function wt(t){return t.type==="root"}function At(t){return t.type==="branch"}function Et(t){return["branch","action","condition","wait"].includes(t.type)}function et(t){return["root","repeat","retry","flip","succeed","fail"].includes(t.type)}function rt(t){return["sequence","selector","lotto","parallel","race","all"].includes(t.type)}function Dt(t){let e=[],r=o=>{e.push(o),rt(o)?o.children.forEach(r):et(o)&&r(o.child)};return r(t),e}function y(t){return typeof t=="number"&&Math.floor(t)===t}function ot(t){return typeof t>"u"||t===null}function c(t,e){let r=t.shift();if(r===void 0)throw new Error("unexpected end of definition");if(e!=null){let i=typeof e=="string"?[e]:e;var o=i.some(n=>r.toUpperCase()===n.toUpperCase());if(!o){let n=i.map(a=>"'"+a+"'").join(" or ");throw new Error("unexpected token found. Expected "+n+" but got '"+r+"'")}}return r}function vt(t){let e={},r=t.replace(/\"(\\.|[^"\\])*\"/g,o=>{var i=o.substring(1,o.length-1),n=Object.keys(e).find(a=>e[a]===i);return n||(n=`@@${Object.keys(e).length}@@`,e[n]=i),n});return{placeholders:e,processedDefinition:r}}function St(t){return t=t.replace(/\(/g," ( "),t=t.replace(/\)/g," ) "),t=t.replace(/\{/g," { "),t=t.replace(/\}/g," } "),t=t.replace(/\]/g," ] "),t=t.replace(/\[/g," [ "),t=t.replace(/\,/g," , "),t.replace(/\s+/g," ").trim().split(" ")}function w(t,e){let r=[];if(!["[","("].includes(t[0]))return r;let o=c(t,["[","("])==="["?"]":")",i=[];for(;t.length&&t[0]!==o;)i.push(t.shift());return i.forEach((n,a)=>{if(!(a&1)){let d=Yt(n,e);r.push(d)}else if(n!==",")throw new Error(`invalid argument list, expected ',' or ']' but got '${n}'`)}),c(t,o),r}function Yt(t,e){return t==="null"?{value:null,type:"null"}:t==="true"||t==="false"?{value:t==="true",type:"boolean"}:isNaN(t)?t.match(/^@@\d+@@$/g)?{value:e[t].replace('\\"','"'),type:"string"}:{value:t,type:"identifier"}:{value:parseFloat(t),isInteger:parseFloat(t)===parseInt(t,10),type:"number"}}function p(t,e){let r=["while","until","entry","exit","step"],o={},i=t[0]?.toLowerCase();for(;r.includes(i);){if(o[i])throw new Error(`duplicate attribute '${t[0].toUpperCase()}' found for node`);t.shift();let[n,...a]=w(t,e);if(n?.type!=="identifier")throw new Error("expected agent function or registered function name identifier argument for attribute");a.filter(s=>s.type==="identifier").forEach(s=>{throw new Error(`invalid attribute argument value '${s.value}', must be string, number, boolean or null`)}),o[i]={call:n.value,args:a.map(({value:s})=>s)},i=t[0]?.toLowerCase()}return o}function C(t){let{placeholders:e,processedDefinition:r}=vt(t),o=St(r);return jt(o,e)}function jt(t,e){if(t.length<3)throw new Error("invalid token count");if(t.filter(a=>a==="{").length!==t.filter(a=>a==="}").length)throw new Error("scope character mismatch");let r=[],o=[],i=a=>{if(wt(a)){if(r[r.length-1]?.length)throw new Error("a root node cannot be the child of another node");o.push(a),r.push([a]);return}if(!r.length||!r[r.length-1].length)throw new Error("expected root node at base of definition");let s=r[r.length-1],d=s[s.length-1];if(rt(d))d.children=d.children||[],d.children.push(a);else if(et(d)){if(d.child)throw new Error("a decorator node must only have a single child node");d.child=a}Et(a)||s.push(a)},n=()=>{let a=null,s=r[r.length-1];return s.length&&(a=s.pop()),s.length||r.pop(),a};for(;t.length;){let a=t.shift();switch(a.toUpperCase()){case"ROOT":{i(qt(t,e));break}case"SUCCEED":{i(Wt(t,e));break}case"FAIL":{i(Jt(t,e));break}case"FLIP":{i(Vt(t,e));break}case"REPEAT":{i(Qt(t,e));break}case"RETRY":{i(Ht(t,e));break}case"SEQUENCE":{i(Kt(t,e));break}case"SELECTOR":{i(zt(t,e));break}case"PARALLEL":{i(Xt(t,e));break}case"RACE":{i(Zt(t,e));break}case"ALL":{i(te(t,e));break}case"LOTTO":{i(ee(t,e));break}case"ACTION":{i(re(t,e));break}case"CONDITION":{i(oe(t,e));break}case"WAIT":{i(ie(t,e));break}case"BRANCH":{i(ne(t,e));break}case"}":{let s=n();s&&ae(s);break}default:throw new Error(`unexpected token: ${a}`)}}return o}function qt(t,e){let r={type:"root"},o=w(t,e);if(o.length)if(o.length===1&&o[0].type==="identifier")r.id=o[0].value;else throw new Error("expected single root name argument");return r={...r,...p(t,e)},c(t,"{"),r}function Wt(t,e){let r={type:"succeed",...p(t,e)};return c(t,"{"),r}function Jt(t,e){let r={type:"fail",...p(t,e)};return c(t,"{"),r}function Vt(t,e){let r={type:"flip",...p(t,e)};return c(t,"{"),r}function Qt(t,e){let r={type:"repeat"},o=w(t,e);if(o.length)if(o.filter(i=>i.type!=="number"||!i.isInteger).forEach(()=>{throw new Error("repeat node iteration counts must be integer values")}),o.length===1){if(r.iterations=o[0].value,r.iterations<0)throw new Error("a repeat node must have a positive number of iterations if defined")}else if(o.length===2){if(r.iterations=[o[0].value,o[1].value],r.iterations[0]<0||r.iterations[1]<0)throw new Error("a repeat node must have a positive minimum and maximum iteration count if defined");if(r.iterations[0]>r.iterations[1])throw new Error("a repeat node must not have a minimum iteration count that exceeds the maximum iteration count")}else throw new Error("invalid number of repeat node iteration count arguments defined");return r={...r,...p(t,e)},c(t,"{"),r}function Ht(t,e){let r={type:"retry"},o=w(t,e);if(o.length)if(o.filter(i=>i.type!=="number"||!i.isInteger).forEach(()=>{throw new Error("retry node attempt counts must be integer values")}),o.length===1){if(r.attempts=o[0].value,r.attempts<0)throw new Error("a retry node must have a positive number of attempts if defined")}else if(o.length===2){if(r.attempts=[o[0].value,o[1].value],r.attempts[0]<0||r.attempts[1]<0)throw new Error("a retry node must have a positive minimum and maximum attempt count if defined");if(r.attempts[0]>r.attempts[1])throw new Error("a retry node must not have a minimum attempt count that exceeds the maximum attempt count")}else throw new Error("invalid number of retry node attempt count arguments defined");return r={...r,...p(t,e)},c(t,"{"),r}function Kt(t,e){let r={type:"sequence",...p(t,e)};return c(t,"{"),r}function zt(t,e){let r={type:"selector",...p(t,e)};return c(t,"{"),r}function Xt(t,e){let r={type:"parallel",...p(t,e)};return c(t,"{"),r}function Zt(t,e){let r={type:"race",...p(t,e)};return c(t,"{"),r}function te(t,e){let r={type:"all",...p(t,e)};return c(t,"{"),r}function ee(t,e){let r=w(t,e);r.filter(i=>i.type!=="number"||!i.isInteger||i.value<0).forEach(()=>{throw new Error("lotto node weight arguments must be positive integer values")});let o={type:"lotto",...p(t,e)};return r.length&&(o.weights=r.map(({value:i})=>i)),c(t,"{"),o}function re(t,e){let[r,...o]=w(t,e);if(r?.type!=="identifier")throw new Error("expected action name identifier argument");return o.filter(i=>i.type==="identifier").forEach(i=>{throw new Error(`invalid action node argument value '${i.value}', must be string, number, boolean or null`)}),{type:"action",call:r.value,args:o.map(({value:i})=>i),...p(t,e)}}function oe(t,e){let[r,...o]=w(t,e);if(r?.type!=="identifier")throw new Error("expected condition name identifier argument");return o.filter(i=>i.type==="identifier").forEach(i=>{throw new Error(`invalid condition node argument value '${i.value}', must be string, number, boolean or null`)}),{type:"condition",call:r.value,args:o.map(({value:i})=>i),...p(t,e)}}function ie(t,e){let r={type:"wait"},o=w(t,e);if(o.length){if(o.filter(i=>i.type!=="number"||!i.isInteger).forEach(()=>{throw new Error("wait node durations must be integer values")}),o.length===1){if(r.duration=o[0].value,r.duration<0)throw new Error("a wait node must have a positive duration")}else if(o.length===2){if(r.duration=[o[0].value,o[1].value],r.duration[0]<0||r.duration[1]<0)throw new Error("a wait node must have a positive minimum and maximum duration");if(r.duration[0]>r.duration[1])throw new Error("a wait node must not have a minimum duration that exceeds the maximum duration")}else if(o.length>2)throw new Error("invalid number of wait node duration arguments defined")}return{...r,...p(t,e)}}function ne(t,e){let r=w(t,e);if(r.length!==1||r[0].type!=="identifier")throw new Error("expected single branch name argument");return{type:"branch",ref:r[0].value}}function ae(t){if(et(t)&&ot(t.child))throw new Error(`a ${t.type} node must have a single child node defined`);if(rt(t)&&!t.children?.length)throw new Error(`a ${t.type} node must have at least a single child node defined`);if(t.type==="lotto"&&typeof t.weights<"u"&&t.weights.length!==t.children.length)throw new Error("expected a number of weight arguments matching the number of child nodes for lotto node")}function it(t){return t===null||typeof t>"u"?A("definition is null or undefined"):typeof t=="string"?se(t):typeof t=="object"?nt(t):A(`unexpected definition type of '${typeof t}'`)}function se(t){let e;try{e=C(t)}catch(n){return A(n.message)}let r=e.filter(({id:n})=>typeof n>"u"),o=e.filter(({id:n})=>typeof n=="string"&&n.length>0);if(r.length!==1)return A("expected single unnamed root node at base of definition to act as main root");let i=[];for(let{id:n}of o){if(i.includes(n))return A(`multiple root nodes found with duplicate name '${n}'`);i.push(n)}try{at(e,!1)}catch(n){return A(n.message)}return{succeeded:!0,json:e}}function nt(t){let e=Array.isArray(t)?t:[t];try{e.forEach(n=>b(n,0))}catch(n){return n instanceof Error?A(n.message):A(`unexpected error: ${n}`)}let r=e.filter(({id:n})=>typeof n>"u"),o=e.filter(({id:n})=>typeof n=="string"&&n.length>0);if(r.length!==1)return A("expected single root node without 'id' property defined to act as main root");let i=[];for(let{id:n}of o){if(i.includes(n))return A(`multiple root nodes found with duplicate 'id' property value of '${n}'`);i.push(n)}try{at(e,!1)}catch(n){return A(n.message)}return{succeeded:!0,json:e}}function at(t,e){let r=t.map(i=>({id:i.id,refs:Dt(i).filter(At).map(({ref:n})=>n)})),o=(i,n=[])=>{if(n.includes(i.id)){let s=[...n,i.id].filter(d=>!!d).join(" => ");throw new Error(`circular dependency found in branch node references: ${s}`)}for(let a of i.refs){let s=r.find(({id:d})=>d===a);if(s)o(s,[...n,i.id]);else if(e)throw new Error(i.id?`subtree '${i.id}' has branch node that references root node '${a}' which has not been defined`:`primary tree has branch node that references root node '${a}' which has not been defined`)}};o(r.find(i=>typeof i.id>"u"))}function b(t,e){if(typeof t!="object"||typeof t.type!="string"||t.type.length===0)throw new Error(`node definition is not an object or 'type' property is not a non-empty string at depth '${e}'`);if(e===0&&t.type!=="root")throw new Error(`expected root node at base of definition but got node of type '${t.type}'`);switch(t.type){case"action":me(t,e);break;case"condition":ge(t,e);break;case"wait":be(t,e);break;case"branch":he(t,e);break;case"root":ue(t,e);break;case"succeed":de(t,e);break;case"fail":le(t,e);break;case"flip":ce(t,e);break;case"repeat":pe(t,e);break;case"retry":fe(t,e);break;case"sequence":ye(t,e);break;case"selector":Ne(t,e);break;case"parallel":we(t,e);break;case"race":Ae(t,e);break;case"all":Ee(t,e);break;case"lotto":De(t,e);break;default:throw new Error(`unexpected node type of '${t.type}' at depth '${e}'`)}}function f(t,e){["while","until","entry","exit","step"].forEach(r=>{let o=t[r];if(!(typeof o>"u")){if(typeof o!="object")throw new Error(`expected attribute '${r}' to be an object for '${t.type}' node at depth '${e}'`);if(typeof o.call!="string"||o.call.length===0)throw new Error(`expected 'call' property for attribute '${r}' to be a non-empty string for '${t.type}' node at depth '${e}'`);if(typeof o.args<"u"&&!Array.isArray(o.args))throw new Error(`expected 'args' property for attribute '${r}' to be an array for '${t.type}' node at depth '${e}'`)}})}function ue(t,e){if(t.type!=="root")throw new Error("expected node type of 'root' for root node");if(e>0)throw new Error("a root node cannot be the child of another node");if(typeof t.id<"u"&&(typeof t.id!="string"||t.id.length===0))throw new Error("expected non-empty string for 'id' property if defined for root node");if(typeof t.child>"u")throw new Error("expected property 'child' to be defined for root node");f(t,e),b(t.child,e+1)}function de(t,e){if(t.type!=="succeed")throw new Error(`expected node type of 'succeed' for succeed node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for succeed node at depth '${e}'`);f(t,e),b(t.child,e+1)}function le(t,e){if(t.type!=="fail")throw new Error(`expected node type of 'fail' for fail node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for fail node at depth '${e}'`);f(t,e),b(t.child,e+1)}function ce(t,e){if(t.type!=="flip")throw new Error(`expected node type of 'flip' for flip node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for flip node at depth '${e}'`);f(t,e),b(t.child,e+1)}function pe(t,e){if(t.type!=="repeat")throw new Error(`expected node type of 'repeat' for repeat node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for repeat node at depth '${e}'`);if(typeof t.iterations<"u")if(Array.isArray(t.iterations)){let r=!!t.iterations.filter(o=>!y(o)).length;if(t.iterations.length!==2||r)throw new Error(`expected array containing two integer values for 'iterations' property if defined for repeat node at depth '${e}'`);if(t.iterations[0]<0||t.iterations[1]<0)throw new Error(`expected positive minimum and maximum iterations count for 'iterations' property if defined for repeat node at depth '${e}'`);if(t.iterations[0]>t.iterations[1])throw new Error(`expected minimum iterations count that does not exceed the maximum iterations count for 'iterations' property if defined for repeat node at depth '${e}'`)}else if(y(t.iterations)){if(t.iterations<0)throw new Error(`expected positive iterations count for 'iterations' property if defined for repeat node at depth '${e}'`)}else throw new Error(`expected integer value or array containing two integer values for 'iterations' property if defined for repeat node at depth '${e}'`);f(t,e),b(t.child,e+1)}function fe(t,e){if(t.type!=="retry")throw new Error(`expected node type of 'retry' for retry node at depth '${e}'`);if(typeof t.child>"u")throw new Error(`expected property 'child' to be defined for retry node at depth '${e}'`);if(typeof t.attempts<"u")if(Array.isArray(t.attempts)){let r=!!t.attempts.filter(o=>!y(o)).length;if(t.attempts.length!==2||r)throw new Error(`expected array containing two integer values for 'attempts' property if defined for retry node at depth '${e}'`);if(t.attempts[0]<0||t.attempts[1]<0)throw new Error(`expected positive minimum and maximum attempts count for 'attempts' property if defined for retry node at depth '${e}'`);if(t.attempts[0]>t.attempts[1])throw new Error(`expected minimum attempts count that does not exceed the maximum attempts count for 'attempts' property if defined for retry node at depth '${e}'`)}else if(y(t.attempts)){if(t.attempts<0)throw new Error(`expected positive attempts count for 'attempts' property if defined for retry node at depth '${e}'`)}else throw new Error(`expected integer value or array containing two integer values for 'attempts' property if defined for retry node at depth '${e}'`);f(t,e),b(t.child,e+1)}function he(t,e){if(t.type!=="branch")throw new Error(`expected node type of 'branch' for branch node at depth '${e}'`);if(typeof t.ref!="string"||t.ref.length===0)throw new Error(`expected non-empty string for 'ref' property for branch node at depth '${e}'`);["while","until"].forEach(r=>{if(typeof t[r]<"u")throw new Error(`guards should not be defined for branch nodes but guard '${r}' was defined for branch node at depth '${e}'`)}),["entry","exit","step"].forEach(r=>{if(typeof t[r]<"u")throw new Error(`callbacks should not be defined for branch nodes but callback '${r}' was defined for branch node at depth '${e}'`)})}function me(t,e){if(t.type!=="action")throw new Error(`expected node type of 'action' for action node at depth '${e}'`);if(typeof t.call!="string"||t.call.length===0)throw new Error(`expected non-empty string for 'call' property of action node at depth '${e}'`);if(typeof t.args<"u"&&!Array.isArray(t.args))throw new Error(`expected array for 'args' property if defined for action node at depth '${e}'`);f(t,e)}function ge(t,e){if(t.type!=="condition")throw new Error(`expected node type of 'condition' for condition node at depth '${e}'`);if(typeof t.call!="string"||t.call.length===0)throw new Error(`expected non-empty string for 'call' property of condition node at depth '${e}'`);if(typeof t.args<"u"&&!Array.isArray(t.args))throw new Error(`expected array for 'args' property if defined for condition node at depth '${e}'`);f(t,e)}function be(t,e){if(t.type!=="wait")throw new Error(`expected node type of 'wait' for wait node at depth '${e}'`);if(typeof t.duration<"u")if(Array.isArray(t.duration)){let r=!!t.duration.filter(o=>!y(o)).length;if(t.duration.length!==2||r)throw new Error(`expected array containing two integer values for 'duration' property if defined for wait node at depth '${e}'`);if(t.duration[0]<0||t.duration[1]<0)throw new Error(`expected positive minimum and maximum duration for 'duration' property if defined for wait node at depth '${e}'`);if(t.duration[0]>t.duration[1])throw new Error(`expected minimum duration value that does not exceed the maximum duration value for 'duration' property if defined for wait node at depth '${e}'`)}else if(y(t.duration)){if(t.duration<0)throw new Error(`expected positive duration value for 'duration' property if defined for wait node at depth '${e}'`)}else throw new Error(`expected integer value or array containing two integer values for 'duration' property if defined for wait node at depth '${e}'`);f(t,e)}function ye(t,e){if(t.type!=="sequence")throw new Error(`expected node type of 'sequence' for sequence node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for sequence node at depth '${e}'`);f(t,e),t.children.forEach(r=>b(r,e+1))}function Ne(t,e){if(t.type!=="selector")throw new Error(`expected node type of 'selector' for selector node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for selector node at depth '${e}'`);f(t,e),t.children.forEach(r=>b(r,e+1))}function we(t,e){if(t.type!=="parallel")throw new Error(`expected node type of 'parallel' for parallel node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for parallel node at depth '${e}'`);f(t,e),t.children.forEach(r=>b(r,e+1))}function Ae(t,e){if(t.type!=="race")throw new Error(`expected node type of 'race' for race node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for race node at depth '${e}'`);f(t,e),t.children.forEach(r=>b(r,e+1))}function Ee(t,e){if(t.type!=="all")throw new Error(`expected node type of 'all' for all node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for all node at depth '${e}'`);f(t,e),t.children.forEach(r=>b(r,e+1))}function De(t,e){if(t.type!=="lotto")throw new Error(`expected node type of 'lotto' for lotto node at depth '${e}'`);if(!Array.isArray(t.children)||t.children.length===0)throw new Error(`expected non-empty 'children' array to be defined for lotto node at depth '${e}'`);if(typeof t.weights<"u"&&(!Array.isArray(t.weights)||t.weights.length!==t.children.length||t.weights.filter(r=>!y(r)).length||t.weights.filter(r=>r<0).length))throw new Error(`expected an array of positive integer weight values with a length matching the number of child nodes for 'weights' property if defined for lotto node at depth '${e}'`);f(t,e),t.children.forEach(r=>b(r,e+1))}function A(t){return{succeeded:!1,errorMessage:t}}var S=class extends Error{constructor(r){super("A guard path condition has failed");this.source=r}isSourceNode=r=>r===this.source};var T=class{constructor(e){this.nodes=e}evaluate=e=>{for(let r of this.nodes)for(let o of r.guards)if(!o.isSatisfied(e))throw new S(r.node)}};function xt(){var t=function(){return((1+Math.random())*65536|0).toString(16).substring(1)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}var E=class{constructor(e,r,o){this.type=e;this.options=o;this.uid=xt(),this.attributes={entry:r.find(({type:i})=>i==="entry"),step:r.find(({type:i})=>i==="step"),exit:r.find(({type:i})=>i==="exit"),while:r.find(({type:i})=>i==="while"),until:r.find(({type:i})=>i==="until")}}uid;attributes;_state="mistreevous.ready";_guardPath;getState=()=>this._state;setState=e=>{let r=this._state;this._state=e,r!==e&&this.onStateChanged(r)};getUid=()=>this.uid;getType=()=>this.type;getAttributes=()=>Object.values(this.attributes).filter(e=>!!e);setGuardPath=e=>this._guardPath=e;hasGuardPath=()=>!!this._guardPath;is(e){return this._state===e}reset(){this.setState("mistreevous.ready")}abort(e){!this.is("mistreevous.running")||(this.reset(),this.attributes.exit?.callAgentFunction(e,!1,!0))}update(e){if(!(this.is("mistreevous.succeeded")||this.is("mistreevous.failed")))try{this._guardPath.evaluate(e),this.is("mistreevous.ready")&&this.attributes.entry?.callAgentFunction(e),this.attributes.step?.callAgentFunction(e),this.onUpdate(e),(this.is("mistreevous.succeeded")||this.is("mistreevous.failed"))&&this.attributes.exit?.callAgentFunction(e,this.is("mistreevous.succeeded"),!1)}catch(r){if(r instanceof S&&r.isSourceNode(this))this.abort(e),this.setState("mistreevous.failed");else throw r}}getDetails(){return{id:this.uid,name:this.getName(),type:this.type,while:this.attributes.while?.getDetails(),until:this.attributes.until?.getDetails(),entry:this.attributes.entry?.getDetails(),step:this.attributes.step?.getDetails(),exit:this.attributes.exit?.getDetails(),state:this._state}}onStateChanged(e){this.options.onNodeStateChange?.({id:this.uid,type:this.type,while:this.attributes.while?.getDetails(),until:this.attributes.until?.getDetails(),entry:this.attributes.entry?.getDetails(),step:this.attributes.step?.getDetails(),exit:this.attributes.exit?.getDetails(),previousState:e,state:this._state})}};var h=class extends E{constructor(r,o,i,n){super(r,o,i);this.children=n}isLeafNode=()=>!1;getChildren=()=>this.children;reset=()=>{this.setState("mistreevous.ready"),this.children.forEach(r=>r.reset())};abort=r=>{!this.is("mistreevous.running")||(this.children.forEach(o=>o.abort(r)),this.reset(),this.attributes.exit?.callAgentFunction(r,!1,!0))};getDetails(){return{...super.getDetails(),children:this.children.map(r=>r.getDetails())}}};var L=class extends h{constructor(e,r,o){super("parallel",e,r,o)}onUpdate(e){for(let r of this.children)(r.getState()==="mistreevous.ready"||r.getState()==="mistreevous.running")&&r.update(e);if(this.children.find(r=>r.is("mistreevous.failed"))){this.setState("mistreevous.failed");for(let r of this.children)r.getState()==="mistreevous.running"&&r.abort(e);return}if(this.children.every(r=>r.is("mistreevous.succeeded"))){this.setState("mistreevous.succeeded");return}this.setState("mistreevous.running")}getName=()=>"PARALLEL"};var O=class extends h{constructor(e,r,o){super("race",e,r,o)}onUpdate(e){for(let r of this.children)(r.getState()==="mistreevous.ready"||r.getState()==="mistreevous.running")&&r.update(e);if(this.children.find(r=>r.is("mistreevous.succeeded"))){this.setState("mistreevous.succeeded");for(let r of this.children)r.getState()==="mistreevous.running"&&r.abort(e);return}if(this.children.every(r=>r.is("mistreevous.failed"))){this.setState("mistreevous.failed");return}this.setState("mistreevous.running")}getName=()=>"RACE"};var P=class extends h{constructor(e,r,o){super("all",e,r,o)}onUpdate(e){for(let r of this.children)(r.getState()==="mistreevous.ready"||r.getState()==="mistreevous.running")&&r.update(e);if(this.children.every(r=>r.is("mistreevous.succeeded")||r.is("mistreevous.failed"))){this.setState(this.children.find(r=>r.is("mistreevous.succeeded"))?"mistreevous.succeeded":"mistreevous.failed");return}this.setState("mistreevous.running")}getName=()=>"ALL"};var G=class extends h{constructor(r,o,i){super("selector",r,o,i);this.children=i}onUpdate(r){for(let o of this.children){if((o.getState()==="mistreevous.ready"||o.getState()==="mistreevous.running")&&o.update(r),o.getState()==="mistreevous.succeeded"){this.setState("mistreevous.succeeded");return}if(o.getState()==="mistreevous.failed")if(this.children.indexOf(o)===this.children.length-1){this.setState("mistreevous.failed");return}else continue;if(o.getState()==="mistreevous.running"){this.setState("mistreevous.running");return}throw new Error("child node was not in an expected state.")}}getName=()=>"SELECTOR"};var k=class extends h{constructor(r,o,i){super("sequence",r,o,i);this.children=i}onUpdate(r){for(let o of this.children){if((o.getState()==="mistreevous.ready"||o.getState()==="mistreevous.running")&&o.update(r),o.getState()==="mistreevous.succeeded")if(this.children.indexOf(o)===this.children.length-1){this.setState("mistreevous.succeeded");return}else continue;if(o.getState()==="mistreevous.failed"){this.setState("mistreevous.failed");return}if(o.getState()==="mistreevous.running"){this.setState("mistreevous.running");return}throw new Error("child node was not in an expected state.")}}getName=()=>"SEQUENCE"};var Ft=Bt($t());var B=class extends h{constructor(r,o,i,n){super("lotto",r,o,n);this.weights=i}selectedChild;onUpdate(r){if(this.is("mistreevous.ready")){let o=(0,Ft.default)({random:this.options.random,participants:this.children.map((i,n)=>[i,this.weights?.[n]||1])});this.selectedChild=o.draw()||void 0}if(!this.selectedChild)throw new Error("failed to update lotto node as it has no active child");(this.selectedChild.getState()==="mistreevous.ready"||this.selectedChild.getState()==="mistreevous.running")&&this.selectedChild.update(r),this.setState(this.selectedChild.getState())}getName=()=>this.weights?`LOTTO [${this.weights.join(",")}]`:"LOTTO"};var m=class extends E{constructor(r,o,i,n){super(r,o,i);this.child=n}isLeafNode=()=>!1;getChildren=()=>[this.child];reset=()=>{this.setState("mistreevous.ready"),this.child.reset()};abort=r=>{!this.is("mistreevous.running")||(this.child.abort(r),this.reset(),this.attributes.exit?.callAgentFunction(r,!1,!0))};getDetails(){return{...super.getDetails(),children:[this.child.getDetails()]}}};var _=class extends m{constructor(e,r,o){super("fail",e,r,o)}onUpdate(e){switch((this.child.getState()==="mistreevous.ready"||this.child.getState()==="mistreevous.running")&&this.child.update(e),this.child.getState()){case"mistreevous.running":this.setState("mistreevous.running");break;case"mistreevous.succeeded":case"mistreevous.failed":this.setState("mistreevous.failed");break;default:this.setState("mistreevous.ready")}}getName=()=>"FAIL"};var Y=class extends m{constructor(e,r,o){super("flip",e,r,o)}onUpdate(e){switch((this.child.getState()==="mistreevous.ready"||this.child.getState()==="mistreevous.running")&&this.child.update(e),this.child.getState()){case"mistreevous.running":this.setState("mistreevous.running");break;case"mistreevous.succeeded":this.setState("mistreevous.failed");break;case"mistreevous.failed":this.setState("mistreevous.succeeded");break;default:this.setState("mistreevous.ready")}}getName=()=>"FLIP"};var j=class extends m{constructor(r,o,i,n,a,s){super("repeat",r,o,s);this.iterations=i;this.iterationsMin=n;this.iterationsMax=a}targetIterationCount=null;currentIterationCount=0;onUpdate(r){if(this.is("mistreevous.ready")&&(this.child.reset(),this.currentIterationCount=0,this.setTargetIterationCount()),this.canIterate())if(this.setState("mistreevous.running"),this.child.getState()==="mistreevous.succeeded"&&this.child.reset(),this.child.update(r),this.child.getState()==="mistreevous.failed"){this.setState("mistreevous.failed");return}else this.child.getState()==="mistreevous.succeeded"&&(this.currentIterationCount+=1);else this.setState("mistreevous.succeeded")}getName=()=>this.iterations!==null?`REPEAT ${this.iterations}x`:this.iterationsMin!==null&&this.iterationsMax!==null?`REPEAT ${this.iterationsMin}x-${this.iterationsMax}x`:"REPEAT";reset=()=>{this.setState("mistreevous.ready"),this.currentIterationCount=0,this.child.reset()};canIterate=()=>this.targetIterationCount!==null?this.currentIterationCount{if(this.iterations!==null)this.targetIterationCount=this.iterations;else if(this.iterationsMin!==null&&this.iterationsMax!==null){let r=typeof this.options.random=="function"?this.options.random:Math.random;this.targetIterationCount=Math.floor(r()*(this.iterationsMax-this.iterationsMin+1)+this.iterationsMin)}else this.targetIterationCount=null}};var q=class extends m{constructor(r,o,i,n,a,s){super("retry",r,o,s);this.attempts=i;this.attemptsMin=n;this.attemptsMax=a}targetAttemptCount=null;currentAttemptCount=0;onUpdate(r){if(this.is("mistreevous.ready")&&(this.child.reset(),this.currentAttemptCount=0,this.setTargetAttemptCount()),this.canAttempt())if(this.setState("mistreevous.running"),this.child.getState()==="mistreevous.failed"&&this.child.reset(),this.child.update(r),this.child.getState()==="mistreevous.succeeded"){this.setState("mistreevous.succeeded");return}else this.child.getState()==="mistreevous.failed"&&(this.currentAttemptCount+=1);else this.setState("mistreevous.failed")}getName=()=>this.attempts!==null?`RETRY ${this.attempts}x`:this.attemptsMin!==null&&this.attemptsMax!==null?`RETRY ${this.attemptsMin}x-${this.attemptsMax}x`:"RETRY";reset=()=>{this.setState("mistreevous.ready"),this.currentAttemptCount=0,this.child.reset()};canAttempt=()=>this.targetAttemptCount!==null?this.currentAttemptCount{if(this.attempts!==null)this.targetAttemptCount=this.attempts;else if(this.attemptsMin!==null&&this.attemptsMax!==null){let r=typeof this.options.random=="function"?this.options.random:Math.random;this.targetAttemptCount=Math.floor(r()*(this.attemptsMax-this.attemptsMin+1)+this.attemptsMin)}else this.targetAttemptCount=null}};var W=class extends m{constructor(e,r,o){super("root",e,r,o)}onUpdate(e){(this.child.getState()==="mistreevous.ready"||this.child.getState()==="mistreevous.running")&&this.child.update(e),this.setState(this.child.getState())}getName=()=>"ROOT"};var J=class extends m{constructor(e,r,o){super("succeed",e,r,o)}onUpdate(e){switch((this.child.getState()==="mistreevous.ready"||this.child.getState()==="mistreevous.running")&&this.child.update(e),this.child.getState()){case"mistreevous.running":this.setState("mistreevous.running");break;case"mistreevous.succeeded":case"mistreevous.failed":this.setState("mistreevous.succeeded");break;default:this.setState("mistreevous.ready")}}getName=()=>"SUCCEED"};var D=class extends E{isLeafNode=()=>!0};var V=class extends D{constructor(r,o,i,n){super("action",r,o);this.actionName=i;this.actionArguments=n}isUsingUpdatePromise=!1;updatePromiseResult=null;onUpdate(r){if(this.isUsingUpdatePromise){if(!this.updatePromiseResult)return;let{isResolved:n,value:a}=this.updatePromiseResult;if(n){if(a!=="mistreevous.succeeded"&&a!=="mistreevous.failed")throw new Error("action node promise resolved with an invalid value, expected a State.SUCCEEDED or State.FAILED value to be returned");this.setState(a);return}else throw new Error(`action function '${this.actionName}' promise rejected with '${a}'`)}let o=u.getFuncInvoker(r,this.actionName);if(o===null)throw new Error(`cannot update action node as the action '${this.actionName}' function is not defined on the agent and has not been registered`);let i;try{i=o(this.actionArguments)}catch(n){throw n instanceof Error?new Error(`action function '${this.actionName}' threw: ${n.stack}`):new Error(`action function '${this.actionName}' threw: ${n}`)}i instanceof Promise?(i.then(n=>{!this.isUsingUpdatePromise||(this.updatePromiseResult={isResolved:!0,value:n})},n=>{!this.isUsingUpdatePromise||(this.updatePromiseResult={isResolved:!1,value:n})}),this.setState("mistreevous.running"),this.isUsingUpdatePromise=!0):(this.validateUpdateResult(i),this.setState(i||"mistreevous.running"))}getName=()=>this.actionName;reset=()=>{this.setState("mistreevous.ready"),this.isUsingUpdatePromise=!1,this.updatePromiseResult=null};getDetails(){return{...super.getDetails(),args:this.actionArguments}}onStateChanged(r){this.options.onNodeStateChange?.({id:this.uid,type:this.getType(),args:this.actionArguments,while:this.attributes.while?.getDetails(),until:this.attributes.until?.getDetails(),entry:this.attributes.entry?.getDetails(),step:this.attributes.step?.getDetails(),exit:this.attributes.exit?.getDetails(),previousState:r,state:this.getState()})}validateUpdateResult=r=>{switch(r){case"mistreevous.succeeded":case"mistreevous.failed":case"mistreevous.running":case void 0:return;default:throw new Error(`expected action function '${this.actionName}' to return an optional State.SUCCEEDED or State.FAILED value but returned '${r}'`)}}};var Q=class extends D{constructor(r,o,i,n){super("condition",r,o);this.conditionName=i;this.conditionArguments=n}onUpdate(r){let o=u.getFuncInvoker(r,this.conditionName);if(o===null)throw new Error(`cannot update condition node as the condition '${this.conditionName}' function is not defined on the agent and has not been registered`);let i;try{i=o(this.conditionArguments)}catch(n){throw n instanceof Error?new Error(`condition function '${this.conditionName}' threw: ${n.stack}`):new Error(`condition function '${this.conditionName}' threw: ${n}`)}if(typeof i!="boolean")throw new Error(`expected condition function '${this.conditionName}' to return a boolean but returned '${i}'`);this.setState(i?"mistreevous.succeeded":"mistreevous.failed")}getName=()=>this.conditionName;getDetails(){return{...super.getDetails(),args:this.conditionArguments}}onStateChanged(r){this.options.onNodeStateChange?.({id:this.uid,type:this.getType(),args:this.conditionArguments,while:this.attributes.while?.getDetails(),until:this.attributes.until?.getDetails(),entry:this.attributes.entry?.getDetails(),step:this.attributes.step?.getDetails(),exit:this.attributes.exit?.getDetails(),previousState:r,state:this.getState()})}};var H=class extends D{constructor(r,o,i,n,a){super("wait",r,o);this.duration=i;this.durationMin=n;this.durationMax=a}initialUpdateTime=0;totalDuration=null;waitedDuration=0;onUpdate(r){if(this.is("mistreevous.ready")){if(this.initialUpdateTime=new Date().getTime(),this.waitedDuration=0,this.duration!==null)this.totalDuration=this.duration;else if(this.durationMin!==null&&this.durationMax!==null){let o=typeof this.options.random=="function"?this.options.random:Math.random;this.totalDuration=Math.floor(o()*(this.durationMax-this.durationMin+1)+this.durationMin)}else this.totalDuration=null;this.setState("mistreevous.running")}if(this.totalDuration!==null){if(typeof this.options.getDeltaTime=="function"){let o=this.options.getDeltaTime();if(typeof o!="number"||isNaN(o))throw new Error("The delta time must be a valid number and not NaN.");this.waitedDuration+=o*1e3}else this.waitedDuration=new Date().getTime()-this.initialUpdateTime;this.waitedDuration>=this.totalDuration&&this.setState("mistreevous.succeeded")}}getName=()=>this.duration!==null?`WAIT ${this.duration}ms`:this.durationMin!==null&&this.durationMax!==null?`WAIT ${this.durationMin}ms-${this.durationMax}ms`:"WAIT"};var x=class{constructor(e,r){this.type=e;this.args=r}};var R=class extends x{constructor(r,o,i){super(r,o);this.condition=i}getCondition=()=>this.condition;isGuard=()=>!0;getDetails(){return{type:this.type,args:this.args,calls:this.getCondition()}}};var K=class extends R{constructor(e,r){super("while",r,e)}isSatisfied=e=>{let r=u.getFuncInvoker(e,this.getCondition());if(r===null)throw new Error(`cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`);let o;try{o=r(this.args)}catch(i){throw i instanceof Error?new Error(`guard condition function '${this.getCondition()}' threw: ${i.stack}`):new Error(`guard condition function '${this.getCondition()}' threw: ${i}`)}if(typeof o!="boolean")throw new Error(`expected guard condition function '${this.getCondition()}' to return a boolean but returned '${o}'`);return o}};var z=class extends R{constructor(e,r){super("until",r,e)}isSatisfied=e=>{let r=u.getFuncInvoker(e,this.getCondition());if(r===null)throw new Error(`cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`);let o;try{o=r(this.args)}catch(i){throw i instanceof Error?new Error(`guard condition function '${this.getCondition()}' threw: ${i.stack}`):new Error(`guard condition function '${this.getCondition()}' threw: ${i}`)}if(typeof o!="boolean")throw new Error(`expected guard condition function '${this.getCondition()}' to return a boolean but returned '${o}'`);return!o}};var v=class extends x{constructor(r,o,i){super(r,o);this.functionName=i}getFunctionName=()=>this.functionName;isGuard=()=>!1;getDetails(){return{type:this.type,args:this.args,calls:this.getFunctionName()}}};var X=class extends v{constructor(e,r){super("entry",r,e)}callAgentFunction=e=>{let r=u.getFuncInvoker(e,this.getFunctionName());if(r===null)throw new Error(`cannot call entry function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`);r(this.args)}};var Z=class extends v{constructor(e,r){super("step",r,e)}callAgentFunction=e=>{let r=u.getFuncInvoker(e,this.getFunctionName());if(r===null)throw new Error(`cannot call step function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`);r(this.args)}};var tt=class extends v{constructor(e,r){super("exit",r,e)}callAgentFunction=(e,r,o)=>{let i=u.getFuncInvoker(e,this.getFunctionName());if(i===null)throw new Error(`cannot call exit function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`);i([{succeeded:r,aborted:o},...this.args])}};var ht=Symbol("__root__");function mt(t,e){let r=Fe(t);at([r[ht],...Object.values(r)],!0);let o=g(r[ht],r,e);return Te(o),o}function g(t,e,r){let o=$e(t);switch(t.type){case"root":return new W(o,r,g(t.child,e,r));case"repeat":let i=null,n=null,a=null;return Array.isArray(t.iterations)?(n=t.iterations[0],a=t.iterations[1]):y(t.iterations)&&(i=t.iterations),new j(o,r,i,n,a,g(t.child,e,r));case"retry":let s=null,d=null,U=null;return Array.isArray(t.attempts)?(d=t.attempts[0],U=t.attempts[1]):y(t.attempts)&&(s=t.attempts),new q(o,r,s,d,U,g(t.child,e,r));case"flip":return new Y(o,r,g(t.child,e,r));case"succeed":return new J(o,r,g(t.child,e,r));case"fail":return new _(o,r,g(t.child,e,r));case"sequence":return new k(o,r,t.children.map(N=>g(N,e,r)));case"selector":return new G(o,r,t.children.map(N=>g(N,e,r)));case"parallel":return new L(o,r,t.children.map(N=>g(N,e,r)));case"race":return new O(o,r,t.children.map(N=>g(N,e,r)));case"all":return new P(o,r,t.children.map(N=>g(N,e,r)));case"lotto":return new B(o,r,t.weights,t.children.map(N=>g(N,e,r)));case"branch":return g(e[t.ref].child,e,r);case"action":return new V(o,r,t.call,t.args||[]);case"condition":return new Q(o,r,t.call,t.args||[]);case"wait":let gt=null,bt=null,yt=null;return Array.isArray(t.duration)?(bt=t.duration[0],yt=t.duration[1]):y(t.duration)&&(gt=t.duration),new H(o,r,gt,bt,yt)}}function $e(t){let e=[];return t.while&&e.push(new K(t.while.call,t.while.args??[])),t.until&&e.push(new z(t.until.call,t.until.args??[])),t.entry&&e.push(new X(t.entry.call,t.entry.args??[])),t.step&&e.push(new Z(t.step.call,t.step.args??[])),t.exit&&e.push(new tt(t.exit.call,t.exit.args??[])),e}function Fe(t){let e={};for(let[r,o]of Object.entries(u.getSubtrees()))e[r]={...o,id:r};for(let r of t)e[r.id??ht]=r;return e}function Te(t){let e=[],r=(o,i)=>{o=o.concat(i),i.isLeafNode()?e.push(o):i.getChildren().forEach(n=>r(o,n))};r([],t),e.forEach(o=>{for(let i=0;i({node:s,guards:s.getAttributes().filter(d=>d.isGuard())})).filter(s=>s.guards.length>0));n.setGuardPath(a)}})}var lt=class{constructor(e,r,o={}){this.agent=r;this.options=o;if(ot(e))throw new Error("tree definition not defined");if(typeof r!="object"||r===null)throw new Error("the agent must be an object and not null");let{succeeded:i,errorMessage:n,json:a}=it(e);if(!i)throw new Error(`invalid definition: ${n}`);if(!a)throw new Error("expected json definition to be returned as part of successful definition validation response");try{this._rootNode=mt(a,o)}catch(s){throw new Error(`error building tree: ${s.message}`)}}_rootNode;isRunning(){return this._rootNode.getState()==="mistreevous.running"}getState(){return this._rootNode.getState()}step(){(this._rootNode.getState()==="mistreevous.succeeded"||this._rootNode.getState()==="mistreevous.failed")&&this._rootNode.reset();try{this._rootNode.update(this.agent)}catch(e){throw new Error(`error stepping tree: ${e.message}`)}}reset(){this._rootNode.reset()}getTreeNodeDetails(){return this._rootNode.getDetails()}static register(e,r){if(typeof r=="function"){u.setFunc(e,r);return}if(typeof r=="string"){let o;try{o=C(r)}catch(i){throw new Error(`error registering definition, invalid MDSL: ${i.message}`)}if(o.length!=1||typeof o[0].id<"u")throw new Error("error registering definition: expected a single unnamed root node");try{let{succeeded:i,errorMessage:n}=nt(o[0]);if(!i)throw new Error(n)}catch(i){throw new Error(`error registering definition: ${i.message}`)}u.setSubtree(e,o[0])}else if(typeof r=="object"&&!Array.isArray(r)){try{let{succeeded:o,errorMessage:i}=nt(r);if(!o)throw new Error(i)}catch(o){throw new Error(`error registering definition: ${o.message}`)}u.setSubtree(e,r)}else throw new Error("unexpected value, expected string mdsl definition, root node json definition or function")}static unregister(e){u.remove(e)}static unregisterAll(){u.empty()}};return _t(Le);})(); //# sourceMappingURL=mistreevous.min.js.map diff --git a/dist/mistreevous.min.js.map b/dist/mistreevous.min.js.map index b016e6c..42d673b 100644 --- a/dist/mistreevous.min.js.map +++ b/dist/mistreevous.min.js.map @@ -1,7 +1,7 @@ { "version": 3, - "sources": ["../node_modules/lotto-draw/dist/Participant.js", "../node_modules/lotto-draw/dist/Utilities.js", "../node_modules/lotto-draw/dist/Lotto.js", "../node_modules/lotto-draw/dist/createLotto.js", "../node_modules/lotto-draw/dist/index.js", "../src/index.ts", "../src/State.ts", "../src/Lookup.ts", "../src/BehaviourTreeDefinitionUtilities.ts", "../src/mdsl/MDSLUtilities.ts", "../src/mdsl/MDSLNodeArgumentParser.ts", "../src/mdsl/MDSLNodeAttributeParser.ts", "../src/mdsl/MDSLDefinitionParser.ts", "../src/BehaviourTreeDefinitionValidator.ts", "../src/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/Utilities.ts", "../src/nodes/Node.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Parallel.ts", "../src/nodes/composite/Race.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/leaf/Leaf.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/attributes/Attribute.ts", "../src/attributes/guards/Guard.ts", "../src/attributes/guards/While.ts", "../src/attributes/guards/Until.ts", "../src/attributes/callbacks/Callback.ts", "../src/attributes/callbacks/Entry.ts", "../src/attributes/callbacks/Step.ts", "../src/attributes/callbacks/Exit.ts", "../src/BehaviourTreeBuilder.ts", "../src/BehaviourTree.ts"], - "sourcesContent": ["\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Participant = void 0;\r\n/**\r\n * A participant that holds a number of tickets.\r\n */\r\nvar Participant = /** @class */ (function () {\r\n /**\r\n * Creates an instance of the Participant class.\r\n * @param participant The actual participant.\r\n * @param tickets The number of tickets held by the participant.\r\n */\r\n function Participant(participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n this._participant = participant;\r\n this._tickets = tickets;\r\n }\r\n Object.defineProperty(Participant.prototype, \"participant\", {\r\n /** Gets the actual participant. */\r\n get: function () {\r\n return this._participant;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(Participant.prototype, \"tickets\", {\r\n /** Gets or sets the number of tickets held by the participant. */\r\n get: function () {\r\n return this._tickets;\r\n },\r\n set: function (value) {\r\n this._tickets = value;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n return Participant;\r\n}());\r\nexports.Participant = Participant;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.isNaturalNumber = exports.isNullOrUndefined = void 0;\r\n/**\r\n * Gets whether the value provided is null or undefined.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is null or undefined.\r\n */\r\nfunction isNullOrUndefined(value) {\r\n return value === null || value === undefined;\r\n}\r\nexports.isNullOrUndefined = isNullOrUndefined;\r\n/**\r\n * Gets whether the value provided is a natural number.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is a natural number.\r\n */\r\nfunction isNaturalNumber(value) {\r\n return typeof value === \"number\" && value >= 1 && Math.floor(value) === value;\r\n}\r\nexports.isNaturalNumber = isNaturalNumber;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Lotto = void 0;\r\nvar Participant_1 = require(\"./Participant\");\r\nvar Utilities_1 = require(\"./Utilities\");\r\n/**\r\n * Represents a lotto consisting of a number of pickable ticket-holding participants.\r\n */\r\nvar Lotto = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of Lotto.\r\n * @param customRandom The custom RNG to use in place of Math.random().\r\n */\r\n function Lotto(customRandom) {\r\n /** The array of participants that are holding tickets in the lotto. */\r\n this._participants = [];\r\n this._customRandom = customRandom;\r\n }\r\n /**\r\n * Adds a participant with the specified number of tickets, or adds to the participant ticket count if the participant already holds tickets.\r\n * @param participant The participant to add or to increase the ticket count for if they already hold tickets.\r\n * @param tickets The number of tickets, defaults to 1.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.add = function (participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n // Check whether this participant has already been added.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n if (existingParticipant) {\r\n // The participant has already been added to the lotto so just add to their ticket count.\r\n existingParticipant.tickets += tickets;\r\n }\r\n else {\r\n // The participant is not part of the lotto so we should add them.\r\n this._participants.push(new Participant_1.Participant(participant, tickets));\r\n }\r\n return this;\r\n };\r\n /**\r\n * Removes the specified number of tickets for the given participant from the draw, or all tickets if a ticket number is not defined.\r\n * @param participant The participant to remove tickets for.\r\n * @param tickets The number of tickets to remove, or undefined if all tickets are to be removed.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.remove = function (participant, tickets) {\r\n // Attempt to get the existing participant.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n // There is nothing to do if the specified participant isn't even part of the lotto.\r\n if (!existingParticipant) {\r\n return this;\r\n }\r\n // Check whether a tickets value was given.\r\n if (tickets !== undefined) {\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n existingParticipant.tickets -= tickets;\r\n // If the participant no longer holds any tickets then they should be removed.\r\n if (existingParticipant.tickets < 1) {\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n }\r\n else {\r\n // We are removing all tickets for the participant so just remove them from the lotto.\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n return this;\r\n };\r\n /**\r\n * Draw a winning ticket and return the participant that holds the ticket.\r\n * @param options The draw options.\r\n * @returns The participant that holds the winning ticket.\r\n */\r\n Lotto.prototype.draw = function (options) {\r\n if (options === void 0) { options = {}; }\r\n // If we have no participants then just return null.\r\n if (this._participants.length === 0) {\r\n return null;\r\n }\r\n var redrawable = (0, Utilities_1.isNullOrUndefined)(options.redrawable) ? true : options.redrawable;\r\n var pickable = [];\r\n this._participants.forEach(function (_a) {\r\n var participant = _a.participant, tickets = _a.tickets;\r\n for (var ticketCount = 0; ticketCount < tickets; ticketCount++) {\r\n pickable.push(participant);\r\n }\r\n });\r\n var random;\r\n // We need a random floating-point number between 0 (inclusive) and 1 to scale up to pick our winner.\r\n // If a custom random function exists then we should use that or fall back to Math.random().\r\n if (this._customRandom) {\r\n // Call our custom random function to get a random floating-point number.\r\n random = this._customRandom();\r\n // Verify that the result of calling our custom random function is a number between 0 (inclusive) and 1.\r\n if (typeof random !== \"number\" || random < 0 || random >= 1) {\r\n throw new Error(\"the 'random' function provided did not return a number between 0 (inclusive) and 1\");\r\n }\r\n }\r\n else {\r\n // No custom random function was defined so just use good ol' Math.random().\r\n random = Math.random();\r\n }\r\n // Pick a winning participant.\r\n var winner = pickable[Math.floor(random * pickable.length)];\r\n // If the ticket isn't redrawable then we should remove a ticket from the winning participants ticket count.\r\n if (!redrawable) {\r\n this.remove(winner, 1);\r\n }\r\n // Return the winning participant.\r\n return winner;\r\n };\r\n /**\r\n * Draws multiple winning tickets and return an array of the participants that hold the winning tickets.\r\n * @param tickets The number of winning tickets to draw.\r\n * @param options The draw multiple options.\r\n * @returns An array of the participants that hold the winning tickets.\r\n */\r\n Lotto.prototype.drawMultiple = function (tickets, options) {\r\n if (options === void 0) { options = {}; }\r\n var uniqueResults = (0, Utilities_1.isNullOrUndefined)(options.unique) ? false : options.unique;\r\n // Handle cases where the user has asked for zero tickets (no idea why they would do this be we should trust them).\r\n if (tickets === 0) {\r\n return [];\r\n }\r\n // Now that we know out tickets value is not zero we should check that it is a valid natural number.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n var result = [];\r\n // Keep drawing tickets until we either reach the number of required tickets or we simply run out of tickets to draw.\r\n // We can run out of tickets to draw if 'options.redrawable' is explicity 'false' or we just had no participants when 'drawMultiple' was called.\r\n while (result.length < tickets && this._participants.length > 0) {\r\n result.push(this.draw(options));\r\n }\r\n // If the 'unique' draw option is set then we need to remove duplicates from the result list.\r\n if (uniqueResults) {\r\n // Create an array to store our unique results.\r\n var unique = [];\r\n // Iterate over all of our participants (with potential duplicates) and populate our array of unique values.\r\n for (var _i = 0, result_1 = result; _i < result_1.length; _i++) {\r\n var participant = result_1[_i];\r\n if (unique.indexOf(participant) === -1) {\r\n unique.push(participant);\r\n }\r\n }\r\n result = unique;\r\n }\r\n return result;\r\n };\r\n return Lotto;\r\n}());\r\nexports.Lotto = Lotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.createLotto = void 0;\r\nvar Lotto_1 = require(\"./Lotto\");\r\n/**\r\n * A function that creates and returns a Lotto instance.\r\n * @param participantsOrOptions An array of initial participants or options relating to the creation of a Lotto instance.\r\n * @returns A new Lotto instance.\r\n */\r\nfunction createLotto(participantsOrOptions) {\r\n // If no initial participants or lotto options were provided as an argument then we can just return a new lotto instance now.\r\n if (!participantsOrOptions) {\r\n return new Lotto_1.Lotto();\r\n }\r\n // Check whether we were provided with an array of initial participants or a lotto options object.\r\n if (Array.isArray(participantsOrOptions)) {\r\n // We are dealing with a pre-defined array of participants.\r\n var participants = participantsOrOptions;\r\n var lotto_1 = new Lotto_1.Lotto();\r\n // If the lotto participants have been defined upfront then we will need to add them all to our lotto instance now.\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_1.add(participant, tokens);\r\n });\r\n // Return the Lotto instance.\r\n return lotto_1;\r\n }\r\n else {\r\n // We are dealing with some lotto options.\r\n var random = participantsOrOptions.random, participants = participantsOrOptions.participants;\r\n // Create a Lotto instance passing the custom RNG function to use in place of Math.random() (which could be undefined).\r\n var lotto_2 = new Lotto_1.Lotto(random);\r\n // If the lotto participants have been defined upfront as part of the options then we will need to add them all to our lotto instance now.\r\n if (participants) {\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_2.add(participant, tokens);\r\n });\r\n }\r\n // Return the Lotto instance.\r\n return lotto_2;\r\n }\r\n}\r\nexports.createLotto = createLotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar createLotto_1 = require(\"./createLotto\");\r\nexports.default = createLotto_1.createLotto;\r\n", "import State from \"./State\";\nimport { BehaviourTree } from \"./BehaviourTree\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { NodeDetails, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n /**\n * The state that a node will be in when it has not been visited yet in the execution of the tree.\n */\n READY = \"mistreevous.ready\",\n /**\n * The state that a node will be in when it is still being processed and will usually represent or encompass a long-running action.\n */\n RUNNING = \"mistreevous.running\",\n /**\n * The state that a node will be in when it is no longer being processed and has succeeded.\n */\n SUCCEEDED = \"mistreevous.succeeded\",\n /**\n * The state that a node will be in when it is no longer being processed but has failed.\n */\n FAILED = \"mistreevous.failed\"\n}\n\nexport { State as default };\n\nexport type CompleteState = State.SUCCEEDED | State.FAILED;\nexport type AnyState = State.READY | State.RUNNING | CompleteState;\n", "import { ActionResult, Agent, GlobalFunction } from \"./Agent\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\n\nexport type InvokerFunction = (args: any[]) => ActionResult | boolean;\n\n/**\n * A singleton used to store and lookup registered functions and subtrees.\n */\nexport default class Lookup {\n /**\n * The object holding any registered functions keyed on function name.\n */\n private static registeredFunctions: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered subtree root node definitions keyed on tree name.\n */\n private static registeredSubtrees: { [key: string]: RootNodeDefinition } = {};\n\n /**\n * Gets the function with the specified name.\n * @param name The name of the function.\n * @returns The function with the specified name.\n */\n public static getFunc(name: string): GlobalFunction {\n return this.registeredFunctions[name];\n }\n\n /**\n * Sets the function with the specified name for later lookup.\n * @param name The name of the function.\n * @param func The function.\n */\n public static setFunc(name: string, func: GlobalFunction): void {\n this.registeredFunctions[name] = func;\n }\n\n /**\n * Gets the function invoker for the specified agent and function name.\n * If a function with the specified name exists on the agent object then it will\n * be returned, otherwise we will then check the registered functions for a match.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param name The function name.\n * @returns The function invoker for the specified agent and function name.\n */\n static getFuncInvoker(agent: Agent, name: string): InvokerFunction | null {\n // Check whether the agent contains the specified function.\n const agentFunction = agent[name];\n if (agentFunction && typeof agentFunction === \"function\") {\n return (args: any[]) => agentFunction.apply(agent, args);\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.registeredFunctions[name] && typeof this.registeredFunctions[name] === \"function\") {\n const registeredFunction = this.registeredFunctions[name];\n return (args: any[]) => registeredFunction(agent, ...args);\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets all registered subtree root node definitions.\n */\n static getSubtrees(): { [key: string]: RootNodeDefinition } {\n return this.registeredSubtrees;\n }\n\n /**\n * Sets the subtree with the specified name for later lookup.\n * @param name The name of the subtree.\n * @param subtree The subtree.\n */\n static setSubtree(name: string, subtree: RootNodeDefinition) {\n this.registeredSubtrees[name] = subtree;\n }\n\n /**\n * Removes the registered function or subtree with the specified name.\n * @param name The name of the registered function or subtree.\n */\n static remove(name: string) {\n delete this.registeredFunctions[name];\n delete this.registeredSubtrees[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.registeredFunctions = {};\n this.registeredSubtrees = {};\n }\n}\n", "import {\n NodeDefinition,\n RootNodeDefinition,\n DecoratorNodeDefinition,\n CompositeNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition\n} from \"./BehaviourTreeDefinition\";\n\n/**\n * A type guard function that returns true if the specified node satisfies the RootNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the RootNodeDefinition type.\n */\nexport function isRootNode(node: NodeDefinition): node is RootNodeDefinition {\n return node.type === \"root\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the BranchNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the BranchNodeDefinition type.\n */\nexport function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition {\n return node.type === \"branch\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the NodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the NodeDefinition type.\n */\nexport function isLeafNode(node: NodeDefinition): node is NodeDefinition {\n return [\"branch\", \"action\", \"condition\", \"wait\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the DecoratorNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the DecoratorNodeDefinition type.\n */\nexport function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefinition {\n return [\"root\", \"repeat\", \"retry\", \"flip\", \"succeed\", \"fail\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the CompositeNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type.\n */\nexport function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition {\n return [\"sequence\", \"selector\", \"lotto\", \"parallel\", \"race\"].includes(node.type);\n}\n\n/**\n * Flatten a node definition into an array of all of its nested node definitions.\n * @param nodeDefinition The node definition to flatten.\n * @returns An array of all of nested node definitions.\n */\nexport function flattenDefinition(nodeDefinition: AnyNodeDefinition): AnyNodeDefinition[] {\n const nodes: AnyNodeDefinition[] = [];\n\n const processNode = (currentNodeDefinition: AnyNodeDefinition) => {\n nodes.push(currentNodeDefinition);\n\n if (isCompositeNode(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNode(currentNodeDefinition)) {\n processNode(currentNodeDefinition.child);\n }\n };\n\n processNode(nodeDefinition);\n\n return nodes;\n}\n\n/**\n * Determines whether the passed value is an integer.\n * @param value The value to check.\n * @returns Whether the passed value is an integer.\n */\nexport function isInteger(value: unknown): boolean {\n return typeof value === \"number\" && Math.floor(value) === value;\n}\n\n/**\n * Determines whether the passed value is null or undefined.\n * @param value The value to check.\n * @returns Whether the passed value is null or undefined.\n */\nexport function isNullOrUndefined(value: unknown): boolean {\n return typeof value === \"undefined\" || value === null;\n}\n", "/**\n * A type defining an object that holds a reference to substitued string literals parsed from the definition.\n */\nexport type StringLiteralPlaceholders = { [key: string]: string };\n\n/**\n * Pop the next raw token from the specified array of tokens and throw an error if it wasn't the expected one.\n * @param tokens The array of tokens.\n * @param expected An optional string or array or items, one of which must match the next popped token.\n * @returns The popped token.\n */\nexport function popAndCheck(tokens: string[], expected?: string | string[]): string {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token but there aren't any.\n if (popped === undefined) {\n throw new Error(\"unexpected end of definition\");\n }\n\n // Do we have an expected token/tokens array?\n if (expected != undefined) {\n // Get an array of expected values, if the popped token matches any then we are all good.\n const expectedValues = typeof expected === \"string\" ? [expected] : expected;\n\n // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase());\n\n // Throw an error if the popped token didn't match any of our expected items.\n if (!tokenMatchesExpectation) {\n const expectationString = expectedValues.map((item) => \"'\" + item + \"'\").join(\" or \");\n throw new Error(\"unexpected token found. Expected \" + expectationString + \" but got '\" + popped + \"'\");\n }\n }\n\n // Return the popped token.\n return popped;\n}\n\n/**\n * Swaps out any node/attribute argument string literals with placeholders.\n * @param definition The definition.\n * @returns An object containing a mapping of placeholders to original string values as well as the processed definition string.\n */\nexport function substituteStringLiterals(definition: string): {\n placeholders: StringLiteralPlaceholders;\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: StringLiteralPlaceholders = {};\n\n // Replace any string literals wrapped with double quotes in our definition with placeholders to be processed later.\n const processedDefinition = definition.replace(/\\\"(\\\\.|[^\"\\\\])*\\\"/g, (match) => {\n var strippedMatch = match.substring(1, match.length - 1);\n var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch);\n\n // If we have no existing string literal match then create a new placeholder.\n if (!placeholder) {\n placeholder = `@@${Object.keys(placeholders).length}@@`;\n placeholders[placeholder] = strippedMatch;\n }\n\n return placeholder;\n });\n\n return { placeholders, processedDefinition };\n}\n\n/**\n * Parse the tree definition into an array of raw tokens.\n * @param definition The definition.\n * @returns An array of tokens parsed from the definition.\n */\nexport function parseTokensFromDefinition(definition: string): string[] {\n // Add some space around various important characters so that they can be plucked out easier as individual tokens.\n definition = definition.replace(/\\(/g, \" ( \");\n definition = definition.replace(/\\)/g, \" ) \");\n definition = definition.replace(/\\{/g, \" { \");\n definition = definition.replace(/\\}/g, \" } \");\n definition = definition.replace(/\\]/g, \" ] \");\n definition = definition.replace(/\\[/g, \" [ \");\n definition = definition.replace(/\\,/g, \" , \");\n\n // Split the definition into raw token form and return it.\n return definition.replace(/\\s+/g, \" \").trim().split(\" \");\n}\n", "import { StringLiteralPlaceholders, popAndCheck } from \"./MDSLUtilities\";\n\n/**\n * A type representing any node function argument.\n */\ntype Argument = {\n /**\n * The argument value.\n */\n value: T;\n /**\n * The argument type, used for validation.\n */\n type: string;\n};\n\ntype NullArgument = Argument & {\n type: \"null\";\n};\n\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\n\ntype NumberArgument = Argument & {\n type: \"number\";\n /**\n * A flag defining whether the number argument value is a valid integer. (used for validation)\n */\n isInteger: boolean;\n};\n\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\n\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\n\n/**\n * A type representing a reference to any node function argument.\n */\ntype AnyArgument = NullArgument | BooleanArgument | NumberArgument | StringPlaceholderArgument | IdentifierArgument;\n\n/**\n * Parse an array of argument definitions from the specified tokens array.\n * @param tokens The array tokens to parse the argument definitions from.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @param argumentValidator The argument validator function.\n * @param validationFailedMessage The exception message to throw if argument validation fails.\n * @returns An array of argument definitions parsed from the specified tokens array.\n */\nexport function parseArgumentTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): AnyArgument[] {\n const argumentList: AnyArgument[] = [];\n\n // If the next token is not a '[' or '(' then we have no arguments to parse.\n if (![\"[\", \"(\"].includes(tokens[0])) {\n return argumentList;\n }\n\n // Any lists of arguments will always be wrapped in '[]' for node arguments or '()' for attribute arguments.\n // We are looking for a '[' or '(' opener that wraps the argument tokens and the relevant closer.\n const closingToken = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closingToken) {\n // The next token is part of our arguments list.\n argumentListTokens.push(tokens.shift()!);\n }\n\n // Validate the order of the argument tokens. Each token must either be a ',' or a single argument that satisfies the validator.\n argumentListTokens.forEach((token, index) => {\n // Get whether this token should be an actual argument.\n const shouldBeArgumentToken = !(index & 1);\n\n // If the current token should be an actual argument then validate it, otherwise it should be a ',' token.\n if (shouldBeArgumentToken) {\n // Get the argument definition.\n const argumentDefinition = getArgumentDefinition(token, stringArgumentPlaceholders);\n\n // This is a valid argument!\n argumentList.push(argumentDefinition);\n } else {\n // The current token should be a ',' token.\n if (token !== \",\") {\n throw new Error(`invalid argument list, expected ',' or ']' but got '${token}'`);\n }\n }\n });\n\n // The arguments list should terminate with a ']' or ')' token, depending on the opener.\n popAndCheck(tokens, closingToken);\n\n // Return the arguments.\n return argumentList;\n}\n\n/**\n * Gets an argument value definition.\n * @param token The argument token.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An argument value definition.\n */\nfunction getArgumentDefinition(token: string, stringArgumentPlaceholders: StringLiteralPlaceholders): AnyArgument {\n // Check whether the token represents a null value.\n if (token === \"null\") {\n return {\n value: null,\n type: \"null\"\n } as NullArgument;\n }\n\n // Check whether the token represents a boolean value.\n if (token === \"true\" || token === \"false\") {\n return {\n value: token === \"true\",\n type: \"boolean\"\n } as BooleanArgument;\n }\n\n // Check whether the token represents a number value.\n // TODO: Relies on broken isNaN - see MDN.\n // if (!Number.isNaN(token)) {\n if (!isNaN(token as any)) {\n return {\n value: parseFloat(token),\n isInteger: parseFloat(token) === parseInt(token, 10),\n type: \"number\"\n } as NumberArgument;\n }\n\n // Check whether the token is a placeholder (e.g. @@0@@) representing a string literal.\n if (token.match(/^@@\\d+@@$/g)) {\n return {\n value: stringArgumentPlaceholders[token].replace('\\\\\"', '\"'),\n type: \"string\"\n } as StringPlaceholderArgument;\n }\n\n // The only remaining option is that the argument value is an identifier.\n return {\n value: token,\n type: \"identifier\"\n } as IdentifierArgument;\n}\n", "import { NodeAttributeDefinition } from \"../BehaviourTreeDefinition\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { StringLiteralPlaceholders } from \"./MDSLUtilities\";\n\n/**\n * A type defining the attribute definitions of a node.\n */\ntype NodeAttributes = {\n while?: NodeAttributeDefinition;\n until?: NodeAttributeDefinition;\n entry?: NodeAttributeDefinition;\n exit?: NodeAttributeDefinition;\n step?: NodeAttributeDefinition;\n};\n\n/**\n * Parse any node attribute definitions from the specified tokens array.\n * @param tokens The array of remaining tokens.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An object of attribute definitions defined by any directly following tokens.\n */\nexport function parseAttributeTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): NodeAttributes {\n const nodeAttributeNames: (keyof NodeAttributes)[] = [\"while\", \"until\", \"entry\", \"exit\", \"step\"];\n\n // Create an object to hold any attributes found.\n const attributes: NodeAttributes = {};\n\n // Try to get the name of the attribute for the next token.\n let nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n\n // Pull attribute tokens as well as their arguments off of the tokens stack until we have no more.\n while (nodeAttributeNames.includes(nextAttributeName)) {\n // Check to make sure that we have not already created an attribute definition of this type.\n if (attributes[nextAttributeName]) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Remove the attribute name token from the array of tokens.\n tokens.shift();\n\n // Grab the attribute arguments, assuming the first to be an identifier.\n const [attributeCallIdentifier, ...attributeArguments] = parseArgumentTokens(\n tokens,\n stringArgumentPlaceholders\n );\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeCallIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected agent function or registered function name identifier argument for attribute\");\n }\n\n // Any attribute arguments (other than the expected call identifier) must have a type of string, number, boolean or null.\n attributeArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid attribute argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Create the attribute definition and add it to the object of attribute definitions found.\n attributes[nextAttributeName] = {\n call: attributeCallIdentifier.value,\n args: attributeArguments.map(({ value }) => value)\n };\n\n // Try to get the next attribute name token, as there could be multiple.\n nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n }\n\n return attributes;\n}\n", "import {\n ActionNodeDefinition,\n AnyChildNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition,\n ConditionNodeDefinition,\n FailNodeDefinition,\n FlipNodeDefinition,\n LottoNodeDefinition,\n ParallelNodeDefinition,\n RaceNodeDefinition,\n RepeatNodeDefinition,\n RetryNodeDefinition,\n RootNodeDefinition,\n SelectorNodeDefinition,\n SequenceNodeDefinition,\n SucceedNodeDefinition,\n WaitNodeDefinition\n} from \"../BehaviourTreeDefinition\";\nimport {\n isCompositeNode,\n isDecoratorNode,\n isLeafNode,\n isNullOrUndefined,\n isRootNode\n} from \"../BehaviourTreeDefinitionUtilities\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { parseAttributeTokens } from \"./MDSLNodeAttributeParser\";\nimport {\n StringLiteralPlaceholders,\n parseTokensFromDefinition,\n popAndCheck,\n substituteStringLiterals\n} from \"./MDSLUtilities\";\n\n/**\n * Convert the MDSL tree definition string into an equivalent JSON definition.\n * @param definition The tree definition string as MDSL.\n * @returns The root node JSON definitions.\n */\nexport function convertMDSLToJSON(definition: string): RootNodeDefinition[] {\n // Swap out any node/attribute argument string literals with a placeholder and get a mapping of placeholders to original values as well as the processed definition.\n const { placeholders, processedDefinition } = substituteStringLiterals(definition);\n\n // Parse our definition definition string into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\n return convertTokensToJSONDefinition(tokens, placeholders);\n}\n\n/**\n * Converts the specified tree definition tokens into a JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definitions.\n */\nfunction convertTokensToJSONDefinition(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RootNodeDefinition[] {\n // There must be at least 3 tokens for the tree definition to be valid. 'ROOT', '{' and '}'.\n if (tokens.length < 3) {\n throw new Error(\"invalid token count\");\n }\n\n // We should have a matching number of '{' and '}' tokens. If not, then there are scopes that have not been properly closed.\n if (tokens.filter((token) => token === \"{\").length !== tokens.filter((token) => token === \"}\").length) {\n throw new Error(\"scope character mismatch\");\n }\n\n // Create an array of tree stack arrays where root nodes will always be at the botton and the current composite/decorator node at the top.\n // There should be an element in this array for every root node defined and every element should be an array with a root note as the first element.\n // E.g. A definition with two root nodes defined:\n // [\n // [root, lotto, sequence],\n // [root, selector]\n // ]\n const treeStacks: [Partial, ...Partial[]][] = [];\n\n // Create an array of all root node definitions that we create.\n const rootNodes: Partial[] = [];\n\n // A helper function used to push node definitions onto the tree stack.\n const pushNode = (node: AnyNodeDefinition) => {\n // If the node is a root node then we need to create a new tree stack array with the root node at the root.\n if (isRootNode(node)) {\n // We need to double-check that this root node is not the child of another node.\n // We can do this by checking whether the top tree stack is not empty (contains an existing node)\n if (treeStacks[treeStacks.length - 1]?.length) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Add the root node definition to our array of all parsed root node definitions.\n rootNodes.push(node);\n\n // Add the root node definition to the root of a new tree stack.\n treeStacks.push([node]);\n\n return;\n }\n\n // All non-root nodes should be pushed after their root nodes so handle cases\n // where we may not have any tree stacks or our top-most tree stack is empty.\n if (!treeStacks.length || !treeStacks[treeStacks.length - 1].length) {\n throw new Error(\"expected root node at base of definition\");\n }\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Get the top-most node in the current tree stack, this will be a composite/decorator node\n // for which we will populate its children array if composite or setting its child if a decorator.\n const topTreeStackTopNode = topTreeStack[topTreeStack.length - 1] as AnyNodeDefinition;\n\n // If the top-most node in the current root stack is a composite or decorator\n // node then the current node should be added as a child of the top-most node.\n if (isCompositeNode(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNode(topTreeStackTopNode)) {\n // If the top node already has a child node set then throw an error as a decorator should only have a single child.\n if (topTreeStackTopNode.child) {\n throw new Error(\"a decorator node must only have a single child node\");\n }\n\n topTreeStackTopNode.child = node;\n }\n\n // If the node we are adding is also a composite or decorator node, then we should push it\n // onto the current tree stack, as subsequent nodes will be added as its child/children.\n if (!isLeafNode(node)) {\n topTreeStack.push(node);\n }\n };\n\n // A helper function used to pop the top-most node definition off of the tree stack and return it.\n const popNode = (): AnyNodeDefinition | null => {\n let poppedNode: AnyNodeDefinition | null = null;\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Pop the top-most node in the current tree stack if there is one.\n if (topTreeStack.length) {\n poppedNode = topTreeStack.pop() as AnyNodeDefinition;\n }\n\n // We don't want any empty tree stacks in our stack of tree stacks.\n if (!topTreeStack.length) {\n treeStacks.pop();\n }\n\n return poppedNode;\n };\n\n // We should keep processing the raw tokens until we run out of them.\n while (tokens.length) {\n // Grab the next token.\n const token = tokens.shift()!;\n\n // How we create the next node depends on the current raw token value.\n switch (token.toUpperCase()) {\n case \"ROOT\": {\n pushNode(createRootNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SUCCEED\": {\n pushNode(createSucceedNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FAIL\": {\n pushNode(createFailNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FLIP\": {\n pushNode(createFlipNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"REPEAT\": {\n pushNode(createRepeatNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RETRY\": {\n pushNode(createRetryNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SEQUENCE\": {\n pushNode(createSequenceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SELECTOR\": {\n pushNode(createSelectorNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"PARALLEL\": {\n pushNode(createParallelNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RACE\": {\n pushNode(createRaceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"LOTTO\": {\n pushNode(createLottoNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ACTION\": {\n pushNode(createActionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"CONDITION\": {\n pushNode(createConditionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"WAIT\": {\n pushNode(createWaitNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"BRANCH\": {\n pushNode(createBranchNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope and means that we have to pop a node off of the current stack.\n const poppedNode = popNode();\n\n // Now that we have a node definition we can carry out any validation that may require the node to be fully populated.\n if (poppedNode) {\n validatePoppedNode(poppedNode);\n }\n\n break;\n }\n\n default: {\n throw new Error(`unexpected token: ${token}`);\n }\n }\n }\n\n return rootNodes as RootNodeDefinition[];\n}\n\n/**\n * Creates a root node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definition.\n */\nfunction createRootNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RootNodeDefinition {\n // Create the root node definition.\n let node = {\n type: \"root\"\n } as Partial;\n\n // Parse any node arguments, we should only have one if any which will be an identifier argument for the root identifier.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Check whether any node arguments were defined.\n if (nodeArguments.length) {\n // We should only have one argument, if any, which will be an identifier argument for the root identifier.\n if (nodeArguments.length === 1 && nodeArguments[0].type === \"identifier\") {\n // The root node identifier will be the first and only node argument value.\n node.id = nodeArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the root node definition.\n return node as RootNodeDefinition;\n}\n\n/**\n * Creates a succeed node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The succeed node JSON definition.\n */\nfunction createSucceedNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SucceedNodeDefinition {\n const node = {\n type: \"succeed\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SucceedNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the succeed node definition.\n return node;\n}\n\n/**\n * Creates a fail node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The fail node JSON definition.\n */\nfunction createFailNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FailNodeDefinition {\n const node = {\n type: \"fail\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FailNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the fail node definition.\n return node;\n}\n\n/**\n * Creates a flip node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The flip node JSON definition.\n */\nfunction createFlipNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FlipNodeDefinition {\n const node = {\n type: \"flip\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FlipNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the flip node definition.\n return node;\n}\n\n/**\n * Creates a repeat node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The repeat node JSON definition.\n */\nfunction createRepeatNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RepeatNodeDefinition {\n let node = { type: \"repeat\" } as RepeatNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a repeat node are optional. We may have:\n // - No node arguments, in which case the repeat note will iterate indefinitely.\n // - One node argument which will be the explicit number of iterations to make.\n // - Two node arguments which define the min and max iteration bounds from which a random iteration count will be picked.\n if (nodeArguments.length) {\n // All repeat node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`repeat node iteration counts must be integer values`);\n });\n\n // We should have got one or two iteration counts.\n if (nodeArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = nodeArguments[0].value as number;\n\n // A repeat node must have a positive number of iterations if defined.\n if (node.iterations < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A repeat node must have a positive min and max iteration count if they are defined.\n if (node.iterations[0] < 0 || node.iterations[1] < 0) {\n throw new Error(\"a repeat node must have a positive minimum and maximum iteration count if defined\");\n }\n\n // A repeat node must not have an minimum iteration count that exceeds the maximum iteration count.\n if (node.iterations[0] > node.iterations[1]) {\n throw new Error(\n \"a repeat node must not have a minimum iteration count that exceeds the maximum iteration count\"\n );\n }\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of repeat node iteration count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the repeat node definition.\n return node;\n}\n\n/**\n * Creates a retry node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The retry node JSON definition.\n */\nfunction createRetryNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RetryNodeDefinition {\n let node = { type: \"retry\" } as RetryNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a retry node are optional. We may have:\n // - No node arguments, in which case the retry note will attempt indefinitely.\n // - One node argument which will be the explicit number of attempts to make.\n // - Two node arguments which define the min and max attempt bounds from which a random attempt count will be picked.\n if (nodeArguments.length) {\n // All retry node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`retry node attempt counts must be integer values`);\n });\n\n // We should have got one or two attempt counts.\n if (nodeArguments.length === 1) {\n // A static attempt count was defined.\n node.attempts = nodeArguments[0].value as number;\n\n // A retry node must have a positive number of attempts if defined.\n if (node.attempts < 0) {\n throw new Error(\"a retry node must have a positive number of attempts if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum attempt count was defined.\n node.attempts = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (node.attempts[0] < 0 || node.attempts[1] < 0) {\n throw new Error(\"a retry node must have a positive minimum and maximum attempt count if defined\");\n }\n\n // A retry node must not have a minimum attempt count that exceeds the maximum attempt count.\n if (node.attempts[0] > node.attempts[1]) {\n throw new Error(\n \"a retry node must not have a minimum attempt count that exceeds the maximum attempt count\"\n );\n }\n } else {\n // An incorrect number of attempt counts was defined.\n throw new Error(\"invalid number of retry node attempt count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the retry node definition.\n return node;\n}\n\n/**\n * Creates a sequence node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The sequence node JSON definition.\n */\nfunction createSequenceNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SequenceNodeDefinition {\n const node = {\n type: \"sequence\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SequenceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the sequence node definition.\n return node;\n}\n\n/**\n * Creates a selector node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The selector node JSON definition.\n */\nfunction createSelectorNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SelectorNodeDefinition {\n const node = {\n type: \"selector\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SelectorNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the selector node definition.\n return node;\n}\n\n/**\n * Creates a parallel node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The parallel node JSON definition.\n */\nfunction createParallelNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ParallelNodeDefinition {\n const node = {\n type: \"parallel\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as ParallelNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the parallel node definition.\n return node;\n}\n\n/**\n * Creates a race node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The race node JSON definition.\n */\nfunction createRaceNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RaceNodeDefinition {\n const node = {\n type: \"race\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as RaceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the race node definition.\n return node;\n}\n\n/**\n * Creates a lotto node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The lotto node JSON definition.\n */\nfunction createLottoNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): LottoNodeDefinition {\n // If any node arguments have been defined then they must be our weights.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // All lotto node arguments MUST be of type number and must be positive integers.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger || arg.value < 0)\n .forEach(() => {\n throw new Error(`lotto node weight arguments must be positive integer values`);\n });\n\n const node = {\n type: \"lotto\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as LottoNodeDefinition;\n\n // Apply the weights if any were defined.\n if (nodeArguments.length) {\n node.weights = nodeArguments.map(({ value }) => value) as number[];\n }\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the lotto node definition.\n return node;\n}\n\n/**\n * Creates an action node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The action node JSON definition.\n */\nfunction createActionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ActionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the action name\n // and agent function to invoke for the action, all other arguments are to be passed as arguments to that function.\n const [actionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require an action name argument.\n if (actionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid action node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the action node definition.\n return {\n type: \"action\",\n call: actionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a condition node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The condition node JSON definition.\n */\nfunction createConditionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ConditionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the condition name\n // and agent function to invoke for the condition, all other arguments are to be passed as arguments to that function.\n const [conditionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require a condition name argument.\n if (conditionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid condition node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the condition node definition.\n return {\n type: \"condition\",\n call: conditionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a wait node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The wait node JSON definition.\n */\nfunction createWaitNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): WaitNodeDefinition {\n let node = { type: \"wait\" } as WaitNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a wait node are optional. We may have:\n // - No node arguments, in which case the wait will be indefinite until it is aborted.\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n if (nodeArguments.length) {\n // All wait node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`wait node durations must be integer values`);\n });\n\n // We may have:\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n // - Too many arguments, which is not valid.\n if (nodeArguments.length === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0].value as number;\n\n // If an explict duration was defined then it must be a positive number.\n if (node.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.duration = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A wait node must have a positive min and max duration.\n if (node.duration[0] < 0 || node.duration[1] < 0) {\n throw new Error(\"a wait node must have a positive minimum and maximum duration\");\n }\n\n // A wait node must not have a minimum duration that exceeds the maximum duration.\n if (node.duration[0] > node.duration[1]) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else if (nodeArguments.length > 2) {\n // An incorrect number of duration arguments were defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n }\n\n // Return the wait node definition.\n return { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n}\n\n/**\n * Creates a branch node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The branch node JSON definition.\n */\nfunction createBranchNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): BranchNodeDefinition {\n // Parse any node arguments, we should have one which will be an identifier argument for the root ref.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // We should have only a single identifer argument for a branch node, which is the root ref.\n if (nodeArguments.length !== 1 || nodeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // Return the branch node definition.\n return { type: \"branch\", ref: nodeArguments[0].value };\n}\n\n/**\n * Validate a fully-populated node definition that was popped off of the tree stack.\n * @param definition The popped node to validate.\n */\nfunction validatePoppedNode(definition: AnyNodeDefinition): void {\n // Decorators MUST have a child defined.\n if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) {\n throw new Error(`a ${definition.type} node must have a single child node defined`);\n }\n\n // Composites MUST have at least one child defined.\n if (isCompositeNode(definition) && !definition.children?.length) {\n throw new Error(`a ${definition.type} node must have at least a single child node defined`);\n }\n\n // We need to make sure that lotto nodes that have weights defined have a number of weights matching the number of child nodes.\n if (definition.type === \"lotto\") {\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (definition.weights.length !== definition.children.length) {\n throw new Error(\n \"expected a number of weight arguments matching the number of child nodes for lotto node\"\n );\n }\n }\n }\n}\n", "import { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { flattenDefinition, isBranchNode, isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\n/**\n * An object representing the result of validating a tree definition.\n */\nexport type DefinitionValidationResult = {\n /**\n * A flag defining whether validation succeeded.\n */\n succeeded: boolean;\n /**\n * A string containing the error message if validation did not succeed.\n */\n errorMessage?: string;\n /**\n * The definition as json if the validation was successful, or undefined if validation did not succeed.\n */\n json?: RootNodeDefinition[];\n};\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON or MDSL, not taking any globally registered subtrees into consideration.\n * @param definition The behaviour tree definition in the form of JSON or MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateDefinition(definition: any): DefinitionValidationResult {\n // The definition must be defined.\n if (definition === null || typeof definition === \"undefined\") {\n return createValidationFailureResult(\"definition is null or undefined\");\n }\n\n // We are expecting a definition in one of three different forms:\n // - A string which we will assume is MDSL and we will parse this to JSON before validation.\n // - An array which we will assume is an array of root node definitions with at least one being the primary root node (no 'id' property)\n // - An object which we will assume is the primary root node and should not have an 'id' property.\n if (typeof definition === \"string\") {\n // The definition is a string which we can assume is MDSL, so attempt to validate it.\n return validateMDSLDefinition(definition);\n } else if (typeof definition === \"object\") {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n return validateJSONDefinition(definition);\n } else {\n return createValidationFailureResult(`unexpected definition type of '${typeof definition}'`);\n }\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of MDSL.\n * @param definition The behaviour tree definition in the form of MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nfunction validateMDSLDefinition(definition: string): DefinitionValidationResult {\n let rootNodeDefinitions;\n\n // The first thing the we need to do is to attempt to convert our MDSL into JSON.\n try {\n // The definition is a string which we can assume is MDSL, so attempt to parse it to a JSON definition in the form of an array of root node definitions.\n rootNodeDefinitions = convertMDSLToJSON(definition);\n } catch (exception) {\n // We failed to parse the JSON from the MDSL, this is likely to be the result of it not being a valid MDSL string.\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single unnamed root node at base of definition to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(`multiple root nodes found with duplicate name '${id}'`);\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON.\n * @param definition The behaviour tree definition in the form of JSON.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateJSONDefinition(\n definition: RootNodeDefinition | RootNodeDefinition[]\n): DefinitionValidationResult {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n const rootNodeDefinitions = Array.isArray(definition) ? definition : [definition];\n\n // Iterate over our array of root nodes and call validateNode for each, passing an initial depth of 0, wrapped in a try catch to handle validation failures.\n try {\n rootNodeDefinitions.forEach((rootNodeDefinition) => validateNode(rootNodeDefinition, 0));\n } catch (error) {\n // Handle cases where we have caught a thrown Error and return a failure result with the error message.\n if (error instanceof Error) {\n return createValidationFailureResult(error.message);\n }\n\n // No idea what happened here!\n return createValidationFailureResult(`unexpected error: ${error}`);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single root node without 'id' property defined to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(\n `multiple root nodes found with duplicate 'id' property value of '${id}'`\n );\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the branch -> subtree links across all provided root node definitions.\n * This will not consider branch nodes that reference any globally registered subtrees unless includesGlobalSubtrees\n * is set to true, in which case we will also verify that there are no broken branch -> subtree links.\n * @param rootNodeDefinitions The array of root node definitions.\n * @param includesGlobalSubtrees A flag defining whether the array includes all global subtree root node definitions.\n */\nexport function validateBranchSubtreeLinks(rootNodeDefinitions: RootNodeDefinition[], includesGlobalSubtrees: boolean) {\n // Create a mapping of root node identifiers to other root nodes that they reference via branch nodes.\n // Below is an example of a mapping that includes a circular dependency (root => a => b => c => a)\n // [{ refs: [\"a\", \"b\"] }, { id: \"a\", refs: [\"b\"] }, { id: \"b\", refs: [\"c\"] }, { id: \"c\", refs: [\"a\"] }]\n const rootNodeMappings: { id: string | undefined; refs: string[] }[] = rootNodeDefinitions.map(\n (rootNodeDefinition) => ({\n id: rootNodeDefinition.id,\n refs: flattenDefinition(rootNodeDefinition)\n .filter(isBranchNode)\n .map(({ ref }) => ref)\n })\n );\n\n // A recursive function to walk through the mappings, keeping track of which root nodes we have visited in the form of a path of root node identifiers.\n const followRefs = (mapping: { id: string | undefined; refs: string[] }, path: (string | undefined)[] = []) => {\n // Have we found a circular dependency?\n if (path.includes(mapping.id)) {\n // We found a circular dependency! Get the bad path of root node identifiers.\n const badPath = [...path, mapping.id];\n\n // Create the formatted path value. [undefined, \"a\", \"b\", \"c\", \"a\"] would be formatted as \"a -> b -> c -> a\".\n const badPathFormatted = badPath.filter((element) => !!element).join(\" => \");\n\n // No need to continue, we found a circular dependency.\n throw new Error(`circular dependency found in branch node references: ${badPathFormatted}`);\n }\n\n for (const ref of mapping.refs) {\n // Find the mapping for the root node with an identifer matching the current ref.\n const subMapping = rootNodeMappings.find(({ id }) => id === ref);\n\n // We may not have a mapping for this ref, which is normal when we aren't considering all globally registered subtrees.\n if (subMapping) {\n followRefs(subMapping, [...path, mapping.id]);\n } else if (includesGlobalSubtrees) {\n // We found a reference to a root node that doesn't exist, which is a problem seeing as the root node definitons includes all globally registered subtrees.\n throw new Error(\n mapping.id\n ? `subtree '${mapping.id}' has branch node that references root node '${ref}' which has not been defined`\n : `primary tree has branch node that references root node '${ref}' which has not been defined`\n );\n }\n }\n };\n\n // Start looking for circular dependencies and broken references from the primary root node definition.\n followRefs(rootNodeMappings.find((mapping) => typeof mapping.id === \"undefined\")!);\n}\n\n/**\n * Validate an object that we expect to be a node definition.\n * @param definition An object that we expect to be a node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateNode(definition: any, depth: number): void {\n // Every node must be valid object and have a non-empty 'type' string property.\n if (typeof definition !== \"object\" || typeof definition.type !== \"string\" || definition.type.length === 0) {\n throw new Error(\n `node definition is not an object or 'type' property is not a non-empty string at depth '${depth}'`\n );\n }\n\n // If this node is at the very base of the definition then it MUST be a root node.\n if (depth === 0 && definition.type !== \"root\") {\n throw new Error(`expected root node at base of definition but got node of type '${definition.type}'`);\n }\n\n // How we validate this node definition will depend on its type.\n switch (definition.type) {\n case \"action\":\n validateActionNode(definition, depth);\n break;\n\n case \"condition\":\n validateConditionNode(definition, depth);\n break;\n\n case \"wait\":\n validateWaitNode(definition, depth);\n break;\n\n case \"branch\":\n validateBranchNode(definition, depth);\n break;\n\n case \"root\":\n validateRootNode(definition, depth);\n break;\n\n case \"succeed\":\n validateSucceedNode(definition, depth);\n break;\n\n case \"fail\":\n validateFailNode(definition, depth);\n break;\n\n case \"flip\":\n validateFlipNode(definition, depth);\n break;\n\n case \"repeat\":\n validateRepeatNode(definition, depth);\n break;\n\n case \"retry\":\n validateRetryNode(definition, depth);\n break;\n\n case \"sequence\":\n validateSequenceNode(definition, depth);\n break;\n\n case \"selector\":\n validateSelectorNode(definition, depth);\n break;\n\n case \"parallel\":\n validateParallelNode(definition, depth);\n break;\n\n case \"race\":\n validateRaceNode(definition, depth);\n break;\n\n case \"lotto\":\n validateLottoNode(definition, depth);\n break;\n\n default:\n throw new Error(`unexpected node type of '${definition.type}' at depth '${depth}'`);\n }\n}\n\n/**\n * Validate any attributes for a given node definition.\n * @param definition The node definition.\n * @param depth The depth of the node in the behaviour tree definition.\n */\nfunction validateNodeAttributes(definition: any, depth: number): void {\n // Validate each of the attribute types for this node.\n [\"while\", \"until\", \"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n // Attempt to grab the definition for the current attribute from the node definition.\n const attributeDefinition = definition[attributeName];\n\n // All node attributes are optional, so there is nothing to do if the current attribute is not defined.\n if (typeof attributeDefinition === \"undefined\") {\n return;\n }\n\n // The attribute definition must be an object.\n if (typeof attributeDefinition !== \"object\") {\n throw new Error(\n `expected attribute '${attributeName}' to be an object for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // The 'call' property must be defined for any attribute definition.\n if (typeof attributeDefinition.call !== \"string\" || attributeDefinition.call.length === 0) {\n throw new Error(\n `expected 'call' property for attribute '${attributeName}' to be a non-empty string for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // If any node attribute arguments have been defined then they must have been defined in an array.\n if (typeof attributeDefinition.args !== \"undefined\" && !Array.isArray(attributeDefinition.args)) {\n throw new Error(\n `expected 'args' property for attribute '${attributeName}' to be an array for '${definition.type}' node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a root node definition.\n * @param definition An object that we expect to be a root node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRootNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"root\") {\n throw new Error(\"expected node type of 'root' for root node\");\n }\n\n // A root node cannot be the child of another node.\n if (depth > 0) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Check that, if the root node 'id' property is defined, it is a non-empty string.\n if (typeof definition.id !== \"undefined\" && (typeof definition.id !== \"string\" || definition.id.length === 0)) {\n throw new Error(\"expected non-empty string for 'id' property if defined for root node\");\n }\n\n // A root node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(\"expected property 'child' to be defined for root node\");\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a succeed node definition.\n * @param definition An object that we expect to be a succeed node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSucceedNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"succeed\") {\n throw new Error(`expected node type of 'succeed' for succeed node at depth '${depth}'`);\n }\n\n // A succeed node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for succeed node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a fail node definition.\n * @param definition An object that we expect to be a fail node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFailNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"fail\") {\n throw new Error(`expected node type of 'fail' for fail node at depth '${depth}'`);\n }\n\n // A fail node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for fail node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a flip node definition.\n * @param definition An object that we expect to be a flip node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFlipNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"flip\") {\n throw new Error(`expected node type of 'flip' for flip node at depth '${depth}'`);\n }\n\n // A flip node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for flip node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a repeat node definition.\n * @param definition An object that we expect to be a repeat node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRepeatNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"repeat\") {\n throw new Error(`expected node type of 'repeat' for repeat node at depth '${depth}'`);\n }\n\n // A repeat node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for repeat node at depth '${depth}'`);\n }\n\n // Check whether an 'iterations' property has been defined, it may not have been if this node is to repeat indefinitely.\n if (typeof definition.iterations !== \"undefined\") {\n if (Array.isArray(definition.iterations)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.iterations.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'iterations' property is an array then it MUST contain two integer values.\n if (definition.iterations.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must have a positive min and max iterations count if they are defined.\n if (definition.iterations[0] < 0 || definition.iterations[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must not have a minimum iterations count that exceeds the maximum iterations count.\n if (definition.iterations[0] > definition.iterations[1]) {\n throw new Error(\n `expected minimum iterations count that does not exceed the maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.iterations)) {\n // A repeat node must have a positive number of iterations if defined.\n if (definition.iterations < 0) {\n throw new Error(\n `expected positive iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a retry node definition.\n * @param definition An object that we expect to be a retry node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRetryNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"retry\") {\n throw new Error(`expected node type of 'retry' for retry node at depth '${depth}'`);\n }\n\n // A retry node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for retry node at depth '${depth}'`);\n }\n\n // Check whether an 'attempts' property has been defined, it may not have been if this node is to retry indefinitely.\n if (typeof definition.attempts !== \"undefined\") {\n if (Array.isArray(definition.attempts)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.attempts.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'attempts' property is an array then it MUST contain two integer values.\n if (definition.attempts.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (definition.attempts[0] < 0 || definition.attempts[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must not have a minimum attempts count that exceeds the maximum attempts count.\n if (definition.attempts[0] > definition.attempts[1]) {\n throw new Error(\n `expected minimum attempts count that does not exceed the maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.attempts)) {\n // A retry node must have a positive number of attempts if defined.\n if (definition.attempts < 0) {\n throw new Error(\n `expected positive attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a branch node definition.\n * @param definition An object that we expect to be a branch node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateBranchNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"branch\") {\n throw new Error(`expected node type of 'branch' for branch node at depth '${depth}'`);\n }\n\n // Check that the branch node 'ref' property is defined and is a non-empty string.\n if (typeof definition.ref !== \"string\" || definition.ref.length === 0) {\n throw new Error(`expected non-empty string for 'ref' property for branch node at depth '${depth}'`);\n }\n\n // It is invalid to define guard attributes for a branch node as they should be defined on the referenced root node.\n [\"while\", \"until\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `guards should not be defined for branch nodes but guard '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n\n // It is invalid to define callback attributes for a branch node as they should be defined on the referenced root node.\n [\"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `callbacks should not be defined for branch nodes but callback '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a action node definition.\n * @param definition An object that we expect to be a action node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateActionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"action\") {\n throw new Error(`expected node type of 'action' for action node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a action node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of action node at depth '${depth}'`);\n }\n\n // If any action function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for action node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a condition node definition.\n * @param definition An object that we expect to be a condition node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateConditionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"condition\") {\n throw new Error(`expected node type of 'condition' for condition node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a condition node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of condition node at depth '${depth}'`);\n }\n\n // If any condition function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for condition node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a wait node definition.\n * @param definition An object that we expect to be a wait node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateWaitNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"wait\") {\n throw new Error(`expected node type of 'wait' for wait node at depth '${depth}'`);\n }\n\n // Check whether a 'duration' property has been defined, it may not have been if this node is to wait indefinitely.\n if (typeof definition.duration !== \"undefined\") {\n if (Array.isArray(definition.duration)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.duration.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'duration' property is an array then it MUST contain two integer values.\n if (definition.duration.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must have a positive min and max duration value if they are defined.\n if (definition.duration[0] < 0 || definition.duration[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum duration for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must not have a minimum duration value that exceeds the maximum duration value.\n if (definition.duration[0] > definition.duration[1]) {\n throw new Error(\n `expected minimum duration value that does not exceed the maximum duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.duration)) {\n // A wait node must have a positive duration value if defined.\n if (definition.duration < 0) {\n throw new Error(\n `expected positive duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a sequence node definition.\n * @param definition An object that we expect to be a sequence node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSequenceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"sequence\") {\n throw new Error(`expected node type of 'sequence' for sequence node at depth '${depth}'`);\n }\n\n // A sequence node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for sequence node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a selector node definition.\n * @param definition An object that we expect to be a selector node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSelectorNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"selector\") {\n throw new Error(`expected node type of 'selector' for selector node at depth '${depth}'`);\n }\n\n // A selector node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for selector node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a parallel node definition.\n * @param definition An object that we expect to be a parallel node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateParallelNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"parallel\") {\n throw new Error(`expected node type of 'parallel' for parallel node at depth '${depth}'`);\n }\n\n // A parallel node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for parallel node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a race node definition.\n * @param definition An object that we expect to be a race node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRaceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"race\") {\n throw new Error(`expected node type of 'race' for race node at depth '${depth}'`);\n }\n\n // A race node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for race node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a lotto node definition.\n * @param definition An object that we expect to be a lotto node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateLottoNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"lotto\") {\n throw new Error(`expected node type of 'lotto' for lotto node at depth '${depth}'`);\n }\n\n // A lotto node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for lotto node at depth '${depth}'`);\n }\n\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (\n !Array.isArray(definition.weights) ||\n definition.weights.length !== definition.children.length ||\n definition.weights.filter((value: unknown) => !isInteger(value)).length ||\n definition.weights.filter((value: number) => value < 0).length\n ) {\n throw new Error(\n `expected an array of positive integer weight values with a length matching the number of child nodes for 'weights' property if defined for lotto node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * A helper function to create a failure validation result with the given error message.\n * @param errorMessage The validation failure error message.\n * @returns A failure validation result with the given error message.\n */\nfunction createValidationFailureResult(errorMessage: string): DefinitionValidationResult {\n return { succeeded: false, errorMessage };\n}\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nexport function createUid(): string {\n var S4 = function () {\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n };\n return S4() + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + S4() + S4();\n}\n", "import { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport State, { AnyState } from \"../State\";\nimport { Agent } from \"../Agent\";\nimport Leaf from \"./leaf/Leaf\";\nimport Attribute from \"../attributes/Attribute\";\nimport Entry from \"../attributes/callbacks/Entry\";\nimport Exit from \"../attributes/callbacks/Exit\";\nimport Step from \"../attributes/callbacks/Step\";\nimport While from \"../attributes/guards/While\";\nimport Until from \"../attributes/guards/Until\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\nimport { GuardAttributeDetails } from \"../attributes/guards/Guard\";\nimport { CallbackAttributeDetails } from \"../attributes/callbacks/Callback\";\nimport { createUid } from \"../Utilities\";\n\n/**\n * Details of a tree node instance.\n */\nexport type NodeDetails = {\n /**\n * The tree node identifier.\n */\n id: string;\n /**\n * The tree node type.\n */\n type: string;\n /**\n * The tree node name.\n */\n name: string;\n /**\n * The current state of the tree node.\n */\n state: AnyState;\n /**\n * The array of agent or globally registered function arguments, defined if this is an action or condition node.\n */\n args?: any[];\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: GuardAttributeDetails;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: GuardAttributeDetails;\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: CallbackAttributeDetails;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: CallbackAttributeDetails;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: CallbackAttributeDetails;\n /**\n * The array of the child nodes of this node, defined if this node is a composite or decorator node.\n */\n children?: NodeDetails[];\n};\n\n/**\n * A mapping of attribute names to attributes configured for a node.\n */\ntype Attributes = {\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: Entry;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: Step;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: Exit;\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: While;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: Until;\n};\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node unique identifier.\n */\n protected readonly uid: string;\n /**\n * The node attributes.\n */\n protected readonly attributes: Attributes;\n /**\n * The node state.\n */\n private _state: AnyState = State.READY;\n /**\n * The guard path to evaluate as part of a node update.\n */\n private _guardPath: GuardPath | undefined;\n\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n */\n constructor(private type: string, attributes: Attribute[], protected options: BehaviourTreeOptions) {\n // Create a unique identifier for this node.\n this.uid = createUid();\n\n // Create our attribute mapping.\n this.attributes = {\n entry: attributes.find(({ type }) => type === \"entry\") as Entry,\n step: attributes.find(({ type }) => type === \"step\") as Step,\n exit: attributes.find(({ type }) => type === \"exit\") as Exit,\n while: attributes.find(({ type }) => type === \"while\") as While,\n until: attributes.find(({ type }) => type === \"until\") as Until\n };\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected abstract onUpdate(agent: Agent): void;\n\n /**\n * Gets the name of the node.\n */\n public abstract getName(): string;\n\n /**\n * Gets whether this node is a leaf node.\n */\n public abstract isLeafNode: () => this is Leaf;\n\n /**\n * Gets/Sets the state of the node.\n */\n getState = (): AnyState => this._state;\n setState = (value: AnyState): void => {\n // Grab the original state of this node.\n const previousState = this._state;\n\n // Set the new node state.\n this._state = value;\n\n // If the state actually changed we should handle it.\n if (previousState !== value) {\n this.onStateChanged(previousState);\n }\n };\n\n /**\n * Gets the unique id of the node.\n */\n getUid = () => this.uid;\n\n /**\n * Gets the type of the node.\n */\n getType = () => this.type;\n\n /**\n * Gets the node attributes.\n */\n getAttributes = () => Object.values(this.attributes).filter((attribute) => !!attribute);\n\n /**\n * Sets the guard path to evaluate as part of a node update.\n */\n setGuardPath = (value: GuardPath) => (this._guardPath = value);\n\n /**\n * Gets whether a guard path is assigned to this node.\n */\n hasGuardPath = () => !!this._guardPath;\n\n /**\n * Gets whether this node is in the specified state.\n * @param value The value to compare to the node state.\n */\n public is(value: AnyState): boolean {\n return this._state === value;\n }\n\n /**\n * Reset the state of the node.\n */\n public reset(): void {\n this.setState(State.READY);\n }\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n public abort(agent: Agent): void {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @returns The result of the update.\n */\n public update(agent: Agent): void {\n // If this node is already in a 'SUCCEEDED' or 'FAILED' state then there is nothing to do.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n return;\n }\n\n try {\n // Evaluate all of the guard path conditions for the current tree path.\n this._guardPath!.evaluate(agent);\n\n // If this node is in the READY state then call the ENTRY for this node if it exists.\n if (this.is(State.READY)) {\n this.attributes.entry?.callAgentFunction(agent);\n }\n\n this.attributes.step?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent);\n\n // If this node is now in a 'SUCCEEDED' or 'FAILED' state then call the EXIT for this node if it exists.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n this.attributes.exit?.callAgentFunction(agent, this.is(State.SUCCEEDED), false);\n }\n } catch (error) {\n // If the error is a GuardUnsatisfiedException then we need to determine if this node is the source.\n if (error instanceof GuardUnsatisifedException && error.isSourceNode(this)) {\n // Abort the current node.\n this.abort(agent);\n\n // Any node that is the source of an abort will be a failed node.\n this.setState(State.FAILED);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n id: this.uid,\n name: this.getName(),\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n state: this._state\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n // We should call the onNodeStateChange callback if it was defined.\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this._state\n });\n }\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A composite node that wraps child nodes.\n */\nexport default abstract class Composite extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => this.children;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of any child nodes.\n this.children.forEach((child) => child.reset());\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort any child nodes.\n this.children.forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: this.children.map((child) => child.getDetails())\n };\n }\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A PARALLEL node.\n * The child nodes are executed concurrently until one fails or all succeed.\n */\nexport default class Parallel extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"parallel\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have failed then this node has also failed.\n if (this.children.find((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A parallel node will move into the succeeded state if all child nodes move into the succeeded state.\n if (this.children.every((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RACE node.\n * The child nodes are executed concurrently until one succeeds or all fail.\n */\nexport default class Race extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"race\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have succeeded then this node has also succeeded\n if (this.children.find((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A race node will move into the failed state if all child nodes move into the failed state as none can succeed.\n if (this.children.every((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"RACE\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SELECTOR node.\n * The child nodes are executed in sequence until one succeeds or all fail.\n */\nexport default class Selector extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"selector\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then this node is also a 'SUCCEEDED' node.\n if (child.getState() === State.SUCCEEDED) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the selector nodes.\n return;\n }\n\n // If the current child has a state of 'FAILED' then we should move on to the next child.\n if (child.getState() === State.FAILED) {\n // Find out if the current child is the last one in the selector.\n // If it is then this sequence node has also failed.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the selector as we have completed it.\n return;\n } else {\n // The child node failed, try the next one.\n continue;\n }\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the selector as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SELECTOR\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SEQUENCE node.\n * The child nodes are executed in sequence until one fails or all succeed.\n */\nexport default class Sequence extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"sequence\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then we should move on to the next child.\n if (child.getState() === State.SUCCEEDED) {\n // Find out if the current child is the last one in the sequence.\n // If it is then this sequence node has also succeeded.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the sequence as we have completed it.\n return;\n } else {\n // The child node succeeded, but we have not finished the sequence yet.\n continue;\n }\n }\n\n // If the current child has a state of 'FAILED' then this node is also a 'FAILED' node.\n if (child.getState() === State.FAILED) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the sequence.\n return;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the sequence as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SEQUENCE\";\n}\n", "import createLotto from \"lotto-draw\";\n\nimport Node from \"../Node\";\nimport Composite from \"./Composite\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A LOTTO node.\n * A winning child is picked on the initial update of this node, based on ticket weighting.\n * The state of this node will match the state of the winning child.\n */\nexport default class Lotto extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param weights The child node weights.\n * @param children The child nodes.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private weights: number[] | undefined,\n children: Node[]\n ) {\n super(\"lotto\", attributes, options, children);\n }\n\n /**\n * The child node selected to be the active one.\n */\n private selectedChild: Node | undefined;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to pick a winning child node.\n if (this.is(State.READY)) {\n // Create a lotto draw with which to randomly pick a child node to become the active one.\n const lottoDraw = createLotto({\n // Hook up the optional 'random' behaviour tree function option to the one used by 'lotto-draw'.\n random: this.options.random,\n // Pass in each child node as a participant in the lotto draw with their respective ticket count.\n participants: this.children.map((child, index) => [child, this.weights?.[index] || 1])\n });\n\n // Randomly pick a child based on ticket weighting, this will become the active child for this composite node.\n this.selectedChild = lottoDraw.draw() || undefined;\n }\n\n // If something went wrong and we don't have an active child then we should throw an error.\n if (!this.selectedChild) {\n throw new Error(\"failed to update lotto node as it has no active child\");\n }\n\n // If the selected child has never been updated or is running then we will need to update it now.\n if (this.selectedChild.getState() === State.READY || this.selectedChild.getState() === State.RUNNING) {\n this.selectedChild.update(agent);\n }\n\n // The state of the lotto node is the state of its selected child.\n this.setState(this.selectedChild.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => (this.weights ? `LOTTO [${this.weights.join(\",\")}]` : \"LOTTO\");\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A decorator node that wraps a single child node.\n */\nexport default abstract class Decorator extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected child: Node) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => [this.child];\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of the child node.\n this.child.reset();\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort the child node.\n this.child.abort(agent);\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: [this.child.getDetails()]\n };\n }\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Fail node.\n * This node wraps a single child and will always move to the 'FAILED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Fail extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"fail\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.FAILED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FAIL\";\n}\n", "import Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Flip node.\n * This node wraps a single child and will flip the state of the child state.\n */\nexport default class Flip extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"flip\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n this.setState(State.FAILED);\n break;\n\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FLIP\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A REPEAT node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The REPEAT node will stop and have a 'FAILED' state if its child is ever in a 'FAILED' state after an update.\n * The REPEAT node will attempt to move on to the next iteration if its child is ever in a 'SUCCEEDED' state.\n */\nexport default class Repeat extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param iterations The number of iterations to repeat the child node.\n * @param iterationsMin The minimum possible number of iterations to repeat the child node.\n * @param iterationsMax The maximum possible number of iterations to repeat the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, options, child);\n }\n\n /**\n * The number of target iterations to make.\n */\n private targetIterationCount: number | null = null;\n\n /**\n * The current iteration count.\n */\n private currentIterationCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target iteration count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the FAILED state when we updated it then there is nothing left to do and this node has also failed.\n // If it has moved into the SUCCEEDED state then we have completed the current iteration.\n if (this.child.getState() === State.FAILED) {\n // The child has failed, meaning that this node has failed.\n this.setState(State.FAILED);\n\n return;\n } else if (this.child.getState() === State.SUCCEEDED) {\n // We have completed an iteration.\n this.currentIterationCount += 1;\n }\n } else {\n // This node is in the 'SUCCEEDED' state as we cannot iterate any more.\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.iterations !== null) {\n return `REPEAT ${this.iterations}x`;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n return `REPEAT ${this.iterationsMin}x-${this.iterationsMax}x`;\n } else {\n return \"REPEAT\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with an explicit iteration count or will we be randomly picking a iteration count between the min and max iteration count.\n if (this.iterations !== null) {\n this.targetIterationCount = this.iterations;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n // We will be picking a random iteration count between a min and max iteration count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random iteration count between a min and max iteration count.\n this.targetIterationCount = Math.floor(\n random() * (this.iterationsMax - this.iterationsMin + 1) + this.iterationsMin\n );\n } else {\n this.targetIterationCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RETRY node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The RETRY node will stop and have a 'SUCCEEDED' state if its child is ever in a 'SUCCEEDED' state after an update.\n * The RETRY node will attempt to move on to the next iteration if its child is ever in a 'FAILED' state.\n */\nexport default class Retry extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param attempts The number of attempts to retry the child node.\n * @param attemptsMin The minimum possible number of attempts to retry the child node.\n * @param attemptsMax The maximum possible number of attempts to retry the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, options, child);\n }\n\n /**\n * The number of target attempts to make.\n */\n private targetAttemptCount: number | null = null;\n\n /**\n * The current attempt count.\n */\n private currentAttemptCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target attempt count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Set the target attempt count.\n this.setTargetAttemptCount();\n }\n\n // Do a check to see if we can attempt. If we can then this node will move into the 'RUNNING' state.\n // If we cannot attempt then we have hit our target attempt count, which means that the node has succeeded.\n if (this.canAttempt()) {\n // This node is in the running state and can do its initial attempt.\n this.setState(State.RUNNING);\n\n // We may have already completed an attempt, meaning that the child node will be in the FAILED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.FAILED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the SUCCEEDED state when we updated it then there is nothing left to do and this node has also succeeded.\n // If it has moved into the FAILED state then we have completed the current attempt.\n if (this.child.getState() === State.SUCCEEDED) {\n // The child has succeeded, meaning that this node has succeeded.\n this.setState(State.SUCCEEDED);\n\n return;\n } else if (this.child.getState() === State.FAILED) {\n // We have completed an attempt.\n this.currentAttemptCount += 1;\n }\n } else {\n // This node is in the 'FAILED' state as we cannot iterate any more.\n this.setState(State.FAILED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.attempts !== null) {\n return `RETRY ${this.attempts}x`;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n return `RETRY ${this.attemptsMin}x-${this.attemptsMax}x`;\n } else {\n return \"RETRY\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an attempt can be made.\n * @returns Whether an attempt can be made.\n */\n canAttempt = () => {\n if (this.targetAttemptCount !== null) {\n // We can attempt as long as we have not reached our target attempt count.\n return this.currentAttemptCount < this.targetAttemptCount;\n }\n\n // If neither an attempt count or a condition function were defined then we can attempt indefinitely.\n return true;\n };\n\n /**\n * Sets the target attempt count.\n */\n setTargetAttemptCount = () => {\n // Are we dealing with an explicit attempt count or will we be randomly picking an attempt count between the min and max attempt count.\n if (this.attempts !== null) {\n this.targetAttemptCount = this.attempts;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n // We will be picking a random attempt count between a min and max attempt count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random attempt count between a min and max attempt count.\n this.targetAttemptCount = Math.floor(\n random() * (this.attemptsMax - this.attemptsMin + 1) + this.attemptsMin\n );\n } else {\n this.targetAttemptCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Root node.\n * The root node will have a single child.\n */\nexport default class Root extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"root\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n // Update the child of this node.\n this.child.update(agent);\n }\n\n // The state of the root node is the state of its child.\n this.setState(this.child.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ROOT\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Succeed node.\n * This node wraps a single child and will always move to the 'SUCCEEDED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Succeed extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"succeed\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SUCCEED\";\n}\n", "import Node from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => true;\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State, { CompleteState } from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * The type representing a resolved/rejected update promise.\n */\ntype UpdatePromiseResult = {\n /**\n * Whether the promise was resolved rather than rejected.\n */\n isResolved: boolean;\n\n /**\n * The promise resolved value or rejection reason.\n */\n value: any;\n};\n\n/**\n * An Action leaf node.\n * This represents an immediate or ongoing state of behaviour.\n */\nexport default class Action extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param actionName The action name.\n * @param actionArguments The array of action arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private actionName: string,\n public actionArguments: any[]\n ) {\n super(\"action\", attributes, options);\n }\n\n /**\n * Whether there is a pending update promise.\n */\n private isUsingUpdatePromise = false;\n\n /**\n * The finished state result of an update promise.\n */\n private updatePromiseResult: UpdatePromiseResult | null = null;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the result of this action depends on an update promise then there is nothing to do until it settles.\n if (this.isUsingUpdatePromise) {\n // Are we still waiting for our update promise to settle?\n if (!this.updatePromiseResult) {\n return;\n }\n\n const { isResolved, value } = this.updatePromiseResult;\n\n // Our update promise settled, was it resolved or rejected?\n if (isResolved) {\n // Our promise resolved so check to make sure the result is a valid finished state.\n if (value !== State.SUCCEEDED && value !== State.FAILED) {\n throw new Error(\n \"action node promise resolved with an invalid value, expected a State.SUCCEEDED or State.FAILED value to be returned\"\n );\n }\n\n // Set the state of this node to match the state returned by the promise.\n this.setState(value);\n\n return;\n } else {\n // The promise was rejected, which isn't great.\n throw new Error(`action function '${this.actionName}' promise rejected with '${value}'`);\n }\n }\n\n // Attempt to get the invoker for the action function.\n const actionFuncInvoker = Lookup.getFuncInvoker(agent, this.actionName);\n\n // The action function should be defined.\n if (actionFuncInvoker === null) {\n throw new Error(\n `cannot update action node as the action '${this.actionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let actionFunctionResult;\n\n try {\n // Call the action function, the result of which may be:\n // - The finished state of this action node.\n // - A promise to return a finished node state.\n // - Undefined if the node should remain in the running state.\n actionFunctionResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`action function '${this.actionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`action function '${this.actionName}' threw: ${error}`);\n }\n }\n\n if (actionFunctionResult instanceof Promise) {\n actionFunctionResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the resolved update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: true,\n value: result\n };\n },\n (reason) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort or reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the rejected update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: false,\n value: reason\n };\n }\n );\n\n // This node will be in the 'RUNNING' state until the update promise resolves.\n this.setState(State.RUNNING);\n\n // We are now waiting for the promise returned by the use to resolve before we know what state this node is in.\n this.isUsingUpdatePromise = true;\n } else {\n // Validate the returned value.\n this.validateUpdateResult(actionFunctionResult);\n\n // Set the state of this node, this may be undefined, which just means that the node is still in the 'RUNNING' state.\n this.setState(actionFunctionResult || State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.actionName;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // There is no longer an update promise that we care about.\n this.isUsingUpdatePromise = false;\n this.updatePromiseResult = null;\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.actionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.actionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n\n /**\n * Validate the result of an update function call.\n * @param result The result of an update function call.\n */\n private validateUpdateResult = (result: CompleteState | State.RUNNING) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case State.RUNNING:\n case undefined:\n return;\n default:\n throw new Error(\n `expected action function '${this.actionName}' to return an optional State.SUCCEEDED or State.FAILED value but returned '${result}'`\n );\n }\n };\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * A Condition leaf node.\n * This will succeed or fail immediately based on an agent predicate, without moving to the 'RUNNING' state.\n */\nexport default class Condition extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param conditionName The name of the condition function.\n * @param conditionArguments The array of condition arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private conditionName: string,\n public conditionArguments: any[]\n ) {\n super(\"condition\", attributes, options);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.conditionName);\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot update condition node as the condition '${this.conditionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.conditionArguments);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`condition function '${this.conditionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`condition function '${this.conditionName}' threw: ${error}`);\n }\n }\n\n // The result of calling the condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected condition function '${this.conditionName}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Set the state of this node based on the result of calling the condition function.\n this.setState(!!conditionFunctionResult ? State.SUCCEEDED : State.FAILED);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.conditionName;\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.conditionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.conditionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { Agent } from \"../../Agent\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A WAIT node.\n * The state of this node will change to SUCCEEDED after a duration of time\n */\nexport default class Wait extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param duration The duration that this node will wait to succeed in milliseconds.\n * @param durationMin The minimum possible duration in milliseconds that this node will wait to succeed.\n * @param durationMax The maximum possible duration in milliseconds that this node will wait to succeed.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, options);\n }\n\n /**\n * The time in milliseconds at which this node was first updated.\n */\n private initialUpdateTime: number = 0;\n\n /**\n * The total duration in milliseconds that this node will be waiting for.\n */\n private totalDuration: number | null = null;\n\n /**\n * The duration in milliseconds that this node has been waiting for.\n */\n private waitedDuration: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to set the initial update time.\n if (this.is(State.READY)) {\n // Set the initial update time.\n this.initialUpdateTime = new Date().getTime();\n\n // Set the initial waited duration.\n this.waitedDuration = 0;\n\n // Are we dealing with an explicit duration or will we be randomly picking a duration between the min and max duration.\n if (this.duration !== null) {\n this.totalDuration = this.duration;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // We will be picking a random duration between a min and max duration, if the optional 'random' behaviour tree\n // function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random duration between a min and max duration.\n this.totalDuration = Math.floor(\n random() * (this.durationMax - this.durationMin + 1) + this.durationMin\n );\n } else {\n this.totalDuration = null;\n }\n\n // The node is now running until we finish waiting.\n this.setState(State.RUNNING);\n }\n\n // If we have no total duration then this wait node will wait indefinitely until it is aborted.\n if (this.totalDuration === null) {\n return;\n }\n\n // If we have a 'getDeltaTime' function defined as part of our options then we will use it to figure out how long we have waited for.\n if (typeof this.options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = this.options.getDeltaTime();\n\n // Our delta time must be a valid number and cannot be NaN.\n if (typeof deltaTime !== \"number\" || isNaN(deltaTime)) {\n throw new Error(\"The delta time must be a valid number and not NaN.\");\n }\n\n // Update the amount of time that this node has been waiting for based on the delta time.\n this.waitedDuration += deltaTime * 1000;\n } else {\n // We are not using a delta time, so we will just work out hom much time has passed since the first update.\n this.waitedDuration = new Date().getTime() - this.initialUpdateTime;\n }\n\n // Have we waited long enough?\n if (this.waitedDuration >= this.totalDuration) {\n // We have finished waiting!\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.duration !== null) {\n return `WAIT ${this.duration}ms`;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n return `WAIT ${this.durationMin}ms-${this.durationMax}ms`;\n } else {\n return \"WAIT\";\n }\n };\n}\n", "import Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: any[];\n};\n\n/**\n * A base node attribute.\n */\nexport default abstract class Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of attribute arguments.\n */\n constructor(public type: string, public args: any[]) {}\n\n /**\n * Gets the attribute details.\n */\n abstract getDetails(): TAttributeDetails;\n\n /**\n * Gets whether this attribute is a guard.\n */\n abstract isGuard: () => this is Guard;\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node guard attribute.\n */\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node guard attribute.\n */\nexport default abstract class Guard extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n */\n constructor(type: string, args: any[], private condition: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the condition function that determines whether the guard is satisfied.\n */\n getCondition = () => this.condition;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => true;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): GuardAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getCondition()\n };\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n abstract isSatisfied(agent: Agent): boolean;\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A WHILE guard which is satisfied as long as the given condition remains true.\n */\nexport default class While extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"while\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return conditionFunctionResult;\n };\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An UNTIL guard which is satisfied as long as the given condition remains false.\n */\nexport default class Until extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"until\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return !conditionFunctionResult;\n };\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node callback attribute.\n */\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node callback attribute.\n */\nexport default abstract class Callback extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param functionName The name of the agent function to call.\n */\n constructor(type: string, args: any[], private functionName: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the agent function to call.\n */\n getFunctionName = () => this.functionName;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => false;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): CallbackAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getFunctionName()\n };\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n abstract callAgentFunction: (agent: Agent, isSuccess: boolean, isAborted: boolean) => void;\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An ENTRY callback which defines an agent function to call when the associated node is updated and moves out of running state.\n */\nexport default class Entry extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"entry\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call entry function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A STEP callback which defines an agent function to call when the associated node is updated.\n */\nexport default class Step extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"step\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call step function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An EXIT callback which defines an agent function to call when the associated node is updated and moves to a finished state or is aborted.\n */\nexport default class Exit extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"exit\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n * @param isSuccess Whether the decorated node was left with a success state.\n * @param isAborted Whether the decorated node was aborted.\n */\n callAgentFunction = (agent: Agent, isSuccess: boolean, isAborted: boolean) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call exit function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function\n callbackFuncInvoker([{ succeeded: isSuccess, aborted: isAborted }, ...this.args]);\n };\n}\n", "import { AnyNodeDefinition, RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport { validateBranchSubtreeLinks } from \"./BehaviourTreeDefinitionValidator\";\nimport { isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport Node from \"./nodes/Node\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Race from \"./nodes/composite/Race\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Root from \"./nodes/decorator/Root\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Lookup from \"./Lookup\";\nimport Attribute from \"./attributes/Attribute\";\nimport Guard from \"./attributes/guards/Guard\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\n/**\n * A type representing any node instance in a behaviour tree.\n */\ntype AnyNode =\n | Root\n | Action\n | Condition\n | Wait\n | Sequence\n | Selector\n | Lotto\n | Parallel\n | Race\n | Repeat\n | Retry\n | Flip\n | Succeed\n | Fail;\n\n/**\n * A type defining a mapping of root node identifiers to root node definitions.\n */\ntype RootNodeDefinitionMap = { [key: string | symbol]: RootNodeDefinition };\n\n/**\n * A symbol to use as the main root key in any root node mappings.\n */\nconst MAIN_ROOT_NODE_KEY = Symbol(\"__root__\");\n\n/**\n * Build and populate the root nodes based on the provided definition, assuming that the definition has been validated.\n * @param definition The root node definitions.\n * @param options The behaviour tree options.\n * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[], options: BehaviourTreeOptions): Root {\n // Create a mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n const rootNodeDefinitionMap = createRootNodeDefinitionMap(definition);\n\n // Now that we have all of our root node definitions (those part of the tree definition and those globally registered)\n // we should validate the branch-subtree links. This will also double-check that we dont have any circular dependencies\n // in our branch-subtree references and that we have no broken branch-subtree links.\n validateBranchSubtreeLinks(\n [rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], ...Object.values(rootNodeDefinitionMap)],\n true\n );\n\n // Create our populated tree of node instances, starting with our main root node.\n const rootNode = nodeFactory(rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], rootNodeDefinitionMap, options) as Root;\n\n // Set a guard path on every leaf of the tree to evaluate as part of each update.\n applyLeafNodeGuardPaths(rootNode);\n\n // We only need to return the main root node.\n return rootNode;\n}\n\n/**\n * A factory function which creates a node instance based on the specified definition.\n * @param definition The node definition.\n * @param rootNodeDefinitionMap The mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n * @param options The behaviour tree options.\n * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(\n definition: AnyNodeDefinition,\n rootNodeDefinitionMap: RootNodeDefinitionMap,\n options: BehaviourTreeOptions\n): AnyNode {\n // Get the attributes for the node.\n const attributes = nodeAttributesFactory(definition);\n\n // Create the node instance based on the definition type.\n switch (definition.type) {\n case \"root\":\n return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"repeat\":\n let iterations: number | null = null;\n let iterationsMin: number | null = null;\n let iterationsMax: number | null = null;\n\n if (Array.isArray(definition.iterations)) {\n iterationsMin = definition.iterations[0];\n iterationsMax = definition.iterations[1];\n } else if (isInteger(definition.iterations)) {\n iterations = definition.iterations!;\n }\n\n return new Repeat(\n attributes,\n options,\n iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"retry\":\n let attempts: number | null = null;\n let attemptsMin: number | null = null;\n let attemptsMax: number | null = null;\n\n if (Array.isArray(definition.attempts)) {\n attemptsMin = definition.attempts[0];\n attemptsMax = definition.attempts[1];\n } else if (isInteger(definition.attempts)) {\n attempts = definition.attempts!;\n }\n\n return new Retry(\n attributes,\n options,\n attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"flip\":\n return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"succeed\":\n return new Succeed(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"fail\":\n return new Fail(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"race\":\n return new Race(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n options,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap, options);\n\n case \"action\":\n return new Action(attributes, options, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, options, definition.call, definition.args || []);\n\n case \"wait\":\n let duration: number | null = null;\n let durationMin: number | null = null;\n let durationMax: number | null = null;\n\n if (Array.isArray(definition.duration)) {\n durationMin = definition.duration[0];\n durationMax = definition.duration[1];\n } else if (isInteger(definition.duration)) {\n duration = definition.duration!;\n }\n\n return new Wait(attributes, options, duration, durationMin, durationMax);\n }\n}\n\n/**\n * Creates an array of node attribute instances based on the specified node definition.\n * @param definition The node definition.\n * @returns An array of node attribute instances based on the specified node definition.\n */\nfunction nodeAttributesFactory(definition: AnyNodeDefinition): Attribute[] {\n const attributes: Attribute[] = [];\n\n if (definition.while) {\n attributes.push(new While(definition.while.call, definition.while.args ?? []));\n }\n\n if (definition.until) {\n attributes.push(new Until(definition.until.call, definition.until.args ?? []));\n }\n\n if (definition.entry) {\n attributes.push(new Entry(definition.entry.call, definition.entry.args ?? []));\n }\n\n if (definition.step) {\n attributes.push(new Step(definition.step.call, definition.step.args ?? []));\n }\n\n if (definition.exit) {\n attributes.push(new Exit(definition.exit.call, definition.exit.args ?? []));\n }\n\n return attributes;\n}\n\n/**\n * Creates a mapping of root node identifers to root node definitions, mixing in globally registered subtree root node definitions.\n * @param definition The root node definitions.\n * @returns A mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n */\nfunction createRootNodeDefinitionMap(definition: RootNodeDefinition[]): RootNodeDefinitionMap {\n // Create a mapping of root node identifers to root node definitions.\n const rootNodeMap: RootNodeDefinitionMap = {};\n\n // Add in any registered subtree root node definitions.\n for (const [name, rootNodeDefinition] of Object.entries(Lookup.getSubtrees())) {\n // The name used when registering the subtree will be used as the root node identifier.\n rootNodeMap[name] = { ...rootNodeDefinition, id: name };\n }\n\n // Populate the map with the root node definitions that were included with the tree definition.\n // We do this after adding any registered subtrees as we want these to take presedence.\n for (const rootNodeDefinition of definition) {\n rootNodeMap[rootNodeDefinition.id ?? MAIN_ROOT_NODE_KEY] = rootNodeDefinition;\n }\n\n return rootNodeMap;\n}\n\n/**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param root The main root tree node.\n */\nfunction applyLeafNodeGuardPaths(root: Root) {\n const nodePaths: Node[][] = [];\n\n const findLeafNodes = (path: Node[], node: Node) => {\n // Add the current node to the path.\n path = path.concat(node);\n\n // Check whether the current node is a leaf node.\n if (node.isLeafNode()) {\n nodePaths.push(path);\n } else {\n (node as Composite | Decorator).getChildren().forEach((child) => findLeafNodes(path, child));\n }\n };\n\n // Find all leaf node paths, starting from the root.\n findLeafNodes([], root);\n\n nodePaths.forEach((path) => {\n // Each node in the current path will have to be assigned a guard path, working from the root outwards.\n for (let depth = 0; depth < path.length; depth++) {\n // Get the node in the path at the current depth.\n const currentNode = path[depth];\n\n // The node may already have been assigned a guard path, if so just skip it.\n if (currentNode.hasGuardPath()) {\n continue;\n }\n\n // Create the guard path for the current node.\n const guardPath = new GuardPath(\n path\n .slice(0, depth + 1)\n .map((node) => ({\n node,\n guards: node.getAttributes().filter((attribute) => attribute.isGuard()) as Guard[]\n }))\n .filter((details) => details.guards.length > 0)\n );\n\n // Assign the guard path to the current node.\n currentNode.setGuardPath(guardPath);\n }\n });\n}\n", "import State, { AnyState } from \"./State\";\nimport Lookup from \"./Lookup\";\nimport Node, { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport { Agent, GlobalFunction } from \"./Agent\";\nimport { CallbackAttributeDetails } from \"./attributes/callbacks/Callback\";\nimport { GuardAttributeDetails } from \"./attributes/guards/Guard\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { validateDefinition, validateJSONDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport buildRootNode from \"./BehaviourTreeBuilder\";\nimport { isNullOrUndefined } from \"./BehaviourTreeDefinitionUtilities\";\n\n/**\n * A representation of a behaviour tree.\n */\nexport class BehaviourTree {\n /**\n * The main root tree node.\n */\n private readonly _rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition as either an MDSL string, root node definition object or array of root node definition objects.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param options The behaviour tree options object.\n */\n constructor(\n definition: string | RootNodeDefinition | RootNodeDefinition[],\n private agent: Agent,\n private options: BehaviourTreeOptions = {}\n ) {\n // The tree definition must be defined.\n if (isNullOrUndefined(definition)) {\n throw new Error(\"tree definition not defined\");\n }\n\n // The agent must be defined and not null.\n if (typeof agent !== \"object\" || agent === null) {\n throw new Error(\"the agent must be an object and not null\");\n }\n\n // We should validate the definition before we try to build the tree nodes.\n const { succeeded, errorMessage, json } = validateDefinition(definition);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(`invalid definition: ${errorMessage}`);\n }\n\n // Double check that we did actually get our json definition as part of our definition validtion.\n if (!json) {\n throw new Error(\n \"expected json definition to be returned as part of successful definition validation response\"\n );\n }\n\n try {\n // Create the populated tree of behaviour tree nodes and get the root node.\n this._rootNode = buildRootNode(json, options);\n } catch (exception) {\n // There was an issue in trying build and populate the behaviour tree.\n throw new Error(`error building tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Gets whether the tree is in the RUNNING state.\n * @returns true if the tree is in the RUNNING state, otherwise false.\n */\n public isRunning(): boolean {\n return this._rootNode.getState() === State.RUNNING;\n }\n\n /**\n * Gets the current tree state of SUCCEEDED, FAILED, READY or RUNNING.\n * @returns The current tree state.\n */\n public getState(): State {\n return this._rootNode.getState();\n }\n\n /**\n * Step the tree.\n * 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.\n * 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\n * 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.\n *\n * 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.\n */\n public step(): void {\n // If the root node has already been stepped to completion then we need to reset it.\n if (this._rootNode.getState() === State.SUCCEEDED || this._rootNode.getState() === State.FAILED) {\n this._rootNode.reset();\n }\n\n try {\n this._rootNode.update(this.agent);\n } catch (exception) {\n throw new Error(`error stepping tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Resets the tree from the root node outwards to each nested node, giving each a state of READY.\n */\n public reset(): void {\n this._rootNode.reset();\n }\n\n /**\n * Gets the details of every node in the tree, starting from the root.\n * @returns The details of every node in the tree, starting from the root.\n */\n public getTreeNodeDetails(): NodeDetails {\n return this._rootNode.getDetails();\n }\n\n /**\n * Registers the action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the function or subtree to register.\n * @param value The function or subtree definition to register.\n */\n static register(name: string, value: GlobalFunction | string | RootNodeDefinition) {\n // Are we going to register a action/condition/guard/callback function?\n if (typeof value === \"function\") {\n Lookup.setFunc(name, value);\n return;\n }\n\n // We are not registering an action/condition/guard/callback function, so we must be registering a subtree.\n if (typeof value === \"string\") {\n let rootNodeDefinitions: RootNodeDefinition[];\n\n // We will assume that any string passed in will be a mdsl definition.\n try {\n rootNodeDefinitions = convertMDSLToJSON(value);\n } catch (exception) {\n throw new Error(`error registering definition, invalid MDSL: ${(exception as Error).message}`);\n }\n\n // This function should only ever be called with a definition containing a single unnamed root node.\n if (rootNodeDefinitions.length != 1 || typeof rootNodeDefinitions[0].id !== \"undefined\") {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(rootNodeDefinitions[0]);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, rootNodeDefinitions[0]);\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // We will assume that any object passed in is a root node definition.\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(value);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, value);\n } else {\n throw new Error(\"unexpected value, expected string mdsl definition, root node json definition or function\");\n }\n }\n\n /**\n * Unregisters the registered action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the registered action/condition/guard/callback function or subtree to unregister.\n */\n static unregister(name: string): void {\n Lookup.remove(name);\n }\n\n /**\n * Unregister all registered action/condition/guard/callback functions and subtrees.\n */\n static unregisterAll(): void {\n Lookup.empty();\n }\n}\n"], - "mappings": "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", - "names": ["require_Participant", "__commonJSMin", "exports", "Participant", "participant", "tickets", "value", "require_Utilities", "__commonJSMin", "exports", "isNullOrUndefined", "value", "isNaturalNumber", "require_Lotto", "__commonJSMin", "exports", "Participant_1", "Utilities_1", "Lotto", "customRandom", "participant", "tickets", "existingParticipant", "part", "options", "redrawable", "pickable", "_a", "ticketCount", "random", "winner", "uniqueResults", "result", "unique", "_i", "result_1", "require_createLotto", "__commonJSMin", "exports", "Lotto_1", "createLotto", "participantsOrOptions", "participants", "lotto_1", "_a", "participant", "tokens", "random", "lotto_2", "require_dist", "__commonJSMin", "exports", "createLotto_1", "src_exports", "__export", "BehaviourTree", "State", "convertMDSLToJSON", "validateDefinition", "State", "Lookup", "name", "func", "agent", "agentFunction", "args", "registeredFunction", "subtree", "__publicField", "isRootNode", "node", "isBranchNode", "isLeafNode", "isDecoratorNode", "isCompositeNode", "flattenDefinition", "nodeDefinition", "nodes", "processNode", "currentNodeDefinition", "isInteger", "value", "isNullOrUndefined", "popAndCheck", "tokens", "expected", "popped", "expectedValues", "tokenMatchesExpectation", "item", "expectationString", "substituteStringLiterals", "definition", "placeholders", "processedDefinition", "match", "strippedMatch", "placeholder", "key", "parseTokensFromDefinition", "parseArgumentTokens", "tokens", "stringArgumentPlaceholders", "argumentList", "closingToken", "popAndCheck", "argumentListTokens", "token", "index", "argumentDefinition", "getArgumentDefinition", "parseAttributeTokens", "tokens", "stringArgumentPlaceholders", "nodeAttributeNames", "attributes", "nextAttributeName", "attributeCallIdentifier", "attributeArguments", "parseArgumentTokens", "arg", "value", "convertMDSLToJSON", "definition", "placeholders", "processedDefinition", "substituteStringLiterals", "tokens", "parseTokensFromDefinition", "convertTokensToJSONDefinition", "stringLiteralPlaceholders", "token", "treeStacks", "rootNodes", "pushNode", "node", "isRootNode", "topTreeStack", "topTreeStackTopNode", "isCompositeNode", "isDecoratorNode", "isLeafNode", "popNode", "poppedNode", "createRootNode", "createSucceedNode", "createFailNode", "createFlipNode", "createRepeatNode", "createRetryNode", "createSequenceNode", "createSelectorNode", "createParallelNode", "createRaceNode", "createLottoNode", "createActionNode", "createConditionNode", "createWaitNode", "createBranchNode", "validatePoppedNode", "nodeArguments", "parseArgumentTokens", "parseAttributeTokens", "popAndCheck", "arg", "value", "actionNameIdentifier", "agentFunctionArgs", "conditionNameIdentifier", "isNullOrUndefined", "validateDefinition", "definition", "createValidationFailureResult", "validateMDSLDefinition", "validateJSONDefinition", "rootNodeDefinitions", "convertMDSLToJSON", "exception", "mainRootNodeDefinitions", "id", "subRootNodeDefinitions", "subRootNodeIdenitifers", "validateBranchSubtreeLinks", "rootNodeDefinition", "validateNode", "error", "includesGlobalSubtrees", "rootNodeMappings", "flattenDefinition", "isBranchNode", "ref", "followRefs", "mapping", "path", "badPathFormatted", "element", "subMapping", "depth", "validateActionNode", "validateConditionNode", "validateWaitNode", "validateBranchNode", "validateRootNode", "validateSucceedNode", "validateFailNode", "validateFlipNode", "validateRepeatNode", "validateRetryNode", "validateSequenceNode", "validateSelectorNode", "validateParallelNode", "validateRaceNode", "validateLottoNode", "validateNodeAttributes", "attributeName", "attributeDefinition", "containsNonInteger", "value", "isInteger", "child", "errorMessage", "GuardUnsatisifedException", "source", "node", "GuardPath", "nodes", "agent", "details", "guard", "GuardUnsatisifedException", "createUid", "S4", "Node", "type", "attributes", "options", "createUid", "value", "previousState", "attribute", "agent", "error", "GuardUnsatisifedException", "Composite", "Node", "type", "attributes", "options", "children", "child", "agent", "Parallel", "Composite", "attributes", "options", "children", "agent", "child", "Race", "Composite", "attributes", "options", "children", "agent", "child", "Selector", "Composite", "attributes", "options", "children", "agent", "child", "Sequence", "Composite", "attributes", "options", "children", "agent", "child", "import_lotto_draw", "Lotto", "Composite", "attributes", "options", "weights", "children", "agent", "lottoDraw", "createLotto", "child", "index", "Decorator", "Node", "type", "attributes", "options", "child", "agent", "Fail", "Decorator", "attributes", "options", "child", "agent", "Flip", "Decorator", "attributes", "options", "child", "agent", "Repeat", "Decorator", "attributes", "options", "iterations", "iterationsMin", "iterationsMax", "child", "agent", "random", "Retry", "Decorator", "attributes", "options", "attempts", "attemptsMin", "attemptsMax", "child", "agent", "random", "Root", "Decorator", "attributes", "options", "child", "agent", "Succeed", "Decorator", "attributes", "options", "child", "agent", "Leaf", "Node", "Action", "Leaf", "attributes", "options", "actionName", "actionArguments", "agent", "isResolved", "value", "actionFuncInvoker", "Lookup", "actionFunctionResult", "error", "result", "reason", "previousState", "Condition", "Leaf", "attributes", "options", "conditionName", "conditionArguments", "agent", "conditionFuncInvoker", "Lookup", "conditionFunctionResult", "error", "previousState", "Wait", "Leaf", "attributes", "options", "duration", "durationMin", "durationMax", "agent", "random", "deltaTime", "Attribute", "type", "args", "Guard", "Attribute", "type", "args", "condition", "While", "Guard", "condition", "args", "agent", "conditionFuncInvoker", "Lookup", "conditionFunctionResult", "error", "Until", "Guard", "condition", "args", "agent", "conditionFuncInvoker", "Lookup", "conditionFunctionResult", "error", "Callback", "Attribute", "type", "args", "functionName", "Entry", "Callback", "functionName", "args", "agent", "callbackFuncInvoker", "Lookup", "Step", "Callback", "functionName", "args", "agent", "callbackFuncInvoker", "Lookup", "Exit", "Callback", "functionName", "args", "agent", "isSuccess", "isAborted", "callbackFuncInvoker", "Lookup", "MAIN_ROOT_NODE_KEY", "buildRootNode", "definition", "options", "rootNodeDefinitionMap", "createRootNodeDefinitionMap", "validateBranchSubtreeLinks", "rootNode", "nodeFactory", "applyLeafNodeGuardPaths", "attributes", "nodeAttributesFactory", "Root", "iterations", "iterationsMin", "iterationsMax", "isInteger", "Repeat", "attempts", "attemptsMin", "attemptsMax", "Retry", "Flip", "Succeed", "Fail", "Sequence", "child", "Selector", "Parallel", "Race", "Lotto", "Action", "Condition", "duration", "durationMin", "durationMax", "Wait", "While", "Until", "Entry", "Step", "Exit", "rootNodeMap", "name", "rootNodeDefinition", "Lookup", "root", "nodePaths", "findLeafNodes", "path", "node", "depth", "currentNode", "guardPath", "GuardPath", "attribute", "details", "BehaviourTree", "definition", "agent", "options", "isNullOrUndefined", "succeeded", "errorMessage", "json", "validateDefinition", "buildRootNode", "exception", "name", "value", "Lookup", "rootNodeDefinitions", "convertMDSLToJSON", "validateJSONDefinition"] + "sources": ["../node_modules/lotto-draw/dist/Participant.js", "../node_modules/lotto-draw/dist/Utilities.js", "../node_modules/lotto-draw/dist/Lotto.js", "../node_modules/lotto-draw/dist/createLotto.js", "../node_modules/lotto-draw/dist/index.js", "../src/index.ts", "../src/State.ts", "../src/Lookup.ts", "../src/BehaviourTreeDefinitionUtilities.ts", "../src/mdsl/MDSLUtilities.ts", "../src/mdsl/MDSLNodeArgumentParser.ts", "../src/mdsl/MDSLNodeAttributeParser.ts", "../src/mdsl/MDSLDefinitionParser.ts", "../src/BehaviourTreeDefinitionValidator.ts", "../src/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/Utilities.ts", "../src/nodes/Node.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Parallel.ts", "../src/nodes/composite/Race.ts", "../src/nodes/composite/All.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/leaf/Leaf.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/attributes/Attribute.ts", "../src/attributes/guards/Guard.ts", "../src/attributes/guards/While.ts", "../src/attributes/guards/Until.ts", "../src/attributes/callbacks/Callback.ts", "../src/attributes/callbacks/Entry.ts", "../src/attributes/callbacks/Step.ts", "../src/attributes/callbacks/Exit.ts", "../src/BehaviourTreeBuilder.ts", "../src/BehaviourTree.ts"], + "sourcesContent": ["\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Participant = void 0;\r\n/**\r\n * A participant that holds a number of tickets.\r\n */\r\nvar Participant = /** @class */ (function () {\r\n /**\r\n * Creates an instance of the Participant class.\r\n * @param participant The actual participant.\r\n * @param tickets The number of tickets held by the participant.\r\n */\r\n function Participant(participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n this._participant = participant;\r\n this._tickets = tickets;\r\n }\r\n Object.defineProperty(Participant.prototype, \"participant\", {\r\n /** Gets the actual participant. */\r\n get: function () {\r\n return this._participant;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n Object.defineProperty(Participant.prototype, \"tickets\", {\r\n /** Gets or sets the number of tickets held by the participant. */\r\n get: function () {\r\n return this._tickets;\r\n },\r\n set: function (value) {\r\n this._tickets = value;\r\n },\r\n enumerable: false,\r\n configurable: true\r\n });\r\n return Participant;\r\n}());\r\nexports.Participant = Participant;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.isNaturalNumber = exports.isNullOrUndefined = void 0;\r\n/**\r\n * Gets whether the value provided is null or undefined.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is null or undefined.\r\n */\r\nfunction isNullOrUndefined(value) {\r\n return value === null || value === undefined;\r\n}\r\nexports.isNullOrUndefined = isNullOrUndefined;\r\n/**\r\n * Gets whether the value provided is a natural number.\r\n * @param value The value to check.\r\n * @returns Whether the value provided is a natural number.\r\n */\r\nfunction isNaturalNumber(value) {\r\n return typeof value === \"number\" && value >= 1 && Math.floor(value) === value;\r\n}\r\nexports.isNaturalNumber = isNaturalNumber;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Lotto = void 0;\r\nvar Participant_1 = require(\"./Participant\");\r\nvar Utilities_1 = require(\"./Utilities\");\r\n/**\r\n * Represents a lotto consisting of a number of pickable ticket-holding participants.\r\n */\r\nvar Lotto = /** @class */ (function () {\r\n /**\r\n * Creates a new instance of Lotto.\r\n * @param customRandom The custom RNG to use in place of Math.random().\r\n */\r\n function Lotto(customRandom) {\r\n /** The array of participants that are holding tickets in the lotto. */\r\n this._participants = [];\r\n this._customRandom = customRandom;\r\n }\r\n /**\r\n * Adds a participant with the specified number of tickets, or adds to the participant ticket count if the participant already holds tickets.\r\n * @param participant The participant to add or to increase the ticket count for if they already hold tickets.\r\n * @param tickets The number of tickets, defaults to 1.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.add = function (participant, tickets) {\r\n if (tickets === void 0) { tickets = 1; }\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n // Check whether this participant has already been added.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n if (existingParticipant) {\r\n // The participant has already been added to the lotto so just add to their ticket count.\r\n existingParticipant.tickets += tickets;\r\n }\r\n else {\r\n // The participant is not part of the lotto so we should add them.\r\n this._participants.push(new Participant_1.Participant(participant, tickets));\r\n }\r\n return this;\r\n };\r\n /**\r\n * Removes the specified number of tickets for the given participant from the draw, or all tickets if a ticket number is not defined.\r\n * @param participant The participant to remove tickets for.\r\n * @param tickets The number of tickets to remove, or undefined if all tickets are to be removed.\r\n * @returns The Lotto instance.\r\n */\r\n Lotto.prototype.remove = function (participant, tickets) {\r\n // Attempt to get the existing participant.\r\n var existingParticipant = this._participants.find(function (part) { return part.participant === participant; });\r\n // There is nothing to do if the specified participant isn't even part of the lotto.\r\n if (!existingParticipant) {\r\n return this;\r\n }\r\n // Check whether a tickets value was given.\r\n if (tickets !== undefined) {\r\n // Check that we have a valid ticket count.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n existingParticipant.tickets -= tickets;\r\n // If the participant no longer holds any tickets then they should be removed.\r\n if (existingParticipant.tickets < 1) {\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n }\r\n else {\r\n // We are removing all tickets for the participant so just remove them from the lotto.\r\n this._participants = this._participants.filter(function (part) { return part !== existingParticipant; });\r\n }\r\n return this;\r\n };\r\n /**\r\n * Draw a winning ticket and return the participant that holds the ticket.\r\n * @param options The draw options.\r\n * @returns The participant that holds the winning ticket.\r\n */\r\n Lotto.prototype.draw = function (options) {\r\n if (options === void 0) { options = {}; }\r\n // If we have no participants then just return null.\r\n if (this._participants.length === 0) {\r\n return null;\r\n }\r\n var redrawable = (0, Utilities_1.isNullOrUndefined)(options.redrawable) ? true : options.redrawable;\r\n var pickable = [];\r\n this._participants.forEach(function (_a) {\r\n var participant = _a.participant, tickets = _a.tickets;\r\n for (var ticketCount = 0; ticketCount < tickets; ticketCount++) {\r\n pickable.push(participant);\r\n }\r\n });\r\n var random;\r\n // We need a random floating-point number between 0 (inclusive) and 1 to scale up to pick our winner.\r\n // If a custom random function exists then we should use that or fall back to Math.random().\r\n if (this._customRandom) {\r\n // Call our custom random function to get a random floating-point number.\r\n random = this._customRandom();\r\n // Verify that the result of calling our custom random function is a number between 0 (inclusive) and 1.\r\n if (typeof random !== \"number\" || random < 0 || random >= 1) {\r\n throw new Error(\"the 'random' function provided did not return a number between 0 (inclusive) and 1\");\r\n }\r\n }\r\n else {\r\n // No custom random function was defined so just use good ol' Math.random().\r\n random = Math.random();\r\n }\r\n // Pick a winning participant.\r\n var winner = pickable[Math.floor(random * pickable.length)];\r\n // If the ticket isn't redrawable then we should remove a ticket from the winning participants ticket count.\r\n if (!redrawable) {\r\n this.remove(winner, 1);\r\n }\r\n // Return the winning participant.\r\n return winner;\r\n };\r\n /**\r\n * Draws multiple winning tickets and return an array of the participants that hold the winning tickets.\r\n * @param tickets The number of winning tickets to draw.\r\n * @param options The draw multiple options.\r\n * @returns An array of the participants that hold the winning tickets.\r\n */\r\n Lotto.prototype.drawMultiple = function (tickets, options) {\r\n if (options === void 0) { options = {}; }\r\n var uniqueResults = (0, Utilities_1.isNullOrUndefined)(options.unique) ? false : options.unique;\r\n // Handle cases where the user has asked for zero tickets (no idea why they would do this be we should trust them).\r\n if (tickets === 0) {\r\n return [];\r\n }\r\n // Now that we know out tickets value is not zero we should check that it is a valid natural number.\r\n if (!(0, Utilities_1.isNaturalNumber)(tickets)) {\r\n throw new Error(\"tickets value must be a natural number\");\r\n }\r\n var result = [];\r\n // Keep drawing tickets until we either reach the number of required tickets or we simply run out of tickets to draw.\r\n // We can run out of tickets to draw if 'options.redrawable' is explicity 'false' or we just had no participants when 'drawMultiple' was called.\r\n while (result.length < tickets && this._participants.length > 0) {\r\n result.push(this.draw(options));\r\n }\r\n // If the 'unique' draw option is set then we need to remove duplicates from the result list.\r\n if (uniqueResults) {\r\n // Create an array to store our unique results.\r\n var unique = [];\r\n // Iterate over all of our participants (with potential duplicates) and populate our array of unique values.\r\n for (var _i = 0, result_1 = result; _i < result_1.length; _i++) {\r\n var participant = result_1[_i];\r\n if (unique.indexOf(participant) === -1) {\r\n unique.push(participant);\r\n }\r\n }\r\n result = unique;\r\n }\r\n return result;\r\n };\r\n return Lotto;\r\n}());\r\nexports.Lotto = Lotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.createLotto = void 0;\r\nvar Lotto_1 = require(\"./Lotto\");\r\n/**\r\n * A function that creates and returns a Lotto instance.\r\n * @param participantsOrOptions An array of initial participants or options relating to the creation of a Lotto instance.\r\n * @returns A new Lotto instance.\r\n */\r\nfunction createLotto(participantsOrOptions) {\r\n // If no initial participants or lotto options were provided as an argument then we can just return a new lotto instance now.\r\n if (!participantsOrOptions) {\r\n return new Lotto_1.Lotto();\r\n }\r\n // Check whether we were provided with an array of initial participants or a lotto options object.\r\n if (Array.isArray(participantsOrOptions)) {\r\n // We are dealing with a pre-defined array of participants.\r\n var participants = participantsOrOptions;\r\n var lotto_1 = new Lotto_1.Lotto();\r\n // If the lotto participants have been defined upfront then we will need to add them all to our lotto instance now.\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_1.add(participant, tokens);\r\n });\r\n // Return the Lotto instance.\r\n return lotto_1;\r\n }\r\n else {\r\n // We are dealing with some lotto options.\r\n var random = participantsOrOptions.random, participants = participantsOrOptions.participants;\r\n // Create a Lotto instance passing the custom RNG function to use in place of Math.random() (which could be undefined).\r\n var lotto_2 = new Lotto_1.Lotto(random);\r\n // If the lotto participants have been defined upfront as part of the options then we will need to add them all to our lotto instance now.\r\n if (participants) {\r\n participants.forEach(function (_a) {\r\n var participant = _a[0], tokens = _a[1];\r\n return lotto_2.add(participant, tokens);\r\n });\r\n }\r\n // Return the Lotto instance.\r\n return lotto_2;\r\n }\r\n}\r\nexports.createLotto = createLotto;\r\n", "\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar createLotto_1 = require(\"./createLotto\");\r\nexports.default = createLotto_1.createLotto;\r\n", "import State from \"./State\";\nimport { BehaviourTree } from \"./BehaviourTree\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { NodeDetails, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n /**\n * The state that a node will be in when it has not been visited yet in the execution of the tree.\n */\n READY = \"mistreevous.ready\",\n /**\n * The state that a node will be in when it is still being processed and will usually represent or encompass a long-running action.\n */\n RUNNING = \"mistreevous.running\",\n /**\n * The state that a node will be in when it is no longer being processed and has succeeded.\n */\n SUCCEEDED = \"mistreevous.succeeded\",\n /**\n * The state that a node will be in when it is no longer being processed but has failed.\n */\n FAILED = \"mistreevous.failed\"\n}\n\nexport { State as default };\n\nexport type CompleteState = State.SUCCEEDED | State.FAILED;\nexport type AnyState = State.READY | State.RUNNING | CompleteState;\n", "import { ActionResult, Agent, GlobalFunction } from \"./Agent\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\n\nexport type InvokerFunction = (args: any[]) => ActionResult | boolean;\n\n/**\n * A singleton used to store and lookup registered functions and subtrees.\n */\nexport default class Lookup {\n /**\n * The object holding any registered functions keyed on function name.\n */\n private static registeredFunctions: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered subtree root node definitions keyed on tree name.\n */\n private static registeredSubtrees: { [key: string]: RootNodeDefinition } = {};\n\n /**\n * Gets the function with the specified name.\n * @param name The name of the function.\n * @returns The function with the specified name.\n */\n public static getFunc(name: string): GlobalFunction {\n return this.registeredFunctions[name];\n }\n\n /**\n * Sets the function with the specified name for later lookup.\n * @param name The name of the function.\n * @param func The function.\n */\n public static setFunc(name: string, func: GlobalFunction): void {\n this.registeredFunctions[name] = func;\n }\n\n /**\n * Gets the function invoker for the specified agent and function name.\n * If a function with the specified name exists on the agent object then it will\n * be returned, otherwise we will then check the registered functions for a match.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param name The function name.\n * @returns The function invoker for the specified agent and function name.\n */\n static getFuncInvoker(agent: Agent, name: string): InvokerFunction | null {\n // Check whether the agent contains the specified function.\n const agentFunction = agent[name];\n if (agentFunction && typeof agentFunction === \"function\") {\n return (args: any[]) => agentFunction.apply(agent, args);\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.registeredFunctions[name] && typeof this.registeredFunctions[name] === \"function\") {\n const registeredFunction = this.registeredFunctions[name];\n return (args: any[]) => registeredFunction(agent, ...args);\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets all registered subtree root node definitions.\n */\n static getSubtrees(): { [key: string]: RootNodeDefinition } {\n return this.registeredSubtrees;\n }\n\n /**\n * Sets the subtree with the specified name for later lookup.\n * @param name The name of the subtree.\n * @param subtree The subtree.\n */\n static setSubtree(name: string, subtree: RootNodeDefinition) {\n this.registeredSubtrees[name] = subtree;\n }\n\n /**\n * Removes the registered function or subtree with the specified name.\n * @param name The name of the registered function or subtree.\n */\n static remove(name: string) {\n delete this.registeredFunctions[name];\n delete this.registeredSubtrees[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.registeredFunctions = {};\n this.registeredSubtrees = {};\n }\n}\n", "import {\n NodeDefinition,\n RootNodeDefinition,\n DecoratorNodeDefinition,\n CompositeNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition\n} from \"./BehaviourTreeDefinition\";\n\n/**\n * A type guard function that returns true if the specified node satisfies the RootNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the RootNodeDefinition type.\n */\nexport function isRootNode(node: NodeDefinition): node is RootNodeDefinition {\n return node.type === \"root\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the BranchNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the BranchNodeDefinition type.\n */\nexport function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition {\n return node.type === \"branch\";\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the NodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the NodeDefinition type.\n */\nexport function isLeafNode(node: NodeDefinition): node is NodeDefinition {\n return [\"branch\", \"action\", \"condition\", \"wait\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the DecoratorNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the DecoratorNodeDefinition type.\n */\nexport function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefinition {\n return [\"root\", \"repeat\", \"retry\", \"flip\", \"succeed\", \"fail\"].includes(node.type);\n}\n\n/**\n * A type guard function that returns true if the specified node satisfies the CompositeNodeDefinition type.\n * @param node The node.\n * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type.\n */\nexport function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition {\n return [\"sequence\", \"selector\", \"lotto\", \"parallel\", \"race\", \"all\"].includes(node.type);\n}\n\n/**\n * Flatten a node definition into an array of all of its nested node definitions.\n * @param nodeDefinition The node definition to flatten.\n * @returns An array of all of nested node definitions.\n */\nexport function flattenDefinition(nodeDefinition: AnyNodeDefinition): AnyNodeDefinition[] {\n const nodes: AnyNodeDefinition[] = [];\n\n const processNode = (currentNodeDefinition: AnyNodeDefinition) => {\n nodes.push(currentNodeDefinition);\n\n if (isCompositeNode(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNode(currentNodeDefinition)) {\n processNode(currentNodeDefinition.child);\n }\n };\n\n processNode(nodeDefinition);\n\n return nodes;\n}\n\n/**\n * Determines whether the passed value is an integer.\n * @param value The value to check.\n * @returns Whether the passed value is an integer.\n */\nexport function isInteger(value: unknown): boolean {\n return typeof value === \"number\" && Math.floor(value) === value;\n}\n\n/**\n * Determines whether the passed value is null or undefined.\n * @param value The value to check.\n * @returns Whether the passed value is null or undefined.\n */\nexport function isNullOrUndefined(value: unknown): boolean {\n return typeof value === \"undefined\" || value === null;\n}\n", "/**\n * A type defining an object that holds a reference to substitued string literals parsed from the definition.\n */\nexport type StringLiteralPlaceholders = { [key: string]: string };\n\n/**\n * Pop the next raw token from the specified array of tokens and throw an error if it wasn't the expected one.\n * @param tokens The array of tokens.\n * @param expected An optional string or array or items, one of which must match the next popped token.\n * @returns The popped token.\n */\nexport function popAndCheck(tokens: string[], expected?: string | string[]): string {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token but there aren't any.\n if (popped === undefined) {\n throw new Error(\"unexpected end of definition\");\n }\n\n // Do we have an expected token/tokens array?\n if (expected != undefined) {\n // Get an array of expected values, if the popped token matches any then we are all good.\n const expectedValues = typeof expected === \"string\" ? [expected] : expected;\n\n // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase());\n\n // Throw an error if the popped token didn't match any of our expected items.\n if (!tokenMatchesExpectation) {\n const expectationString = expectedValues.map((item) => \"'\" + item + \"'\").join(\" or \");\n throw new Error(\"unexpected token found. Expected \" + expectationString + \" but got '\" + popped + \"'\");\n }\n }\n\n // Return the popped token.\n return popped;\n}\n\n/**\n * Swaps out any node/attribute argument string literals with placeholders.\n * @param definition The definition.\n * @returns An object containing a mapping of placeholders to original string values as well as the processed definition string.\n */\nexport function substituteStringLiterals(definition: string): {\n placeholders: StringLiteralPlaceholders;\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: StringLiteralPlaceholders = {};\n\n // Replace any string literals wrapped with double quotes in our definition with placeholders to be processed later.\n const processedDefinition = definition.replace(/\\\"(\\\\.|[^\"\\\\])*\\\"/g, (match) => {\n var strippedMatch = match.substring(1, match.length - 1);\n var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch);\n\n // If we have no existing string literal match then create a new placeholder.\n if (!placeholder) {\n placeholder = `@@${Object.keys(placeholders).length}@@`;\n placeholders[placeholder] = strippedMatch;\n }\n\n return placeholder;\n });\n\n return { placeholders, processedDefinition };\n}\n\n/**\n * Parse the tree definition into an array of raw tokens.\n * @param definition The definition.\n * @returns An array of tokens parsed from the definition.\n */\nexport function parseTokensFromDefinition(definition: string): string[] {\n // Add some space around various important characters so that they can be plucked out easier as individual tokens.\n definition = definition.replace(/\\(/g, \" ( \");\n definition = definition.replace(/\\)/g, \" ) \");\n definition = definition.replace(/\\{/g, \" { \");\n definition = definition.replace(/\\}/g, \" } \");\n definition = definition.replace(/\\]/g, \" ] \");\n definition = definition.replace(/\\[/g, \" [ \");\n definition = definition.replace(/\\,/g, \" , \");\n\n // Split the definition into raw token form and return it.\n return definition.replace(/\\s+/g, \" \").trim().split(\" \");\n}\n", "import { StringLiteralPlaceholders, popAndCheck } from \"./MDSLUtilities\";\n\n/**\n * A type representing any node function argument.\n */\ntype Argument = {\n /**\n * The argument value.\n */\n value: T;\n /**\n * The argument type, used for validation.\n */\n type: string;\n};\n\ntype NullArgument = Argument & {\n type: \"null\";\n};\n\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\n\ntype NumberArgument = Argument & {\n type: \"number\";\n /**\n * A flag defining whether the number argument value is a valid integer. (used for validation)\n */\n isInteger: boolean;\n};\n\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\n\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\n\n/**\n * A type representing a reference to any node function argument.\n */\ntype AnyArgument = NullArgument | BooleanArgument | NumberArgument | StringPlaceholderArgument | IdentifierArgument;\n\n/**\n * Parse an array of argument definitions from the specified tokens array.\n * @param tokens The array tokens to parse the argument definitions from.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @param argumentValidator The argument validator function.\n * @param validationFailedMessage The exception message to throw if argument validation fails.\n * @returns An array of argument definitions parsed from the specified tokens array.\n */\nexport function parseArgumentTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): AnyArgument[] {\n const argumentList: AnyArgument[] = [];\n\n // If the next token is not a '[' or '(' then we have no arguments to parse.\n if (![\"[\", \"(\"].includes(tokens[0])) {\n return argumentList;\n }\n\n // Any lists of arguments will always be wrapped in '[]' for node arguments or '()' for attribute arguments.\n // We are looking for a '[' or '(' opener that wraps the argument tokens and the relevant closer.\n const closingToken = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closingToken) {\n // The next token is part of our arguments list.\n argumentListTokens.push(tokens.shift()!);\n }\n\n // Validate the order of the argument tokens. Each token must either be a ',' or a single argument that satisfies the validator.\n argumentListTokens.forEach((token, index) => {\n // Get whether this token should be an actual argument.\n const shouldBeArgumentToken = !(index & 1);\n\n // If the current token should be an actual argument then validate it, otherwise it should be a ',' token.\n if (shouldBeArgumentToken) {\n // Get the argument definition.\n const argumentDefinition = getArgumentDefinition(token, stringArgumentPlaceholders);\n\n // This is a valid argument!\n argumentList.push(argumentDefinition);\n } else {\n // The current token should be a ',' token.\n if (token !== \",\") {\n throw new Error(`invalid argument list, expected ',' or ']' but got '${token}'`);\n }\n }\n });\n\n // The arguments list should terminate with a ']' or ')' token, depending on the opener.\n popAndCheck(tokens, closingToken);\n\n // Return the arguments.\n return argumentList;\n}\n\n/**\n * Gets an argument value definition.\n * @param token The argument token.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An argument value definition.\n */\nfunction getArgumentDefinition(token: string, stringArgumentPlaceholders: StringLiteralPlaceholders): AnyArgument {\n // Check whether the token represents a null value.\n if (token === \"null\") {\n return {\n value: null,\n type: \"null\"\n } as NullArgument;\n }\n\n // Check whether the token represents a boolean value.\n if (token === \"true\" || token === \"false\") {\n return {\n value: token === \"true\",\n type: \"boolean\"\n } as BooleanArgument;\n }\n\n // Check whether the token represents a number value.\n // TODO: Relies on broken isNaN - see MDN.\n // if (!Number.isNaN(token)) {\n if (!isNaN(token as any)) {\n return {\n value: parseFloat(token),\n isInteger: parseFloat(token) === parseInt(token, 10),\n type: \"number\"\n } as NumberArgument;\n }\n\n // Check whether the token is a placeholder (e.g. @@0@@) representing a string literal.\n if (token.match(/^@@\\d+@@$/g)) {\n return {\n value: stringArgumentPlaceholders[token].replace('\\\\\"', '\"'),\n type: \"string\"\n } as StringPlaceholderArgument;\n }\n\n // The only remaining option is that the argument value is an identifier.\n return {\n value: token,\n type: \"identifier\"\n } as IdentifierArgument;\n}\n", "import { NodeAttributeDefinition } from \"../BehaviourTreeDefinition\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { StringLiteralPlaceholders } from \"./MDSLUtilities\";\n\n/**\n * A type defining the attribute definitions of a node.\n */\ntype NodeAttributes = {\n while?: NodeAttributeDefinition;\n until?: NodeAttributeDefinition;\n entry?: NodeAttributeDefinition;\n exit?: NodeAttributeDefinition;\n step?: NodeAttributeDefinition;\n};\n\n/**\n * Parse any node attribute definitions from the specified tokens array.\n * @param tokens The array of remaining tokens.\n * @param stringArgumentPlaceholders The mapping of string literal node argument placeholders to original values.\n * @returns An object of attribute definitions defined by any directly following tokens.\n */\nexport function parseAttributeTokens(\n tokens: string[],\n stringArgumentPlaceholders: StringLiteralPlaceholders\n): NodeAttributes {\n const nodeAttributeNames: (keyof NodeAttributes)[] = [\"while\", \"until\", \"entry\", \"exit\", \"step\"];\n\n // Create an object to hold any attributes found.\n const attributes: NodeAttributes = {};\n\n // Try to get the name of the attribute for the next token.\n let nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n\n // Pull attribute tokens as well as their arguments off of the tokens stack until we have no more.\n while (nodeAttributeNames.includes(nextAttributeName)) {\n // Check to make sure that we have not already created an attribute definition of this type.\n if (attributes[nextAttributeName]) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Remove the attribute name token from the array of tokens.\n tokens.shift();\n\n // Grab the attribute arguments, assuming the first to be an identifier.\n const [attributeCallIdentifier, ...attributeArguments] = parseArgumentTokens(\n tokens,\n stringArgumentPlaceholders\n );\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeCallIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected agent function or registered function name identifier argument for attribute\");\n }\n\n // Any attribute arguments (other than the expected call identifier) must have a type of string, number, boolean or null.\n attributeArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid attribute argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Create the attribute definition and add it to the object of attribute definitions found.\n attributes[nextAttributeName] = {\n call: attributeCallIdentifier.value,\n args: attributeArguments.map(({ value }) => value)\n };\n\n // Try to get the next attribute name token, as there could be multiple.\n nextAttributeName = tokens[0]?.toLowerCase() as keyof NodeAttributes;\n }\n\n return attributes;\n}\n", "import {\n ActionNodeDefinition,\n AnyChildNodeDefinition,\n AnyNodeDefinition,\n BranchNodeDefinition,\n ConditionNodeDefinition,\n FailNodeDefinition,\n FlipNodeDefinition,\n LottoNodeDefinition,\n ParallelNodeDefinition,\n RaceNodeDefinition,\n AllNodeDefinition,\n RepeatNodeDefinition,\n RetryNodeDefinition,\n RootNodeDefinition,\n SelectorNodeDefinition,\n SequenceNodeDefinition,\n SucceedNodeDefinition,\n WaitNodeDefinition\n} from \"../BehaviourTreeDefinition\";\nimport {\n isCompositeNode,\n isDecoratorNode,\n isLeafNode,\n isNullOrUndefined,\n isRootNode\n} from \"../BehaviourTreeDefinitionUtilities\";\nimport { parseArgumentTokens } from \"./MDSLNodeArgumentParser\";\nimport { parseAttributeTokens } from \"./MDSLNodeAttributeParser\";\nimport {\n StringLiteralPlaceholders,\n parseTokensFromDefinition,\n popAndCheck,\n substituteStringLiterals\n} from \"./MDSLUtilities\";\n\n/**\n * Convert the MDSL tree definition string into an equivalent JSON definition.\n * @param definition The tree definition string as MDSL.\n * @returns The root node JSON definitions.\n */\nexport function convertMDSLToJSON(definition: string): RootNodeDefinition[] {\n // Swap out any node/attribute argument string literals with a placeholder and get a mapping of placeholders to original values as well as the processed definition.\n const { placeholders, processedDefinition } = substituteStringLiterals(definition);\n\n // Parse our definition definition string into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\n return convertTokensToJSONDefinition(tokens, placeholders);\n}\n\n/**\n * Converts the specified tree definition tokens into a JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definitions.\n */\nfunction convertTokensToJSONDefinition(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RootNodeDefinition[] {\n // There must be at least 3 tokens for the tree definition to be valid. 'ROOT', '{' and '}'.\n if (tokens.length < 3) {\n throw new Error(\"invalid token count\");\n }\n\n // We should have a matching number of '{' and '}' tokens. If not, then there are scopes that have not been properly closed.\n if (tokens.filter((token) => token === \"{\").length !== tokens.filter((token) => token === \"}\").length) {\n throw new Error(\"scope character mismatch\");\n }\n\n // Create an array of tree stack arrays where root nodes will always be at the botton and the current composite/decorator node at the top.\n // There should be an element in this array for every root node defined and every element should be an array with a root note as the first element.\n // E.g. A definition with two root nodes defined:\n // [\n // [root, lotto, sequence],\n // [root, selector]\n // ]\n const treeStacks: [Partial, ...Partial[]][] = [];\n\n // Create an array of all root node definitions that we create.\n const rootNodes: Partial[] = [];\n\n // A helper function used to push node definitions onto the tree stack.\n const pushNode = (node: AnyNodeDefinition) => {\n // If the node is a root node then we need to create a new tree stack array with the root node at the root.\n if (isRootNode(node)) {\n // We need to double-check that this root node is not the child of another node.\n // We can do this by checking whether the top tree stack is not empty (contains an existing node)\n if (treeStacks[treeStacks.length - 1]?.length) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Add the root node definition to our array of all parsed root node definitions.\n rootNodes.push(node);\n\n // Add the root node definition to the root of a new tree stack.\n treeStacks.push([node]);\n\n return;\n }\n\n // All non-root nodes should be pushed after their root nodes so handle cases\n // where we may not have any tree stacks or our top-most tree stack is empty.\n if (!treeStacks.length || !treeStacks[treeStacks.length - 1].length) {\n throw new Error(\"expected root node at base of definition\");\n }\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Get the top-most node in the current tree stack, this will be a composite/decorator node\n // for which we will populate its children array if composite or setting its child if a decorator.\n const topTreeStackTopNode = topTreeStack[topTreeStack.length - 1] as AnyNodeDefinition;\n\n // If the top-most node in the current root stack is a composite or decorator\n // node then the current node should be added as a child of the top-most node.\n if (isCompositeNode(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNode(topTreeStackTopNode)) {\n // If the top node already has a child node set then throw an error as a decorator should only have a single child.\n if (topTreeStackTopNode.child) {\n throw new Error(\"a decorator node must only have a single child node\");\n }\n\n topTreeStackTopNode.child = node;\n }\n\n // If the node we are adding is also a composite or decorator node, then we should push it\n // onto the current tree stack, as subsequent nodes will be added as its child/children.\n if (!isLeafNode(node)) {\n topTreeStack.push(node);\n }\n };\n\n // A helper function used to pop the top-most node definition off of the tree stack and return it.\n const popNode = (): AnyNodeDefinition | null => {\n let poppedNode: AnyNodeDefinition | null = null;\n\n // Get the current tree stack that we are populating.\n const topTreeStack = treeStacks[treeStacks.length - 1];\n\n // Pop the top-most node in the current tree stack if there is one.\n if (topTreeStack.length) {\n poppedNode = topTreeStack.pop() as AnyNodeDefinition;\n }\n\n // We don't want any empty tree stacks in our stack of tree stacks.\n if (!topTreeStack.length) {\n treeStacks.pop();\n }\n\n return poppedNode;\n };\n\n // We should keep processing the raw tokens until we run out of them.\n while (tokens.length) {\n // Grab the next token.\n const token = tokens.shift()!;\n\n // How we create the next node depends on the current raw token value.\n switch (token.toUpperCase()) {\n case \"ROOT\": {\n pushNode(createRootNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SUCCEED\": {\n pushNode(createSucceedNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FAIL\": {\n pushNode(createFailNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"FLIP\": {\n pushNode(createFlipNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"REPEAT\": {\n pushNode(createRepeatNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RETRY\": {\n pushNode(createRetryNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SEQUENCE\": {\n pushNode(createSequenceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"SELECTOR\": {\n pushNode(createSelectorNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"PARALLEL\": {\n pushNode(createParallelNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"RACE\": {\n pushNode(createRaceNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ALL\": {\n pushNode(createAllNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"LOTTO\": {\n pushNode(createLottoNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"ACTION\": {\n pushNode(createActionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"CONDITION\": {\n pushNode(createConditionNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"WAIT\": {\n pushNode(createWaitNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"BRANCH\": {\n pushNode(createBranchNode(tokens, stringLiteralPlaceholders));\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope and means that we have to pop a node off of the current stack.\n const poppedNode = popNode();\n\n // Now that we have a node definition we can carry out any validation that may require the node to be fully populated.\n if (poppedNode) {\n validatePoppedNode(poppedNode);\n }\n\n break;\n }\n\n default: {\n throw new Error(`unexpected token: ${token}`);\n }\n }\n }\n\n return rootNodes as RootNodeDefinition[];\n}\n\n/**\n * Creates a root node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The root node JSON definition.\n */\nfunction createRootNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RootNodeDefinition {\n // Create the root node definition.\n let node = {\n type: \"root\"\n } as Partial;\n\n // Parse any node arguments, we should only have one if any which will be an identifier argument for the root identifier.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Check whether any node arguments were defined.\n if (nodeArguments.length) {\n // We should only have one argument, if any, which will be an identifier argument for the root identifier.\n if (nodeArguments.length === 1 && nodeArguments[0].type === \"identifier\") {\n // The root node identifier will be the first and only node argument value.\n node.id = nodeArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the root node definition.\n return node as RootNodeDefinition;\n}\n\n/**\n * Creates a succeed node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The succeed node JSON definition.\n */\nfunction createSucceedNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SucceedNodeDefinition {\n const node = {\n type: \"succeed\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SucceedNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the succeed node definition.\n return node;\n}\n\n/**\n * Creates a fail node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The fail node JSON definition.\n */\nfunction createFailNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FailNodeDefinition {\n const node = {\n type: \"fail\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FailNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the fail node definition.\n return node;\n}\n\n/**\n * Creates a flip node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The flip node JSON definition.\n */\nfunction createFlipNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): FlipNodeDefinition {\n const node = {\n type: \"flip\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as FlipNodeDefinition;\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the flip node definition.\n return node;\n}\n\n/**\n * Creates a repeat node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The repeat node JSON definition.\n */\nfunction createRepeatNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): RepeatNodeDefinition {\n let node = { type: \"repeat\" } as RepeatNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a repeat node are optional. We may have:\n // - No node arguments, in which case the repeat note will iterate indefinitely.\n // - One node argument which will be the explicit number of iterations to make.\n // - Two node arguments which define the min and max iteration bounds from which a random iteration count will be picked.\n if (nodeArguments.length) {\n // All repeat node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`repeat node iteration counts must be integer values`);\n });\n\n // We should have got one or two iteration counts.\n if (nodeArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = nodeArguments[0].value as number;\n\n // A repeat node must have a positive number of iterations if defined.\n if (node.iterations < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A repeat node must have a positive min and max iteration count if they are defined.\n if (node.iterations[0] < 0 || node.iterations[1] < 0) {\n throw new Error(\"a repeat node must have a positive minimum and maximum iteration count if defined\");\n }\n\n // A repeat node must not have an minimum iteration count that exceeds the maximum iteration count.\n if (node.iterations[0] > node.iterations[1]) {\n throw new Error(\n \"a repeat node must not have a minimum iteration count that exceeds the maximum iteration count\"\n );\n }\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of repeat node iteration count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the repeat node definition.\n return node;\n}\n\n/**\n * Creates a retry node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The retry node JSON definition.\n */\nfunction createRetryNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RetryNodeDefinition {\n let node = { type: \"retry\" } as RetryNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a retry node are optional. We may have:\n // - No node arguments, in which case the retry note will attempt indefinitely.\n // - One node argument which will be the explicit number of attempts to make.\n // - Two node arguments which define the min and max attempt bounds from which a random attempt count will be picked.\n if (nodeArguments.length) {\n // All retry node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`retry node attempt counts must be integer values`);\n });\n\n // We should have got one or two attempt counts.\n if (nodeArguments.length === 1) {\n // A static attempt count was defined.\n node.attempts = nodeArguments[0].value as number;\n\n // A retry node must have a positive number of attempts if defined.\n if (node.attempts < 0) {\n throw new Error(\"a retry node must have a positive number of attempts if defined\");\n }\n } else if (nodeArguments.length === 2) {\n // A minimum and maximum attempt count was defined.\n node.attempts = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (node.attempts[0] < 0 || node.attempts[1] < 0) {\n throw new Error(\"a retry node must have a positive minimum and maximum attempt count if defined\");\n }\n\n // A retry node must not have a minimum attempt count that exceeds the maximum attempt count.\n if (node.attempts[0] > node.attempts[1]) {\n throw new Error(\n \"a retry node must not have a minimum attempt count that exceeds the maximum attempt count\"\n );\n }\n } else {\n // An incorrect number of attempt counts was defined.\n throw new Error(\"invalid number of retry node attempt count arguments defined\");\n }\n }\n\n // Grab any node attribute definitions and spread them into the node definition.\n node = { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n\n // This is a decorator node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the retry node definition.\n return node;\n}\n\n/**\n * Creates a sequence node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The sequence node JSON definition.\n */\nfunction createSequenceNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SequenceNodeDefinition {\n const node = {\n type: \"sequence\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SequenceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the sequence node definition.\n return node;\n}\n\n/**\n * Creates a selector node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The selector node JSON definition.\n */\nfunction createSelectorNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): SelectorNodeDefinition {\n const node = {\n type: \"selector\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as SelectorNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the selector node definition.\n return node;\n}\n\n/**\n * Creates a parallel node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The parallel node JSON definition.\n */\nfunction createParallelNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ParallelNodeDefinition {\n const node = {\n type: \"parallel\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as ParallelNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the parallel node definition.\n return node;\n}\n\n/**\n * Creates a race node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The race node JSON definition.\n */\nfunction createRaceNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): RaceNodeDefinition {\n const node = {\n type: \"race\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as RaceNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the race node definition.\n return node;\n}\n\n/**\n * Creates an all node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The all node JSON definition.\n */\nfunction createAllNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): AllNodeDefinition {\n const node = {\n type: \"all\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as AllNodeDefinition;\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the all node definition.\n return node;\n}\n\n/**\n * Creates a lotto node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The lotto node JSON definition.\n */\nfunction createLottoNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): LottoNodeDefinition {\n // If any node arguments have been defined then they must be our weights.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // All lotto node arguments MUST be of type number and must be positive integers.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger || arg.value < 0)\n .forEach(() => {\n throw new Error(`lotto node weight arguments must be positive integer values`);\n });\n\n const node = {\n type: \"lotto\",\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n } as LottoNodeDefinition;\n\n // Apply the weights if any were defined.\n if (nodeArguments.length) {\n node.weights = nodeArguments.map(({ value }) => value) as number[];\n }\n\n // This is a composite node, so we expect an opening '{'.\n popAndCheck(tokens, \"{\");\n\n // Return the lotto node definition.\n return node;\n}\n\n/**\n * Creates an action node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The action node JSON definition.\n */\nfunction createActionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ActionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the action name\n // and agent function to invoke for the action, all other arguments are to be passed as arguments to that function.\n const [actionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require an action name argument.\n if (actionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid action node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the action node definition.\n return {\n type: \"action\",\n call: actionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a condition node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The condition node JSON definition.\n */\nfunction createConditionNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): ConditionNodeDefinition {\n // Parse any node arguments, we should have at least one which will be an identifier argument for the condition name\n // and agent function to invoke for the condition, all other arguments are to be passed as arguments to that function.\n const [conditionNameIdentifier, ...agentFunctionArgs] = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // Our first argument MUST be defined and be an identifier as we require a condition name argument.\n if (conditionNameIdentifier?.type !== \"identifier\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all agent function arguments must be string, number, boolean or null.\n agentFunctionArgs\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n `invalid condition node argument value '${arg.value}', must be string, number, boolean or null`\n );\n });\n\n // Return the condition node definition.\n return {\n type: \"condition\",\n call: conditionNameIdentifier.value,\n args: agentFunctionArgs.map(({ value }) => value),\n ...parseAttributeTokens(tokens, stringLiteralPlaceholders)\n };\n}\n\n/**\n * Creates a wait node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The wait node JSON definition.\n */\nfunction createWaitNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): WaitNodeDefinition {\n let node = { type: \"wait\" } as WaitNodeDefinition;\n\n // Get the node arguments.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // The arguments of a wait node are optional. We may have:\n // - No node arguments, in which case the wait will be indefinite until it is aborted.\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n if (nodeArguments.length) {\n // All wait node arguments MUST be of type number and must be integer.\n nodeArguments\n .filter((arg) => arg.type !== \"number\" || !arg.isInteger)\n .forEach(() => {\n throw new Error(`wait node durations must be integer values`);\n });\n\n // We may have:\n // - One node argument which will be the explicit duration of the wait.\n // - Two node arguments which define the min and max duration bounds from which a random duration will be picked.\n // - Too many arguments, which is not valid.\n if (nodeArguments.length === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0].value as number;\n\n // If an explict duration was defined then it must be a positive number.\n if (node.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.duration = [nodeArguments[0].value as number, nodeArguments[1].value as number];\n\n // A wait node must have a positive min and max duration.\n if (node.duration[0] < 0 || node.duration[1] < 0) {\n throw new Error(\"a wait node must have a positive minimum and maximum duration\");\n }\n\n // A wait node must not have a minimum duration that exceeds the maximum duration.\n if (node.duration[0] > node.duration[1]) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else if (nodeArguments.length > 2) {\n // An incorrect number of duration arguments were defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n }\n\n // Return the wait node definition.\n return { ...node, ...parseAttributeTokens(tokens, stringLiteralPlaceholders) };\n}\n\n/**\n * Creates a branch node JSON definition.\n * @param tokens The tree definition tokens.\n * @param stringLiteralPlaceholders The substituted string literal placeholders.\n * @returns The branch node JSON definition.\n */\nfunction createBranchNode(\n tokens: string[],\n stringLiteralPlaceholders: StringLiteralPlaceholders\n): BranchNodeDefinition {\n // Parse any node arguments, we should have one which will be an identifier argument for the root ref.\n const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders);\n\n // We should have only a single identifer argument for a branch node, which is the root ref.\n if (nodeArguments.length !== 1 || nodeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // Return the branch node definition.\n return { type: \"branch\", ref: nodeArguments[0].value };\n}\n\n/**\n * Validate a fully-populated node definition that was popped off of the tree stack.\n * @param definition The popped node to validate.\n */\nfunction validatePoppedNode(definition: AnyNodeDefinition): void {\n // Decorators MUST have a child defined.\n if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) {\n throw new Error(`a ${definition.type} node must have a single child node defined`);\n }\n\n // Composites MUST have at least one child defined.\n if (isCompositeNode(definition) && !definition.children?.length) {\n throw new Error(`a ${definition.type} node must have at least a single child node defined`);\n }\n\n // We need to make sure that lotto nodes that have weights defined have a number of weights matching the number of child nodes.\n if (definition.type === \"lotto\") {\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (definition.weights.length !== definition.children.length) {\n throw new Error(\n \"expected a number of weight arguments matching the number of child nodes for lotto node\"\n );\n }\n }\n }\n}\n", "import { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { flattenDefinition, isBranchNode, isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\n\n/**\n * An object representing the result of validating a tree definition.\n */\nexport type DefinitionValidationResult = {\n /**\n * A flag defining whether validation succeeded.\n */\n succeeded: boolean;\n /**\n * A string containing the error message if validation did not succeed.\n */\n errorMessage?: string;\n /**\n * The definition as json if the validation was successful, or undefined if validation did not succeed.\n */\n json?: RootNodeDefinition[];\n};\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON or MDSL, not taking any globally registered subtrees into consideration.\n * @param definition The behaviour tree definition in the form of JSON or MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateDefinition(definition: any): DefinitionValidationResult {\n // The definition must be defined.\n if (definition === null || typeof definition === \"undefined\") {\n return createValidationFailureResult(\"definition is null or undefined\");\n }\n\n // We are expecting a definition in one of three different forms:\n // - A string which we will assume is MDSL and we will parse this to JSON before validation.\n // - An array which we will assume is an array of root node definitions with at least one being the primary root node (no 'id' property)\n // - An object which we will assume is the primary root node and should not have an 'id' property.\n if (typeof definition === \"string\") {\n // The definition is a string which we can assume is MDSL, so attempt to validate it.\n return validateMDSLDefinition(definition);\n } else if (typeof definition === \"object\") {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n return validateJSONDefinition(definition);\n } else {\n return createValidationFailureResult(`unexpected definition type of '${typeof definition}'`);\n }\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of MDSL.\n * @param definition The behaviour tree definition in the form of MDSL.\n * @returns An object representing the result of validating the given tree definition.\n */\nfunction validateMDSLDefinition(definition: string): DefinitionValidationResult {\n let rootNodeDefinitions;\n\n // The first thing the we need to do is to attempt to convert our MDSL into JSON.\n try {\n // The definition is a string which we can assume is MDSL, so attempt to parse it to a JSON definition in the form of an array of root node definitions.\n rootNodeDefinitions = convertMDSLToJSON(definition);\n } catch (exception) {\n // We failed to parse the JSON from the MDSL, this is likely to be the result of it not being a valid MDSL string.\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single unnamed root node at base of definition to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(`multiple root nodes found with duplicate name '${id}'`);\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the specified behaviour tree definition in the form of JSON.\n * @param definition The behaviour tree definition in the form of JSON.\n * @returns An object representing the result of validating the given tree definition.\n */\nexport function validateJSONDefinition(\n definition: RootNodeDefinition | RootNodeDefinition[]\n): DefinitionValidationResult {\n // The definition will either be an array (of root node definitions) or an object (the single primary root node definition).\n const rootNodeDefinitions = Array.isArray(definition) ? definition : [definition];\n\n // Iterate over our array of root nodes and call validateNode for each, passing an initial depth of 0, wrapped in a try catch to handle validation failures.\n try {\n rootNodeDefinitions.forEach((rootNodeDefinition) => validateNode(rootNodeDefinition, 0));\n } catch (error) {\n // Handle cases where we have caught a thrown Error and return a failure result with the error message.\n if (error instanceof Error) {\n return createValidationFailureResult(error.message);\n }\n\n // No idea what happened here!\n return createValidationFailureResult(`unexpected error: ${error}`);\n }\n\n // Unpack all of the root node definitions into arrays of main ('id' defined) and sub ('id' not defined) root node definitions.\n const mainRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"undefined\");\n const subRootNodeDefinitions = rootNodeDefinitions.filter(({ id }) => typeof id === \"string\" && id.length > 0);\n\n // We should ALWAYS have exactly one root node definition without an 'id' property defined, which is out main root node definition.\n if (mainRootNodeDefinitions.length !== 1) {\n return createValidationFailureResult(\n \"expected single root node without 'id' property defined to act as main root\"\n );\n }\n\n // We should never have duplicate 'id' properties across our sub root node definitions.\n const subRootNodeIdenitifers: string[] = [];\n for (const { id } of subRootNodeDefinitions) {\n // Have we already come across this 'id' property value?\n if (subRootNodeIdenitifers.includes(id!)) {\n return createValidationFailureResult(\n `multiple root nodes found with duplicate 'id' property value of '${id}'`\n );\n }\n\n subRootNodeIdenitifers.push(id!);\n }\n\n try {\n // Validate our branch -> subtree links and check for any circular dependencies, we don't care about checking for broken subtree links here.\n validateBranchSubtreeLinks(rootNodeDefinitions, false);\n } catch (exception) {\n return createValidationFailureResult((exception as Error).message);\n }\n\n // Our definition was valid!\n return {\n succeeded: true,\n json: rootNodeDefinitions\n };\n}\n\n/**\n * Validates the branch -> subtree links across all provided root node definitions.\n * This will not consider branch nodes that reference any globally registered subtrees unless includesGlobalSubtrees\n * is set to true, in which case we will also verify that there are no broken branch -> subtree links.\n * @param rootNodeDefinitions The array of root node definitions.\n * @param includesGlobalSubtrees A flag defining whether the array includes all global subtree root node definitions.\n */\nexport function validateBranchSubtreeLinks(rootNodeDefinitions: RootNodeDefinition[], includesGlobalSubtrees: boolean) {\n // Create a mapping of root node identifiers to other root nodes that they reference via branch nodes.\n // Below is an example of a mapping that includes a circular dependency (root => a => b => c => a)\n // [{ refs: [\"a\", \"b\"] }, { id: \"a\", refs: [\"b\"] }, { id: \"b\", refs: [\"c\"] }, { id: \"c\", refs: [\"a\"] }]\n const rootNodeMappings: { id: string | undefined; refs: string[] }[] = rootNodeDefinitions.map(\n (rootNodeDefinition) => ({\n id: rootNodeDefinition.id,\n refs: flattenDefinition(rootNodeDefinition)\n .filter(isBranchNode)\n .map(({ ref }) => ref)\n })\n );\n\n // A recursive function to walk through the mappings, keeping track of which root nodes we have visited in the form of a path of root node identifiers.\n const followRefs = (mapping: { id: string | undefined; refs: string[] }, path: (string | undefined)[] = []) => {\n // Have we found a circular dependency?\n if (path.includes(mapping.id)) {\n // We found a circular dependency! Get the bad path of root node identifiers.\n const badPath = [...path, mapping.id];\n\n // Create the formatted path value. [undefined, \"a\", \"b\", \"c\", \"a\"] would be formatted as \"a -> b -> c -> a\".\n const badPathFormatted = badPath.filter((element) => !!element).join(\" => \");\n\n // No need to continue, we found a circular dependency.\n throw new Error(`circular dependency found in branch node references: ${badPathFormatted}`);\n }\n\n for (const ref of mapping.refs) {\n // Find the mapping for the root node with an identifer matching the current ref.\n const subMapping = rootNodeMappings.find(({ id }) => id === ref);\n\n // We may not have a mapping for this ref, which is normal when we aren't considering all globally registered subtrees.\n if (subMapping) {\n followRefs(subMapping, [...path, mapping.id]);\n } else if (includesGlobalSubtrees) {\n // We found a reference to a root node that doesn't exist, which is a problem seeing as the root node definitons includes all globally registered subtrees.\n throw new Error(\n mapping.id\n ? `subtree '${mapping.id}' has branch node that references root node '${ref}' which has not been defined`\n : `primary tree has branch node that references root node '${ref}' which has not been defined`\n );\n }\n }\n };\n\n // Start looking for circular dependencies and broken references from the primary root node definition.\n followRefs(rootNodeMappings.find((mapping) => typeof mapping.id === \"undefined\")!);\n}\n\n/**\n * Validate an object that we expect to be a node definition.\n * @param definition An object that we expect to be a node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateNode(definition: any, depth: number): void {\n // Every node must be valid object and have a non-empty 'type' string property.\n if (typeof definition !== \"object\" || typeof definition.type !== \"string\" || definition.type.length === 0) {\n throw new Error(\n `node definition is not an object or 'type' property is not a non-empty string at depth '${depth}'`\n );\n }\n\n // If this node is at the very base of the definition then it MUST be a root node.\n if (depth === 0 && definition.type !== \"root\") {\n throw new Error(`expected root node at base of definition but got node of type '${definition.type}'`);\n }\n\n // How we validate this node definition will depend on its type.\n switch (definition.type) {\n case \"action\":\n validateActionNode(definition, depth);\n break;\n\n case \"condition\":\n validateConditionNode(definition, depth);\n break;\n\n case \"wait\":\n validateWaitNode(definition, depth);\n break;\n\n case \"branch\":\n validateBranchNode(definition, depth);\n break;\n\n case \"root\":\n validateRootNode(definition, depth);\n break;\n\n case \"succeed\":\n validateSucceedNode(definition, depth);\n break;\n\n case \"fail\":\n validateFailNode(definition, depth);\n break;\n\n case \"flip\":\n validateFlipNode(definition, depth);\n break;\n\n case \"repeat\":\n validateRepeatNode(definition, depth);\n break;\n\n case \"retry\":\n validateRetryNode(definition, depth);\n break;\n\n case \"sequence\":\n validateSequenceNode(definition, depth);\n break;\n\n case \"selector\":\n validateSelectorNode(definition, depth);\n break;\n\n case \"parallel\":\n validateParallelNode(definition, depth);\n break;\n\n case \"race\":\n validateRaceNode(definition, depth);\n break;\n\n case \"all\":\n validateAllNode(definition, depth);\n break;\n\n case \"lotto\":\n validateLottoNode(definition, depth);\n break;\n\n default:\n throw new Error(`unexpected node type of '${definition.type}' at depth '${depth}'`);\n }\n}\n\n/**\n * Validate any attributes for a given node definition.\n * @param definition The node definition.\n * @param depth The depth of the node in the behaviour tree definition.\n */\nfunction validateNodeAttributes(definition: any, depth: number): void {\n // Validate each of the attribute types for this node.\n [\"while\", \"until\", \"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n // Attempt to grab the definition for the current attribute from the node definition.\n const attributeDefinition = definition[attributeName];\n\n // All node attributes are optional, so there is nothing to do if the current attribute is not defined.\n if (typeof attributeDefinition === \"undefined\") {\n return;\n }\n\n // The attribute definition must be an object.\n if (typeof attributeDefinition !== \"object\") {\n throw new Error(\n `expected attribute '${attributeName}' to be an object for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // The 'call' property must be defined for any attribute definition.\n if (typeof attributeDefinition.call !== \"string\" || attributeDefinition.call.length === 0) {\n throw new Error(\n `expected 'call' property for attribute '${attributeName}' to be a non-empty string for '${definition.type}' node at depth '${depth}'`\n );\n }\n\n // If any node attribute arguments have been defined then they must have been defined in an array.\n if (typeof attributeDefinition.args !== \"undefined\" && !Array.isArray(attributeDefinition.args)) {\n throw new Error(\n `expected 'args' property for attribute '${attributeName}' to be an array for '${definition.type}' node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a root node definition.\n * @param definition An object that we expect to be a root node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRootNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"root\") {\n throw new Error(\"expected node type of 'root' for root node\");\n }\n\n // A root node cannot be the child of another node.\n if (depth > 0) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // Check that, if the root node 'id' property is defined, it is a non-empty string.\n if (typeof definition.id !== \"undefined\" && (typeof definition.id !== \"string\" || definition.id.length === 0)) {\n throw new Error(\"expected non-empty string for 'id' property if defined for root node\");\n }\n\n // A root node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(\"expected property 'child' to be defined for root node\");\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a succeed node definition.\n * @param definition An object that we expect to be a succeed node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSucceedNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"succeed\") {\n throw new Error(`expected node type of 'succeed' for succeed node at depth '${depth}'`);\n }\n\n // A succeed node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for succeed node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a fail node definition.\n * @param definition An object that we expect to be a fail node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFailNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"fail\") {\n throw new Error(`expected node type of 'fail' for fail node at depth '${depth}'`);\n }\n\n // A fail node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for fail node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a flip node definition.\n * @param definition An object that we expect to be a flip node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateFlipNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"flip\") {\n throw new Error(`expected node type of 'flip' for flip node at depth '${depth}'`);\n }\n\n // A flip node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for flip node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a repeat node definition.\n * @param definition An object that we expect to be a repeat node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRepeatNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"repeat\") {\n throw new Error(`expected node type of 'repeat' for repeat node at depth '${depth}'`);\n }\n\n // A repeat node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for repeat node at depth '${depth}'`);\n }\n\n // Check whether an 'iterations' property has been defined, it may not have been if this node is to repeat indefinitely.\n if (typeof definition.iterations !== \"undefined\") {\n if (Array.isArray(definition.iterations)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.iterations.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'iterations' property is an array then it MUST contain two integer values.\n if (definition.iterations.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must have a positive min and max iterations count if they are defined.\n if (definition.iterations[0] < 0 || definition.iterations[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n\n // A repeat node must not have a minimum iterations count that exceeds the maximum iterations count.\n if (definition.iterations[0] > definition.iterations[1]) {\n throw new Error(\n `expected minimum iterations count that does not exceed the maximum iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.iterations)) {\n // A repeat node must have a positive number of iterations if defined.\n if (definition.iterations < 0) {\n throw new Error(\n `expected positive iterations count for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'iterations' property if defined for repeat node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a retry node definition.\n * @param definition An object that we expect to be a retry node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRetryNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"retry\") {\n throw new Error(`expected node type of 'retry' for retry node at depth '${depth}'`);\n }\n\n // A retry node is a decorator node, so must have a child node defined.\n if (typeof definition.child === \"undefined\") {\n throw new Error(`expected property 'child' to be defined for retry node at depth '${depth}'`);\n }\n\n // Check whether an 'attempts' property has been defined, it may not have been if this node is to retry indefinitely.\n if (typeof definition.attempts !== \"undefined\") {\n if (Array.isArray(definition.attempts)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.attempts.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'attempts' property is an array then it MUST contain two integer values.\n if (definition.attempts.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must have a positive min and max attempts count if they are defined.\n if (definition.attempts[0] < 0 || definition.attempts[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n\n // A retry node must not have a minimum attempts count that exceeds the maximum attempts count.\n if (definition.attempts[0] > definition.attempts[1]) {\n throw new Error(\n `expected minimum attempts count that does not exceed the maximum attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.attempts)) {\n // A retry node must have a positive number of attempts if defined.\n if (definition.attempts < 0) {\n throw new Error(\n `expected positive attempts count for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'attempts' property if defined for retry node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child node of this decorator node.\n validateNode(definition.child, depth + 1);\n}\n\n/**\n * Validate an object that we expect to be a branch node definition.\n * @param definition An object that we expect to be a branch node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateBranchNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"branch\") {\n throw new Error(`expected node type of 'branch' for branch node at depth '${depth}'`);\n }\n\n // Check that the branch node 'ref' property is defined and is a non-empty string.\n if (typeof definition.ref !== \"string\" || definition.ref.length === 0) {\n throw new Error(`expected non-empty string for 'ref' property for branch node at depth '${depth}'`);\n }\n\n // It is invalid to define guard attributes for a branch node as they should be defined on the referenced root node.\n [\"while\", \"until\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `guards should not be defined for branch nodes but guard '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n\n // It is invalid to define callback attributes for a branch node as they should be defined on the referenced root node.\n [\"entry\", \"exit\", \"step\"].forEach((attributeName) => {\n if (typeof definition[attributeName] !== \"undefined\") {\n throw new Error(\n `callbacks should not be defined for branch nodes but callback '${attributeName}' was defined for branch node at depth '${depth}'`\n );\n }\n });\n}\n\n/**\n * Validate an object that we expect to be a action node definition.\n * @param definition An object that we expect to be a action node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateActionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"action\") {\n throw new Error(`expected node type of 'action' for action node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a action node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of action node at depth '${depth}'`);\n }\n\n // If any action function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for action node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a condition node definition.\n * @param definition An object that we expect to be a condition node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateConditionNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"condition\") {\n throw new Error(`expected node type of 'condition' for condition node at depth '${depth}'`);\n }\n\n // The 'call' property must be defined for a condition node definition.\n if (typeof definition.call !== \"string\" || definition.call.length === 0) {\n throw new Error(`expected non-empty string for 'call' property of condition node at depth '${depth}'`);\n }\n\n // If any condition function arguments have been defined then they must have been defined in an array.\n if (typeof definition.args !== \"undefined\" && !Array.isArray(definition.args)) {\n throw new Error(`expected array for 'args' property if defined for condition node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a wait node definition.\n * @param definition An object that we expect to be a wait node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateWaitNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"wait\") {\n throw new Error(`expected node type of 'wait' for wait node at depth '${depth}'`);\n }\n\n // Check whether a 'duration' property has been defined, it may not have been if this node is to wait indefinitely.\n if (typeof definition.duration !== \"undefined\") {\n if (Array.isArray(definition.duration)) {\n // Check whether any elements of the array are not integer values.\n const containsNonInteger = !!definition.duration.filter((value: unknown) => !isInteger(value)).length;\n\n // If the 'duration' property is an array then it MUST contain two integer values.\n if (definition.duration.length !== 2 || containsNonInteger) {\n throw new Error(\n `expected array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must have a positive min and max duration value if they are defined.\n if (definition.duration[0] < 0 || definition.duration[1] < 0) {\n throw new Error(\n `expected positive minimum and maximum duration for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n\n // A wait node must not have a minimum duration value that exceeds the maximum duration value.\n if (definition.duration[0] > definition.duration[1]) {\n throw new Error(\n `expected minimum duration value that does not exceed the maximum duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else if (isInteger(definition.duration)) {\n // A wait node must have a positive duration value if defined.\n if (definition.duration < 0) {\n throw new Error(\n `expected positive duration value for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n } else {\n throw new Error(\n `expected integer value or array containing two integer values for 'duration' property if defined for wait node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n}\n\n/**\n * Validate an object that we expect to be a sequence node definition.\n * @param definition An object that we expect to be a sequence node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSequenceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"sequence\") {\n throw new Error(`expected node type of 'sequence' for sequence node at depth '${depth}'`);\n }\n\n // A sequence node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for sequence node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a selector node definition.\n * @param definition An object that we expect to be a selector node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateSelectorNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"selector\") {\n throw new Error(`expected node type of 'selector' for selector node at depth '${depth}'`);\n }\n\n // A selector node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for selector node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a parallel node definition.\n * @param definition An object that we expect to be a parallel node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateParallelNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"parallel\") {\n throw new Error(`expected node type of 'parallel' for parallel node at depth '${depth}'`);\n }\n\n // A parallel node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for parallel node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a race node definition.\n * @param definition An object that we expect to be a race node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateRaceNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"race\") {\n throw new Error(`expected node type of 'race' for race node at depth '${depth}'`);\n }\n\n // A race node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for race node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be an all node definition.\n * @param definition An object that we expect to be an all node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateAllNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"all\") {\n throw new Error(`expected node type of 'all' for all node at depth '${depth}'`);\n }\n\n // A all node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for all node at depth '${depth}'`);\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * Validate an object that we expect to be a lotto node definition.\n * @param definition An object that we expect to be a lotto node definition.\n * @param depth The depth of the node in the definition tree.\n */\nfunction validateLottoNode(definition: any, depth: number): void {\n // Check that the node type is correct.\n if (definition.type !== \"lotto\") {\n throw new Error(`expected node type of 'lotto' for lotto node at depth '${depth}'`);\n }\n\n // A lotto node is a composite node, so must have a children nodes array defined.\n if (!Array.isArray(definition.children) || definition.children.length === 0) {\n throw new Error(`expected non-empty 'children' array to be defined for lotto node at depth '${depth}'`);\n }\n\n // Check whether a 'weights' property has been defined, if it has we expect it to be an array of weights.\n if (typeof definition.weights !== \"undefined\") {\n // Check that the weights property is an array of positive integers with an element for each child node element.\n if (\n !Array.isArray(definition.weights) ||\n definition.weights.length !== definition.children.length ||\n definition.weights.filter((value: unknown) => !isInteger(value)).length ||\n definition.weights.filter((value: number) => value < 0).length\n ) {\n throw new Error(\n `expected an array of positive integer weight values with a length matching the number of child nodes for 'weights' property if defined for lotto node at depth '${depth}'`\n );\n }\n }\n\n // Validate the node attributes.\n validateNodeAttributes(definition, depth);\n\n // Validate the child nodes of this composite node.\n definition.children.forEach((child: any) => validateNode(child, depth + 1));\n}\n\n/**\n * A helper function to create a failure validation result with the given error message.\n * @param errorMessage The validation failure error message.\n * @returns A failure validation result with the given error message.\n */\nfunction createValidationFailureResult(errorMessage: string): DefinitionValidationResult {\n return { succeeded: false, errorMessage };\n}\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nexport function createUid(): string {\n var S4 = function () {\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\n };\n return S4() + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + \"-\" + S4() + S4() + S4();\n}\n", "import { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport State, { AnyState } from \"../State\";\nimport { Agent } from \"../Agent\";\nimport Leaf from \"./leaf/Leaf\";\nimport Attribute from \"../attributes/Attribute\";\nimport Entry from \"../attributes/callbacks/Entry\";\nimport Exit from \"../attributes/callbacks/Exit\";\nimport Step from \"../attributes/callbacks/Step\";\nimport While from \"../attributes/guards/While\";\nimport Until from \"../attributes/guards/Until\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\nimport { GuardAttributeDetails } from \"../attributes/guards/Guard\";\nimport { CallbackAttributeDetails } from \"../attributes/callbacks/Callback\";\nimport { createUid } from \"../Utilities\";\n\n/**\n * Details of a tree node instance.\n */\nexport type NodeDetails = {\n /**\n * The tree node identifier.\n */\n id: string;\n /**\n * The tree node type.\n */\n type: string;\n /**\n * The tree node name.\n */\n name: string;\n /**\n * The current state of the tree node.\n */\n state: AnyState;\n /**\n * The array of agent or globally registered function arguments, defined if this is an action or condition node.\n */\n args?: any[];\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: GuardAttributeDetails;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: GuardAttributeDetails;\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: CallbackAttributeDetails;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: CallbackAttributeDetails;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: CallbackAttributeDetails;\n /**\n * The array of the child nodes of this node, defined if this node is a composite or decorator node.\n */\n children?: NodeDetails[];\n};\n\n/**\n * A mapping of attribute names to attributes configured for a node.\n */\ntype Attributes = {\n /**\n * The 'entry' callback attribute configured for this node.\n */\n entry?: Entry;\n /**\n * The 'step' callback attribute configured for this node.\n */\n step?: Step;\n /**\n * The 'exit' callback attribute configured for this node.\n */\n exit?: Exit;\n /**\n * The 'while' guard attribute configured for this node.\n */\n while?: While;\n /**\n * The 'until' guard attribute configured for this node.\n */\n until?: Until;\n};\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node unique identifier.\n */\n protected readonly uid: string;\n /**\n * The node attributes.\n */\n protected readonly attributes: Attributes;\n /**\n * The node state.\n */\n private _state: AnyState = State.READY;\n /**\n * The guard path to evaluate as part of a node update.\n */\n private _guardPath: GuardPath | undefined;\n\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n */\n constructor(private type: string, attributes: Attribute[], protected options: BehaviourTreeOptions) {\n // Create a unique identifier for this node.\n this.uid = createUid();\n\n // Create our attribute mapping.\n this.attributes = {\n entry: attributes.find(({ type }) => type === \"entry\") as Entry,\n step: attributes.find(({ type }) => type === \"step\") as Step,\n exit: attributes.find(({ type }) => type === \"exit\") as Exit,\n while: attributes.find(({ type }) => type === \"while\") as While,\n until: attributes.find(({ type }) => type === \"until\") as Until\n };\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected abstract onUpdate(agent: Agent): void;\n\n /**\n * Gets the name of the node.\n */\n public abstract getName(): string;\n\n /**\n * Gets whether this node is a leaf node.\n */\n public abstract isLeafNode: () => this is Leaf;\n\n /**\n * Gets/Sets the state of the node.\n */\n getState = (): AnyState => this._state;\n setState = (value: AnyState): void => {\n // Grab the original state of this node.\n const previousState = this._state;\n\n // Set the new node state.\n this._state = value;\n\n // If the state actually changed we should handle it.\n if (previousState !== value) {\n this.onStateChanged(previousState);\n }\n };\n\n /**\n * Gets the unique id of the node.\n */\n getUid = () => this.uid;\n\n /**\n * Gets the type of the node.\n */\n getType = () => this.type;\n\n /**\n * Gets the node attributes.\n */\n getAttributes = () => Object.values(this.attributes).filter((attribute) => !!attribute);\n\n /**\n * Sets the guard path to evaluate as part of a node update.\n */\n setGuardPath = (value: GuardPath) => (this._guardPath = value);\n\n /**\n * Gets whether a guard path is assigned to this node.\n */\n hasGuardPath = () => !!this._guardPath;\n\n /**\n * Gets whether this node is in the specified state.\n * @param value The value to compare to the node state.\n */\n public is(value: AnyState): boolean {\n return this._state === value;\n }\n\n /**\n * Reset the state of the node.\n */\n public reset(): void {\n this.setState(State.READY);\n }\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n public abort(agent: Agent): void {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @returns The result of the update.\n */\n public update(agent: Agent): void {\n // If this node is already in a 'SUCCEEDED' or 'FAILED' state then there is nothing to do.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n return;\n }\n\n try {\n // Evaluate all of the guard path conditions for the current tree path.\n this._guardPath!.evaluate(agent);\n\n // If this node is in the READY state then call the ENTRY for this node if it exists.\n if (this.is(State.READY)) {\n this.attributes.entry?.callAgentFunction(agent);\n }\n\n this.attributes.step?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent);\n\n // If this node is now in a 'SUCCEEDED' or 'FAILED' state then call the EXIT for this node if it exists.\n if (this.is(State.SUCCEEDED) || this.is(State.FAILED)) {\n this.attributes.exit?.callAgentFunction(agent, this.is(State.SUCCEEDED), false);\n }\n } catch (error) {\n // If the error is a GuardUnsatisfiedException then we need to determine if this node is the source.\n if (error instanceof GuardUnsatisifedException && error.isSourceNode(this)) {\n // Abort the current node.\n this.abort(agent);\n\n // Any node that is the source of an abort will be a failed node.\n this.setState(State.FAILED);\n } else {\n throw error;\n }\n }\n }\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n id: this.uid,\n name: this.getName(),\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n state: this._state\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n // We should call the onNodeStateChange callback if it was defined.\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.type,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this._state\n });\n }\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A composite node that wraps child nodes.\n */\nexport default abstract class Composite extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => this.children;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of any child nodes.\n this.children.forEach((child) => child.reset());\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort any child nodes.\n this.children.forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: this.children.map((child) => child.getDetails())\n };\n }\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A PARALLEL node.\n * The child nodes are executed concurrently until one fails or all succeed.\n */\nexport default class Parallel extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"parallel\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have failed then this node has also failed.\n if (this.children.find((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A parallel node will move into the succeeded state if all child nodes move into the succeeded state.\n if (this.children.every((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RACE node.\n * The child nodes are executed concurrently until one succeeds or all fail.\n */\nexport default class Race extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"race\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // If any of our child nodes have succeeded then this node has also succeeded.\n if (this.children.find((child) => child.is(State.SUCCEEDED))) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // Abort every running child.\n for (const child of this.children) {\n if (child.getState() === State.RUNNING) {\n child.abort(agent);\n }\n }\n\n return;\n }\n\n // A race node will move into the failed state if all child nodes move into the failed state as none can succeed.\n if (this.children.every((child) => child.is(State.FAILED))) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"RACE\";\n}\n", "import Composite from \"./Composite\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * An ALL node.\n * The child nodes are executed concurrently until all child nodes move to a completed state.\n */\nexport default class All extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) {\n super(\"all\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node, updating any that aren't in a settled state.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n }\n\n // An all node will move into a completed state if all child nodes move into a completed state.\n if (this.children.every((child) => child.is(State.SUCCEEDED) || child.is(State.FAILED))) {\n // If any of our child nodes have succeeded then this node has also succeeded, otherwise it has failed.\n this.setState(this.children.find((child) => child.is(State.SUCCEEDED)) ? State.SUCCEEDED : State.FAILED);\n\n return;\n }\n\n // If we didn't move to a succeeded or failed state then this node is still running.\n this.setState(State.RUNNING);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ALL\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SELECTOR node.\n * The child nodes are executed in sequence until one succeeds or all fail.\n */\nexport default class Selector extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"selector\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then this node is also a 'SUCCEEDED' node.\n if (child.getState() === State.SUCCEEDED) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the selector nodes.\n return;\n }\n\n // If the current child has a state of 'FAILED' then we should move on to the next child.\n if (child.getState() === State.FAILED) {\n // Find out if the current child is the last one in the selector.\n // If it is then this sequence node has also failed.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the selector as we have completed it.\n return;\n } else {\n // The child node failed, try the next one.\n continue;\n }\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the selector as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SELECTOR\";\n}\n", "import Composite from \"./Composite\";\nimport Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A SEQUENCE node.\n * The child nodes are executed in sequence until one fails or all succeed.\n */\nexport default class Sequence extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, protected children: Node[]) {\n super(\"sequence\", attributes, options, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Iterate over all of the children of this node.\n for (const child of this.children) {\n // If the child has never been updated or is running then we will need to update it now.\n if (child.getState() === State.READY || child.getState() === State.RUNNING) {\n // Update the child of this node.\n child.update(agent);\n }\n\n // If the current child has a state of 'SUCCEEDED' then we should move on to the next child.\n if (child.getState() === State.SUCCEEDED) {\n // Find out if the current child is the last one in the sequence.\n // If it is then this sequence node has also succeeded.\n if (this.children.indexOf(child) === this.children.length - 1) {\n // This node is a 'SUCCEEDED' node.\n this.setState(State.SUCCEEDED);\n\n // There is no need to check the rest of the sequence as we have completed it.\n return;\n } else {\n // The child node succeeded, but we have not finished the sequence yet.\n continue;\n }\n }\n\n // If the current child has a state of 'FAILED' then this node is also a 'FAILED' node.\n if (child.getState() === State.FAILED) {\n // This node is a 'FAILED' node.\n this.setState(State.FAILED);\n\n // There is no need to check the rest of the sequence.\n return;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() === State.RUNNING) {\n // This node is a 'RUNNING' node.\n this.setState(State.RUNNING);\n\n // There is no need to check the rest of the sequence as the current child is still running.\n return;\n }\n\n // The child node was not in an expected state.\n throw new Error(\"child node was not in an expected state.\");\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SEQUENCE\";\n}\n", "import createLotto from \"lotto-draw\";\n\nimport Node from \"../Node\";\nimport Composite from \"./Composite\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A LOTTO node.\n * A winning child is picked on the initial update of this node, based on ticket weighting.\n * The state of this node will match the state of the winning child.\n */\nexport default class Lotto extends Composite {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param weights The child node weights.\n * @param children The child nodes.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private weights: number[] | undefined,\n children: Node[]\n ) {\n super(\"lotto\", attributes, options, children);\n }\n\n /**\n * The child node selected to be the active one.\n */\n private selectedChild: Node | undefined;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to pick a winning child node.\n if (this.is(State.READY)) {\n // Create a lotto draw with which to randomly pick a child node to become the active one.\n const lottoDraw = createLotto({\n // Hook up the optional 'random' behaviour tree function option to the one used by 'lotto-draw'.\n random: this.options.random,\n // Pass in each child node as a participant in the lotto draw with their respective ticket count.\n participants: this.children.map((child, index) => [child, this.weights?.[index] || 1])\n });\n\n // Randomly pick a child based on ticket weighting, this will become the active child for this composite node.\n this.selectedChild = lottoDraw.draw() || undefined;\n }\n\n // If something went wrong and we don't have an active child then we should throw an error.\n if (!this.selectedChild) {\n throw new Error(\"failed to update lotto node as it has no active child\");\n }\n\n // If the selected child has never been updated or is running then we will need to update it now.\n if (this.selectedChild.getState() === State.READY || this.selectedChild.getState() === State.RUNNING) {\n this.selectedChild.update(agent);\n }\n\n // The state of the lotto node is the state of its selected child.\n this.setState(this.selectedChild.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => (this.weights ? `LOTTO [${this.weights.join(\",\")}]` : \"LOTTO\");\n}\n", "import Node, { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A decorator node that wraps a single child node.\n */\nexport default abstract class Decorator extends Node {\n /**\n * @param type The node type.\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, protected child: Node) {\n super(type, attributes, options);\n }\n\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => false;\n\n /**\n * Gets the children of this node.\n */\n getChildren = () => [this.child];\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the state of the child node.\n this.child.reset();\n };\n\n /**\n * Abort the running of this node.\n * @param agent The agent.\n */\n abort = (agent: Agent) => {\n // There is nothing to do if this node is not in the running state.\n if (!this.is(State.RUNNING)) {\n return;\n }\n\n // Abort the child node.\n this.child.abort(agent);\n\n // Reset the state of this node.\n this.reset();\n\n this.attributes.exit?.callAgentFunction(agent, false, true);\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n children: [this.child.getDetails()]\n };\n }\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Fail node.\n * This node wraps a single child and will always move to the 'FAILED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Fail extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"fail\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.FAILED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FAIL\";\n}\n", "import Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport Node from \"../Node\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Flip node.\n * This node wraps a single child and will flip the state of the child state.\n */\nexport default class Flip extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"flip\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n this.setState(State.FAILED);\n break;\n\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"FLIP\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A REPEAT node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The REPEAT node will stop and have a 'FAILED' state if its child is ever in a 'FAILED' state after an update.\n * The REPEAT node will attempt to move on to the next iteration if its child is ever in a 'SUCCEEDED' state.\n */\nexport default class Repeat extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param iterations The number of iterations to repeat the child node.\n * @param iterationsMin The minimum possible number of iterations to repeat the child node.\n * @param iterationsMax The maximum possible number of iterations to repeat the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, options, child);\n }\n\n /**\n * The number of target iterations to make.\n */\n private targetIterationCount: number | null = null;\n\n /**\n * The current iteration count.\n */\n private currentIterationCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target iteration count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the FAILED state when we updated it then there is nothing left to do and this node has also failed.\n // If it has moved into the SUCCEEDED state then we have completed the current iteration.\n if (this.child.getState() === State.FAILED) {\n // The child has failed, meaning that this node has failed.\n this.setState(State.FAILED);\n\n return;\n } else if (this.child.getState() === State.SUCCEEDED) {\n // We have completed an iteration.\n this.currentIterationCount += 1;\n }\n } else {\n // This node is in the 'SUCCEEDED' state as we cannot iterate any more.\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.iterations !== null) {\n return `REPEAT ${this.iterations}x`;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n return `REPEAT ${this.iterationsMin}x-${this.iterationsMax}x`;\n } else {\n return \"REPEAT\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with an explicit iteration count or will we be randomly picking a iteration count between the min and max iteration count.\n if (this.iterations !== null) {\n this.targetIterationCount = this.iterations;\n } else if (this.iterationsMin !== null && this.iterationsMax !== null) {\n // We will be picking a random iteration count between a min and max iteration count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random iteration count between a min and max iteration count.\n this.targetIterationCount = Math.floor(\n random() * (this.iterationsMax - this.iterationsMin + 1) + this.iterationsMin\n );\n } else {\n this.targetIterationCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A RETRY node.\n * The node has a single child which can have:\n * -- A number of iterations for which to repeat the child node.\n * -- An infinite repeat loop if neither an iteration count or a condition function is defined.\n * The RETRY node will stop and have a 'SUCCEEDED' state if its child is ever in a 'SUCCEEDED' state after an update.\n * The RETRY node will attempt to move on to the next iteration if its child is ever in a 'FAILED' state.\n */\nexport default class Retry extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param attempts The number of attempts to retry the child node.\n * @param attemptsMin The minimum possible number of attempts to retry the child node.\n * @param attemptsMax The maximum possible number of attempts to retry the child node.\n * @param child The child node.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, options, child);\n }\n\n /**\n * The number of target attempts to make.\n */\n private targetAttemptCount: number | null = null;\n\n /**\n * The current attempt count.\n */\n private currentAttemptCount: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to reset the child and the target attempt count.\n if (this.is(State.READY)) {\n // Reset the child node.\n this.child.reset();\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Set the target attempt count.\n this.setTargetAttemptCount();\n }\n\n // Do a check to see if we can attempt. If we can then this node will move into the 'RUNNING' state.\n // If we cannot attempt then we have hit our target attempt count, which means that the node has succeeded.\n if (this.canAttempt()) {\n // This node is in the running state and can do its initial attempt.\n this.setState(State.RUNNING);\n\n // We may have already completed an attempt, meaning that the child node will be in the FAILED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.FAILED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent);\n\n // If the child moved into the SUCCEEDED state when we updated it then there is nothing left to do and this node has also succeeded.\n // If it has moved into the FAILED state then we have completed the current attempt.\n if (this.child.getState() === State.SUCCEEDED) {\n // The child has succeeded, meaning that this node has succeeded.\n this.setState(State.SUCCEEDED);\n\n return;\n } else if (this.child.getState() === State.FAILED) {\n // We have completed an attempt.\n this.currentAttemptCount += 1;\n }\n } else {\n // This node is in the 'FAILED' state as we cannot iterate any more.\n this.setState(State.FAILED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.attempts !== null) {\n return `RETRY ${this.attempts}x`;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n return `RETRY ${this.attemptsMin}x-${this.attemptsMax}x`;\n } else {\n return \"RETRY\";\n }\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current attempt count.\n this.currentAttemptCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an attempt can be made.\n * @returns Whether an attempt can be made.\n */\n canAttempt = () => {\n if (this.targetAttemptCount !== null) {\n // We can attempt as long as we have not reached our target attempt count.\n return this.currentAttemptCount < this.targetAttemptCount;\n }\n\n // If neither an attempt count or a condition function were defined then we can attempt indefinitely.\n return true;\n };\n\n /**\n * Sets the target attempt count.\n */\n setTargetAttemptCount = () => {\n // Are we dealing with an explicit attempt count or will we be randomly picking an attempt count between the min and max attempt count.\n if (this.attempts !== null) {\n this.targetAttemptCount = this.attempts;\n } else if (this.attemptsMin !== null && this.attemptsMax !== null) {\n // We will be picking a random attempt count between a min and max attempt count, if the optional 'random'\n // behaviour tree function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random attempt count between a min and max attempt count.\n this.targetAttemptCount = Math.floor(\n random() * (this.attemptsMax - this.attemptsMin + 1) + this.attemptsMin\n );\n } else {\n this.targetAttemptCount = null;\n }\n };\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Root node.\n * The root node will have a single child.\n */\nexport default class Root extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"root\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n // Update the child of this node.\n this.child.update(agent);\n }\n\n // The state of the root node is the state of its child.\n this.setState(this.child.getState());\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"ROOT\";\n}\n", "import Node from \"../Node\";\nimport Decorator from \"./Decorator\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A Succeed node.\n * This node wraps a single child and will always move to the 'SUCCEEDED' state when the child moves to a 'SUCCEEDED' or 'FAILED' state.\n */\nexport default class Succeed extends Decorator {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param child The child node.\n */\n constructor(attributes: Attribute[], options: BehaviourTreeOptions, child: Node) {\n super(\"succeed\", attributes, options, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the child has never been updated or is running then we will need to update it now.\n if (this.child.getState() === State.READY || this.child.getState() === State.RUNNING) {\n this.child.update(agent);\n }\n\n // The state of this node will depend in the state of its child.\n switch (this.child.getState()) {\n case State.RUNNING:\n this.setState(State.RUNNING);\n break;\n\n case State.SUCCEEDED:\n case State.FAILED:\n this.setState(State.SUCCEEDED);\n break;\n\n default:\n this.setState(State.READY);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"SUCCEED\";\n}\n", "import Node from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {\n /**\n * Gets whether this node is a leaf node.\n */\n isLeafNode = () => true;\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State, { CompleteState } from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * The type representing a resolved/rejected update promise.\n */\ntype UpdatePromiseResult = {\n /**\n * Whether the promise was resolved rather than rejected.\n */\n isResolved: boolean;\n\n /**\n * The promise resolved value or rejection reason.\n */\n value: any;\n};\n\n/**\n * An Action leaf node.\n * This represents an immediate or ongoing state of behaviour.\n */\nexport default class Action extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param actionName The action name.\n * @param actionArguments The array of action arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private actionName: string,\n public actionArguments: any[]\n ) {\n super(\"action\", attributes, options);\n }\n\n /**\n * Whether there is a pending update promise.\n */\n private isUsingUpdatePromise = false;\n\n /**\n * The finished state result of an update promise.\n */\n private updatePromiseResult: UpdatePromiseResult | null = null;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If the result of this action depends on an update promise then there is nothing to do until it settles.\n if (this.isUsingUpdatePromise) {\n // Are we still waiting for our update promise to settle?\n if (!this.updatePromiseResult) {\n return;\n }\n\n const { isResolved, value } = this.updatePromiseResult;\n\n // Our update promise settled, was it resolved or rejected?\n if (isResolved) {\n // Our promise resolved so check to make sure the result is a valid finished state.\n if (value !== State.SUCCEEDED && value !== State.FAILED) {\n throw new Error(\n \"action node promise resolved with an invalid value, expected a State.SUCCEEDED or State.FAILED value to be returned\"\n );\n }\n\n // Set the state of this node to match the state returned by the promise.\n this.setState(value);\n\n return;\n } else {\n // The promise was rejected, which isn't great.\n throw new Error(`action function '${this.actionName}' promise rejected with '${value}'`);\n }\n }\n\n // Attempt to get the invoker for the action function.\n const actionFuncInvoker = Lookup.getFuncInvoker(agent, this.actionName);\n\n // The action function should be defined.\n if (actionFuncInvoker === null) {\n throw new Error(\n `cannot update action node as the action '${this.actionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let actionFunctionResult;\n\n try {\n // Call the action function, the result of which may be:\n // - The finished state of this action node.\n // - A promise to return a finished node state.\n // - Undefined if the node should remain in the running state.\n actionFunctionResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`action function '${this.actionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`action function '${this.actionName}' threw: ${error}`);\n }\n }\n\n if (actionFunctionResult instanceof Promise) {\n actionFunctionResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the resolved update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: true,\n value: result\n };\n },\n (reason) => {\n // If 'isUpdatePromisePending' is not set then the promise was cleared as it was resolving, probably via an abort or reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Set the rejected update promise result so that it can be handled on the next update of this node.\n this.updatePromiseResult = {\n isResolved: false,\n value: reason\n };\n }\n );\n\n // This node will be in the 'RUNNING' state until the update promise resolves.\n this.setState(State.RUNNING);\n\n // We are now waiting for the promise returned by the use to resolve before we know what state this node is in.\n this.isUsingUpdatePromise = true;\n } else {\n // Validate the returned value.\n this.validateUpdateResult(actionFunctionResult);\n\n // Set the state of this node, this may be undefined, which just means that the node is still in the 'RUNNING' state.\n this.setState(actionFunctionResult || State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.actionName;\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // There is no longer an update promise that we care about.\n this.isUsingUpdatePromise = false;\n this.updatePromiseResult = null;\n };\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.actionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.actionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n\n /**\n * Validate the result of an update function call.\n * @param result The result of an update function call.\n */\n private validateUpdateResult = (result: CompleteState | State.RUNNING) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case State.RUNNING:\n case undefined:\n return;\n default:\n throw new Error(\n `expected action function '${this.actionName}' to return an optional State.SUCCEEDED or State.FAILED value but returned '${result}'`\n );\n }\n };\n}\n", "import { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\nimport { NodeDetails } from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Leaf from \"./Leaf\";\nimport Lookup from \"../../Lookup\";\nimport Attribute from \"../../attributes/Attribute\";\n\n/**\n * A Condition leaf node.\n * This will succeed or fail immediately based on an agent predicate, without moving to the 'RUNNING' state.\n */\nexport default class Condition extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param conditionName The name of the condition function.\n * @param conditionArguments The array of condition arguments.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private conditionName: string,\n public conditionArguments: any[]\n ) {\n super(\"condition\", attributes, options);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.conditionName);\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot update condition node as the condition '${this.conditionName}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.conditionArguments);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`condition function '${this.conditionName}' threw: ${error.stack}`);\n } else {\n throw new Error(`condition function '${this.conditionName}' threw: ${error}`);\n }\n }\n\n // The result of calling the condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected condition function '${this.conditionName}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Set the state of this node based on the result of calling the condition function.\n this.setState(!!conditionFunctionResult ? State.SUCCEEDED : State.FAILED);\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => this.conditionName;\n\n /**\n * Gets the details of this node instance.\n * @returns The details of this node instance.\n */\n public getDetails(): NodeDetails {\n return {\n ...super.getDetails(),\n args: this.conditionArguments\n };\n }\n\n /**\n * Called when the state of this node changes.\n * @param previousState The previous node state.\n */\n protected onStateChanged(previousState: State): void {\n this.options.onNodeStateChange?.({\n id: this.uid,\n type: this.getType(),\n args: this.conditionArguments,\n while: this.attributes.while?.getDetails(),\n until: this.attributes.until?.getDetails(),\n entry: this.attributes.entry?.getDetails(),\n step: this.attributes.step?.getDetails(),\n exit: this.attributes.exit?.getDetails(),\n previousState,\n state: this.getState()\n });\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { Agent } from \"../../Agent\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\n\n/**\n * A WAIT node.\n * The state of this node will change to SUCCEEDED after a duration of time\n */\nexport default class Wait extends Leaf {\n /**\n * @param attributes The node attributes.\n * @param options The behaviour tree options.\n * @param duration The duration that this node will wait to succeed in milliseconds.\n * @param durationMin The minimum possible duration in milliseconds that this node will wait to succeed.\n * @param durationMax The maximum possible duration in milliseconds that this node will wait to succeed.\n */\n constructor(\n attributes: Attribute[],\n options: BehaviourTreeOptions,\n private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, options);\n }\n\n /**\n * The time in milliseconds at which this node was first updated.\n */\n private initialUpdateTime: number = 0;\n\n /**\n * The total duration in milliseconds that this node will be waiting for.\n */\n private totalDuration: number | null = null;\n\n /**\n * The duration in milliseconds that this node has been waiting for.\n */\n private waitedDuration: number = 0;\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n */\n protected onUpdate(agent: Agent): void {\n // If this node is in the READY state then we need to set the initial update time.\n if (this.is(State.READY)) {\n // Set the initial update time.\n this.initialUpdateTime = new Date().getTime();\n\n // Set the initial waited duration.\n this.waitedDuration = 0;\n\n // Are we dealing with an explicit duration or will we be randomly picking a duration between the min and max duration.\n if (this.duration !== null) {\n this.totalDuration = this.duration;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // We will be picking a random duration between a min and max duration, if the optional 'random' behaviour tree\n // function option is defined then we will be using that, otherwise we will fall back to using Math.random.\n const random = typeof this.options.random === \"function\" ? this.options.random : Math.random;\n\n // Pick a random duration between a min and max duration.\n this.totalDuration = Math.floor(\n random() * (this.durationMax - this.durationMin + 1) + this.durationMin\n );\n } else {\n this.totalDuration = null;\n }\n\n // The node is now running until we finish waiting.\n this.setState(State.RUNNING);\n }\n\n // If we have no total duration then this wait node will wait indefinitely until it is aborted.\n if (this.totalDuration === null) {\n return;\n }\n\n // If we have a 'getDeltaTime' function defined as part of our options then we will use it to figure out how long we have waited for.\n if (typeof this.options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = this.options.getDeltaTime();\n\n // Our delta time must be a valid number and cannot be NaN.\n if (typeof deltaTime !== \"number\" || isNaN(deltaTime)) {\n throw new Error(\"The delta time must be a valid number and not NaN.\");\n }\n\n // Update the amount of time that this node has been waiting for based on the delta time.\n this.waitedDuration += deltaTime * 1000;\n } else {\n // We are not using a delta time, so we will just work out hom much time has passed since the first update.\n this.waitedDuration = new Date().getTime() - this.initialUpdateTime;\n }\n\n // Have we waited long enough?\n if (this.waitedDuration >= this.totalDuration) {\n // We have finished waiting!\n this.setState(State.SUCCEEDED);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => {\n if (this.duration !== null) {\n return `WAIT ${this.duration}ms`;\n } else if (this.durationMin !== null && this.durationMax !== null) {\n return `WAIT ${this.durationMin}ms-${this.durationMax}ms`;\n } else {\n return \"WAIT\";\n }\n };\n}\n", "import Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: any[];\n};\n\n/**\n * A base node attribute.\n */\nexport default abstract class Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of attribute arguments.\n */\n constructor(public type: string, public args: any[]) {}\n\n /**\n * Gets the attribute details.\n */\n abstract getDetails(): TAttributeDetails;\n\n /**\n * Gets whether this attribute is a guard.\n */\n abstract isGuard: () => this is Guard;\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node guard attribute.\n */\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node guard attribute.\n */\nexport default abstract class Guard extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n */\n constructor(type: string, args: any[], private condition: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the condition function that determines whether the guard is satisfied.\n */\n getCondition = () => this.condition;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => true;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): GuardAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getCondition()\n };\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n abstract isSatisfied(agent: Agent): boolean;\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A WHILE guard which is satisfied as long as the given condition remains true.\n */\nexport default class While extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"while\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return conditionFunctionResult;\n };\n}\n", "import Guard from \"./Guard\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An UNTIL guard which is satisfied as long as the given condition remains false.\n */\nexport default class Until extends Guard {\n /**\n * @param condition The name of the condition function that determines whether the guard is satisfied.\n * @param args The array of decorator argument definitions.\n */\n constructor(condition: string, args: any[]) {\n super(\"until\", args, condition);\n }\n\n /**\n * Gets whether the guard is satisfied.\n * @param agent The agent.\n * @returns Whether the guard is satisfied.\n */\n isSatisfied = (agent: Agent) => {\n // Attempt to get the invoker for the condition function.\n const conditionFuncInvoker = Lookup.getFuncInvoker(agent, this.getCondition());\n\n // The condition function should be defined.\n if (conditionFuncInvoker === null) {\n throw new Error(\n `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered`\n );\n }\n\n let conditionFunctionResult;\n\n try {\n // Call the guard condition function to determine the state of this node, the result of which should be a boolean.\n conditionFunctionResult = conditionFuncInvoker(this.args);\n } catch (error) {\n // An uncaught error was thrown.\n if (error instanceof Error) {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error.stack}`);\n } else {\n throw new Error(`guard condition function '${this.getCondition()}' threw: ${error}`);\n }\n }\n\n // The result of calling the guard condition function must be a boolean value.\n if (typeof conditionFunctionResult !== \"boolean\") {\n throw new Error(\n `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'`\n );\n }\n\n // Return whether this guard is satisfied.\n return !conditionFunctionResult;\n };\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\n/**\n * Details of a node callback attribute.\n */\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n calls: string;\n} & AttributeDetails;\n\n/**\n * A base node callback attribute.\n */\nexport default abstract class Callback extends Attribute {\n /**\n * @param type The node attribute type.\n * @param args The array of decorator argument definitions.\n * @param functionName The name of the agent function to call.\n */\n constructor(type: string, args: any[], private functionName: string) {\n super(type, args);\n }\n\n /**\n * Gets the name of the agent function to call.\n */\n getFunctionName = () => this.functionName;\n\n /**\n * Gets whether this attribute is a guard.\n */\n isGuard = () => false;\n\n /**\n * Gets the attribute details.\n */\n getDetails(): CallbackAttributeDetails {\n return {\n type: this.type,\n args: this.args,\n calls: this.getFunctionName()\n };\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n abstract callAgentFunction: (agent: Agent, isSuccess: boolean, isAborted: boolean) => void;\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An ENTRY callback which defines an agent function to call when the associated node is updated and moves out of running state.\n */\nexport default class Entry extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"entry\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call entry function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * A STEP callback which defines an agent function to call when the associated node is updated.\n */\nexport default class Step extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"step\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n */\n callAgentFunction = (agent: Agent) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call step function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function.\n callbackFuncInvoker(this.args);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\n\n/**\n * An EXIT callback which defines an agent function to call when the associated node is updated and moves to a finished state or is aborted.\n */\nexport default class Exit extends Callback {\n /**\n * @param functionName The name of the agent function to call.\n * @param args The array of callback argument definitions.\n */\n constructor(functionName: string, args: any[]) {\n super(\"exit\", args, functionName);\n }\n\n /**\n * Attempt to call the agent function that this callback refers to.\n * @param agent The agent.\n * @param isSuccess Whether the decorated node was left with a success state.\n * @param isAborted Whether the decorated node was aborted.\n */\n callAgentFunction = (agent: Agent, isSuccess: boolean, isAborted: boolean) => {\n // Attempt to get the invoker for the callback function.\n const callbackFuncInvoker = Lookup.getFuncInvoker(agent, this.getFunctionName());\n\n // The callback function should be defined.\n if (callbackFuncInvoker === null) {\n throw new Error(\n `cannot call exit function '${this.getFunctionName()}' as is not defined on the agent and has not been registered`\n );\n }\n\n // Call the callback function\n callbackFuncInvoker([{ succeeded: isSuccess, aborted: isAborted }, ...this.args]);\n };\n}\n", "import { AnyNodeDefinition, RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport { validateBranchSubtreeLinks } from \"./BehaviourTreeDefinitionValidator\";\nimport { isInteger } from \"./BehaviourTreeDefinitionUtilities\";\nimport Node from \"./nodes/Node\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Race from \"./nodes/composite/Race\";\nimport All from \"./nodes/composite/All\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Root from \"./nodes/decorator/Root\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Lookup from \"./Lookup\";\nimport Attribute from \"./attributes/Attribute\";\nimport Guard from \"./attributes/guards/Guard\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\n/**\n * A type representing any node instance in a behaviour tree.\n */\ntype AnyNode =\n | Root\n | Action\n | Condition\n | Wait\n | Sequence\n | Selector\n | Lotto\n | Parallel\n | Race\n | All\n | Repeat\n | Retry\n | Flip\n | Succeed\n | Fail;\n\n/**\n * A type defining a mapping of root node identifiers to root node definitions.\n */\ntype RootNodeDefinitionMap = { [key: string | symbol]: RootNodeDefinition };\n\n/**\n * A symbol to use as the main root key in any root node mappings.\n */\nconst MAIN_ROOT_NODE_KEY = Symbol(\"__root__\");\n\n/**\n * Build and populate the root nodes based on the provided definition, assuming that the definition has been validated.\n * @param definition The root node definitions.\n * @param options The behaviour tree options.\n * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[], options: BehaviourTreeOptions): Root {\n // Create a mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n const rootNodeDefinitionMap = createRootNodeDefinitionMap(definition);\n\n // Now that we have all of our root node definitions (those part of the tree definition and those globally registered)\n // we should validate the branch-subtree links. This will also double-check that we dont have any circular dependencies\n // in our branch-subtree references and that we have no broken branch-subtree links.\n validateBranchSubtreeLinks(\n [rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], ...Object.values(rootNodeDefinitionMap)],\n true\n );\n\n // Create our populated tree of node instances, starting with our main root node.\n const rootNode = nodeFactory(rootNodeDefinitionMap[MAIN_ROOT_NODE_KEY], rootNodeDefinitionMap, options) as Root;\n\n // Set a guard path on every leaf of the tree to evaluate as part of each update.\n applyLeafNodeGuardPaths(rootNode);\n\n // We only need to return the main root node.\n return rootNode;\n}\n\n/**\n * A factory function which creates a node instance based on the specified definition.\n * @param definition The node definition.\n * @param rootNodeDefinitionMap The mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n * @param options The behaviour tree options.\n * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(\n definition: AnyNodeDefinition,\n rootNodeDefinitionMap: RootNodeDefinitionMap,\n options: BehaviourTreeOptions\n): AnyNode {\n // Get the attributes for the node.\n const attributes = nodeAttributesFactory(definition);\n\n // Create the node instance based on the definition type.\n switch (definition.type) {\n case \"root\":\n return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"repeat\":\n let iterations: number | null = null;\n let iterationsMin: number | null = null;\n let iterationsMax: number | null = null;\n\n if (Array.isArray(definition.iterations)) {\n iterationsMin = definition.iterations[0];\n iterationsMax = definition.iterations[1];\n } else if (isInteger(definition.iterations)) {\n iterations = definition.iterations!;\n }\n\n return new Repeat(\n attributes,\n options,\n iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"retry\":\n let attempts: number | null = null;\n let attemptsMin: number | null = null;\n let attemptsMax: number | null = null;\n\n if (Array.isArray(definition.attempts)) {\n attemptsMin = definition.attempts[0];\n attemptsMax = definition.attempts[1];\n } else if (isInteger(definition.attempts)) {\n attempts = definition.attempts!;\n }\n\n return new Retry(\n attributes,\n options,\n attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap, options)\n );\n\n case \"flip\":\n return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"succeed\":\n return new Succeed(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"fail\":\n return new Fail(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"race\":\n return new Race(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"all\":\n return new All(\n attributes,\n options,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n options,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap, options);\n\n case \"action\":\n return new Action(attributes, options, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, options, definition.call, definition.args || []);\n\n case \"wait\":\n let duration: number | null = null;\n let durationMin: number | null = null;\n let durationMax: number | null = null;\n\n if (Array.isArray(definition.duration)) {\n durationMin = definition.duration[0];\n durationMax = definition.duration[1];\n } else if (isInteger(definition.duration)) {\n duration = definition.duration!;\n }\n\n return new Wait(attributes, options, duration, durationMin, durationMax);\n }\n}\n\n/**\n * Creates an array of node attribute instances based on the specified node definition.\n * @param definition The node definition.\n * @returns An array of node attribute instances based on the specified node definition.\n */\nfunction nodeAttributesFactory(definition: AnyNodeDefinition): Attribute[] {\n const attributes: Attribute[] = [];\n\n if (definition.while) {\n attributes.push(new While(definition.while.call, definition.while.args ?? []));\n }\n\n if (definition.until) {\n attributes.push(new Until(definition.until.call, definition.until.args ?? []));\n }\n\n if (definition.entry) {\n attributes.push(new Entry(definition.entry.call, definition.entry.args ?? []));\n }\n\n if (definition.step) {\n attributes.push(new Step(definition.step.call, definition.step.args ?? []));\n }\n\n if (definition.exit) {\n attributes.push(new Exit(definition.exit.call, definition.exit.args ?? []));\n }\n\n return attributes;\n}\n\n/**\n * Creates a mapping of root node identifers to root node definitions, mixing in globally registered subtree root node definitions.\n * @param definition The root node definitions.\n * @returns A mapping of root node identifers to root node definitions, including globally registered subtree root node definitions.\n */\nfunction createRootNodeDefinitionMap(definition: RootNodeDefinition[]): RootNodeDefinitionMap {\n // Create a mapping of root node identifers to root node definitions.\n const rootNodeMap: RootNodeDefinitionMap = {};\n\n // Add in any registered subtree root node definitions.\n for (const [name, rootNodeDefinition] of Object.entries(Lookup.getSubtrees())) {\n // The name used when registering the subtree will be used as the root node identifier.\n rootNodeMap[name] = { ...rootNodeDefinition, id: name };\n }\n\n // Populate the map with the root node definitions that were included with the tree definition.\n // We do this after adding any registered subtrees as we want these to take presedence.\n for (const rootNodeDefinition of definition) {\n rootNodeMap[rootNodeDefinition.id ?? MAIN_ROOT_NODE_KEY] = rootNodeDefinition;\n }\n\n return rootNodeMap;\n}\n\n/**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param root The main root tree node.\n */\nfunction applyLeafNodeGuardPaths(root: Root) {\n const nodePaths: Node[][] = [];\n\n const findLeafNodes = (path: Node[], node: Node) => {\n // Add the current node to the path.\n path = path.concat(node);\n\n // Check whether the current node is a leaf node.\n if (node.isLeafNode()) {\n nodePaths.push(path);\n } else {\n (node as Composite | Decorator).getChildren().forEach((child) => findLeafNodes(path, child));\n }\n };\n\n // Find all leaf node paths, starting from the root.\n findLeafNodes([], root);\n\n nodePaths.forEach((path) => {\n // Each node in the current path will have to be assigned a guard path, working from the root outwards.\n for (let depth = 0; depth < path.length; depth++) {\n // Get the node in the path at the current depth.\n const currentNode = path[depth];\n\n // The node may already have been assigned a guard path, if so just skip it.\n if (currentNode.hasGuardPath()) {\n continue;\n }\n\n // Create the guard path for the current node.\n const guardPath = new GuardPath(\n path\n .slice(0, depth + 1)\n .map((node) => ({\n node,\n guards: node.getAttributes().filter((attribute) => attribute.isGuard()) as Guard[]\n }))\n .filter((details) => details.guards.length > 0)\n );\n\n // Assign the guard path to the current node.\n currentNode.setGuardPath(guardPath);\n }\n });\n}\n", "import State, { AnyState } from \"./State\";\nimport Lookup from \"./Lookup\";\nimport Node, { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport { Agent, GlobalFunction } from \"./Agent\";\nimport { CallbackAttributeDetails } from \"./attributes/callbacks/Callback\";\nimport { GuardAttributeDetails } from \"./attributes/guards/Guard\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { RootNodeDefinition } from \"./BehaviourTreeDefinition\";\nimport { validateDefinition, validateJSONDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport buildRootNode from \"./BehaviourTreeBuilder\";\nimport { isNullOrUndefined } from \"./BehaviourTreeDefinitionUtilities\";\n\n/**\n * A representation of a behaviour tree.\n */\nexport class BehaviourTree {\n /**\n * The main root tree node.\n */\n private readonly _rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition as either an MDSL string, root node definition object or array of root node definition objects.\n * @param agent The agent instance that this behaviour tree is modelling behaviour for.\n * @param options The behaviour tree options object.\n */\n constructor(\n definition: string | RootNodeDefinition | RootNodeDefinition[],\n private agent: Agent,\n private options: BehaviourTreeOptions = {}\n ) {\n // The tree definition must be defined.\n if (isNullOrUndefined(definition)) {\n throw new Error(\"tree definition not defined\");\n }\n\n // The agent must be defined and not null.\n if (typeof agent !== \"object\" || agent === null) {\n throw new Error(\"the agent must be an object and not null\");\n }\n\n // We should validate the definition before we try to build the tree nodes.\n const { succeeded, errorMessage, json } = validateDefinition(definition);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(`invalid definition: ${errorMessage}`);\n }\n\n // Double check that we did actually get our json definition as part of our definition validtion.\n if (!json) {\n throw new Error(\n \"expected json definition to be returned as part of successful definition validation response\"\n );\n }\n\n try {\n // Create the populated tree of behaviour tree nodes and get the root node.\n this._rootNode = buildRootNode(json, options);\n } catch (exception) {\n // There was an issue in trying build and populate the behaviour tree.\n throw new Error(`error building tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Gets whether the tree is in the RUNNING state.\n * @returns true if the tree is in the RUNNING state, otherwise false.\n */\n public isRunning(): boolean {\n return this._rootNode.getState() === State.RUNNING;\n }\n\n /**\n * Gets the current tree state of SUCCEEDED, FAILED, READY or RUNNING.\n * @returns The current tree state.\n */\n public getState(): State {\n return this._rootNode.getState();\n }\n\n /**\n * Step the tree.\n * 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.\n * 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\n * 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.\n *\n * 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.\n */\n public step(): void {\n // If the root node has already been stepped to completion then we need to reset it.\n if (this._rootNode.getState() === State.SUCCEEDED || this._rootNode.getState() === State.FAILED) {\n this._rootNode.reset();\n }\n\n try {\n this._rootNode.update(this.agent);\n } catch (exception) {\n throw new Error(`error stepping tree: ${(exception as Error).message}`);\n }\n }\n\n /**\n * Resets the tree from the root node outwards to each nested node, giving each a state of READY.\n */\n public reset(): void {\n this._rootNode.reset();\n }\n\n /**\n * Gets the details of every node in the tree, starting from the root.\n * @returns The details of every node in the tree, starting from the root.\n */\n public getTreeNodeDetails(): NodeDetails {\n return this._rootNode.getDetails();\n }\n\n /**\n * Registers the action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the function or subtree to register.\n * @param value The function or subtree definition to register.\n */\n static register(name: string, value: GlobalFunction | string | RootNodeDefinition) {\n // Are we going to register a action/condition/guard/callback function?\n if (typeof value === \"function\") {\n Lookup.setFunc(name, value);\n return;\n }\n\n // We are not registering an action/condition/guard/callback function, so we must be registering a subtree.\n if (typeof value === \"string\") {\n let rootNodeDefinitions: RootNodeDefinition[];\n\n // We will assume that any string passed in will be a mdsl definition.\n try {\n rootNodeDefinitions = convertMDSLToJSON(value);\n } catch (exception) {\n throw new Error(`error registering definition, invalid MDSL: ${(exception as Error).message}`);\n }\n\n // This function should only ever be called with a definition containing a single unnamed root node.\n if (rootNodeDefinitions.length != 1 || typeof rootNodeDefinitions[0].id !== \"undefined\") {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(rootNodeDefinitions[0]);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, rootNodeDefinitions[0]);\n } else if (typeof value === \"object\" && !Array.isArray(value)) {\n // We will assume that any object passed in is a root node definition.\n\n try {\n // We should validate the subtree as we don't want invalid subtrees available via the lookup.\n const { succeeded, errorMessage } = validateJSONDefinition(value);\n\n // Did our validation fail without error?\n if (!succeeded) {\n throw new Error(errorMessage);\n }\n } catch (exception) {\n throw new Error(`error registering definition: ${(exception as Error).message}`);\n }\n\n // Everything seems hunky-dory, register the subtree.\n Lookup.setSubtree(name, value);\n } else {\n throw new Error(\"unexpected value, expected string mdsl definition, root node json definition or function\");\n }\n }\n\n /**\n * Unregisters the registered action/condition/guard/callback function or subtree with the given name.\n * @param name The name of the registered action/condition/guard/callback function or subtree to unregister.\n */\n static unregister(name: string): void {\n Lookup.remove(name);\n }\n\n /**\n * Unregister all registered action/condition/guard/callback functions and subtrees.\n */\n static unregisterAll(): void {\n Lookup.empty();\n }\n}\n"], + "mappings": "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", + "names": ["require_Participant", "__commonJSMin", "exports", "Participant", "participant", "tickets", "value", "require_Utilities", "__commonJSMin", "exports", "isNullOrUndefined", "value", "isNaturalNumber", "require_Lotto", "__commonJSMin", "exports", "Participant_1", "Utilities_1", "Lotto", "customRandom", "participant", "tickets", "existingParticipant", "part", "options", "redrawable", "pickable", "_a", "ticketCount", "random", "winner", "uniqueResults", "result", "unique", "_i", "result_1", "require_createLotto", "__commonJSMin", "exports", "Lotto_1", "createLotto", "participantsOrOptions", "participants", "lotto_1", "_a", "participant", "tokens", "random", "lotto_2", "require_dist", "__commonJSMin", "exports", "createLotto_1", "src_exports", "__export", "BehaviourTree", "State", "convertMDSLToJSON", "validateDefinition", "State", "Lookup", "name", "func", "agent", "agentFunction", "args", "registeredFunction", "subtree", "__publicField", "isRootNode", "node", "isBranchNode", "isLeafNode", "isDecoratorNode", "isCompositeNode", "flattenDefinition", "nodeDefinition", "nodes", "processNode", "currentNodeDefinition", "isInteger", "value", "isNullOrUndefined", "popAndCheck", "tokens", "expected", "popped", "expectedValues", "tokenMatchesExpectation", "item", "expectationString", "substituteStringLiterals", "definition", "placeholders", "processedDefinition", "match", "strippedMatch", "placeholder", "key", "parseTokensFromDefinition", "parseArgumentTokens", "tokens", "stringArgumentPlaceholders", "argumentList", "closingToken", "popAndCheck", "argumentListTokens", "token", "index", "argumentDefinition", "getArgumentDefinition", "parseAttributeTokens", "tokens", "stringArgumentPlaceholders", "nodeAttributeNames", "attributes", "nextAttributeName", "attributeCallIdentifier", "attributeArguments", "parseArgumentTokens", "arg", "value", "convertMDSLToJSON", "definition", "placeholders", "processedDefinition", "substituteStringLiterals", "tokens", "parseTokensFromDefinition", "convertTokensToJSONDefinition", "stringLiteralPlaceholders", "token", "treeStacks", "rootNodes", "pushNode", "node", "isRootNode", "topTreeStack", "topTreeStackTopNode", "isCompositeNode", "isDecoratorNode", "isLeafNode", "popNode", "poppedNode", "createRootNode", "createSucceedNode", "createFailNode", "createFlipNode", "createRepeatNode", "createRetryNode", "createSequenceNode", "createSelectorNode", "createParallelNode", "createRaceNode", "createAllNode", "createLottoNode", "createActionNode", "createConditionNode", "createWaitNode", "createBranchNode", "validatePoppedNode", "nodeArguments", "parseArgumentTokens", "parseAttributeTokens", "popAndCheck", "arg", "value", "actionNameIdentifier", "agentFunctionArgs", "conditionNameIdentifier", "isNullOrUndefined", "validateDefinition", "definition", "createValidationFailureResult", "validateMDSLDefinition", "validateJSONDefinition", "rootNodeDefinitions", "convertMDSLToJSON", "exception", "mainRootNodeDefinitions", "id", "subRootNodeDefinitions", "subRootNodeIdenitifers", "validateBranchSubtreeLinks", "rootNodeDefinition", "validateNode", "error", "includesGlobalSubtrees", "rootNodeMappings", "flattenDefinition", "isBranchNode", "ref", "followRefs", "mapping", "path", "badPathFormatted", "element", "subMapping", "depth", "validateActionNode", "validateConditionNode", "validateWaitNode", "validateBranchNode", "validateRootNode", "validateSucceedNode", "validateFailNode", "validateFlipNode", "validateRepeatNode", "validateRetryNode", "validateSequenceNode", "validateSelectorNode", "validateParallelNode", "validateRaceNode", "validateAllNode", "validateLottoNode", "validateNodeAttributes", "attributeName", "attributeDefinition", "containsNonInteger", "value", "isInteger", "child", "errorMessage", "GuardUnsatisifedException", "source", "node", "GuardPath", "nodes", "agent", "details", "guard", "GuardUnsatisifedException", "createUid", "S4", "Node", "type", "attributes", "options", "createUid", "value", "previousState", "attribute", "agent", "error", "GuardUnsatisifedException", "Composite", "Node", "type", "attributes", "options", "children", "child", "agent", "Parallel", "Composite", "attributes", "options", "children", "agent", "child", "Race", "Composite", "attributes", "options", "children", "agent", "child", "All", "Composite", "attributes", "options", "children", "agent", "child", "Selector", "Composite", "attributes", "options", "children", "agent", "child", "Sequence", "Composite", "attributes", "options", "children", "agent", "child", "import_lotto_draw", "Lotto", "Composite", "attributes", "options", "weights", "children", "agent", "lottoDraw", "createLotto", "child", "index", "Decorator", "Node", "type", "attributes", "options", "child", "agent", "Fail", "Decorator", "attributes", "options", "child", "agent", "Flip", "Decorator", "attributes", "options", "child", "agent", "Repeat", "Decorator", "attributes", "options", "iterations", "iterationsMin", "iterationsMax", "child", "agent", "random", "Retry", "Decorator", "attributes", "options", "attempts", "attemptsMin", "attemptsMax", "child", "agent", "random", "Root", "Decorator", "attributes", "options", "child", "agent", "Succeed", "Decorator", "attributes", "options", "child", "agent", "Leaf", "Node", "Action", "Leaf", "attributes", "options", "actionName", "actionArguments", "agent", "isResolved", "value", "actionFuncInvoker", "Lookup", "actionFunctionResult", "error", "result", "reason", "previousState", "Condition", "Leaf", "attributes", "options", "conditionName", "conditionArguments", "agent", "conditionFuncInvoker", "Lookup", "conditionFunctionResult", "error", "previousState", "Wait", "Leaf", "attributes", "options", "duration", "durationMin", "durationMax", "agent", "random", "deltaTime", "Attribute", "type", "args", "Guard", "Attribute", "type", "args", "condition", "While", "Guard", "condition", "args", "agent", "conditionFuncInvoker", "Lookup", "conditionFunctionResult", "error", "Until", "Guard", "condition", "args", "agent", "conditionFuncInvoker", "Lookup", "conditionFunctionResult", "error", "Callback", "Attribute", "type", "args", "functionName", "Entry", "Callback", "functionName", "args", "agent", "callbackFuncInvoker", "Lookup", "Step", "Callback", "functionName", "args", "agent", "callbackFuncInvoker", "Lookup", "Exit", "Callback", "functionName", "args", "agent", "isSuccess", "isAborted", "callbackFuncInvoker", "Lookup", "MAIN_ROOT_NODE_KEY", "buildRootNode", "definition", "options", "rootNodeDefinitionMap", "createRootNodeDefinitionMap", "validateBranchSubtreeLinks", "rootNode", "nodeFactory", "applyLeafNodeGuardPaths", "attributes", "nodeAttributesFactory", "Root", "iterations", "iterationsMin", "iterationsMax", "isInteger", "Repeat", "attempts", "attemptsMin", "attemptsMax", "Retry", "Flip", "Succeed", "Fail", "Sequence", "child", "Selector", "Parallel", "Race", "All", "Lotto", "Action", "Condition", "duration", "durationMin", "durationMax", "Wait", "While", "Until", "Entry", "Step", "Exit", "rootNodeMap", "name", "rootNodeDefinition", "Lookup", "root", "nodePaths", "findLeafNodes", "path", "node", "depth", "currentNode", "guardPath", "GuardPath", "attribute", "details", "BehaviourTree", "definition", "agent", "options", "isNullOrUndefined", "succeeded", "errorMessage", "json", "validateDefinition", "buildRootNode", "exception", "name", "value", "Lookup", "rootNodeDefinitions", "convertMDSLToJSON", "validateJSONDefinition"] } diff --git a/dist/nodes/composite/All.d.ts b/dist/nodes/composite/All.d.ts new file mode 100644 index 0000000..25e7aa8 --- /dev/null +++ b/dist/nodes/composite/All.d.ts @@ -0,0 +1,26 @@ +import Composite from "./Composite"; +import Node from "../Node"; +import { Agent } from "../../Agent"; +import Attribute from "../../attributes/Attribute"; +import { BehaviourTreeOptions } from "../../BehaviourTreeOptions"; +/** + * An ALL node. + * The child nodes are executed concurrently until all child nodes move to a completed state. + */ +export default class All extends Composite { + /** + * @param attributes The node attributes. + * @param options The behaviour tree options. + * @param children The child nodes. + */ + constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]); + /** + * Called when the node is being updated. + * @param agent The agent. + */ + protected onUpdate(agent: Agent): void; + /** + * Gets the name of the node. + */ + getName: () => string; +} diff --git a/src/BehaviourTreeBuilder.ts b/src/BehaviourTreeBuilder.ts index e348592..6b4abef 100644 --- a/src/BehaviourTreeBuilder.ts +++ b/src/BehaviourTreeBuilder.ts @@ -7,6 +7,7 @@ import Composite from "./nodes/composite/Composite"; import Decorator from "./nodes/decorator/Decorator"; import Parallel from "./nodes/composite/Parallel"; import Race from "./nodes/composite/Race"; +import All from "./nodes/composite/All"; import Selector from "./nodes/composite/Selector"; import Sequence from "./nodes/composite/Sequence"; import Lotto from "./nodes/composite/Lotto"; @@ -42,6 +43,7 @@ type AnyNode = | Lotto | Parallel | Race + | All | Repeat | Retry | Flip @@ -185,6 +187,13 @@ function nodeFactory( definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options)) ); + case "all": + return new All( + attributes, + options, + definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap, options)) + ); + case "lotto": return new Lotto( attributes, diff --git a/src/BehaviourTreeDefinition.ts b/src/BehaviourTreeDefinition.ts index 3851e3b..eff08e0 100644 --- a/src/BehaviourTreeDefinition.ts +++ b/src/BehaviourTreeDefinition.ts @@ -180,6 +180,16 @@ export interface RaceNodeDefinition extends CompositeNodeDefinition { type: "race"; } +/** + * An all node. + */ +export interface AllNodeDefinition extends CompositeNodeDefinition { + /** + * The node type. + */ + type: "all"; +} + /** * A root node. */ @@ -265,6 +275,7 @@ export type AnyNodeDefinition = | LottoNodeDefinition | ParallelNodeDefinition | RaceNodeDefinition + | AllNodeDefinition | RootNodeDefinition | RepeatNodeDefinition | RetryNodeDefinition diff --git a/src/BehaviourTreeDefinitionUtilities.ts b/src/BehaviourTreeDefinitionUtilities.ts index 9d70b3a..49012ba 100644 --- a/src/BehaviourTreeDefinitionUtilities.ts +++ b/src/BehaviourTreeDefinitionUtilities.ts @@ -49,7 +49,7 @@ export function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefi * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type. */ export function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition { - return ["sequence", "selector", "lotto", "parallel", "race"].includes(node.type); + return ["sequence", "selector", "lotto", "parallel", "race", "all"].includes(node.type); } /** diff --git a/src/BehaviourTreeDefinitionValidator.ts b/src/BehaviourTreeDefinitionValidator.ts index b4df1c9..6ed5de7 100644 --- a/src/BehaviourTreeDefinitionValidator.ts +++ b/src/BehaviourTreeDefinitionValidator.ts @@ -293,6 +293,10 @@ function validateNode(definition: any, depth: number): void { validateRaceNode(definition, depth); break; + case "all": + validateAllNode(definition, depth); + break; + case "lotto": validateLottoNode(definition, depth); break; @@ -801,6 +805,29 @@ function validateRaceNode(definition: any, depth: number): void { definition.children.forEach((child: any) => validateNode(child, depth + 1)); } +/** + * Validate an object that we expect to be an all node definition. + * @param definition An object that we expect to be an all node definition. + * @param depth The depth of the node in the definition tree. + */ +function validateAllNode(definition: any, depth: number): void { + // Check that the node type is correct. + if (definition.type !== "all") { + throw new Error(`expected node type of 'all' for all node at depth '${depth}'`); + } + + // A all node is a composite node, so must have a children nodes array defined. + if (!Array.isArray(definition.children) || definition.children.length === 0) { + throw new Error(`expected non-empty 'children' array to be defined for all node at depth '${depth}'`); + } + + // Validate the node attributes. + validateNodeAttributes(definition, depth); + + // Validate the child nodes of this composite node. + definition.children.forEach((child: any) => validateNode(child, depth + 1)); +} + /** * Validate an object that we expect to be a lotto node definition. * @param definition An object that we expect to be a lotto node definition. diff --git a/src/mdsl/MDSLDefinitionParser.ts b/src/mdsl/MDSLDefinitionParser.ts index 91a72a0..d9c4c16 100644 --- a/src/mdsl/MDSLDefinitionParser.ts +++ b/src/mdsl/MDSLDefinitionParser.ts @@ -9,6 +9,7 @@ import { LottoNodeDefinition, ParallelNodeDefinition, RaceNodeDefinition, + AllNodeDefinition, RepeatNodeDefinition, RetryNodeDefinition, RootNodeDefinition, @@ -210,6 +211,11 @@ function convertTokensToJSONDefinition( break; } + case "ALL": { + pushNode(createAllNode(tokens, stringLiteralPlaceholders)); + break; + } + case "LOTTO": { pushNode(createLottoNode(tokens, stringLiteralPlaceholders)); break; @@ -568,6 +574,25 @@ function createRaceNode(tokens: string[], stringLiteralPlaceholders: StringLiter return node; } +/** + * Creates an all node JSON definition. + * @param tokens The tree definition tokens. + * @param stringLiteralPlaceholders The substituted string literal placeholders. + * @returns The all node JSON definition. + */ +function createAllNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): AllNodeDefinition { + const node = { + type: "all", + ...parseAttributeTokens(tokens, stringLiteralPlaceholders) + } as AllNodeDefinition; + + // This is a composite node, so we expect an opening '{'. + popAndCheck(tokens, "{"); + + // Return the all node definition. + return node; +} + /** * Creates a lotto node JSON definition. * @param tokens The tree definition tokens. diff --git a/src/nodes/composite/All.ts b/src/nodes/composite/All.ts new file mode 100644 index 0000000..b4a9f6d --- /dev/null +++ b/src/nodes/composite/All.ts @@ -0,0 +1,52 @@ +import Composite from "./Composite"; +import State from "../../State"; +import Node from "../Node"; +import { Agent } from "../../Agent"; +import Attribute from "../../attributes/Attribute"; +import { BehaviourTreeOptions } from "../../BehaviourTreeOptions"; + +/** + * An ALL node. + * The child nodes are executed concurrently until all child nodes move to a completed state. + */ +export default class All extends Composite { + /** + * @param attributes The node attributes. + * @param options The behaviour tree options. + * @param children The child nodes. + */ + constructor(attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]) { + super("all", attributes, options, children); + } + + /** + * Called when the node is being updated. + * @param agent The agent. + */ + protected onUpdate(agent: Agent): void { + // Iterate over all of the children of this node, updating any that aren't in a settled state. + for (const child of this.children) { + // If the child has never been updated or is running then we will need to update it now. + if (child.getState() === State.READY || child.getState() === State.RUNNING) { + // Update the child of this node. + child.update(agent); + } + } + + // An all node will move into a completed state if all child nodes move into a completed state. + if (this.children.every((child) => child.is(State.SUCCEEDED) || child.is(State.FAILED))) { + // If any of our child nodes have succeeded then this node has also succeeded, otherwise it has failed. + this.setState(this.children.find((child) => child.is(State.SUCCEEDED)) ? State.SUCCEEDED : State.FAILED); + + return; + } + + // If we didn't move to a succeeded or failed state then this node is still running. + this.setState(State.RUNNING); + } + + /** + * Gets the name of the node. + */ + getName = () => "ALL"; +} diff --git a/src/nodes/composite/Race.ts b/src/nodes/composite/Race.ts index 3c574b6..113db99 100644 --- a/src/nodes/composite/Race.ts +++ b/src/nodes/composite/Race.ts @@ -33,7 +33,7 @@ export default class Race extends Composite { } } - // If any of our child nodes have succeeded then this node has also succeeded + // If any of our child nodes have succeeded then this node has also succeeded. if (this.children.find((child) => child.is(State.SUCCEEDED))) { // This node is a 'SUCCEEDED' node. this.setState(State.SUCCEEDED); diff --git a/test/nodes/composite/All.spec.ts b/test/nodes/composite/All.spec.ts new file mode 100644 index 0000000..6f46ffb --- /dev/null +++ b/test/nodes/composite/All.spec.ts @@ -0,0 +1,484 @@ +import { assert } from "chai"; + +import { BehaviourTree, State } from "../../../src/index"; +import { RootNodeDefinition } from "../../../src/BehaviourTreeDefinition"; + +import { findNode } from "../../TestUtilities"; + +describe("An All node", () => { + describe("on tree initialisation", () => { + describe("will error if the node does not have at least one child", () => { + it("(MDSL)", () => { + const definition = "root { all {} }"; + assert.throws( + () => new BehaviourTree(definition, {}), + Error, + "invalid definition: a all node must have at least a single child" + ); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "all", + children: [] + } + }; + assert.throws( + () => new BehaviourTree(definition, {}), + Error, + "invalid definition: expected non-empty 'children' array to be defined for all node at depth '1'" + ); + }); + }); + }); + + describe("when updated as part of a tree step will", () => { + describe("update each child node concurrently", () => { + it("(MDSL)", () => { + const definition = "root { all { action [actionRunning1] action [actionRunning2] } }"; + const agent = { + actionRunning1: () => State.RUNNING, + actionRunning2: () => State.RUNNING + }; + const tree = new BehaviourTree(definition, agent); + + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "all").state, State.READY); + assert.strictEqual(findNode(tree, "action", "actionRunning1").state, State.READY); + assert.strictEqual(findNode(tree, "action", "actionRunning2").state, State.READY); + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "actionRunning1").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "actionRunning2").state, State.RUNNING); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "all", + children: [ + { + type: "action", + call: "actionRunning1" + }, + { + type: "action", + call: "actionRunning2" + } + ] + } + }; + const agent = { + actionRunning1: () => State.RUNNING, + actionRunning2: () => State.RUNNING + }; + const tree = new BehaviourTree(definition, agent); + + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "all").state, State.READY); + assert.strictEqual(findNode(tree, "action", "actionRunning1").state, State.READY); + assert.strictEqual(findNode(tree, "action", "actionRunning2").state, State.READY); + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "actionRunning1").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "actionRunning2").state, State.RUNNING); + }); + }); + + describe("move to the SUCCEEDED state if all child nodes move to either the SUCCEEDED or FAILED state and at least one child is in the SUCCEEDED state", () => { + it("(MDSL)", () => { + const definition = "root { all { action [action1] action [action2] action [action3] } }"; + const agent = { + action1: () => State.RUNNING, + action2: () => State.RUNNING, + action3: () => State.RUNNING + }; + const tree = new BehaviourTree(definition, agent); + + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "all").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action1").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action2").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action3").state, State.READY); + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action1 = () => State.SUCCEEDED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action2 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action3 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "all").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.FAILED); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "all", + children: [ + { + type: "action", + call: "action1" + }, + { + type: "action", + call: "action2" + }, + { + type: "action", + call: "action3" + } + ] + } + }; + const agent = { + action1: () => State.RUNNING, + action2: () => State.RUNNING, + action3: () => State.RUNNING + }; + const tree = new BehaviourTree(definition, agent); + + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "all").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action1").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action2").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action3").state, State.READY); + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action1 = () => State.SUCCEEDED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action2 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action3 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "all").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.FAILED); + }); + }); + + describe("move to the FAILED state if all child nodes move to either the SUCCEEDED or FAILED state and all child nodes are in the FAILED state", () => { + it("(MDSL)", () => { + const definition = "root { all { action [action1] action [action2] action [action3] } }"; + const agent = { + action1: () => State.RUNNING, + action2: () => State.RUNNING, + action3: () => State.RUNNING + }; + const tree = new BehaviourTree(definition, agent); + + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "all").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action1").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action2").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action3").state, State.READY); + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action1 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action2 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action3 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "all").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action1").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.FAILED); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "all", + children: [ + { + type: "action", + call: "action1" + }, + { + type: "action", + call: "action2" + }, + { + type: "action", + call: "action3" + } + ] + } + }; + const agent = { + action1: () => State.RUNNING, + action2: () => State.RUNNING, + action3: () => State.RUNNING + }; + const tree = new BehaviourTree(definition, agent); + + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "all").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action1").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action2").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action3").state, State.READY); + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action1 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action2 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action3 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "all").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action1").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.FAILED); + }); + }); + + describe("move to the RUNNING state if any child nodes are in the RUNNING state", () => { + it("(MDSL)", () => { + const definition = "root { all { action [action1] action [action2] action [action3] } }"; + const agent = { + action1: () => State.RUNNING, + action2: () => State.RUNNING, + action3: () => State.RUNNING + }; + const tree = new BehaviourTree(definition, agent); + + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "all").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action1").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action2").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action3").state, State.READY); + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action1 = () => State.SUCCEEDED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action2 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action3 = () => State.SUCCEEDED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "all").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.SUCCEEDED); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "all", + children: [ + { + type: "action", + call: "action1" + }, + { + type: "action", + call: "action2" + }, + { + type: "action", + call: "action3" + } + ] + } + }; + const agent = { + action1: () => State.RUNNING, + action2: () => State.RUNNING, + action3: () => State.RUNNING + }; + const tree = new BehaviourTree(definition, agent); + + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "all").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action1").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action2").state, State.READY); + assert.strictEqual(findNode(tree, "action", "action3").state, State.READY); + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action1 = () => State.SUCCEEDED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action2 = () => State.FAILED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "all").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.RUNNING); + + agent.action3 = () => State.SUCCEEDED; + + tree.step(); + + assert.strictEqual(findNode(tree, "root").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "all").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action1").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action", "action2").state, State.FAILED); + assert.strictEqual(findNode(tree, "action", "action3").state, State.SUCCEEDED); + }); + }); + }); +});