From 074bf9bfd6771f3699f58db66742ba9c3fe75551 Mon Sep 17 00:00:00 2001 From: Nikolas Howard Date: Thu, 27 Jun 2024 13:43:49 +0100 Subject: [PATCH 1/3] Added ESLint --- .eslintignore | 2 + .eslintrc | 16 + dist/index.js | 25 +- dist/index.js.map | 4 +- dist/mistreevous.js | 25 +- dist/mistreevous.js.map | 4 +- dist/mistreevous.min.js | 2 +- dist/mistreevous.min.js.map | 6 +- package-lock.json | 1150 ++++++++++++++++++++++++++- package.json | 8 +- src/BehaviourTree.ts | 10 +- src/BehaviourTreeBuilder.ts | 9 +- src/Utilities.ts | 2 +- src/mdsl/MDSLDefinitionParser.ts | 2 +- src/mdsl/MDSLUtilities.ts | 10 +- src/nodes/leaf/Condition.ts | 2 +- test/BehaviourTree.spec.ts | 2 +- test/nodes/decorator/Repeat.spec.ts | 2 +- test/nodes/decorator/Retry.spec.ts | 2 +- test/nodes/leaf/Wait.spec.ts | 4 +- 20 files changed, 1216 insertions(+), 71 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..76add87 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..a6acd14 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,16 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "plugins": [ + "@typescript-eslint" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@typescript-eslint/no-explicit-any": ["off"], + "@typescript-eslint/no-unused-vars": ["off"] + } + } \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 3cfb535..895f33b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -347,7 +347,7 @@ function popAndCheck(tokens, expected) { } if (expected != void 0) { const expectedValues = typeof expected === "string" ? [expected] : expected; - var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase()); + const tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase()); if (!tokenMatchesExpectation) { const expectationString = expectedValues.map((item) => "'" + item + "'").join(" or "); throw new Error("unexpected token found. Expected " + expectationString + " but got '" + popped + "'"); @@ -357,9 +357,9 @@ function popAndCheck(tokens, expected) { } function substituteStringLiterals(definition) { const placeholders = {}; - const processedDefinition = definition.replace(/\"(\\.|[^"\\])*\"/g, (match) => { - var strippedMatch = match.substring(1, match.length - 1); - var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch); + const processedDefinition = definition.replace(/"(\\.|[^"\\])*"/g, (match) => { + const strippedMatch = match.substring(1, match.length - 1); + let placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch); if (!placeholder) { placeholder = `@@${Object.keys(placeholders).length}@@`; placeholders[placeholder] = strippedMatch; @@ -375,7 +375,7 @@ function parseTokensFromDefinition(definition) { definition = definition.replace(/\}/g, " } "); definition = definition.replace(/\]/g, " ] "); definition = definition.replace(/\[/g, " [ "); - definition = definition.replace(/\,/g, " , "); + definition = definition.replace(/,/g, " , "); return definition.replace(/\s+/g, " ").trim().split(" "); } @@ -791,7 +791,7 @@ function createConditionNode(tokens, stringLiteralPlaceholders) { }; } function createWaitNode(tokens, stringLiteralPlaceholders) { - let node = { type: "wait" }; + const node = { type: "wait" }; const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders); if (nodeArguments.length) { nodeArguments.filter((arg) => arg.type !== "number" || !arg.isInteger).forEach(() => { @@ -1338,7 +1338,7 @@ var GuardPath = class { // src/Utilities.ts function createUid() { - var S4 = function() { + const S4 = function() { return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1); }; return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4(); @@ -2032,7 +2032,7 @@ var Condition = class extends Leaf { `expected condition function '${this.conditionName}' to return a boolean but returned '${conditionFunctionResult}'` ); } - this.setState(!!conditionFunctionResult ? "mistreevous.succeeded" /* SUCCEEDED */ : "mistreevous.failed" /* FAILED */); + this.setState(conditionFunctionResult ? "mistreevous.succeeded" /* SUCCEEDED */ : "mistreevous.failed" /* FAILED */); } getName = () => this.conditionName; getDetails() { @@ -2280,7 +2280,7 @@ function nodeFactory(definition, rootNodeDefinitionMap, options) { switch (definition.type) { case "root": return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options)); - case "repeat": + case "repeat": { let iterations = null; let iterationsMin = null; let iterationsMax = null; @@ -2298,7 +2298,8 @@ function nodeFactory(definition, rootNodeDefinitionMap, options) { iterationsMax, nodeFactory(definition.child, rootNodeDefinitionMap, options) ); - case "retry": + } + case "retry": { let attempts = null; let attemptsMin = null; let attemptsMax = null; @@ -2316,6 +2317,7 @@ function nodeFactory(definition, rootNodeDefinitionMap, options) { attemptsMax, nodeFactory(definition.child, rootNodeDefinitionMap, options) ); + } case "flip": return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options)); case "succeed": @@ -2365,7 +2367,7 @@ function nodeFactory(definition, rootNodeDefinitionMap, options) { return new Action(attributes, options, definition.call, definition.args || []); case "condition": return new Condition(attributes, options, definition.call, definition.args || []); - case "wait": + case "wait": { let duration = null; let durationMin = null; let durationMax = null; @@ -2376,6 +2378,7 @@ function nodeFactory(definition, rootNodeDefinitionMap, options) { duration = definition.duration; } return new Wait(attributes, options, duration, durationMin, durationMax); + } } } function nodeAttributesFactory(definition) { diff --git a/dist/index.js.map b/dist/index.js.map index 4f23c9d..773d7bf 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/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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", + "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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 const 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 const 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\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\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/**\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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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 66a10eb..f1142b4 100644 --- a/dist/mistreevous.js +++ b/dist/mistreevous.js @@ -347,7 +347,7 @@ var mistreevous = (() => { } if (expected != void 0) { const expectedValues = typeof expected === "string" ? [expected] : expected; - var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase()); + const tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase()); if (!tokenMatchesExpectation) { const expectationString = expectedValues.map((item) => "'" + item + "'").join(" or "); throw new Error("unexpected token found. Expected " + expectationString + " but got '" + popped + "'"); @@ -357,9 +357,9 @@ var mistreevous = (() => { } function substituteStringLiterals(definition) { const placeholders = {}; - const processedDefinition = definition.replace(/\"(\\.|[^"\\])*\"/g, (match) => { - var strippedMatch = match.substring(1, match.length - 1); - var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch); + const processedDefinition = definition.replace(/"(\\.|[^"\\])*"/g, (match) => { + const strippedMatch = match.substring(1, match.length - 1); + let placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch); if (!placeholder) { placeholder = `@@${Object.keys(placeholders).length}@@`; placeholders[placeholder] = strippedMatch; @@ -375,7 +375,7 @@ var mistreevous = (() => { definition = definition.replace(/\}/g, " } "); definition = definition.replace(/\]/g, " ] "); definition = definition.replace(/\[/g, " [ "); - definition = definition.replace(/\,/g, " , "); + definition = definition.replace(/,/g, " , "); return definition.replace(/\s+/g, " ").trim().split(" "); } @@ -791,7 +791,7 @@ var mistreevous = (() => { }; } function createWaitNode(tokens, stringLiteralPlaceholders) { - let node = { type: "wait" }; + const node = { type: "wait" }; const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders); if (nodeArguments.length) { nodeArguments.filter((arg) => arg.type !== "number" || !arg.isInteger).forEach(() => { @@ -1338,7 +1338,7 @@ var mistreevous = (() => { // src/Utilities.ts function createUid() { - var S4 = function() { + const S4 = function() { return ((1 + Math.random()) * 65536 | 0).toString(16).substring(1); }; return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4(); @@ -2032,7 +2032,7 @@ var mistreevous = (() => { `expected condition function '${this.conditionName}' to return a boolean but returned '${conditionFunctionResult}'` ); } - this.setState(!!conditionFunctionResult ? "mistreevous.succeeded" /* SUCCEEDED */ : "mistreevous.failed" /* FAILED */); + this.setState(conditionFunctionResult ? "mistreevous.succeeded" /* SUCCEEDED */ : "mistreevous.failed" /* FAILED */); } getName = () => this.conditionName; getDetails() { @@ -2280,7 +2280,7 @@ var mistreevous = (() => { switch (definition.type) { case "root": return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options)); - case "repeat": + case "repeat": { let iterations = null; let iterationsMin = null; let iterationsMax = null; @@ -2298,7 +2298,8 @@ var mistreevous = (() => { iterationsMax, nodeFactory(definition.child, rootNodeDefinitionMap, options) ); - case "retry": + } + case "retry": { let attempts = null; let attemptsMin = null; let attemptsMax = null; @@ -2316,6 +2317,7 @@ var mistreevous = (() => { attemptsMax, nodeFactory(definition.child, rootNodeDefinitionMap, options) ); + } case "flip": return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options)); case "succeed": @@ -2365,7 +2367,7 @@ var mistreevous = (() => { return new Action(attributes, options, definition.call, definition.args || []); case "condition": return new Condition(attributes, options, definition.call, definition.args || []); - case "wait": + case "wait": { let duration = null; let durationMin = null; let durationMax = null; @@ -2376,6 +2378,7 @@ var mistreevous = (() => { duration = definition.duration; } return new Wait(attributes, options, duration, durationMin, durationMax); + } } } function nodeAttributesFactory(definition) { diff --git a/dist/mistreevous.js.map b/dist/mistreevous.js.map index e8a3fd9..29d8508 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/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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", + "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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 const 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 const 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\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\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/**\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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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 dced975..e664cd0 100644 --- a/dist/mistreevous.min.js +++ b/dist/mistreevous.min.js @@ -1,2 +1,2 @@ -"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);})(); +"use strict";var mistreevous=(()=>{var It=Object.create;var I=Object.defineProperty;var Ut=Object.getOwnPropertyDescriptor;var $t=Object.getOwnPropertyNames;var Ft=Object.getPrototypeOf,Tt=Object.prototype.hasOwnProperty;var Lt=(t,e,r)=>e in t?I(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var U=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Ot=(t,e)=>{for(var r in e)I(t,r,{get:e[r],enumerable:!0})},mt=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of $t(e))!Tt.call(t,i)&&i!==r&&I(t,i,{get:()=>e[i],enumerable:!(o=Ut(e,i))||o.enumerable});return t};var Pt=(t,e,r)=>(r=t!=null?It(Ft(t)):{},mt(e||!t||!t.__esModule?I(r,"default",{value:t,enumerable:!0}):r,t)),Gt=t=>mt(I({},"__esModule",{value:!0}),t);var dt=(t,e,r)=>(Lt(t,typeof e!="symbol"?e+"":e,r),r);var Dt=U(nt=>{"use strict";Object.defineProperty(nt,"__esModule",{value:!0});nt.Participant=void 0;var we=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}();nt.Participant=we});var vt=U(C=>{"use strict";Object.defineProperty(C,"__esModule",{value:!0});C.isNaturalNumber=C.isNullOrUndefined=void 0;function Ae(t){return t==null}C.isNullOrUndefined=Ae;function Ee(t){return typeof t=="number"&&t>=1&&Math.floor(t)===t}C.isNaturalNumber=Ee});var St=U(at=>{"use strict";Object.defineProperty(at,"__esModule",{value:!0});at.Lotto=void 0;var De=Dt(),G=vt(),ve=function(){function t(e){this._participants=[],this._customRandom=e}return t.prototype.add=function(e,r){if(r===void 0&&(r=1),!(0,G.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 De.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,G.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,G.isNullOrUndefined)(e.redrawable)?!0:e.redrawable,o=[];this._participants.forEach(function(a){for(var s=a.participant,d=a.tickets,ht=0;ht=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,G.isNullOrUndefined)(r.unique)?!1:r.unique;if(e===0)return[];if(!(0,G.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(st,"__esModule",{value:!0});st.createLotto=void 0;var lt=St();function Se(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}}st.createLotto=Se});var Rt=U(ct=>{"use strict";Object.defineProperty(ct,"__esModule",{value:!0});var xe=xt();ct.default=xe.createLotto});var Ue={};Ot(Ue,{BehaviourTree:()=>ut,State:()=>l,convertMDSLToJSON:()=>R,validateDefinition:()=>rt});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={}}};dt(u,"registeredFunctions",{}),dt(u,"registeredSubtrees",{});function gt(t){return t.type==="root"}function bt(t){return t.type==="branch"}function yt(t){return["branch","action","condition","wait"].includes(t.type)}function Z(t){return["root","repeat","retry","flip","succeed","fail"].includes(t.type)}function tt(t){return["sequence","selector","lotto","parallel","race","all"].includes(t.type)}function Nt(t){let e=[],r=o=>{e.push(o),tt(o)?o.children.forEach(r):Z(o)&&r(o.child)};return r(t),e}function y(t){return typeof t=="number"&&Math.floor(t)===t}function et(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 o=typeof e=="string"?[e]:e;if(!o.some(n=>r.toUpperCase()===n.toUpperCase())){let n=o.map(a=>"'"+a+"'").join(" or ");throw new Error("unexpected token found. Expected "+n+" but got '"+r+"'")}}return r}function wt(t){let e={},r=t.replace(/"(\\.|[^"\\])*"/g,o=>{let 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 At(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=c(t,["[","("])==="["?"]":")",i=[];for(;t.length&&t[0]!==o;)i.push(t.shift());return i.forEach((n,a)=>{if(!(a&1)){let d=kt(n,e);r.push(d)}else if(n!==",")throw new Error(`invalid argument list, expected ',' or ']' but got '${n}'`)}),c(t,o),r}function kt(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 R(t){let{placeholders:e,processedDefinition:r}=wt(t),o=At(r);return Mt(o,e)}function Mt(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(gt(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(tt(d))d.children=d.children||[],d.children.push(a);else if(Z(d)){if(d.child)throw new Error("a decorator node must only have a single child node");d.child=a}yt(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(Bt(t,e));break}case"SUCCEED":{i(_t(t,e));break}case"FAIL":{i(Yt(t,e));break}case"FLIP":{i(jt(t,e));break}case"REPEAT":{i(qt(t,e));break}case"RETRY":{i(Wt(t,e));break}case"SEQUENCE":{i(Jt(t,e));break}case"SELECTOR":{i(Vt(t,e));break}case"PARALLEL":{i(Qt(t,e));break}case"RACE":{i(Ht(t,e));break}case"ALL":{i(Kt(t,e));break}case"LOTTO":{i(zt(t,e));break}case"ACTION":{i(Xt(t,e));break}case"CONDITION":{i(Zt(t,e));break}case"WAIT":{i(te(t,e));break}case"BRANCH":{i(ee(t,e));break}case"}":{let s=n();s&&re(s);break}default:throw new Error(`unexpected token: ${a}`)}}return o}function Bt(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)},c(t,"{"),r}function _t(t,e){let r={type:"succeed",...p(t,e)};return c(t,"{"),r}function Yt(t,e){let r={type:"fail",...p(t,e)};return c(t,"{"),r}function jt(t,e){let r={type:"flip",...p(t,e)};return c(t,"{"),r}function qt(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)},c(t,"{"),r}function Wt(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)},c(t,"{"),r}function Jt(t,e){let r={type:"sequence",...p(t,e)};return c(t,"{"),r}function Vt(t,e){let r={type:"selector",...p(t,e)};return c(t,"{"),r}function Qt(t,e){let r={type:"parallel",...p(t,e)};return c(t,"{"),r}function Ht(t,e){let r={type:"race",...p(t,e)};return c(t,"{"),r}function Kt(t,e){let r={type:"all",...p(t,e)};return c(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)),c(t,"{"),o}function Xt(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 Zt(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 te(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 ee(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 re(t){if(Z(t)&&et(t.child))throw new Error(`a ${t.type} node must have a single child node defined`);if(tt(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 rt(t){return t===null||typeof t>"u"?w("definition is null or undefined"):typeof t=="string"?oe(t):typeof t=="object"?ot(t):w(`unexpected definition type of '${typeof t}'`)}function oe(t){let e;try{e=R(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{it(e,!1)}catch(n){return w(n.message)}return{succeeded:!0,json:e}}function ot(t){let e=Array.isArray(t)?t:[t];try{e.forEach(n=>b(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{it(e,!1)}catch(n){return w(n.message)}return{succeeded:!0,json:e}}function it(t,e){let r=t.map(i=>({id:i.id,refs:Nt(i).filter(bt).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":ce(t,e);break;case"condition":pe(t,e);break;case"wait":fe(t,e);break;case"branch":le(t,e);break;case"root":ie(t,e);break;case"succeed":ne(t,e);break;case"fail":ae(t,e);break;case"flip":se(t,e);break;case"repeat":ue(t,e);break;case"retry":de(t,e);break;case"sequence":he(t,e);break;case"selector":me(t,e);break;case"parallel":ge(t,e);break;case"race":be(t,e);break;case"all":ye(t,e);break;case"lotto":Ne(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 ie(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 ne(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 ae(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 se(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 ue(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 de(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 le(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 ce(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 pe(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 fe(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 he(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 me(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 ge(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 be(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 ye(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 Ne(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 w(t){return{succeeded:!1,errorMessage:t}}var v=class extends Error{constructor(r){super("A guard path condition has failed");this.source=r}isSourceNode=r=>r===this.source};var $=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 v(r.node)}};function Et(){let t=function(){return((1+Math.random())*65536|0).toString(16).substring(1)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}var A=class{constructor(e,r,o){this.type=e;this.options=o;this.uid=Et(),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 v&&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 A{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 F=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 T=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 L=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 O=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 P=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 Ct=Pt(Rt());var k=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,Ct.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 A{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 M=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 B=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 _=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 Y=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 j=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 q=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 E=class extends A{isLeafNode=()=>!0};var W=class extends E{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 J=class extends E{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 V=class extends E{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 S=class{constructor(e,r){this.type=e;this.args=r}};var x=class extends S{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 Q=class extends x{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 H=class extends x{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 D=class extends S{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 K=class extends D{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 D{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 X=class extends D{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 pt=Symbol("__root__");function ft(t,e){let r=Ce(t);it([r[pt],...Object.values(r)],!0);let o=g(r[pt],r,e);return Ie(o),o}function g(t,e,r){let o=Re(t);switch(t.type){case"root":return new j(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 _(o,r,i,n,a,g(t.child,e,r))}case"retry":{let i=null,n=null,a=null;return Array.isArray(t.attempts)?(n=t.attempts[0],a=t.attempts[1]):y(t.attempts)&&(i=t.attempts),new Y(o,r,i,n,a,g(t.child,e,r))}case"flip":return new B(o,r,g(t.child,e,r));case"succeed":return new q(o,r,g(t.child,e,r));case"fail":return new M(o,r,g(t.child,e,r));case"sequence":return new P(o,r,t.children.map(i=>g(i,e,r)));case"selector":return new O(o,r,t.children.map(i=>g(i,e,r)));case"parallel":return new F(o,r,t.children.map(i=>g(i,e,r)));case"race":return new T(o,r,t.children.map(i=>g(i,e,r)));case"all":return new L(o,r,t.children.map(i=>g(i,e,r)));case"lotto":return new k(o,r,t.weights,t.children.map(i=>g(i,e,r)));case"branch":return g(e[t.ref].child,e,r);case"action":return new W(o,r,t.call,t.args||[]);case"condition":return new J(o,r,t.call,t.args||[]);case"wait":{let i=null,n=null,a=null;return Array.isArray(t.duration)?(n=t.duration[0],a=t.duration[1]):y(t.duration)&&(i=t.duration),new V(o,r,i,n,a)}}}function Re(t){let e=[];return t.while&&e.push(new Q(t.while.call,t.while.args??[])),t.until&&e.push(new H(t.until.call,t.until.args??[])),t.entry&&e.push(new K(t.entry.call,t.entry.args??[])),t.step&&e.push(new z(t.step.call,t.step.args??[])),t.exit&&e.push(new X(t.exit.call,t.exit.args??[])),e}function Ce(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??pt]=r;return e}function Ie(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 ut=class{constructor(e,r,o={}){this.agent=r;this.options=o;if(et(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}=rt(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=ft(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=R(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}=ot(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}=ot(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 Gt(Ue);})(); //# sourceMappingURL=mistreevous.min.js.map diff --git a/dist/mistreevous.min.js.map b/dist/mistreevous.min.js.map index 42d673b..953cfba 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/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"] + "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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 const 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 const 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\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\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/**\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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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", "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/package-lock.json b/package-lock.json index 4d80f69..2e8a4a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,11 @@ "@types/chai": "^4.3.11", "@types/mocha": "^10.0.6", "@types/sinon": "^17.0.3", + "@typescript-eslint/eslint-plugin": "^7.14.1", + "@typescript-eslint/parser": "^7.14.1", "chai": "^4.4.1", "esbuild": "^0.15.18", + "eslint": "^8.57.0", "expect": "^25.5.0", "mocha": "^10.2.0", "npm-run-all": "^4.1.5", @@ -112,6 +115,97 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, "node_modules/@jest/types": { "version": "25.5.0", "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", @@ -201,6 +295,41 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@sinonjs/commons": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", @@ -352,6 +481,233 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", + "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/type-utils": "7.14.1", + "@typescript-eslint/utils": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", + "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", + "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", + "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.14.1", + "@typescript-eslint/utils": "7.14.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", + "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", + "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/visitor-keys": "7.14.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", + "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.14.1", + "@typescript-eslint/types": "7.14.1", + "@typescript-eslint/typescript-estree": "7.14.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", + "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.14.1", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -364,6 +720,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", @@ -373,6 +738,22 @@ "node": ">=0.4.0" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -443,6 +824,15 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -508,6 +898,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -695,6 +1094,12 @@ "node": ">=6" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -729,6 +1134,30 @@ "node": ">= 8.3" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -1180,16 +1609,293 @@ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, "engines": { - "node": ">=6" + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=0.10.0" } }, "node_modules/expect": { @@ -1223,6 +1929,61 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1260,6 +2021,26 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1393,12 +2174,53 @@ "node": ">= 6" } }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1477,6 +2299,40 @@ "he": "bin/he" } }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1658,6 +2514,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -1954,15 +2819,6 @@ "node": ">=8" } }, - "node_modules/jest-message-util/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-message-util/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -1996,18 +2852,58 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -2057,6 +2953,12 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -2154,6 +3056,15 @@ "node": ">= 0.10.0" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -2294,6 +3205,12 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -2427,6 +3344,23 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2457,6 +3391,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2499,6 +3445,15 @@ "isarray": "0.0.1" } }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -2541,6 +3496,15 @@ "node": ">=4" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "2.7.1", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", @@ -2585,6 +3549,35 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -2655,6 +3648,64 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2799,6 +3850,15 @@ "node": ">=8" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -2968,6 +4028,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2980,6 +4046,18 @@ "node": ">=8.0" } }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -3032,6 +4110,18 @@ "node": ">=0.3.1" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -3041,6 +4131,18 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", @@ -3076,6 +4178,15 @@ "dev": true, "peer": true }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -3120,6 +4231,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", diff --git a/package.json b/package.json index 6c29968..94e7dfe 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,11 @@ "@types/chai": "^4.3.11", "@types/mocha": "^10.0.6", "@types/sinon": "^17.0.3", + "@typescript-eslint/eslint-plugin": "^7.14.1", + "@typescript-eslint/parser": "^7.14.1", "chai": "^4.4.1", "esbuild": "^0.15.18", + "eslint": "^8.57.0", "expect": "^25.5.0", "mocha": "^10.2.0", "npm-run-all": "^4.1.5", @@ -25,13 +28,14 @@ "scripts": { "build": "npm-run-all build:format build:node build:web build:web-minified build:typecheck", "watch": "npm run build:node -- --watch", - "test": "npm-run-all build test:unit-test", + "test": "npm-run-all lint build test:unit-test", "build:format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "build:node": "esbuild ./src/index.ts --bundle --sourcemap --outdir=dist --platform=node", "build:web": "esbuild ./src/index.ts --bundle --sourcemap --platform=browser --global-name=mistreevous --outfile=dist/mistreevous.js", "build:web-minified": "esbuild ./src/index.ts --bundle --sourcemap --platform=browser --global-name=mistreevous --minify --outfile=dist/mistreevous.min.js", "build:typecheck": "tsc --emitDeclarationOnly", - "test:unit-test": "mocha --require ts-node/register 'test/**/*.spec.ts'" + "test:unit-test": "mocha --require ts-node/register 'test/**/*.spec.ts'", + "lint": "eslint . --ext .ts" }, "repository": { "type": "git", diff --git a/src/BehaviourTree.ts b/src/BehaviourTree.ts index f212db9..36e241e 100644 --- a/src/BehaviourTree.ts +++ b/src/BehaviourTree.ts @@ -1,14 +1,8 @@ -import State, { AnyState } from "./State"; +import State from "./State"; import Lookup from "./Lookup"; -import Node, { NodeDetails } from "./nodes/Node"; +import { NodeDetails } from "./nodes/Node"; import Root from "./nodes/decorator/Root"; -import Action from "./nodes/leaf/Action"; -import Condition from "./nodes/leaf/Condition"; -import Composite from "./nodes/composite/Composite"; -import Decorator from "./nodes/decorator/Decorator"; import { Agent, GlobalFunction } from "./Agent"; -import { CallbackAttributeDetails } from "./attributes/callbacks/Callback"; -import { GuardAttributeDetails } from "./attributes/guards/Guard"; import { BehaviourTreeOptions } from "./BehaviourTreeOptions"; import { convertMDSLToJSON } from "./mdsl/MDSLDefinitionParser"; import { RootNodeDefinition } from "./BehaviourTreeDefinition"; diff --git a/src/BehaviourTreeBuilder.ts b/src/BehaviourTreeBuilder.ts index 6b4abef..01c59db 100644 --- a/src/BehaviourTreeBuilder.ts +++ b/src/BehaviourTreeBuilder.ts @@ -108,7 +108,7 @@ function nodeFactory( case "root": return new Root(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options)); - case "repeat": + case "repeat": { let iterations: number | null = null; let iterationsMin: number | null = null; let iterationsMax: number | null = null; @@ -128,8 +128,9 @@ function nodeFactory( iterationsMax, nodeFactory(definition.child, rootNodeDefinitionMap, options) ); + } - case "retry": + case "retry": { let attempts: number | null = null; let attemptsMin: number | null = null; let attemptsMax: number | null = null; @@ -149,6 +150,7 @@ function nodeFactory( attemptsMax, nodeFactory(definition.child, rootNodeDefinitionMap, options) ); + } case "flip": return new Flip(attributes, options, nodeFactory(definition.child, rootNodeDefinitionMap, options)); @@ -211,7 +213,7 @@ function nodeFactory( case "condition": return new Condition(attributes, options, definition.call, definition.args || []); - case "wait": + case "wait": { let duration: number | null = null; let durationMin: number | null = null; let durationMax: number | null = null; @@ -224,6 +226,7 @@ function nodeFactory( } return new Wait(attributes, options, duration, durationMin, durationMax); + } } } diff --git a/src/Utilities.ts b/src/Utilities.ts index cacec6d..c0e46cb 100644 --- a/src/Utilities.ts +++ b/src/Utilities.ts @@ -3,7 +3,7 @@ * @returns A randomly generated node uid. */ export function createUid(): string { - var S4 = function () { + const S4 = function () { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); }; return S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4(); diff --git a/src/mdsl/MDSLDefinitionParser.ts b/src/mdsl/MDSLDefinitionParser.ts index d9c4c16..2ba4e2a 100644 --- a/src/mdsl/MDSLDefinitionParser.ts +++ b/src/mdsl/MDSLDefinitionParser.ts @@ -708,7 +708,7 @@ function createConditionNode( * @returns The wait node JSON definition. */ function createWaitNode(tokens: string[], stringLiteralPlaceholders: StringLiteralPlaceholders): WaitNodeDefinition { - let node = { type: "wait" } as WaitNodeDefinition; + const node = { type: "wait" } as WaitNodeDefinition; // Get the node arguments. const nodeArguments = parseArgumentTokens(tokens, stringLiteralPlaceholders); diff --git a/src/mdsl/MDSLUtilities.ts b/src/mdsl/MDSLUtilities.ts index 036d61f..33a1f20 100644 --- a/src/mdsl/MDSLUtilities.ts +++ b/src/mdsl/MDSLUtilities.ts @@ -24,7 +24,7 @@ export function popAndCheck(tokens: string[], expected?: string | string[]): str const expectedValues = typeof expected === "string" ? [expected] : expected; // Check whether the popped token matches at least one of our expected items. - var tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase()); + const tokenMatchesExpectation = expectedValues.some((item) => popped.toUpperCase() === item.toUpperCase()); // Throw an error if the popped token didn't match any of our expected items. if (!tokenMatchesExpectation) { @@ -50,9 +50,9 @@ export function substituteStringLiterals(definition: string): { const placeholders: StringLiteralPlaceholders = {}; // Replace any string literals wrapped with double quotes in our definition with placeholders to be processed later. - const processedDefinition = definition.replace(/\"(\\.|[^"\\])*\"/g, (match) => { - var strippedMatch = match.substring(1, match.length - 1); - var placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch); + const processedDefinition = definition.replace(/"(\\.|[^"\\])*"/g, (match) => { + const strippedMatch = match.substring(1, match.length - 1); + let placeholder = Object.keys(placeholders).find((key) => placeholders[key] === strippedMatch); // If we have no existing string literal match then create a new placeholder. if (!placeholder) { @@ -79,7 +79,7 @@ export function parseTokensFromDefinition(definition: string): string[] { definition = definition.replace(/\}/g, " } "); definition = definition.replace(/\]/g, " ] "); definition = definition.replace(/\[/g, " [ "); - definition = definition.replace(/\,/g, " , "); + definition = definition.replace(/,/g, " , "); // Split the definition into raw token form and return it. return definition.replace(/\s+/g, " ").trim().split(" "); diff --git a/src/nodes/leaf/Condition.ts b/src/nodes/leaf/Condition.ts index 175b69a..476fe11 100644 --- a/src/nodes/leaf/Condition.ts +++ b/src/nodes/leaf/Condition.ts @@ -63,7 +63,7 @@ export default class Condition extends Leaf { } // Set the state of this node based on the result of calling the condition function. - this.setState(!!conditionFunctionResult ? State.SUCCEEDED : State.FAILED); + this.setState(conditionFunctionResult ? State.SUCCEEDED : State.FAILED); } /** diff --git a/test/BehaviourTree.spec.ts b/test/BehaviourTree.spec.ts index 19da05d..2f1b77f 100644 --- a/test/BehaviourTree.spec.ts +++ b/test/BehaviourTree.spec.ts @@ -308,7 +308,7 @@ describe("A BehaviourTree instance", () => { }); describe("has a 'getTreeNodeDetails' function that gets the node details for the tree", () => { - var sandbox: SinonSandbox; + let sandbox: SinonSandbox; beforeEach(() => { sandbox = sinon.createSandbox(); diff --git a/test/nodes/decorator/Repeat.spec.ts b/test/nodes/decorator/Repeat.spec.ts index 057213b..79a8252 100644 --- a/test/nodes/decorator/Repeat.spec.ts +++ b/test/nodes/decorator/Repeat.spec.ts @@ -158,7 +158,7 @@ describe("A Repeat node", () => { }); describe("when updated as part of a tree step", () => { - var sandbox: SinonSandbox; + let sandbox: SinonSandbox; beforeEach(() => { sandbox = sinon.createSandbox(); diff --git a/test/nodes/decorator/Retry.spec.ts b/test/nodes/decorator/Retry.spec.ts index 59df623..5d58cf0 100644 --- a/test/nodes/decorator/Retry.spec.ts +++ b/test/nodes/decorator/Retry.spec.ts @@ -158,7 +158,7 @@ describe("A Retry node", () => { }); describe("when updated as part of a tree step", () => { - var sandbox: SinonSandbox; + let sandbox: SinonSandbox; beforeEach(() => { sandbox = sinon.createSandbox(); diff --git a/test/nodes/leaf/Wait.spec.ts b/test/nodes/leaf/Wait.spec.ts index 6c923aa..8c061fb 100644 --- a/test/nodes/leaf/Wait.spec.ts +++ b/test/nodes/leaf/Wait.spec.ts @@ -117,8 +117,8 @@ describe("A Wait node", () => { }); describe("when updated as part of a tree step", () => { - var clock: SinonFakeTimers; - var sandbox: SinonSandbox; + let clock: SinonFakeTimers; + let sandbox: SinonSandbox; beforeEach(() => { clock = sinon.useFakeTimers(); From 5388af88b42967fc352dc55b1cbdf1d182a5c9b5 Mon Sep 17 00:00:00 2001 From: Nikolas Howard Date: Fri, 28 Jun 2024 09:52:29 +0100 Subject: [PATCH 2/3] updated typescript and mocha --- .vscode/settings.json | 1 + dist/BehaviourTreeDefinitionUtilities.d.ts | 10 +- dist/attributes/Attribute.d.ts | 5 - dist/attributes/callbacks/Callback.d.ts | 4 - dist/attributes/guards/Guard.d.ts | 4 - dist/index.js | 45 +- dist/index.js.map | 6 +- dist/mistreevous.js | 45 +- dist/mistreevous.js.map | 6 +- dist/mistreevous.min.js | 2 +- dist/mistreevous.min.js.map | 8 +- dist/nodes/Node.d.ts | 5 - dist/nodes/composite/Composite.d.ts | 4 - dist/nodes/decorator/Decorator.d.ts | 4 - dist/nodes/leaf/Leaf.d.ts | 4 - package-lock.json | 2293 ++++++++++++-------- package.json | 8 +- src/BehaviourTreeBuilder.ts | 5 +- src/BehaviourTreeDefinitionUtilities.ts | 14 +- src/BehaviourTreeDefinitionValidator.ts | 4 +- src/attributes/Attribute.ts | 5 - src/attributes/callbacks/Callback.ts | 5 - src/attributes/guards/Guard.ts | 5 - src/mdsl/MDSLDefinitionParser.ts | 20 +- src/nodes/Node.ts | 5 - src/nodes/composite/Composite.ts | 5 - src/nodes/decorator/Decorator.ts | 5 - src/nodes/leaf/Leaf.ts | 7 +- 28 files changed, 1450 insertions(+), 1084 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 7a73a41..00ad71f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,2 +1,3 @@ { + "typescript.tsdk": "node_modules\\typescript\\lib" } \ No newline at end of file diff --git a/dist/BehaviourTreeDefinitionUtilities.d.ts b/dist/BehaviourTreeDefinitionUtilities.d.ts index bbf6b0e..c95a5f2 100644 --- a/dist/BehaviourTreeDefinitionUtilities.d.ts +++ b/dist/BehaviourTreeDefinitionUtilities.d.ts @@ -4,31 +4,31 @@ import { NodeDefinition, RootNodeDefinition, DecoratorNodeDefinition, CompositeN * @param node The node. * @returns A value of true if the specified node satisfies the RootNodeDefinition type. */ -export declare function isRootNode(node: NodeDefinition): node is RootNodeDefinition; +export declare function isRootNodeDefinition(node: NodeDefinition): node is RootNodeDefinition; /** * A type guard function that returns true if the specified node satisfies the BranchNodeDefinition type. * @param node The node. * @returns A value of true if the specified node satisfies the BranchNodeDefinition type. */ -export declare function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition; +export declare function isBranchNodeDefinition(node: NodeDefinition): node is BranchNodeDefinition; /** * A type guard function that returns true if the specified node satisfies the NodeDefinition type. * @param node The node. * @returns A value of true if the specified node satisfies the NodeDefinition type. */ -export declare function isLeafNode(node: NodeDefinition): node is NodeDefinition; +export declare function isLeafNodeDefinition(node: NodeDefinition): node is NodeDefinition; /** * A type guard function that returns true if the specified node satisfies the DecoratorNodeDefinition type. * @param node The node. * @returns A value of true if the specified node satisfies the DecoratorNodeDefinition type. */ -export declare function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefinition; +export declare function isDecoratorNodeDefinition(node: NodeDefinition): node is DecoratorNodeDefinition; /** * A type guard function that returns true if the specified node satisfies the CompositeNodeDefinition type. * @param node The node. * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type. */ -export declare function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition; +export declare function isCompositeNodeDefinition(node: NodeDefinition): node is CompositeNodeDefinition; /** * Flatten a node definition into an array of all of its nested node definitions. * @param nodeDefinition The node definition to flatten. diff --git a/dist/attributes/Attribute.d.ts b/dist/attributes/Attribute.d.ts index 515015a..f5556db 100644 --- a/dist/attributes/Attribute.d.ts +++ b/dist/attributes/Attribute.d.ts @@ -1,4 +1,3 @@ -import Guard from "./guards/Guard"; export type AttributeDetails = { /** The attribute type. */ type: string; @@ -20,8 +19,4 @@ export default abstract class Attribute this is Guard; } diff --git a/dist/attributes/callbacks/Callback.d.ts b/dist/attributes/callbacks/Callback.d.ts index 84ebff1..2f8eb69 100644 --- a/dist/attributes/callbacks/Callback.d.ts +++ b/dist/attributes/callbacks/Callback.d.ts @@ -22,10 +22,6 @@ export default abstract class Callback extends Attribute string; - /** - * Gets whether this attribute is a guard. - */ - isGuard: () => boolean; /** * Gets the attribute details. */ diff --git a/dist/attributes/guards/Guard.d.ts b/dist/attributes/guards/Guard.d.ts index f6be9c2..0af59de 100644 --- a/dist/attributes/guards/Guard.d.ts +++ b/dist/attributes/guards/Guard.d.ts @@ -22,10 +22,6 @@ export default abstract class Guard extends Attribute { * Gets the name of the condition function that determines whether the guard is satisfied. */ getCondition: () => string; - /** - * Gets whether this attribute is a guard. - */ - isGuard: () => boolean; /** * Gets the attribute details. */ diff --git a/dist/index.js b/dist/index.js index 895f33b..86df2a8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -304,28 +304,28 @@ __publicField(Lookup, "registeredFunctions", {}); __publicField(Lookup, "registeredSubtrees", {}); // src/BehaviourTreeDefinitionUtilities.ts -function isRootNode(node) { +function isRootNodeDefinition(node) { return node.type === "root"; } -function isBranchNode(node) { +function isBranchNodeDefinition(node) { return node.type === "branch"; } -function isLeafNode(node) { +function isLeafNodeDefinition(node) { return ["branch", "action", "condition", "wait"].includes(node.type); } -function isDecoratorNode(node) { +function isDecoratorNodeDefinition(node) { return ["root", "repeat", "retry", "flip", "succeed", "fail"].includes(node.type); } -function isCompositeNode(node) { +function isCompositeNodeDefinition(node) { return ["sequence", "selector", "lotto", "parallel", "race", "all"].includes(node.type); } function flattenDefinition(nodeDefinition) { const nodes = []; const processNode = (currentNodeDefinition) => { nodes.push(currentNodeDefinition); - if (isCompositeNode(currentNodeDefinition)) { + if (isCompositeNodeDefinition(currentNodeDefinition)) { currentNodeDefinition.children.forEach(processNode); - } else if (isDecoratorNode(currentNodeDefinition)) { + } else if (isDecoratorNodeDefinition(currentNodeDefinition)) { processNode(currentNodeDefinition.child); } }; @@ -483,7 +483,7 @@ function convertTokensToJSONDefinition(tokens, stringLiteralPlaceholders) { const treeStacks = []; const rootNodes = []; const pushNode = (node) => { - if (isRootNode(node)) { + if (isRootNodeDefinition(node)) { if (treeStacks[treeStacks.length - 1]?.length) { throw new Error("a root node cannot be the child of another node"); } @@ -496,16 +496,16 @@ function convertTokensToJSONDefinition(tokens, stringLiteralPlaceholders) { } const topTreeStack = treeStacks[treeStacks.length - 1]; const topTreeStackTopNode = topTreeStack[topTreeStack.length - 1]; - if (isCompositeNode(topTreeStackTopNode)) { + if (isCompositeNodeDefinition(topTreeStackTopNode)) { topTreeStackTopNode.children = topTreeStackTopNode.children || []; topTreeStackTopNode.children.push(node); - } else if (isDecoratorNode(topTreeStackTopNode)) { + } else if (isDecoratorNodeDefinition(topTreeStackTopNode)) { if (topTreeStackTopNode.child) { throw new Error("a decorator node must only have a single child node"); } topTreeStackTopNode.child = node; } - if (!isLeafNode(node)) { + if (!isLeafNodeDefinition(node)) { topTreeStack.push(node); } }; @@ -824,10 +824,10 @@ function createBranchNode(tokens, stringLiteralPlaceholders) { return { type: "branch", ref: nodeArguments[0].value }; } function validatePoppedNode(definition) { - if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) { + if (isDecoratorNodeDefinition(definition) && isNullOrUndefined(definition.child)) { throw new Error(`a ${definition.type} node must have a single child node defined`); } - if (isCompositeNode(definition) && !definition.children?.length) { + if (isCompositeNodeDefinition(definition) && !definition.children?.length) { throw new Error(`a ${definition.type} node must have at least a single child node defined`); } if (definition.type === "lotto") { @@ -925,7 +925,7 @@ function validateBranchSubtreeLinks(rootNodeDefinitions, includesGlobalSubtrees) const rootNodeMappings = rootNodeDefinitions.map( (rootNodeDefinition) => ({ id: rootNodeDefinition.id, - refs: flattenDefinition(rootNodeDefinition).filter(isBranchNode).map(({ ref }) => ref) + refs: flattenDefinition(rootNodeDefinition).filter(isBranchNodeDefinition).map(({ ref }) => ref) }) ); const followRefs = (mapping, path = []) => { @@ -1439,13 +1439,16 @@ var Node = class { } }; +// src/nodes/leaf/Leaf.ts +var Leaf = class extends Node { +}; + // src/nodes/composite/Composite.ts var Composite = class extends Node { constructor(type, attributes, options, children) { super(type, attributes, options); this.children = children; } - isLeafNode = () => false; getChildren = () => this.children; reset = () => { this.setState("mistreevous.ready" /* READY */); @@ -1644,7 +1647,6 @@ var Decorator = class extends Node { super(type, attributes, options); this.child = child; } - isLeafNode = () => false; getChildren = () => [this.child]; reset = () => { this.setState("mistreevous.ready" /* READY */); @@ -1886,11 +1888,6 @@ var Succeed = class extends Decorator { getName = () => "SUCCEED"; }; -// src/nodes/leaf/Leaf.ts -var Leaf = class extends Node { - isLeafNode = () => true; -}; - // src/nodes/leaf/Action.ts var Action = class extends Leaf { constructor(attributes, options, actionName, actionArguments) { @@ -2126,7 +2123,6 @@ var Guard = class extends Attribute { this.condition = condition; } getCondition = () => this.condition; - isGuard = () => true; getDetails() { return { type: this.type, @@ -2205,7 +2201,6 @@ var Callback = class extends Attribute { this.functionName = functionName; } getFunctionName = () => this.functionName; - isGuard = () => false; getDetails() { return { type: this.type, @@ -2414,7 +2409,7 @@ function applyLeafNodeGuardPaths(root) { const nodePaths = []; const findLeafNodes = (path, node) => { path = path.concat(node); - if (node.isLeafNode()) { + if (node instanceof Leaf) { nodePaths.push(path); } else { node.getChildren().forEach((child) => findLeafNodes(path, child)); @@ -2430,7 +2425,7 @@ function applyLeafNodeGuardPaths(root) { const guardPath = new GuardPath( path.slice(0, depth + 1).map((node) => ({ node, - guards: node.getAttributes().filter((attribute) => attribute.isGuard()) + guards: node.getAttributes().filter((attribute) => attribute instanceof Guard) })).filter((details) => details.guards.length > 0) ); currentNode.setGuardPath(guardPath); diff --git a/dist/index.js.map b/dist/index.js.map index 773d7bf..5a1b4c9 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/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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 const 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 const 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\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\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/**\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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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/leaf/Leaf.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/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 isRootNodeDefinition(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 isBranchNodeDefinition(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 isLeafNodeDefinition(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 isDecoratorNodeDefinition(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 isCompositeNodeDefinition(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 (isCompositeNodeDefinition(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNodeDefinition(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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 isCompositeNodeDefinition,\n isDecoratorNodeDefinition,\n isLeafNodeDefinition,\n isNullOrUndefined,\n isRootNodeDefinition\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 (isRootNodeDefinition(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 (isCompositeNodeDefinition(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNodeDefinition(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 (!isLeafNodeDefinition(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 const 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 (isDecoratorNodeDefinition(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 (isCompositeNodeDefinition(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, isBranchNodeDefinition, 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(isBranchNodeDefinition)\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 const 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/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 from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {}\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 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 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 { 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", "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 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 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 Leaf from \"./nodes/leaf/Leaf\";\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\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\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/**\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 instanceof Leaf) {\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 instanceof 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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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 f1142b4..f297c08 100644 --- a/dist/mistreevous.js +++ b/dist/mistreevous.js @@ -304,28 +304,28 @@ var mistreevous = (() => { __publicField(Lookup, "registeredSubtrees", {}); // src/BehaviourTreeDefinitionUtilities.ts - function isRootNode(node) { + function isRootNodeDefinition(node) { return node.type === "root"; } - function isBranchNode(node) { + function isBranchNodeDefinition(node) { return node.type === "branch"; } - function isLeafNode(node) { + function isLeafNodeDefinition(node) { return ["branch", "action", "condition", "wait"].includes(node.type); } - function isDecoratorNode(node) { + function isDecoratorNodeDefinition(node) { return ["root", "repeat", "retry", "flip", "succeed", "fail"].includes(node.type); } - function isCompositeNode(node) { + function isCompositeNodeDefinition(node) { return ["sequence", "selector", "lotto", "parallel", "race", "all"].includes(node.type); } function flattenDefinition(nodeDefinition) { const nodes = []; const processNode = (currentNodeDefinition) => { nodes.push(currentNodeDefinition); - if (isCompositeNode(currentNodeDefinition)) { + if (isCompositeNodeDefinition(currentNodeDefinition)) { currentNodeDefinition.children.forEach(processNode); - } else if (isDecoratorNode(currentNodeDefinition)) { + } else if (isDecoratorNodeDefinition(currentNodeDefinition)) { processNode(currentNodeDefinition.child); } }; @@ -483,7 +483,7 @@ var mistreevous = (() => { const treeStacks = []; const rootNodes = []; const pushNode = (node) => { - if (isRootNode(node)) { + if (isRootNodeDefinition(node)) { if (treeStacks[treeStacks.length - 1]?.length) { throw new Error("a root node cannot be the child of another node"); } @@ -496,16 +496,16 @@ var mistreevous = (() => { } const topTreeStack = treeStacks[treeStacks.length - 1]; const topTreeStackTopNode = topTreeStack[topTreeStack.length - 1]; - if (isCompositeNode(topTreeStackTopNode)) { + if (isCompositeNodeDefinition(topTreeStackTopNode)) { topTreeStackTopNode.children = topTreeStackTopNode.children || []; topTreeStackTopNode.children.push(node); - } else if (isDecoratorNode(topTreeStackTopNode)) { + } else if (isDecoratorNodeDefinition(topTreeStackTopNode)) { if (topTreeStackTopNode.child) { throw new Error("a decorator node must only have a single child node"); } topTreeStackTopNode.child = node; } - if (!isLeafNode(node)) { + if (!isLeafNodeDefinition(node)) { topTreeStack.push(node); } }; @@ -824,10 +824,10 @@ var mistreevous = (() => { return { type: "branch", ref: nodeArguments[0].value }; } function validatePoppedNode(definition) { - if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) { + if (isDecoratorNodeDefinition(definition) && isNullOrUndefined(definition.child)) { throw new Error(`a ${definition.type} node must have a single child node defined`); } - if (isCompositeNode(definition) && !definition.children?.length) { + if (isCompositeNodeDefinition(definition) && !definition.children?.length) { throw new Error(`a ${definition.type} node must have at least a single child node defined`); } if (definition.type === "lotto") { @@ -925,7 +925,7 @@ var mistreevous = (() => { const rootNodeMappings = rootNodeDefinitions.map( (rootNodeDefinition) => ({ id: rootNodeDefinition.id, - refs: flattenDefinition(rootNodeDefinition).filter(isBranchNode).map(({ ref }) => ref) + refs: flattenDefinition(rootNodeDefinition).filter(isBranchNodeDefinition).map(({ ref }) => ref) }) ); const followRefs = (mapping, path = []) => { @@ -1439,13 +1439,16 @@ var mistreevous = (() => { } }; + // src/nodes/leaf/Leaf.ts + var Leaf = class extends Node { + }; + // src/nodes/composite/Composite.ts var Composite = class extends Node { constructor(type, attributes, options, children) { super(type, attributes, options); this.children = children; } - isLeafNode = () => false; getChildren = () => this.children; reset = () => { this.setState("mistreevous.ready" /* READY */); @@ -1644,7 +1647,6 @@ var mistreevous = (() => { super(type, attributes, options); this.child = child; } - isLeafNode = () => false; getChildren = () => [this.child]; reset = () => { this.setState("mistreevous.ready" /* READY */); @@ -1886,11 +1888,6 @@ var mistreevous = (() => { getName = () => "SUCCEED"; }; - // src/nodes/leaf/Leaf.ts - var Leaf = class extends Node { - isLeafNode = () => true; - }; - // src/nodes/leaf/Action.ts var Action = class extends Leaf { constructor(attributes, options, actionName, actionArguments) { @@ -2126,7 +2123,6 @@ var mistreevous = (() => { this.condition = condition; } getCondition = () => this.condition; - isGuard = () => true; getDetails() { return { type: this.type, @@ -2205,7 +2201,6 @@ var mistreevous = (() => { this.functionName = functionName; } getFunctionName = () => this.functionName; - isGuard = () => false; getDetails() { return { type: this.type, @@ -2414,7 +2409,7 @@ var mistreevous = (() => { const nodePaths = []; const findLeafNodes = (path, node) => { path = path.concat(node); - if (node.isLeafNode()) { + if (node instanceof Leaf) { nodePaths.push(path); } else { node.getChildren().forEach((child) => findLeafNodes(path, child)); @@ -2430,7 +2425,7 @@ var mistreevous = (() => { const guardPath = new GuardPath( path.slice(0, depth + 1).map((node) => ({ node, - guards: node.getAttributes().filter((attribute) => attribute.isGuard()) + guards: node.getAttributes().filter((attribute) => attribute instanceof Guard) })).filter((details) => details.guards.length > 0) ); currentNode.setGuardPath(guardPath); diff --git a/dist/mistreevous.js.map b/dist/mistreevous.js.map index 29d8508..c094275 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/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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 const 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 const 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\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\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/**\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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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/leaf/Leaf.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/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 isRootNodeDefinition(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 isBranchNodeDefinition(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 isLeafNodeDefinition(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 isDecoratorNodeDefinition(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 isCompositeNodeDefinition(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 (isCompositeNodeDefinition(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNodeDefinition(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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 isCompositeNodeDefinition,\n isDecoratorNodeDefinition,\n isLeafNodeDefinition,\n isNullOrUndefined,\n isRootNodeDefinition\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 (isRootNodeDefinition(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 (isCompositeNodeDefinition(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNodeDefinition(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 (!isLeafNodeDefinition(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 const 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 (isDecoratorNodeDefinition(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 (isCompositeNodeDefinition(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, isBranchNodeDefinition, 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(isBranchNodeDefinition)\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 const 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/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 from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {}\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 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 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 { 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", "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 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 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 Leaf from \"./nodes/leaf/Leaf\";\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\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\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/**\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 instanceof Leaf) {\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 instanceof 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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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 e664cd0..41985c5 100644 --- a/dist/mistreevous.min.js +++ b/dist/mistreevous.min.js @@ -1,2 +1,2 @@ -"use strict";var mistreevous=(()=>{var It=Object.create;var I=Object.defineProperty;var Ut=Object.getOwnPropertyDescriptor;var $t=Object.getOwnPropertyNames;var Ft=Object.getPrototypeOf,Tt=Object.prototype.hasOwnProperty;var Lt=(t,e,r)=>e in t?I(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var U=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Ot=(t,e)=>{for(var r in e)I(t,r,{get:e[r],enumerable:!0})},mt=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of $t(e))!Tt.call(t,i)&&i!==r&&I(t,i,{get:()=>e[i],enumerable:!(o=Ut(e,i))||o.enumerable});return t};var Pt=(t,e,r)=>(r=t!=null?It(Ft(t)):{},mt(e||!t||!t.__esModule?I(r,"default",{value:t,enumerable:!0}):r,t)),Gt=t=>mt(I({},"__esModule",{value:!0}),t);var dt=(t,e,r)=>(Lt(t,typeof e!="symbol"?e+"":e,r),r);var Dt=U(nt=>{"use strict";Object.defineProperty(nt,"__esModule",{value:!0});nt.Participant=void 0;var we=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}();nt.Participant=we});var vt=U(C=>{"use strict";Object.defineProperty(C,"__esModule",{value:!0});C.isNaturalNumber=C.isNullOrUndefined=void 0;function Ae(t){return t==null}C.isNullOrUndefined=Ae;function Ee(t){return typeof t=="number"&&t>=1&&Math.floor(t)===t}C.isNaturalNumber=Ee});var St=U(at=>{"use strict";Object.defineProperty(at,"__esModule",{value:!0});at.Lotto=void 0;var De=Dt(),G=vt(),ve=function(){function t(e){this._participants=[],this._customRandom=e}return t.prototype.add=function(e,r){if(r===void 0&&(r=1),!(0,G.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 De.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,G.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,G.isNullOrUndefined)(e.redrawable)?!0:e.redrawable,o=[];this._participants.forEach(function(a){for(var s=a.participant,d=a.tickets,ht=0;ht=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,G.isNullOrUndefined)(r.unique)?!1:r.unique;if(e===0)return[];if(!(0,G.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(st,"__esModule",{value:!0});st.createLotto=void 0;var lt=St();function Se(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}}st.createLotto=Se});var Rt=U(ct=>{"use strict";Object.defineProperty(ct,"__esModule",{value:!0});var xe=xt();ct.default=xe.createLotto});var Ue={};Ot(Ue,{BehaviourTree:()=>ut,State:()=>l,convertMDSLToJSON:()=>R,validateDefinition:()=>rt});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={}}};dt(u,"registeredFunctions",{}),dt(u,"registeredSubtrees",{});function gt(t){return t.type==="root"}function bt(t){return t.type==="branch"}function yt(t){return["branch","action","condition","wait"].includes(t.type)}function Z(t){return["root","repeat","retry","flip","succeed","fail"].includes(t.type)}function tt(t){return["sequence","selector","lotto","parallel","race","all"].includes(t.type)}function Nt(t){let e=[],r=o=>{e.push(o),tt(o)?o.children.forEach(r):Z(o)&&r(o.child)};return r(t),e}function y(t){return typeof t=="number"&&Math.floor(t)===t}function et(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 o=typeof e=="string"?[e]:e;if(!o.some(n=>r.toUpperCase()===n.toUpperCase())){let n=o.map(a=>"'"+a+"'").join(" or ");throw new Error("unexpected token found. Expected "+n+" but got '"+r+"'")}}return r}function wt(t){let e={},r=t.replace(/"(\\.|[^"\\])*"/g,o=>{let 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 At(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=c(t,["[","("])==="["?"]":")",i=[];for(;t.length&&t[0]!==o;)i.push(t.shift());return i.forEach((n,a)=>{if(!(a&1)){let d=kt(n,e);r.push(d)}else if(n!==",")throw new Error(`invalid argument list, expected ',' or ']' but got '${n}'`)}),c(t,o),r}function kt(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 R(t){let{placeholders:e,processedDefinition:r}=wt(t),o=At(r);return Mt(o,e)}function Mt(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(gt(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(tt(d))d.children=d.children||[],d.children.push(a);else if(Z(d)){if(d.child)throw new Error("a decorator node must only have a single child node");d.child=a}yt(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(Bt(t,e));break}case"SUCCEED":{i(_t(t,e));break}case"FAIL":{i(Yt(t,e));break}case"FLIP":{i(jt(t,e));break}case"REPEAT":{i(qt(t,e));break}case"RETRY":{i(Wt(t,e));break}case"SEQUENCE":{i(Jt(t,e));break}case"SELECTOR":{i(Vt(t,e));break}case"PARALLEL":{i(Qt(t,e));break}case"RACE":{i(Ht(t,e));break}case"ALL":{i(Kt(t,e));break}case"LOTTO":{i(zt(t,e));break}case"ACTION":{i(Xt(t,e));break}case"CONDITION":{i(Zt(t,e));break}case"WAIT":{i(te(t,e));break}case"BRANCH":{i(ee(t,e));break}case"}":{let s=n();s&&re(s);break}default:throw new Error(`unexpected token: ${a}`)}}return o}function Bt(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)},c(t,"{"),r}function _t(t,e){let r={type:"succeed",...p(t,e)};return c(t,"{"),r}function Yt(t,e){let r={type:"fail",...p(t,e)};return c(t,"{"),r}function jt(t,e){let r={type:"flip",...p(t,e)};return c(t,"{"),r}function qt(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)},c(t,"{"),r}function Wt(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)},c(t,"{"),r}function Jt(t,e){let r={type:"sequence",...p(t,e)};return c(t,"{"),r}function Vt(t,e){let r={type:"selector",...p(t,e)};return c(t,"{"),r}function Qt(t,e){let r={type:"parallel",...p(t,e)};return c(t,"{"),r}function Ht(t,e){let r={type:"race",...p(t,e)};return c(t,"{"),r}function Kt(t,e){let r={type:"all",...p(t,e)};return c(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)),c(t,"{"),o}function Xt(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 Zt(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 te(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 ee(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 re(t){if(Z(t)&&et(t.child))throw new Error(`a ${t.type} node must have a single child node defined`);if(tt(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 rt(t){return t===null||typeof t>"u"?w("definition is null or undefined"):typeof t=="string"?oe(t):typeof t=="object"?ot(t):w(`unexpected definition type of '${typeof t}'`)}function oe(t){let e;try{e=R(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{it(e,!1)}catch(n){return w(n.message)}return{succeeded:!0,json:e}}function ot(t){let e=Array.isArray(t)?t:[t];try{e.forEach(n=>b(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{it(e,!1)}catch(n){return w(n.message)}return{succeeded:!0,json:e}}function it(t,e){let r=t.map(i=>({id:i.id,refs:Nt(i).filter(bt).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":ce(t,e);break;case"condition":pe(t,e);break;case"wait":fe(t,e);break;case"branch":le(t,e);break;case"root":ie(t,e);break;case"succeed":ne(t,e);break;case"fail":ae(t,e);break;case"flip":se(t,e);break;case"repeat":ue(t,e);break;case"retry":de(t,e);break;case"sequence":he(t,e);break;case"selector":me(t,e);break;case"parallel":ge(t,e);break;case"race":be(t,e);break;case"all":ye(t,e);break;case"lotto":Ne(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 ie(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 ne(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 ae(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 se(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 ue(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 de(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 le(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 ce(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 pe(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 fe(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 he(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 me(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 ge(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 be(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 ye(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 Ne(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 w(t){return{succeeded:!1,errorMessage:t}}var v=class extends Error{constructor(r){super("A guard path condition has failed");this.source=r}isSourceNode=r=>r===this.source};var $=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 v(r.node)}};function Et(){let t=function(){return((1+Math.random())*65536|0).toString(16).substring(1)};return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}var A=class{constructor(e,r,o){this.type=e;this.options=o;this.uid=Et(),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 v&&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 A{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 F=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 T=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 L=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 O=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 P=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 Ct=Pt(Rt());var k=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,Ct.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 A{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 M=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 B=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 _=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 Y=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 j=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 q=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 E=class extends A{isLeafNode=()=>!0};var W=class extends E{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 J=class extends E{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 V=class extends E{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 S=class{constructor(e,r){this.type=e;this.args=r}};var x=class extends S{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 Q=class extends x{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 H=class extends x{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 D=class extends S{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 K=class extends D{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 D{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 X=class extends D{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 pt=Symbol("__root__");function ft(t,e){let r=Ce(t);it([r[pt],...Object.values(r)],!0);let o=g(r[pt],r,e);return Ie(o),o}function g(t,e,r){let o=Re(t);switch(t.type){case"root":return new j(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 _(o,r,i,n,a,g(t.child,e,r))}case"retry":{let i=null,n=null,a=null;return Array.isArray(t.attempts)?(n=t.attempts[0],a=t.attempts[1]):y(t.attempts)&&(i=t.attempts),new Y(o,r,i,n,a,g(t.child,e,r))}case"flip":return new B(o,r,g(t.child,e,r));case"succeed":return new q(o,r,g(t.child,e,r));case"fail":return new M(o,r,g(t.child,e,r));case"sequence":return new P(o,r,t.children.map(i=>g(i,e,r)));case"selector":return new O(o,r,t.children.map(i=>g(i,e,r)));case"parallel":return new F(o,r,t.children.map(i=>g(i,e,r)));case"race":return new T(o,r,t.children.map(i=>g(i,e,r)));case"all":return new L(o,r,t.children.map(i=>g(i,e,r)));case"lotto":return new k(o,r,t.weights,t.children.map(i=>g(i,e,r)));case"branch":return g(e[t.ref].child,e,r);case"action":return new W(o,r,t.call,t.args||[]);case"condition":return new J(o,r,t.call,t.args||[]);case"wait":{let i=null,n=null,a=null;return Array.isArray(t.duration)?(n=t.duration[0],a=t.duration[1]):y(t.duration)&&(i=t.duration),new V(o,r,i,n,a)}}}function Re(t){let e=[];return t.while&&e.push(new Q(t.while.call,t.while.args??[])),t.until&&e.push(new H(t.until.call,t.until.args??[])),t.entry&&e.push(new K(t.entry.call,t.entry.args??[])),t.step&&e.push(new z(t.step.call,t.step.args??[])),t.exit&&e.push(new X(t.exit.call,t.exit.args??[])),e}function Ce(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??pt]=r;return e}function Ie(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 ut=class{constructor(e,r,o={}){this.agent=r;this.options=o;if(et(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}=rt(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=ft(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=R(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}=ot(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}=ot(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 Gt(Ue);})(); +"use strict";var mistreevous=(()=>{var It=Object.create;var I=Object.defineProperty;var Ut=Object.getOwnPropertyDescriptor;var $t=Object.getOwnPropertyNames;var Ft=Object.getPrototypeOf,Tt=Object.prototype.hasOwnProperty;var Lt=(t,e,r)=>e in t?I(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r;var U=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Ot=(t,e)=>{for(var r in e)I(t,r,{get:e[r],enumerable:!0})},mt=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of $t(e))!Tt.call(t,i)&&i!==r&&I(t,i,{get:()=>e[i],enumerable:!(o=Ut(e,i))||o.enumerable});return t};var Pt=(t,e,r)=>(r=t!=null?It(Ft(t)):{},mt(e||!t||!t.__esModule?I(r,"default",{value:t,enumerable:!0}):r,t)),kt=t=>mt(I({},"__esModule",{value:!0}),t);var dt=(t,e,r)=>(Lt(t,typeof e!="symbol"?e+"":e,r),r);var Dt=U(nt=>{"use strict";Object.defineProperty(nt,"__esModule",{value:!0});nt.Participant=void 0;var we=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}();nt.Participant=we});var vt=U(C=>{"use strict";Object.defineProperty(C,"__esModule",{value:!0});C.isNaturalNumber=C.isNullOrUndefined=void 0;function Ae(t){return t==null}C.isNullOrUndefined=Ae;function Ee(t){return typeof t=="number"&&t>=1&&Math.floor(t)===t}C.isNaturalNumber=Ee});var St=U(at=>{"use strict";Object.defineProperty(at,"__esModule",{value:!0});at.Lotto=void 0;var De=Dt(),k=vt(),ve=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 De.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,ht=0;ht=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(st,"__esModule",{value:!0});st.createLotto=void 0;var ct=St();function Se(t){if(!t)return new ct.Lotto;if(Array.isArray(t)){var e=t,r=new ct.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 ct.Lotto(o);return e&&e.forEach(function(a){var s=a[0],d=a[1];return i.add(s,d)}),i}}st.createLotto=Se});var Rt=U(lt=>{"use strict";Object.defineProperty(lt,"__esModule",{value:!0});var xe=xt();lt.default=xe.createLotto});var Ue={};Ot(Ue,{BehaviourTree:()=>ut,State:()=>c,convertMDSLToJSON:()=>R,validateDefinition:()=>rt});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={}}};dt(u,"registeredFunctions",{}),dt(u,"registeredSubtrees",{});function gt(t){return t.type==="root"}function bt(t){return t.type==="branch"}function yt(t){return["branch","action","condition","wait"].includes(t.type)}function Z(t){return["root","repeat","retry","flip","succeed","fail"].includes(t.type)}function tt(t){return["sequence","selector","lotto","parallel","race","all"].includes(t.type)}function Nt(t){let e=[],r=o=>{e.push(o),tt(o)?o.children.forEach(r):Z(o)&&r(o.child)};return r(t),e}function y(t){return typeof t=="number"&&Math.floor(t)===t}function et(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 o=typeof e=="string"?[e]:e;if(!o.some(n=>r.toUpperCase()===n.toUpperCase())){let n=o.map(a=>"'"+a+"'").join(" or ");throw new Error("unexpected token found. Expected "+n+" but got '"+r+"'")}}return r}function wt(t){let e={},r=t.replace(/"(\\.|[^"\\])*"/g,o=>{let 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 At(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=Gt(n,e);r.push(d)}else if(n!==",")throw new Error(`invalid argument list, expected ',' or ']' but got '${n}'`)}),l(t,o),r}function Gt(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 R(t){let{placeholders:e,processedDefinition:r}=wt(t),o=At(r);return Mt(o,e)}function Mt(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(gt(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(tt(d))d.children=d.children||[],d.children.push(a);else if(Z(d)){if(d.child)throw new Error("a decorator node must only have a single child node");d.child=a}yt(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(Bt(t,e));break}case"SUCCEED":{i(_t(t,e));break}case"FAIL":{i(Yt(t,e));break}case"FLIP":{i(jt(t,e));break}case"REPEAT":{i(qt(t,e));break}case"RETRY":{i(Wt(t,e));break}case"SEQUENCE":{i(Jt(t,e));break}case"SELECTOR":{i(Vt(t,e));break}case"PARALLEL":{i(Qt(t,e));break}case"RACE":{i(Ht(t,e));break}case"ALL":{i(Kt(t,e));break}case"LOTTO":{i(zt(t,e));break}case"ACTION":{i(Xt(t,e));break}case"CONDITION":{i(Zt(t,e));break}case"WAIT":{i(te(t,e));break}case"BRANCH":{i(ee(t,e));break}case"}":{let s=n();s&&re(s);break}default:throw new Error(`unexpected token: ${a}`)}}return o}function Bt(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 _t(t,e){let r={type:"succeed",...p(t,e)};return l(t,"{"),r}function Yt(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 qt(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 Wt(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 Jt(t,e){let r={type:"sequence",...p(t,e)};return l(t,"{"),r}function Vt(t,e){let r={type:"selector",...p(t,e)};return l(t,"{"),r}function Qt(t,e){let r={type:"parallel",...p(t,e)};return l(t,"{"),r}function Ht(t,e){let r={type:"race",...p(t,e)};return l(t,"{"),r}function Kt(t,e){let r={type:"all",...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 Xt(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 Zt(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 te(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 ee(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 re(t){if(Z(t)&&et(t.child))throw new Error(`a ${t.type} node must have a single child node defined`);if(tt(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 rt(t){return t===null||typeof t>"u"?w("definition is null or undefined"):typeof t=="string"?oe(t):typeof t=="object"?ot(t):w(`unexpected definition type of '${typeof t}'`)}function oe(t){let e;try{e=R(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{it(e,!1)}catch(n){return w(n.message)}return{succeeded:!0,json:e}}function ot(t){let e=Array.isArray(t)?t:[t];try{e.forEach(n=>b(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{it(e,!1)}catch(n){return w(n.message)}return{succeeded:!0,json:e}}function it(t,e){let r=t.map(i=>({id:i.id,refs:Nt(i).filter(bt).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":le(t,e);break;case"condition":pe(t,e);break;case"wait":fe(t,e);break;case"branch":ce(t,e);break;case"root":ie(t,e);break;case"succeed":ne(t,e);break;case"fail":ae(t,e);break;case"flip":se(t,e);break;case"repeat":ue(t,e);break;case"retry":de(t,e);break;case"sequence":he(t,e);break;case"selector":me(t,e);break;case"parallel":ge(t,e);break;case"race":be(t,e);break;case"all":ye(t,e);break;case"lotto":Ne(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 ie(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 ne(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 ae(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 se(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 ue(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 de(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 ce(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 le(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 pe(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 fe(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 he(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 me(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 ge(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 be(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 ye(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 Ne(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 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 $=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 Et(){let 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=Et(),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 A=class extends E{};var h=class extends E{constructor(r,o,i,n){super(r,o,i);this.children=n}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 F=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 T=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 L=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 O=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 P=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 Ct=Pt(Rt());var G=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,Ct.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}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 M=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 B=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 _=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 Y=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 j=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 q=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 W=class extends A{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 J=class extends A{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 V=class extends A{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 D=class extends x{constructor(r,o,i){super(r,o);this.condition=i}getCondition=()=>this.condition;getDetails(){return{type:this.type,args:this.args,calls:this.getCondition()}}};var Q=class extends D{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 H=class extends D{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;getDetails(){return{type:this.type,args:this.args,calls:this.getFunctionName()}}};var K=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 X=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 pt=Symbol("__root__");function ft(t,e){let r=Ce(t);it([r[pt],...Object.values(r)],!0);let o=g(r[pt],r,e);return Ie(o),o}function g(t,e,r){let o=Re(t);switch(t.type){case"root":return new j(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 _(o,r,i,n,a,g(t.child,e,r))}case"retry":{let i=null,n=null,a=null;return Array.isArray(t.attempts)?(n=t.attempts[0],a=t.attempts[1]):y(t.attempts)&&(i=t.attempts),new Y(o,r,i,n,a,g(t.child,e,r))}case"flip":return new B(o,r,g(t.child,e,r));case"succeed":return new q(o,r,g(t.child,e,r));case"fail":return new M(o,r,g(t.child,e,r));case"sequence":return new P(o,r,t.children.map(i=>g(i,e,r)));case"selector":return new O(o,r,t.children.map(i=>g(i,e,r)));case"parallel":return new F(o,r,t.children.map(i=>g(i,e,r)));case"race":return new T(o,r,t.children.map(i=>g(i,e,r)));case"all":return new L(o,r,t.children.map(i=>g(i,e,r)));case"lotto":return new G(o,r,t.weights,t.children.map(i=>g(i,e,r)));case"branch":return g(e[t.ref].child,e,r);case"action":return new W(o,r,t.call,t.args||[]);case"condition":return new J(o,r,t.call,t.args||[]);case"wait":{let i=null,n=null,a=null;return Array.isArray(t.duration)?(n=t.duration[0],a=t.duration[1]):y(t.duration)&&(i=t.duration),new V(o,r,i,n,a)}}}function Re(t){let e=[];return t.while&&e.push(new Q(t.while.call,t.while.args??[])),t.until&&e.push(new H(t.until.call,t.until.args??[])),t.entry&&e.push(new K(t.entry.call,t.entry.args??[])),t.step&&e.push(new z(t.step.call,t.step.args??[])),t.exit&&e.push(new X(t.exit.call,t.exit.args??[])),e}function Ce(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??pt]=r;return e}function Ie(t){let e=[],r=(o,i)=>{o=o.concat(i),i instanceof A?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 instanceof D)})).filter(s=>s.guards.length>0));n.setGuardPath(a)}})}var ut=class{constructor(e,r,o={}){this.agent=r;this.options=o;if(et(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}=rt(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=ft(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=R(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}=ot(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}=ot(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 kt(Ue);})(); //# sourceMappingURL=mistreevous.min.js.map diff --git a/dist/mistreevous.min.js.map b/dist/mistreevous.min.js.map index 953cfba..15b5049 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/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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 const 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 const 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\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\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/**\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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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", "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"] + "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/leaf/Leaf.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/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 isRootNodeDefinition(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 isBranchNodeDefinition(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 isLeafNodeDefinition(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 isDecoratorNodeDefinition(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 isCompositeNodeDefinition(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 (isCompositeNodeDefinition(currentNodeDefinition)) {\n currentNodeDefinition.children.forEach(processNode);\n } else if (isDecoratorNodeDefinition(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 const 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 const strippedMatch = match.substring(1, match.length - 1);\n let 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 isCompositeNodeDefinition,\n isDecoratorNodeDefinition,\n isLeafNodeDefinition,\n isNullOrUndefined,\n isRootNodeDefinition\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 (isRootNodeDefinition(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 (isCompositeNodeDefinition(topTreeStackTopNode)) {\n topTreeStackTopNode.children = topTreeStackTopNode.children || [];\n topTreeStackTopNode.children.push(node);\n } else if (isDecoratorNodeDefinition(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 (!isLeafNodeDefinition(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 const 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 (isDecoratorNodeDefinition(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 (isCompositeNodeDefinition(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, isBranchNodeDefinition, 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(isBranchNodeDefinition)\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 const 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/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 from \"../Node\";\n\n/**\n * A leaf node.\n */\nexport default abstract class Leaf extends Node {}\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 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 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 { 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", "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 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 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 Leaf from \"./nodes/leaf/Leaf\";\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\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\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/**\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 instanceof Leaf) {\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 instanceof 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 from \"./State\";\nimport Lookup from \"./Lookup\";\nimport { NodeDetails } from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\nimport { Agent, GlobalFunction } from \"./Agent\";\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": "yyBAAA,IAAAA,GAAAC,EAAAC,IAAA,cACA,OAAO,eAAeA,GAAS,aAAc,CAAE,MAAO,EAAK,CAAC,EAC5DA,GAAQ,YAAc,OAItB,IAAIC,GAA6B,UAAY,CAMzC,SAASA,EAAYC,EAAaC,EAAS,CACnCA,IAAY,SAAUA,EAAU,GACpC,KAAK,aAAeD,EACpB,KAAK,SAAWC,CACpB,CACA,cAAO,eAAeF,EAAY,UAAW,cAAe,CAExD,IAAK,UAAY,CACb,OAAO,KAAK,YAChB,EACA,WAAY,GACZ,aAAc,EAClB,CAAC,EACD,OAAO,eAAeA,EAAY,UAAW,UAAW,CAEpD,IAAK,UAAY,CACb,OAAO,KAAK,QAChB,EACA,IAAK,SAAUG,EAAO,CAClB,KAAK,SAAWA,CACpB,EACA,WAAY,GACZ,aAAc,EAClB,CAAC,EACMH,CACX,EAAE,EACFD,GAAQ,YAAcC,KCtCtB,IAAAI,GAAAC,EAAAC,GAAA,cACA,OAAO,eAAeA,EAAS,aAAc,CAAE,MAAO,EAAK,CAAC,EAC5DA,EAAQ,gBAAkBA,EAAQ,kBAAoB,OAMtD,SAASC,GAAkBC,EAAO,CAC9B,OAAOA,GAAU,IACrB,CACAF,EAAQ,kBAAoBC,GAM5B,SAASE,GAAgBD,EAAO,CAC5B,OAAO,OAAOA,GAAU,UAAYA,GAAS,GAAK,KAAK,MAAMA,CAAK,IAAMA,CAC5E,CACAF,EAAQ,gBAAkBG,KCpB1B,IAAAC,GAAAC,EAAAC,IAAA,cACA,OAAO,eAAeA,GAAS,aAAc,CAAE,MAAO,EAAK,CAAC,EAC5DA,GAAQ,MAAQ,OAChB,IAAIC,GAAgB,KAChBC,EAAc,KAIdC,GAAuB,UAAY,CAKnC,SAASA,EAAMC,EAAc,CAEzB,KAAK,cAAgB,CAAC,EACtB,KAAK,cAAgBA,CACzB,CAOA,OAAAD,EAAM,UAAU,IAAM,SAAUE,EAAaC,EAAS,CAGlD,GAFIA,IAAY,SAAUA,EAAU,GAEhC,EA3BZ,EA2BiBJ,EAAY,iBAAiBI,CAAO,EACzC,MAAM,IAAI,MAAM,wCAAwC,EAG5D,IAAIC,EAAsB,KAAK,cAAc,KAAK,SAAUC,EAAM,CAAE,OAAOA,EAAK,cAAgBH,CAAa,CAAC,EAC9G,OAAIE,EAEAA,EAAoB,SAAWD,EAI/B,KAAK,cAAc,KAAK,IAAIL,GAAc,YAAYI,EAAaC,CAAO,CAAC,EAExE,IACX,EAOAH,EAAM,UAAU,OAAS,SAAUE,EAAaC,EAAS,CAErD,IAAIC,EAAsB,KAAK,cAAc,KAAK,SAAUC,EAAM,CAAE,OAAOA,EAAK,cAAgBH,CAAa,CAAC,EAE9G,GAAI,CAACE,EACD,OAAO,KAGX,GAAID,IAAY,OAAW,CAEvB,GAAI,EA1DhB,EA0DqBJ,EAAY,iBAAiBI,CAAO,EACzC,MAAM,IAAI,MAAM,wCAAwC,EAE5DC,EAAoB,SAAWD,EAE3BC,EAAoB,QAAU,IAC9B,KAAK,cAAgB,KAAK,cAAc,OAAO,SAAUC,EAAM,CAAE,OAAOA,IAASD,CAAqB,CAAC,EAE/G,MAGI,KAAK,cAAgB,KAAK,cAAc,OAAO,SAAUC,EAAM,CAAE,OAAOA,IAASD,CAAqB,CAAC,EAE3G,OAAO,IACX,EAMAJ,EAAM,UAAU,KAAO,SAAUM,EAAS,CAGtC,GAFIA,IAAY,SAAUA,EAAU,CAAC,GAEjC,KAAK,cAAc,SAAW,EAC9B,OAAO,KAEX,IAAIC,GApFZ,EAoF6BR,EAAY,mBAAmBO,EAAQ,UAAU,EAAI,GAAOA,EAAQ,WACrFE,EAAW,CAAC,EAChB,KAAK,cAAc,QAAQ,SAAUC,EAAI,CAErC,QADIP,EAAcO,EAAG,YAAaN,EAAUM,EAAG,QACtCC,GAAc,EAAGA,GAAcP,EAASO,KAC7CF,EAAS,KAAKN,CAAW,CAEjC,CAAC,EACD,IAAIS,EAGJ,GAAI,KAAK,eAIL,GAFAA,EAAS,KAAK,cAAc,EAExB,OAAOA,GAAW,UAAYA,EAAS,GAAKA,GAAU,EACtD,MAAM,IAAI,MAAM,oFAAoF,OAKxGA,EAAS,KAAK,OAAO,EAGzB,IAAIC,EAASJ,EAAS,KAAK,MAAMG,EAASH,EAAS,MAAM,GAEzD,OAAKD,GACD,KAAK,OAAOK,EAAQ,CAAC,EAGlBA,CACX,EAOAZ,EAAM,UAAU,aAAe,SAAUG,EAASG,EAAS,CACnDA,IAAY,SAAUA,EAAU,CAAC,GACrC,IAAIO,GA5HZ,EA4HgCd,EAAY,mBAAmBO,EAAQ,MAAM,EAAI,GAAQA,EAAQ,OAEzF,GAAIH,IAAY,EACZ,MAAO,CAAC,EAGZ,GAAI,EAlIZ,EAkIiBJ,EAAY,iBAAiBI,CAAO,EACzC,MAAM,IAAI,MAAM,wCAAwC,EAK5D,QAHIW,EAAS,CAAC,EAGPA,EAAO,OAASX,GAAW,KAAK,cAAc,OAAS,GAC1DW,EAAO,KAAK,KAAK,KAAKR,CAAO,CAAC,EAGlC,GAAIO,EAAe,CAIf,QAFIE,EAAS,CAAC,EAELC,EAAK,EAAGC,EAAWH,EAAQE,EAAKC,EAAS,OAAQD,IAAM,CAC5D,IAAId,EAAce,EAASD,GACvBD,EAAO,QAAQb,CAAW,IAAM,IAChCa,EAAO,KAAKb,CAAW,CAE/B,CACAY,EAASC,CACb,CACA,OAAOD,CACX,EACOd,CACX,EAAE,EACFH,GAAQ,MAAQG,KC5JhB,IAAAkB,GAAAC,EAAAC,IAAA,cACA,OAAO,eAAeA,GAAS,aAAc,CAAE,MAAO,EAAK,CAAC,EAC5DA,GAAQ,YAAc,OACtB,IAAIC,GAAU,KAMd,SAASC,GAAYC,EAAuB,CAExC,GAAI,CAACA,EACD,OAAO,IAAIF,GAAQ,MAGvB,GAAI,MAAM,QAAQE,CAAqB,EAAG,CAEtC,IAAIC,EAAeD,EACfE,EAAU,IAAIJ,GAAQ,MAE1B,OAAAG,EAAa,QAAQ,SAAUE,EAAI,CAC/B,IAAIC,EAAcD,EAAG,GAAIE,EAASF,EAAG,GACrC,OAAOD,EAAQ,IAAIE,EAAaC,CAAM,CAC1C,CAAC,EAEMH,CACX,KACK,CAED,IAAII,EAASN,EAAsB,OAAQC,EAAeD,EAAsB,aAE5EO,EAAU,IAAIT,GAAQ,MAAMQ,CAAM,EAEtC,OAAIL,GACAA,EAAa,QAAQ,SAAUE,EAAI,CAC/B,IAAIC,EAAcD,EAAG,GAAIE,EAASF,EAAG,GACrC,OAAOI,EAAQ,IAAIH,EAAaC,CAAM,CAC1C,CAAC,EAGEE,CACX,CACJ,CACAV,GAAQ,YAAcE,KC3CtB,IAAAS,GAAAC,EAAAC,IAAA,cACA,OAAO,eAAeA,GAAS,aAAc,CAAE,MAAO,EAAK,CAAC,EAC5D,IAAIC,GAAgB,KACpBD,GAAQ,QAAUC,GAAc,cCHhC,IAAAC,GAAA,GAAAC,GAAAD,GAAA,mBAAAE,GAAA,UAAAC,EAAA,sBAAAC,EAAA,uBAAAC,KCGO,IAAKC,OAIRA,EAAA,MAAQ,oBAIRA,EAAA,QAAU,sBAIVA,EAAA,UAAY,wBAIZA,EAAA,OAAS,qBAhBDA,OAAA,ICKZ,IAAqBC,EAArB,KAA4B,CAexB,OAAc,QAAQC,EAA8B,CAChD,OAAO,KAAK,oBAAoBA,EACpC,CAOA,OAAc,QAAQA,EAAcC,EAA4B,CAC5D,KAAK,oBAAoBD,GAAQC,CACrC,CAUA,OAAO,eAAeC,EAAcF,EAAsC,CAEtE,IAAMG,EAAgBD,EAAMF,GAC5B,GAAIG,GAAiB,OAAOA,GAAkB,WAC1C,OAAQC,GAAgBD,EAAc,MAAMD,EAAOE,CAAI,EAI3D,GAAI,KAAK,oBAAoBJ,IAAS,OAAO,KAAK,oBAAoBA,IAAU,WAAY,CACxF,IAAMK,EAAqB,KAAK,oBAAoBL,GACpD,OAAQI,GAAgBC,EAAmBH,EAAO,GAAGE,CAAI,CAC7D,CAGA,OAAO,IACX,CAKA,OAAO,aAAqD,CACxD,OAAO,KAAK,kBAChB,CAOA,OAAO,WAAWJ,EAAcM,EAA6B,CACzD,KAAK,mBAAmBN,GAAQM,CACpC,CAMA,OAAO,OAAON,EAAc,CACxB,OAAO,KAAK,oBAAoBA,GAChC,OAAO,KAAK,mBAAmBA,EACnC,CAKA,OAAO,OAAQ,CACX,KAAK,oBAAsB,CAAC,EAC5B,KAAK,mBAAqB,CAAC,CAC/B,CACJ,EAjFIO,GAJiBR,EAIF,sBAAyD,CAAC,GAIzEQ,GARiBR,EAQF,qBAA4D,CAAC,GCFzE,SAASS,GAAqBC,EAAkD,CACnF,OAAOA,EAAK,OAAS,MACzB,CAOO,SAASC,GAAuBD,EAAoD,CACvF,OAAOA,EAAK,OAAS,QACzB,CAOO,SAASE,GAAqBF,EAA8C,CAC/E,MAAO,CAAC,SAAU,SAAU,YAAa,MAAM,EAAE,SAASA,EAAK,IAAI,CACvE,CAOO,SAASG,EAA0BH,EAAuD,CAC7F,MAAO,CAAC,OAAQ,SAAU,QAAS,OAAQ,UAAW,MAAM,EAAE,SAASA,EAAK,IAAI,CACpF,CAOO,SAASI,GAA0BJ,EAAuD,CAC7F,MAAO,CAAC,WAAY,WAAY,QAAS,WAAY,OAAQ,KAAK,EAAE,SAASA,EAAK,IAAI,CAC1F,CAOO,SAASK,GAAkBC,EAAwD,CACtF,IAAMC,EAA6B,CAAC,EAE9BC,EAAeC,GAA6C,CAC9DF,EAAM,KAAKE,CAAqB,EAE5BL,GAA0BK,CAAqB,EAC/CA,EAAsB,SAAS,QAAQD,CAAW,EAC3CL,EAA0BM,CAAqB,GACtDD,EAAYC,EAAsB,KAAK,CAE/C,EAEA,OAAAD,EAAYF,CAAc,EAEnBC,CACX,CAOO,SAASG,EAAUC,EAAyB,CAC/C,OAAO,OAAOA,GAAU,UAAY,KAAK,MAAMA,CAAK,IAAMA,CAC9D,CAOO,SAASC,GAAkBD,EAAyB,CACvD,OAAO,OAAOA,EAAU,KAAeA,IAAU,IACrD,CClFO,SAASE,EAAYC,EAAkBC,EAAsC,CAEhF,IAAMC,EAASF,EAAO,MAAM,EAG5B,GAAIE,IAAW,OACX,MAAM,IAAI,MAAM,8BAA8B,EAIlD,GAAID,GAAY,KAAW,CAEvB,IAAME,EAAiB,OAAOF,GAAa,SAAW,CAACA,CAAQ,EAAIA,EAMnE,GAAI,CAH4BE,EAAe,KAAMC,GAASF,EAAO,YAAY,IAAME,EAAK,YAAY,CAAC,EAG3E,CAC1B,IAAMC,EAAoBF,EAAe,IAAKC,GAAS,IAAMA,EAAO,GAAG,EAAE,KAAK,MAAM,EACpF,MAAM,IAAI,MAAM,oCAAsCC,EAAoB,aAAeH,EAAS,GAAG,CACzG,CACJ,CAGA,OAAOA,CACX,CAOO,SAASI,GAAyBC,EAGvC,CAEE,IAAMC,EAA0C,CAAC,EAG3CC,EAAsBF,EAAW,QAAQ,mBAAqBG,GAAU,CAC1E,IAAMC,EAAgBD,EAAM,UAAU,EAAGA,EAAM,OAAS,CAAC,EACrDE,EAAc,OAAO,KAAKJ,CAAY,EAAE,KAAMK,GAAQL,EAAaK,KAASF,CAAa,EAG7F,OAAKC,IACDA,EAAc,KAAK,OAAO,KAAKJ,CAAY,EAAE,WAC7CA,EAAaI,GAAeD,GAGzBC,CACX,CAAC,EAED,MAAO,CAAE,aAAAJ,EAAc,oBAAAC,CAAoB,CAC/C,CAOO,SAASK,GAA0BP,EAA8B,CAEpE,OAAAA,EAAaA,EAAW,QAAQ,MAAO,KAAK,EAC5CA,EAAaA,EAAW,QAAQ,MAAO,KAAK,EAC5CA,EAAaA,EAAW,QAAQ,MAAO,KAAK,EAC5CA,EAAaA,EAAW,QAAQ,MAAO,KAAK,EAC5CA,EAAaA,EAAW,QAAQ,MAAO,KAAK,EAC5CA,EAAaA,EAAW,QAAQ,MAAO,KAAK,EAC5CA,EAAaA,EAAW,QAAQ,KAAM,KAAK,EAGpCA,EAAW,QAAQ,OAAQ,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,CAC3D,CChCO,SAASQ,EACZC,EACAC,EACa,CACb,IAAMC,EAA8B,CAAC,EAGrC,GAAI,CAAC,CAAC,IAAK,GAAG,EAAE,SAASF,EAAO,EAAE,EAC9B,OAAOE,EAKX,IAAMC,EAAeC,EAAYJ,EAAQ,CAAC,IAAK,GAAG,CAAC,IAAM,IAAM,IAAM,IAE/DK,EAA+B,CAAC,EAGtC,KAAOL,EAAO,QAAUA,EAAO,KAAOG,GAElCE,EAAmB,KAAKL,EAAO,MAAM,CAAE,EAI3C,OAAAK,EAAmB,QAAQ,CAACC,EAAOC,IAAU,CAKzC,GAH8B,EAAEA,EAAQ,GAGb,CAEvB,IAAMC,EAAqBC,GAAsBH,EAAOL,CAA0B,EAGlFC,EAAa,KAAKM,CAAkB,CACxC,SAEQF,IAAU,IACV,MAAM,IAAI,MAAM,uDAAuDA,IAAQ,CAG3F,CAAC,EAGDF,EAAYJ,EAAQG,CAAY,EAGzBD,CACX,CAQA,SAASO,GAAsBH,EAAeL,EAAoE,CAE9G,OAAIK,IAAU,OACH,CACH,MAAO,KACP,KAAM,MACV,EAIAA,IAAU,QAAUA,IAAU,QACvB,CACH,MAAOA,IAAU,OACjB,KAAM,SACV,EAMC,MAAMA,CAAY,EASnBA,EAAM,MAAM,YAAY,EACjB,CACH,MAAOL,EAA2BK,GAAO,QAAQ,MAAO,GAAG,EAC3D,KAAM,QACV,EAIG,CACH,MAAOA,EACP,KAAM,YACV,EAnBW,CACH,MAAO,WAAWA,CAAK,EACvB,UAAW,WAAWA,CAAK,IAAM,SAASA,EAAO,EAAE,EACnD,KAAM,QACV,CAgBR,CCjIO,SAASI,EACZC,EACAC,EACc,CACd,IAAMC,EAA+C,CAAC,QAAS,QAAS,QAAS,OAAQ,MAAM,EAGzFC,EAA6B,CAAC,EAGhCC,EAAoBJ,EAAO,IAAI,YAAY,EAG/C,KAAOE,EAAmB,SAASE,CAAiB,GAAG,CAEnD,GAAID,EAAWC,GACX,MAAM,IAAI,MAAM,wBAAwBJ,EAAO,GAAG,YAAY,mBAAmB,EAIrFA,EAAO,MAAM,EAGb,GAAM,CAACK,KAA4BC,CAAkB,EAAIC,EACrDP,EACAC,CACJ,EAGA,GAAII,GAAyB,OAAS,aAClC,MAAM,IAAI,MAAM,uFAAuF,EAI3GC,EACK,OAAQE,GAAQA,EAAI,OAAS,YAAY,EACzC,QAASA,GAAQ,CACd,MAAM,IAAI,MACN,qCAAqCA,EAAI,iDAC7C,CACJ,CAAC,EAGLL,EAAWC,GAAqB,CAC5B,KAAMC,EAAwB,MAC9B,KAAMC,EAAmB,IAAI,CAAC,CAAE,MAAAG,CAAM,IAAMA,CAAK,CACrD,EAGAL,EAAoBJ,EAAO,IAAI,YAAY,CAC/C,CAEA,OAAOG,CACX,CCjCO,SAASO,EAAkBC,EAA0C,CAExE,GAAM,CAAE,aAAAC,EAAc,oBAAAC,CAAoB,EAAIC,GAAyBH,CAAU,EAG3EI,EAASC,GAA0BH,CAAmB,EAE5D,OAAOI,GAA8BF,EAAQH,CAAY,CAC7D,CAQA,SAASK,GACLF,EACAG,EACoB,CAEpB,GAAIH,EAAO,OAAS,EAChB,MAAM,IAAI,MAAM,qBAAqB,EAIzC,GAAIA,EAAO,OAAQI,GAAUA,IAAU,GAAG,EAAE,SAAWJ,EAAO,OAAQI,GAAUA,IAAU,GAAG,EAAE,OAC3F,MAAM,IAAI,MAAM,0BAA0B,EAU9C,IAAMC,EAAoF,CAAC,EAGrFC,EAA2C,CAAC,EAG5CC,EAAYC,GAA4B,CAE1C,GAAIC,GAAqBD,CAAI,EAAG,CAG5B,GAAIH,EAAWA,EAAW,OAAS,IAAI,OACnC,MAAM,IAAI,MAAM,iDAAiD,EAIrEC,EAAU,KAAKE,CAAI,EAGnBH,EAAW,KAAK,CAACG,CAAI,CAAC,EAEtB,MACJ,CAIA,GAAI,CAACH,EAAW,QAAU,CAACA,EAAWA,EAAW,OAAS,GAAG,OACzD,MAAM,IAAI,MAAM,0CAA0C,EAI9D,IAAMK,EAAeL,EAAWA,EAAW,OAAS,GAI9CM,EAAsBD,EAAaA,EAAa,OAAS,GAI/D,GAAIE,GAA0BD,CAAmB,EAC7CA,EAAoB,SAAWA,EAAoB,UAAY,CAAC,EAChEA,EAAoB,SAAS,KAAKH,CAAI,UAC/BK,EAA0BF,CAAmB,EAAG,CAEvD,GAAIA,EAAoB,MACpB,MAAM,IAAI,MAAM,qDAAqD,EAGzEA,EAAoB,MAAQH,CAChC,CAIKM,GAAqBN,CAAI,GAC1BE,EAAa,KAAKF,CAAI,CAE9B,EAGMO,EAAU,IAAgC,CAC5C,IAAIC,EAAuC,KAGrCN,EAAeL,EAAWA,EAAW,OAAS,GAGpD,OAAIK,EAAa,SACbM,EAAaN,EAAa,IAAI,GAI7BA,EAAa,QACdL,EAAW,IAAI,EAGZW,CACX,EAGA,KAAOhB,EAAO,QAAQ,CAElB,IAAMI,EAAQJ,EAAO,MAAM,EAG3B,OAAQI,EAAM,YAAY,EAAG,CACzB,IAAK,OAAQ,CACTG,EAASU,GAAejB,EAAQG,CAAyB,CAAC,EAC1D,KACJ,CAEA,IAAK,UAAW,CACZI,EAASW,GAAkBlB,EAAQG,CAAyB,CAAC,EAC7D,KACJ,CAEA,IAAK,OAAQ,CACTI,EAASY,GAAenB,EAAQG,CAAyB,CAAC,EAC1D,KACJ,CAEA,IAAK,OAAQ,CACTI,EAASa,GAAepB,EAAQG,CAAyB,CAAC,EAC1D,KACJ,CAEA,IAAK,SAAU,CACXI,EAASc,GAAiBrB,EAAQG,CAAyB,CAAC,EAC5D,KACJ,CAEA,IAAK,QAAS,CACVI,EAASe,GAAgBtB,EAAQG,CAAyB,CAAC,EAC3D,KACJ,CAEA,IAAK,WAAY,CACbI,EAASgB,GAAmBvB,EAAQG,CAAyB,CAAC,EAC9D,KACJ,CAEA,IAAK,WAAY,CACbI,EAASiB,GAAmBxB,EAAQG,CAAyB,CAAC,EAC9D,KACJ,CAEA,IAAK,WAAY,CACbI,EAASkB,GAAmBzB,EAAQG,CAAyB,CAAC,EAC9D,KACJ,CAEA,IAAK,OAAQ,CACTI,EAASmB,GAAe1B,EAAQG,CAAyB,CAAC,EAC1D,KACJ,CAEA,IAAK,MAAO,CACRI,EAASoB,GAAc3B,EAAQG,CAAyB,CAAC,EACzD,KACJ,CAEA,IAAK,QAAS,CACVI,EAASqB,GAAgB5B,EAAQG,CAAyB,CAAC,EAC3D,KACJ,CAEA,IAAK,SAAU,CACXI,EAASsB,GAAiB7B,EAAQG,CAAyB,CAAC,EAC5D,KACJ,CAEA,IAAK,YAAa,CACdI,EAASuB,GAAoB9B,EAAQG,CAAyB,CAAC,EAC/D,KACJ,CAEA,IAAK,OAAQ,CACTI,EAASwB,GAAe/B,EAAQG,CAAyB,CAAC,EAC1D,KACJ,CAEA,IAAK,SAAU,CACXI,EAASyB,GAAiBhC,EAAQG,CAAyB,CAAC,EAC5D,KACJ,CAEA,IAAK,IAAK,CAEN,IAAMa,EAAaD,EAAQ,EAGvBC,GACAiB,GAAmBjB,CAAU,EAGjC,KACJ,CAEA,QACI,MAAM,IAAI,MAAM,qBAAqBZ,GAAO,CAEpD,CACJ,CAEA,OAAOE,CACX,CAQA,SAASW,GAAejB,EAAkBG,EAA0E,CAEhH,IAAIK,EAAO,CACP,KAAM,MACV,EAGM0B,EAAgBC,EAAoBnC,EAAQG,CAAyB,EAG3E,GAAI+B,EAAc,OAEd,GAAIA,EAAc,SAAW,GAAKA,EAAc,GAAG,OAAS,aAExD1B,EAAK,GAAK0B,EAAc,GAAG,UAE3B,OAAM,IAAI,MAAM,oCAAoC,EAK5D,OAAA1B,EAAO,CAAE,GAAGA,EAAM,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAAE,EAG7EkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASU,GACLlB,EACAG,EACqB,CACrB,IAAMK,EAAO,CACT,KAAM,UACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAAkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASW,GAAenB,EAAkBG,EAA0E,CAChH,IAAMK,EAAO,CACT,KAAM,OACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAAkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASY,GAAepB,EAAkBG,EAA0E,CAChH,IAAMK,EAAO,CACT,KAAM,OACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAAkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASa,GACLrB,EACAG,EACoB,CACpB,IAAIK,EAAO,CAAE,KAAM,QAAS,EAGtB0B,EAAgBC,EAAoBnC,EAAQG,CAAyB,EAM3E,GAAI+B,EAAc,OASd,GAPAA,EACK,OAAQI,GAAQA,EAAI,OAAS,UAAY,CAACA,EAAI,SAAS,EACvD,QAAQ,IAAM,CACX,MAAM,IAAI,MAAM,qDAAqD,CACzE,CAAC,EAGDJ,EAAc,SAAW,GAKzB,GAHA1B,EAAK,WAAa0B,EAAc,GAAG,MAG/B1B,EAAK,WAAa,EAClB,MAAM,IAAI,MAAM,oEAAoE,UAEjF0B,EAAc,SAAW,EAAG,CAKnC,GAHA1B,EAAK,WAAa,CAAC0B,EAAc,GAAG,MAAiBA,EAAc,GAAG,KAAe,EAGjF1B,EAAK,WAAW,GAAK,GAAKA,EAAK,WAAW,GAAK,EAC/C,MAAM,IAAI,MAAM,mFAAmF,EAIvG,GAAIA,EAAK,WAAW,GAAKA,EAAK,WAAW,GACrC,MAAM,IAAI,MACN,gGACJ,CAER,KAEI,OAAM,IAAI,MAAM,iEAAiE,EAKzF,OAAAA,EAAO,CAAE,GAAGA,EAAM,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAAE,EAG7EkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASc,GAAgBtB,EAAkBG,EAA2E,CAClH,IAAIK,EAAO,CAAE,KAAM,OAAQ,EAGrB0B,EAAgBC,EAAoBnC,EAAQG,CAAyB,EAM3E,GAAI+B,EAAc,OASd,GAPAA,EACK,OAAQI,GAAQA,EAAI,OAAS,UAAY,CAACA,EAAI,SAAS,EACvD,QAAQ,IAAM,CACX,MAAM,IAAI,MAAM,kDAAkD,CACtE,CAAC,EAGDJ,EAAc,SAAW,GAKzB,GAHA1B,EAAK,SAAW0B,EAAc,GAAG,MAG7B1B,EAAK,SAAW,EAChB,MAAM,IAAI,MAAM,iEAAiE,UAE9E0B,EAAc,SAAW,EAAG,CAKnC,GAHA1B,EAAK,SAAW,CAAC0B,EAAc,GAAG,MAAiBA,EAAc,GAAG,KAAe,EAG/E1B,EAAK,SAAS,GAAK,GAAKA,EAAK,SAAS,GAAK,EAC3C,MAAM,IAAI,MAAM,gFAAgF,EAIpG,GAAIA,EAAK,SAAS,GAAKA,EAAK,SAAS,GACjC,MAAM,IAAI,MACN,2FACJ,CAER,KAEI,OAAM,IAAI,MAAM,8DAA8D,EAKtF,OAAAA,EAAO,CAAE,GAAGA,EAAM,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAAE,EAG7EkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASe,GACLvB,EACAG,EACsB,CACtB,IAAMK,EAAO,CACT,KAAM,WACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAAkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASgB,GACLxB,EACAG,EACsB,CACtB,IAAMK,EAAO,CACT,KAAM,WACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAAkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASiB,GACLzB,EACAG,EACsB,CACtB,IAAMK,EAAO,CACT,KAAM,WACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAAkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASkB,GAAe1B,EAAkBG,EAA0E,CAChH,IAAMK,EAAO,CACT,KAAM,OACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAAkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASmB,GAAc3B,EAAkBG,EAAyE,CAC9G,IAAMK,EAAO,CACT,KAAM,MACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAAkC,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASoB,GAAgB5B,EAAkBG,EAA2E,CAElH,IAAM+B,EAAgBC,EAAoBnC,EAAQG,CAAyB,EAG3E+B,EACK,OAAQI,GAAQA,EAAI,OAAS,UAAY,CAACA,EAAI,WAAaA,EAAI,MAAQ,CAAC,EACxE,QAAQ,IAAM,CACX,MAAM,IAAI,MAAM,6DAA6D,CACjF,CAAC,EAEL,IAAM9B,EAAO,CACT,KAAM,QACN,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAC7D,EAGA,OAAI+B,EAAc,SACd1B,EAAK,QAAU0B,EAAc,IAAI,CAAC,CAAE,MAAAK,CAAM,IAAMA,CAAK,GAIzDF,EAAYrC,EAAQ,GAAG,EAGhBQ,CACX,CAQA,SAASqB,GACL7B,EACAG,EACoB,CAGpB,GAAM,CAACqC,KAAyBC,CAAiB,EAAIN,EAAoBnC,EAAQG,CAAyB,EAG1G,GAAIqC,GAAsB,OAAS,aAC/B,MAAM,IAAI,MAAM,0CAA0C,EAI9D,OAAAC,EACK,OAAQH,GAAQA,EAAI,OAAS,YAAY,EACzC,QAASA,GAAQ,CACd,MAAM,IAAI,MACN,uCAAuCA,EAAI,iDAC/C,CACJ,CAAC,EAGE,CACH,KAAM,SACN,KAAME,EAAqB,MAC3B,KAAMC,EAAkB,IAAI,CAAC,CAAE,MAAAF,CAAM,IAAMA,CAAK,EAChD,GAAGH,EAAqBpC,EAAQG,CAAyB,CAC7D,CACJ,CAQA,SAAS2B,GACL9B,EACAG,EACuB,CAGvB,GAAM,CAACuC,KAA4BD,CAAiB,EAAIN,EAAoBnC,EAAQG,CAAyB,EAG7G,GAAIuC,GAAyB,OAAS,aAClC,MAAM,IAAI,MAAM,6CAA6C,EAIjE,OAAAD,EACK,OAAQH,GAAQA,EAAI,OAAS,YAAY,EACzC,QAASA,GAAQ,CACd,MAAM,IAAI,MACN,0CAA0CA,EAAI,iDAClD,CACJ,CAAC,EAGE,CACH,KAAM,YACN,KAAMI,EAAwB,MAC9B,KAAMD,EAAkB,IAAI,CAAC,CAAE,MAAAF,CAAM,IAAMA,CAAK,EAChD,GAAGH,EAAqBpC,EAAQG,CAAyB,CAC7D,CACJ,CAQA,SAAS4B,GAAe/B,EAAkBG,EAA0E,CAChH,IAAMK,EAAO,CAAE,KAAM,MAAO,EAGtB0B,EAAgBC,EAAoBnC,EAAQG,CAAyB,EAM3E,GAAI+B,EAAc,QAYd,GAVAA,EACK,OAAQI,GAAQA,EAAI,OAAS,UAAY,CAACA,EAAI,SAAS,EACvD,QAAQ,IAAM,CACX,MAAM,IAAI,MAAM,4CAA4C,CAChE,CAAC,EAMDJ,EAAc,SAAW,GAKzB,GAHA1B,EAAK,SAAW0B,EAAc,GAAG,MAG7B1B,EAAK,SAAW,EAChB,MAAM,IAAI,MAAM,2CAA2C,UAExD0B,EAAc,SAAW,EAAG,CAKnC,GAHA1B,EAAK,SAAW,CAAC0B,EAAc,GAAG,MAAiBA,EAAc,GAAG,KAAe,EAG/E1B,EAAK,SAAS,GAAK,GAAKA,EAAK,SAAS,GAAK,EAC3C,MAAM,IAAI,MAAM,+DAA+D,EAInF,GAAIA,EAAK,SAAS,GAAKA,EAAK,SAAS,GACjC,MAAM,IAAI,MAAM,gFAAgF,CAExG,SAAW0B,EAAc,OAAS,EAE9B,MAAM,IAAI,MAAM,wDAAwD,EAKhF,MAAO,CAAE,GAAG1B,EAAM,GAAG4B,EAAqBpC,EAAQG,CAAyB,CAAE,CACjF,CAQA,SAAS6B,GACLhC,EACAG,EACoB,CAEpB,IAAM+B,EAAgBC,EAAoBnC,EAAQG,CAAyB,EAG3E,GAAI+B,EAAc,SAAW,GAAKA,EAAc,GAAG,OAAS,aACxD,MAAM,IAAI,MAAM,sCAAsC,EAI1D,MAAO,CAAE,KAAM,SAAU,IAAKA,EAAc,GAAG,KAAM,CACzD,CAMA,SAASD,GAAmBrC,EAAqC,CAE7D,GAAIiB,EAA0BjB,CAAU,GAAK+C,GAAkB/C,EAAW,KAAK,EAC3E,MAAM,IAAI,MAAM,KAAKA,EAAW,iDAAiD,EAIrF,GAAIgB,GAA0BhB,CAAU,GAAK,CAACA,EAAW,UAAU,OAC/D,MAAM,IAAI,MAAM,KAAKA,EAAW,0DAA0D,EAI9F,GAAIA,EAAW,OAAS,SAEhB,OAAOA,EAAW,QAAY,KAE1BA,EAAW,QAAQ,SAAWA,EAAW,SAAS,OAClD,MAAM,IAAI,MACN,yFACJ,CAIhB,CChxBO,SAASgD,GAAmBC,EAA6C,CAE5E,OAAIA,IAAe,MAAQ,OAAOA,EAAe,IACtCC,EAA8B,iCAAiC,EAOtE,OAAOD,GAAe,SAEfE,GAAuBF,CAAU,EACjC,OAAOA,GAAe,SAEtBG,GAAuBH,CAAU,EAEjCC,EAA8B,kCAAkC,OAAOD,IAAa,CAEnG,CAOA,SAASE,GAAuBF,EAAgD,CAC5E,IAAII,EAGJ,GAAI,CAEAA,EAAsBC,EAAkBL,CAAU,CACtD,OAASM,EAAP,CAEE,OAAOL,EAA+BK,EAAoB,OAAO,CACrE,CAGA,IAAMC,EAA0BH,EAAoB,OAAO,CAAC,CAAE,GAAAI,CAAG,IAAM,OAAOA,EAAO,GAAW,EAC1FC,EAAyBL,EAAoB,OAAO,CAAC,CAAE,GAAAI,CAAG,IAAM,OAAOA,GAAO,UAAYA,EAAG,OAAS,CAAC,EAG7G,GAAID,EAAwB,SAAW,EACnC,OAAON,EACH,6EACJ,EAIJ,IAAMS,EAAmC,CAAC,EAC1C,OAAW,CAAE,GAAAF,CAAG,IAAKC,EAAwB,CAEzC,GAAIC,EAAuB,SAASF,CAAG,EACnC,OAAOP,EAA8B,kDAAkDO,IAAK,EAGhGE,EAAuB,KAAKF,CAAG,CACnC,CAEA,GAAI,CAEAG,GAA2BP,EAAqB,EAAK,CACzD,OAASE,EAAP,CACE,OAAOL,EAA+BK,EAAoB,OAAO,CACrE,CAGA,MAAO,CACH,UAAW,GACX,KAAMF,CACV,CACJ,CAOO,SAASD,GACZH,EAC0B,CAE1B,IAAMI,EAAsB,MAAM,QAAQJ,CAAU,EAAIA,EAAa,CAACA,CAAU,EAGhF,GAAI,CACAI,EAAoB,QAASQ,GAAuBC,EAAaD,EAAoB,CAAC,CAAC,CAC3F,OAASE,EAAP,CAEE,OAAIA,aAAiB,MACVb,EAA8Ba,EAAM,OAAO,EAI/Cb,EAA8B,qBAAqBa,GAAO,CACrE,CAGA,IAAMP,EAA0BH,EAAoB,OAAO,CAAC,CAAE,GAAAI,CAAG,IAAM,OAAOA,EAAO,GAAW,EAC1FC,EAAyBL,EAAoB,OAAO,CAAC,CAAE,GAAAI,CAAG,IAAM,OAAOA,GAAO,UAAYA,EAAG,OAAS,CAAC,EAG7G,GAAID,EAAwB,SAAW,EACnC,OAAON,EACH,6EACJ,EAIJ,IAAMS,EAAmC,CAAC,EAC1C,OAAW,CAAE,GAAAF,CAAG,IAAKC,EAAwB,CAEzC,GAAIC,EAAuB,SAASF,CAAG,EACnC,OAAOP,EACH,oEAAoEO,IACxE,EAGJE,EAAuB,KAAKF,CAAG,CACnC,CAEA,GAAI,CAEAG,GAA2BP,EAAqB,EAAK,CACzD,OAASE,EAAP,CACE,OAAOL,EAA+BK,EAAoB,OAAO,CACrE,CAGA,MAAO,CACH,UAAW,GACX,KAAMF,CACV,CACJ,CASO,SAASO,GAA2BP,EAA2CW,EAAiC,CAInH,IAAMC,EAAiEZ,EAAoB,IACtFQ,IAAwB,CACrB,GAAIA,EAAmB,GACvB,KAAMK,GAAkBL,CAAkB,EACrC,OAAOM,EAAsB,EAC7B,IAAI,CAAC,CAAE,IAAAC,CAAI,IAAMA,CAAG,CAC7B,EACJ,EAGMC,EAAa,CAACC,EAAqDC,EAA+B,CAAC,IAAM,CAE3G,GAAIA,EAAK,SAASD,EAAQ,EAAE,EAAG,CAK3B,IAAME,EAHU,CAAC,GAAGD,EAAMD,EAAQ,EAAE,EAGH,OAAQG,GAAY,CAAC,CAACA,CAAO,EAAE,KAAK,MAAM,EAG3E,MAAM,IAAI,MAAM,wDAAwDD,GAAkB,CAC9F,CAEA,QAAWJ,KAAOE,EAAQ,KAAM,CAE5B,IAAMI,EAAaT,EAAiB,KAAK,CAAC,CAAE,GAAAR,CAAG,IAAMA,IAAOW,CAAG,EAG/D,GAAIM,EACAL,EAAWK,EAAY,CAAC,GAAGH,EAAMD,EAAQ,EAAE,CAAC,UACrCN,EAEP,MAAM,IAAI,MACNM,EAAQ,GACF,YAAYA,EAAQ,kDAAkDF,gCACtE,2DAA2DA,+BACrE,CAER,CACJ,EAGAC,EAAWJ,EAAiB,KAAMK,GAAY,OAAOA,EAAQ,GAAO,GAAW,CAAE,CACrF,CAOA,SAASR,EAAab,EAAiB0B,EAAqB,CAExD,GAAI,OAAO1B,GAAe,UAAY,OAAOA,EAAW,MAAS,UAAYA,EAAW,KAAK,SAAW,EACpG,MAAM,IAAI,MACN,2FAA2F0B,IAC/F,EAIJ,GAAIA,IAAU,GAAK1B,EAAW,OAAS,OACnC,MAAM,IAAI,MAAM,kEAAkEA,EAAW,OAAO,EAIxG,OAAQA,EAAW,KAAM,CACrB,IAAK,SACD2B,GAAmB3B,EAAY0B,CAAK,EACpC,MAEJ,IAAK,YACDE,GAAsB5B,EAAY0B,CAAK,EACvC,MAEJ,IAAK,OACDG,GAAiB7B,EAAY0B,CAAK,EAClC,MAEJ,IAAK,SACDI,GAAmB9B,EAAY0B,CAAK,EACpC,MAEJ,IAAK,OACDK,GAAiB/B,EAAY0B,CAAK,EAClC,MAEJ,IAAK,UACDM,GAAoBhC,EAAY0B,CAAK,EACrC,MAEJ,IAAK,OACDO,GAAiBjC,EAAY0B,CAAK,EAClC,MAEJ,IAAK,OACDQ,GAAiBlC,EAAY0B,CAAK,EAClC,MAEJ,IAAK,SACDS,GAAmBnC,EAAY0B,CAAK,EACpC,MAEJ,IAAK,QACDU,GAAkBpC,EAAY0B,CAAK,EACnC,MAEJ,IAAK,WACDW,GAAqBrC,EAAY0B,CAAK,EACtC,MAEJ,IAAK,WACDY,GAAqBtC,EAAY0B,CAAK,EACtC,MAEJ,IAAK,WACDa,GAAqBvC,EAAY0B,CAAK,EACtC,MAEJ,IAAK,OACDc,GAAiBxC,EAAY0B,CAAK,EAClC,MAEJ,IAAK,MACDe,GAAgBzC,EAAY0B,CAAK,EACjC,MAEJ,IAAK,QACDgB,GAAkB1C,EAAY0B,CAAK,EACnC,MAEJ,QACI,MAAM,IAAI,MAAM,4BAA4B1B,EAAW,mBAAmB0B,IAAQ,CAC1F,CACJ,CAOA,SAASiB,EAAuB3C,EAAiB0B,EAAqB,CAElE,CAAC,QAAS,QAAS,QAAS,OAAQ,MAAM,EAAE,QAASkB,GAAkB,CAEnE,IAAMC,EAAsB7C,EAAW4C,GAGvC,GAAI,SAAOC,EAAwB,KAKnC,IAAI,OAAOA,GAAwB,SAC/B,MAAM,IAAI,MACN,uBAAuBD,2BAAuC5C,EAAW,wBAAwB0B,IACrG,EAIJ,GAAI,OAAOmB,EAAoB,MAAS,UAAYA,EAAoB,KAAK,SAAW,EACpF,MAAM,IAAI,MACN,2CAA2CD,oCAAgD5C,EAAW,wBAAwB0B,IAClI,EAIJ,GAAI,OAAOmB,EAAoB,KAAS,KAAe,CAAC,MAAM,QAAQA,EAAoB,IAAI,EAC1F,MAAM,IAAI,MACN,2CAA2CD,0BAAsC5C,EAAW,wBAAwB0B,IACxH,EAER,CAAC,CACL,CAOA,SAASK,GAAiB/B,EAAiB0B,EAAqB,CAE5D,GAAI1B,EAAW,OAAS,OACpB,MAAM,IAAI,MAAM,4CAA4C,EAIhE,GAAI0B,EAAQ,EACR,MAAM,IAAI,MAAM,iDAAiD,EAIrE,GAAI,OAAO1B,EAAW,GAAO,MAAgB,OAAOA,EAAW,IAAO,UAAYA,EAAW,GAAG,SAAW,GACvG,MAAM,IAAI,MAAM,sEAAsE,EAI1F,GAAI,OAAOA,EAAW,MAAU,IAC5B,MAAM,IAAI,MAAM,uDAAuD,EAI3E2C,EAAuB3C,EAAY0B,CAAK,EAGxCb,EAAab,EAAW,MAAO0B,EAAQ,CAAC,CAC5C,CAOA,SAASM,GAAoBhC,EAAiB0B,EAAqB,CAE/D,GAAI1B,EAAW,OAAS,UACpB,MAAM,IAAI,MAAM,8DAA8D0B,IAAQ,EAI1F,GAAI,OAAO1B,EAAW,MAAU,IAC5B,MAAM,IAAI,MAAM,sEAAsE0B,IAAQ,EAIlGiB,EAAuB3C,EAAY0B,CAAK,EAGxCb,EAAab,EAAW,MAAO0B,EAAQ,CAAC,CAC5C,CAOA,SAASO,GAAiBjC,EAAiB0B,EAAqB,CAE5D,GAAI1B,EAAW,OAAS,OACpB,MAAM,IAAI,MAAM,wDAAwD0B,IAAQ,EAIpF,GAAI,OAAO1B,EAAW,MAAU,IAC5B,MAAM,IAAI,MAAM,mEAAmE0B,IAAQ,EAI/FiB,EAAuB3C,EAAY0B,CAAK,EAGxCb,EAAab,EAAW,MAAO0B,EAAQ,CAAC,CAC5C,CAOA,SAASQ,GAAiBlC,EAAiB0B,EAAqB,CAE5D,GAAI1B,EAAW,OAAS,OACpB,MAAM,IAAI,MAAM,wDAAwD0B,IAAQ,EAIpF,GAAI,OAAO1B,EAAW,MAAU,IAC5B,MAAM,IAAI,MAAM,mEAAmE0B,IAAQ,EAI/FiB,EAAuB3C,EAAY0B,CAAK,EAGxCb,EAAab,EAAW,MAAO0B,EAAQ,CAAC,CAC5C,CAOA,SAASS,GAAmBnC,EAAiB0B,EAAqB,CAE9D,GAAI1B,EAAW,OAAS,SACpB,MAAM,IAAI,MAAM,4DAA4D0B,IAAQ,EAIxF,GAAI,OAAO1B,EAAW,MAAU,IAC5B,MAAM,IAAI,MAAM,qEAAqE0B,IAAQ,EAIjG,GAAI,OAAO1B,EAAW,WAAe,IACjC,GAAI,MAAM,QAAQA,EAAW,UAAU,EAAG,CAEtC,IAAM8C,EAAqB,CAAC,CAAC9C,EAAW,WAAW,OAAQ+C,GAAmB,CAACC,EAAUD,CAAK,CAAC,EAAE,OAGjG,GAAI/C,EAAW,WAAW,SAAW,GAAK8C,EACtC,MAAM,IAAI,MACN,+GAA+GpB,IACnH,EAIJ,GAAI1B,EAAW,WAAW,GAAK,GAAKA,EAAW,WAAW,GAAK,EAC3D,MAAM,IAAI,MACN,yHAAyH0B,IAC7H,EAIJ,GAAI1B,EAAW,WAAW,GAAKA,EAAW,WAAW,GACjD,MAAM,IAAI,MACN,sJAAsJ0B,IAC1J,CAER,SAAWsB,EAAUhD,EAAW,UAAU,GAEtC,GAAIA,EAAW,WAAa,EACxB,MAAM,IAAI,MACN,qGAAqG0B,IACzG,MAGJ,OAAM,IAAI,MACN,gIAAgIA,IACpI,EAKRiB,EAAuB3C,EAAY0B,CAAK,EAGxCb,EAAab,EAAW,MAAO0B,EAAQ,CAAC,CAC5C,CAOA,SAASU,GAAkBpC,EAAiB0B,EAAqB,CAE7D,GAAI1B,EAAW,OAAS,QACpB,MAAM,IAAI,MAAM,0DAA0D0B,IAAQ,EAItF,GAAI,OAAO1B,EAAW,MAAU,IAC5B,MAAM,IAAI,MAAM,oEAAoE0B,IAAQ,EAIhG,GAAI,OAAO1B,EAAW,SAAa,IAC/B,GAAI,MAAM,QAAQA,EAAW,QAAQ,EAAG,CAEpC,IAAM8C,EAAqB,CAAC,CAAC9C,EAAW,SAAS,OAAQ+C,GAAmB,CAACC,EAAUD,CAAK,CAAC,EAAE,OAG/F,GAAI/C,EAAW,SAAS,SAAW,GAAK8C,EACpC,MAAM,IAAI,MACN,4GAA4GpB,IAChH,EAIJ,GAAI1B,EAAW,SAAS,GAAK,GAAKA,EAAW,SAAS,GAAK,EACvD,MAAM,IAAI,MACN,oHAAoH0B,IACxH,EAIJ,GAAI1B,EAAW,SAAS,GAAKA,EAAW,SAAS,GAC7C,MAAM,IAAI,MACN,+IAA+I0B,IACnJ,CAER,SAAWsB,EAAUhD,EAAW,QAAQ,GAEpC,GAAIA,EAAW,SAAW,EACtB,MAAM,IAAI,MACN,gGAAgG0B,IACpG,MAGJ,OAAM,IAAI,MACN,6HAA6HA,IACjI,EAKRiB,EAAuB3C,EAAY0B,CAAK,EAGxCb,EAAab,EAAW,MAAO0B,EAAQ,CAAC,CAC5C,CAOA,SAASI,GAAmB9B,EAAiB0B,EAAqB,CAE9D,GAAI1B,EAAW,OAAS,SACpB,MAAM,IAAI,MAAM,4DAA4D0B,IAAQ,EAIxF,GAAI,OAAO1B,EAAW,KAAQ,UAAYA,EAAW,IAAI,SAAW,EAChE,MAAM,IAAI,MAAM,0EAA0E0B,IAAQ,EAItG,CAAC,QAAS,OAAO,EAAE,QAASkB,GAAkB,CAC1C,GAAI,OAAO5C,EAAW4C,GAAmB,IACrC,MAAM,IAAI,MACN,4DAA4DA,4CAAwDlB,IACxH,CAER,CAAC,EAGD,CAAC,QAAS,OAAQ,MAAM,EAAE,QAASkB,GAAkB,CACjD,GAAI,OAAO5C,EAAW4C,GAAmB,IACrC,MAAM,IAAI,MACN,kEAAkEA,4CAAwDlB,IAC9H,CAER,CAAC,CACL,CAOA,SAASC,GAAmB3B,EAAiB0B,EAAqB,CAE9D,GAAI1B,EAAW,OAAS,SACpB,MAAM,IAAI,MAAM,4DAA4D0B,IAAQ,EAIxF,GAAI,OAAO1B,EAAW,MAAS,UAAYA,EAAW,KAAK,SAAW,EAClE,MAAM,IAAI,MAAM,0EAA0E0B,IAAQ,EAItG,GAAI,OAAO1B,EAAW,KAAS,KAAe,CAAC,MAAM,QAAQA,EAAW,IAAI,EACxE,MAAM,IAAI,MAAM,2EAA2E0B,IAAQ,EAIvGiB,EAAuB3C,EAAY0B,CAAK,CAC5C,CAOA,SAASE,GAAsB5B,EAAiB0B,EAAqB,CAEjE,GAAI1B,EAAW,OAAS,YACpB,MAAM,IAAI,MAAM,kEAAkE0B,IAAQ,EAI9F,GAAI,OAAO1B,EAAW,MAAS,UAAYA,EAAW,KAAK,SAAW,EAClE,MAAM,IAAI,MAAM,6EAA6E0B,IAAQ,EAIzG,GAAI,OAAO1B,EAAW,KAAS,KAAe,CAAC,MAAM,QAAQA,EAAW,IAAI,EACxE,MAAM,IAAI,MAAM,8EAA8E0B,IAAQ,EAI1GiB,EAAuB3C,EAAY0B,CAAK,CAC5C,CAOA,SAASG,GAAiB7B,EAAiB0B,EAAqB,CAE5D,GAAI1B,EAAW,OAAS,OACpB,MAAM,IAAI,MAAM,wDAAwD0B,IAAQ,EAIpF,GAAI,OAAO1B,EAAW,SAAa,IAC/B,GAAI,MAAM,QAAQA,EAAW,QAAQ,EAAG,CAEpC,IAAM8C,EAAqB,CAAC,CAAC9C,EAAW,SAAS,OAAQ+C,GAAmB,CAACC,EAAUD,CAAK,CAAC,EAAE,OAG/F,GAAI/C,EAAW,SAAS,SAAW,GAAK8C,EACpC,MAAM,IAAI,MACN,2GAA2GpB,IAC/G,EAIJ,GAAI1B,EAAW,SAAS,GAAK,GAAKA,EAAW,SAAS,GAAK,EACvD,MAAM,IAAI,MACN,6GAA6G0B,IACjH,EAIJ,GAAI1B,EAAW,SAAS,GAAKA,EAAW,SAAS,GAC7C,MAAM,IAAI,MACN,8IAA8I0B,IAClJ,CAER,SAAWsB,EAAUhD,EAAW,QAAQ,GAEpC,GAAIA,EAAW,SAAW,EACtB,MAAM,IAAI,MACN,+FAA+F0B,IACnG,MAGJ,OAAM,IAAI,MACN,4HAA4HA,IAChI,EAKRiB,EAAuB3C,EAAY0B,CAAK,CAC5C,CAOA,SAASW,GAAqBrC,EAAiB0B,EAAqB,CAEhE,GAAI1B,EAAW,OAAS,WACpB,MAAM,IAAI,MAAM,gEAAgE0B,IAAQ,EAI5F,GAAI,CAAC,MAAM,QAAQ1B,EAAW,QAAQ,GAAKA,EAAW,SAAS,SAAW,EACtE,MAAM,IAAI,MAAM,iFAAiF0B,IAAQ,EAI7GiB,EAAuB3C,EAAY0B,CAAK,EAGxC1B,EAAW,SAAS,QAASiD,GAAepC,EAAaoC,EAAOvB,EAAQ,CAAC,CAAC,CAC9E,CAOA,SAASY,GAAqBtC,EAAiB0B,EAAqB,CAEhE,GAAI1B,EAAW,OAAS,WACpB,MAAM,IAAI,MAAM,gEAAgE0B,IAAQ,EAI5F,GAAI,CAAC,MAAM,QAAQ1B,EAAW,QAAQ,GAAKA,EAAW,SAAS,SAAW,EACtE,MAAM,IAAI,MAAM,iFAAiF0B,IAAQ,EAI7GiB,EAAuB3C,EAAY0B,CAAK,EAGxC1B,EAAW,SAAS,QAASiD,GAAepC,EAAaoC,EAAOvB,EAAQ,CAAC,CAAC,CAC9E,CAOA,SAASa,GAAqBvC,EAAiB0B,EAAqB,CAEhE,GAAI1B,EAAW,OAAS,WACpB,MAAM,IAAI,MAAM,gEAAgE0B,IAAQ,EAI5F,GAAI,CAAC,MAAM,QAAQ1B,EAAW,QAAQ,GAAKA,EAAW,SAAS,SAAW,EACtE,MAAM,IAAI,MAAM,iFAAiF0B,IAAQ,EAI7GiB,EAAuB3C,EAAY0B,CAAK,EAGxC1B,EAAW,SAAS,QAASiD,GAAepC,EAAaoC,EAAOvB,EAAQ,CAAC,CAAC,CAC9E,CAOA,SAASc,GAAiBxC,EAAiB0B,EAAqB,CAE5D,GAAI1B,EAAW,OAAS,OACpB,MAAM,IAAI,MAAM,wDAAwD0B,IAAQ,EAIpF,GAAI,CAAC,MAAM,QAAQ1B,EAAW,QAAQ,GAAKA,EAAW,SAAS,SAAW,EACtE,MAAM,IAAI,MAAM,6EAA6E0B,IAAQ,EAIzGiB,EAAuB3C,EAAY0B,CAAK,EAGxC1B,EAAW,SAAS,QAASiD,GAAepC,EAAaoC,EAAOvB,EAAQ,CAAC,CAAC,CAC9E,CAOA,SAASe,GAAgBzC,EAAiB0B,EAAqB,CAE3D,GAAI1B,EAAW,OAAS,MACpB,MAAM,IAAI,MAAM,sDAAsD0B,IAAQ,EAIlF,GAAI,CAAC,MAAM,QAAQ1B,EAAW,QAAQ,GAAKA,EAAW,SAAS,SAAW,EACtE,MAAM,IAAI,MAAM,4EAA4E0B,IAAQ,EAIxGiB,EAAuB3C,EAAY0B,CAAK,EAGxC1B,EAAW,SAAS,QAASiD,GAAepC,EAAaoC,EAAOvB,EAAQ,CAAC,CAAC,CAC9E,CAOA,SAASgB,GAAkB1C,EAAiB0B,EAAqB,CAE7D,GAAI1B,EAAW,OAAS,QACpB,MAAM,IAAI,MAAM,0DAA0D0B,IAAQ,EAItF,GAAI,CAAC,MAAM,QAAQ1B,EAAW,QAAQ,GAAKA,EAAW,SAAS,SAAW,EACtE,MAAM,IAAI,MAAM,8EAA8E0B,IAAQ,EAI1G,GAAI,OAAO1B,EAAW,QAAY,MAG1B,CAAC,MAAM,QAAQA,EAAW,OAAO,GACjCA,EAAW,QAAQ,SAAWA,EAAW,SAAS,QAClDA,EAAW,QAAQ,OAAQ+C,GAAmB,CAACC,EAAUD,CAAK,CAAC,EAAE,QACjE/C,EAAW,QAAQ,OAAQ+C,GAAkBA,EAAQ,CAAC,EAAE,QAExD,MAAM,IAAI,MACN,mKAAmKrB,IACvK,EAKRiB,EAAuB3C,EAAY0B,CAAK,EAGxC1B,EAAW,SAAS,QAASiD,GAAepC,EAAaoC,EAAOvB,EAAQ,CAAC,CAAC,CAC9E,CAOA,SAASzB,EAA8BiD,EAAkD,CACrF,MAAO,CAAE,UAAW,GAAO,aAAAA,CAAa,CAC5C,CCt2BA,IAAqBC,EAArB,cAAuD,KAAM,CAIzD,YAAoBC,EAAc,CAC9B,MAAM,mCAAmC,EADzB,YAAAA,CAEpB,CAOA,aAAgBC,GAAeA,IAAS,KAAK,MACjD,ECNA,IAAqBC,EAArB,KAA+B,CAI3B,YAAoBC,EAAwB,CAAxB,WAAAA,CAAyB,CAO7C,SAAYC,GAAiB,CAEzB,QAAWC,KAAW,KAAK,MAEvB,QAAWC,KAASD,EAAQ,OAExB,GAAI,CAACC,EAAM,YAAYF,CAAK,EACxB,MAAM,IAAIG,EAA0BF,EAAQ,IAAI,CAIhE,CACJ,EChCO,SAASG,IAAoB,CAChC,IAAMC,EAAK,UAAY,CACnB,QAAU,EAAI,KAAK,OAAO,GAAK,MAAW,GAAG,SAAS,EAAE,EAAE,UAAU,CAAC,CACzE,EACA,OAAOA,EAAG,EAAIA,EAAG,EAAI,IAAMA,EAAG,EAAI,IAAMA,EAAG,EAAI,IAAMA,EAAG,EAAI,IAAMA,EAAG,EAAIA,EAAG,EAAIA,EAAG,CACvF,CCsFA,IAA8BC,EAA9B,KAAmC,CAuB/B,YAAoBC,EAAcC,EAAmCC,EAA+B,CAAhF,UAAAF,EAAiD,aAAAE,EAEjE,KAAK,IAAMC,GAAU,EAGrB,KAAK,WAAa,CACd,MAAOF,EAAW,KAAK,CAAC,CAAE,KAAAD,CAAK,IAAMA,IAAS,OAAO,EACrD,KAAMC,EAAW,KAAK,CAAC,CAAE,KAAAD,CAAK,IAAMA,IAAS,MAAM,EACnD,KAAMC,EAAW,KAAK,CAAC,CAAE,KAAAD,CAAK,IAAMA,IAAS,MAAM,EACnD,MAAOC,EAAW,KAAK,CAAC,CAAE,KAAAD,CAAK,IAAMA,IAAS,OAAO,EACrD,MAAOC,EAAW,KAAK,CAAC,CAAE,KAAAD,CAAK,IAAMA,IAAS,OAAO,CACzD,CACJ,CA/BmB,IAIA,WAIX,2BAIA,WAmCR,SAAW,IAAgB,KAAK,OAChC,SAAYI,GAA0B,CAElC,IAAMC,EAAgB,KAAK,OAG3B,KAAK,OAASD,EAGVC,IAAkBD,GAClB,KAAK,eAAeC,CAAa,CAEzC,EAKA,OAAS,IAAM,KAAK,IAKpB,QAAU,IAAM,KAAK,KAKrB,cAAgB,IAAM,OAAO,OAAO,KAAK,UAAU,EAAE,OAAQC,GAAc,CAAC,CAACA,CAAS,EAKtF,aAAgBF,GAAsB,KAAK,WAAaA,EAKxD,aAAe,IAAM,CAAC,CAAC,KAAK,WAMrB,GAAGA,EAA0B,CAChC,OAAO,KAAK,SAAWA,CAC3B,CAKO,OAAc,CACjB,KAAK,4BAAoB,CAC7B,CAMO,MAAMG,EAAoB,CAEzB,CAAC,KAAK,wBAAgB,IAK1B,KAAK,MAAM,EAEX,KAAK,WAAW,MAAM,kBAAkBA,EAAO,GAAO,EAAI,EAC9D,CAOO,OAAOA,EAAoB,CAE9B,GAAI,OAAK,0BAAkB,GAAK,KAAK,uBAAe,GAIpD,GAAI,CAEA,KAAK,WAAY,SAASA,CAAK,EAG3B,KAAK,sBAAc,GACnB,KAAK,WAAW,OAAO,kBAAkBA,CAAK,EAGlD,KAAK,WAAW,MAAM,kBAAkBA,CAAK,EAG7C,KAAK,SAASA,CAAK,GAGf,KAAK,0BAAkB,GAAK,KAAK,uBAAe,IAChD,KAAK,WAAW,MAAM,kBAAkBA,EAAO,KAAK,0BAAkB,EAAG,EAAK,CAEtF,OAASC,EAAP,CAEE,GAAIA,aAAiBC,GAA6BD,EAAM,aAAa,IAAI,EAErE,KAAK,MAAMD,CAAK,EAGhB,KAAK,6BAAqB,MAE1B,OAAMC,CAEd,CACJ,CAMO,YAA0B,CAC7B,MAAO,CACH,GAAI,KAAK,IACT,KAAM,KAAK,QAAQ,EACnB,KAAM,KAAK,KACX,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,KAAM,KAAK,WAAW,MAAM,WAAW,EACvC,KAAM,KAAK,WAAW,MAAM,WAAW,EACvC,MAAO,KAAK,MAChB,CACJ,CAMU,eAAeH,EAA4B,CAEjD,KAAK,QAAQ,oBAAoB,CAC7B,GAAI,KAAK,IACT,KAAM,KAAK,KACX,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,KAAM,KAAK,WAAW,MAAM,WAAW,EACvC,KAAM,KAAK,WAAW,MAAM,WAAW,EACvC,cAAAA,EACA,MAAO,KAAK,MAChB,CAAC,CACL,CACJ,EClSA,IAA8BK,EAA9B,cAA2CC,CAAK,CAAC,ECIjD,IAA8BC,EAA9B,cAAgDC,CAAK,CAOjD,YAAYC,EAAcC,EAAyBC,EAAyCC,EAAkB,CAC1G,MAAMH,EAAMC,EAAYC,CAAO,EADyD,cAAAC,CAE5F,CAKA,YAAc,IAAM,KAAK,SAKzB,MAAQ,IAAM,CAEV,KAAK,4BAAoB,EAGzB,KAAK,SAAS,QAASC,GAAUA,EAAM,MAAM,CAAC,CAClD,EAMA,MAASC,GAAiB,CAElB,CAAC,KAAK,wBAAgB,IAK1B,KAAK,SAAS,QAASD,GAAUA,EAAM,MAAMC,CAAK,CAAC,EAGnD,KAAK,MAAM,EAEX,KAAK,WAAW,MAAM,kBAAkBA,EAAO,GAAO,EAAI,EAC9D,EAMO,YAA0B,CAC7B,MAAO,CACH,GAAG,MAAM,WAAW,EACpB,SAAU,KAAK,SAAS,IAAKD,GAAUA,EAAM,WAAW,CAAC,CAC7D,CACJ,CACJ,ECtDA,IAAqBE,EAArB,cAAsCC,CAAU,CAM5C,YAAYC,EAAyBC,EAA+BC,EAAkB,CAClF,MAAM,WAAYF,EAAYC,EAASC,CAAQ,CACnD,CAMU,SAASC,EAAoB,CAEnC,QAAWC,KAAS,KAAK,UAEjBA,EAAM,SAAS,yBAAqBA,EAAM,SAAS,4BAEnDA,EAAM,OAAOD,CAAK,EAK1B,GAAI,KAAK,SAAS,KAAMC,GAAUA,EAAM,uBAAe,CAAC,EAAG,CAEvD,KAAK,6BAAqB,EAG1B,QAAWA,KAAS,KAAK,SACjBA,EAAM,SAAS,2BACfA,EAAM,MAAMD,CAAK,EAIzB,MACJ,CAGA,GAAI,KAAK,SAAS,MAAOC,GAAUA,EAAM,0BAAkB,CAAC,EAAG,CAE3D,KAAK,gCAAwB,EAE7B,MACJ,CAGA,KAAK,8BAAsB,CAC/B,CAKA,QAAU,IAAM,UACpB,ECvDA,IAAqBC,EAArB,cAAkCC,CAAU,CAMxC,YAAYC,EAAyBC,EAA+BC,EAAkB,CAClF,MAAM,OAAQF,EAAYC,EAASC,CAAQ,CAC/C,CAMU,SAASC,EAAoB,CAEnC,QAAWC,KAAS,KAAK,UAEjBA,EAAM,SAAS,yBAAqBA,EAAM,SAAS,4BAEnDA,EAAM,OAAOD,CAAK,EAK1B,GAAI,KAAK,SAAS,KAAMC,GAAUA,EAAM,0BAAkB,CAAC,EAAG,CAE1D,KAAK,gCAAwB,EAG7B,QAAWA,KAAS,KAAK,SACjBA,EAAM,SAAS,2BACfA,EAAM,MAAMD,CAAK,EAIzB,MACJ,CAGA,GAAI,KAAK,SAAS,MAAOC,GAAUA,EAAM,uBAAe,CAAC,EAAG,CAExD,KAAK,6BAAqB,EAE1B,MACJ,CAGA,KAAK,8BAAsB,CAC/B,CAKA,QAAU,IAAM,MACpB,ECvDA,IAAqBC,EAArB,cAAiCC,CAAU,CAMvC,YAAYC,EAAyBC,EAA+BC,EAAkB,CAClF,MAAM,MAAOF,EAAYC,EAASC,CAAQ,CAC9C,CAMU,SAASC,EAAoB,CAEnC,QAAWC,KAAS,KAAK,UAEjBA,EAAM,SAAS,yBAAqBA,EAAM,SAAS,4BAEnDA,EAAM,OAAOD,CAAK,EAK1B,GAAI,KAAK,SAAS,MAAOC,GAAUA,EAAM,0BAAkB,GAAKA,EAAM,uBAAe,CAAC,EAAG,CAErF,KAAK,SAAS,KAAK,SAAS,KAAMA,GAAUA,EAAM,0BAAkB,CAAC,8CAAkC,EAEvG,MACJ,CAGA,KAAK,8BAAsB,CAC/B,CAKA,QAAU,IAAM,KACpB,ECxCA,IAAqBC,EAArB,cAAsCC,CAAU,CAM5C,YAAYC,EAAyBC,EAAyCC,EAAkB,CAC5F,MAAM,WAAYF,EAAYC,EAASC,CAAQ,EAD2B,cAAAA,CAE9E,CAMU,SAASC,EAAoB,CAEnC,QAAWC,KAAS,KAAK,SAAU,CAQ/B,IANIA,EAAM,SAAS,yBAAqBA,EAAM,SAAS,4BAEnDA,EAAM,OAAOD,CAAK,EAIlBC,EAAM,SAAS,4BAAuB,CAEtC,KAAK,gCAAwB,EAG7B,MACJ,CAGA,GAAIA,EAAM,SAAS,yBAGf,GAAI,KAAK,SAAS,QAAQA,CAAK,IAAM,KAAK,SAAS,OAAS,EAAG,CAE3D,KAAK,6BAAqB,EAG1B,MACJ,KAEI,UAKR,GAAIA,EAAM,SAAS,0BAAqB,CAEpC,KAAK,8BAAsB,EAG3B,MACJ,CAGA,MAAM,IAAI,MAAM,0CAA0C,CAC9D,CACJ,CAKA,QAAU,IAAM,UACpB,EClEA,IAAqBC,EAArB,cAAsCC,CAAU,CAM5C,YAAYC,EAAyBC,EAAyCC,EAAkB,CAC5F,MAAM,WAAYF,EAAYC,EAASC,CAAQ,EAD2B,cAAAA,CAE9E,CAMU,SAASC,EAAoB,CAEnC,QAAWC,KAAS,KAAK,SAAU,CAQ/B,IANIA,EAAM,SAAS,yBAAqBA,EAAM,SAAS,4BAEnDA,EAAM,OAAOD,CAAK,EAIlBC,EAAM,SAAS,4BAGf,GAAI,KAAK,SAAS,QAAQA,CAAK,IAAM,KAAK,SAAS,OAAS,EAAG,CAE3D,KAAK,gCAAwB,EAG7B,MACJ,KAEI,UAKR,GAAIA,EAAM,SAAS,yBAAoB,CAEnC,KAAK,6BAAqB,EAG1B,MACJ,CAGA,GAAIA,EAAM,SAAS,0BAAqB,CAEpC,KAAK,8BAAsB,EAG3B,MACJ,CAGA,MAAM,IAAI,MAAM,0CAA0C,CAC9D,CACJ,CAKA,QAAU,IAAM,UACpB,EC7EA,IAAAC,GAAwB,SAcxB,IAAqBC,EAArB,cAAmCC,CAAU,CAOzC,YACIC,EACAC,EACQC,EACRC,EACF,CACE,MAAM,QAASH,EAAYC,EAASE,CAAQ,EAHpC,aAAAD,CAIZ,CAKQ,cAME,SAASE,EAAoB,CAEnC,GAAI,KAAK,sBAAc,EAAG,CAEtB,IAAMC,KAAY,GAAAC,SAAkB,CAEhC,OAAQ,KAAK,QAAQ,OAErB,aAAc,KAAK,SAAS,IAAI,CAACC,EAAOC,IAAU,CAACD,EAAO,KAAK,UAAUC,IAAU,CAAC,CAAC,CACzF,CAAC,EAGD,KAAK,cAAgBH,EAAU,KAAK,GAAK,MAC7C,CAGA,GAAI,CAAC,KAAK,cACN,MAAM,IAAI,MAAM,uDAAuD,GAIvE,KAAK,cAAc,SAAS,yBAAqB,KAAK,cAAc,SAAS,4BAC7E,KAAK,cAAc,OAAOD,CAAK,EAInC,KAAK,SAAS,KAAK,cAAc,SAAS,CAAC,CAC/C,CAKA,QAAU,IAAO,KAAK,QAAU,UAAU,KAAK,QAAQ,KAAK,GAAG,KAAO,OAC1E,EC/DA,IAA8BK,EAA9B,cAAgDC,CAAK,CAOjD,YAAYC,EAAcC,EAAyBC,EAAyCC,EAAa,CACrG,MAAMH,EAAMC,EAAYC,CAAO,EADyD,WAAAC,CAE5F,CAKA,YAAc,IAAM,CAAC,KAAK,KAAK,EAK/B,MAAQ,IAAM,CAEV,KAAK,4BAAoB,EAGzB,KAAK,MAAM,MAAM,CACrB,EAMA,MAASC,GAAiB,CAElB,CAAC,KAAK,wBAAgB,IAK1B,KAAK,MAAM,MAAMA,CAAK,EAGtB,KAAK,MAAM,EAEX,KAAK,WAAW,MAAM,kBAAkBA,EAAO,GAAO,EAAI,EAC9D,EAMO,YAA0B,CAC7B,MAAO,CACH,GAAG,MAAM,WAAW,EACpB,SAAU,CAAC,KAAK,MAAM,WAAW,CAAC,CACtC,CACJ,CACJ,ECtDA,IAAqBC,EAArB,cAAkCC,CAAU,CAMxC,YAAYC,EAAyBC,EAA+BC,EAAa,CAC7E,MAAM,OAAQF,EAAYC,EAASC,CAAK,CAC5C,CAMU,SAASC,EAAoB,CAOnC,QALI,KAAK,MAAM,SAAS,yBAAqB,KAAK,MAAM,SAAS,4BAC7D,KAAK,MAAM,OAAOA,CAAK,EAInB,KAAK,MAAM,SAAS,EAAG,CAC3B,0BACI,KAAK,8BAAsB,EAC3B,MAEJ,4BACA,yBACI,KAAK,6BAAqB,EAC1B,MAEJ,QACI,KAAK,4BAAoB,CACjC,CACJ,CAKA,QAAU,IAAM,MACpB,ECxCA,IAAqBC,EAArB,cAAkCC,CAAU,CAMxC,YAAYC,EAAyBC,EAA+BC,EAAa,CAC7E,MAAM,OAAQF,EAAYC,EAASC,CAAK,CAC5C,CAMU,SAASC,EAAoB,CAOnC,QALI,KAAK,MAAM,SAAS,yBAAqB,KAAK,MAAM,SAAS,4BAC7D,KAAK,MAAM,OAAOA,CAAK,EAInB,KAAK,MAAM,SAAS,EAAG,CAC3B,0BACI,KAAK,8BAAsB,EAC3B,MAEJ,4BACI,KAAK,6BAAqB,EAC1B,MAEJ,yBACI,KAAK,gCAAwB,EAC7B,MAEJ,QACI,KAAK,4BAAoB,CACjC,CACJ,CAKA,QAAU,IAAM,MACpB,ECvCA,IAAqBC,EAArB,cAAoCC,CAAU,CAS1C,YACIC,EACAC,EACQC,EACAC,EACAC,EACRC,EACF,CACE,MAAM,SAAUL,EAAYC,EAASI,CAAK,EALlC,gBAAAH,EACA,mBAAAC,EACA,mBAAAC,CAIZ,CAKQ,qBAAsC,KAKtC,sBAAgC,EAM9B,SAASE,EAAoB,CAenC,GAbI,KAAK,sBAAc,IAEnB,KAAK,MAAM,MAAM,EAGjB,KAAK,sBAAwB,EAG7B,KAAK,wBAAwB,GAK7B,KAAK,WAAW,EAehB,GAbA,KAAK,8BAAsB,EAIvB,KAAK,MAAM,SAAS,6BACpB,KAAK,MAAM,MAAM,EAIrB,KAAK,MAAM,OAAOA,CAAK,EAInB,KAAK,MAAM,SAAS,yBAAoB,CAExC,KAAK,6BAAqB,EAE1B,MACJ,MAAW,KAAK,MAAM,SAAS,8BAE3B,KAAK,uBAAyB,QAIlC,KAAK,gCAAwB,CAErC,CAKA,QAAU,IACF,KAAK,aAAe,KACb,UAAU,KAAK,cACf,KAAK,gBAAkB,MAAQ,KAAK,gBAAkB,KACtD,UAAU,KAAK,kBAAkB,KAAK,iBAEtC,SAOf,MAAQ,IAAM,CAEV,KAAK,4BAAoB,EAGzB,KAAK,sBAAwB,EAG7B,KAAK,MAAM,MAAM,CACrB,EAMQ,WAAa,IACb,KAAK,uBAAyB,KAEvB,KAAK,sBAAwB,KAAK,qBAItC,GAMH,wBAA0B,IAAM,CAEpC,GAAI,KAAK,aAAe,KACpB,KAAK,qBAAuB,KAAK,mBAC1B,KAAK,gBAAkB,MAAQ,KAAK,gBAAkB,KAAM,CAGnE,IAAMC,EAAS,OAAO,KAAK,QAAQ,QAAW,WAAa,KAAK,QAAQ,OAAS,KAAK,OAGtF,KAAK,qBAAuB,KAAK,MAC7BA,EAAO,GAAK,KAAK,cAAgB,KAAK,cAAgB,GAAK,KAAK,aACpE,CACJ,MACI,KAAK,qBAAuB,IAEpC,CACJ,EC5IA,IAAqBC,EAArB,cAAmCC,CAAU,CASzC,YACIC,EACAC,EACQC,EACAC,EACAC,EACRC,EACF,CACE,MAAM,QAASL,EAAYC,EAASI,CAAK,EALjC,cAAAH,EACA,iBAAAC,EACA,iBAAAC,CAIZ,CAKQ,mBAAoC,KAKpC,oBAA8B,EAM5B,SAASE,EAAoB,CAenC,GAbI,KAAK,sBAAc,IAEnB,KAAK,MAAM,MAAM,EAGjB,KAAK,oBAAsB,EAG3B,KAAK,sBAAsB,GAK3B,KAAK,WAAW,EAehB,GAbA,KAAK,8BAAsB,EAIvB,KAAK,MAAM,SAAS,0BACpB,KAAK,MAAM,MAAM,EAIrB,KAAK,MAAM,OAAOA,CAAK,EAInB,KAAK,MAAM,SAAS,4BAAuB,CAE3C,KAAK,gCAAwB,EAE7B,MACJ,MAAW,KAAK,MAAM,SAAS,2BAE3B,KAAK,qBAAuB,QAIhC,KAAK,6BAAqB,CAElC,CAKA,QAAU,IACF,KAAK,WAAa,KACX,SAAS,KAAK,YACd,KAAK,cAAgB,MAAQ,KAAK,cAAgB,KAClD,SAAS,KAAK,gBAAgB,KAAK,eAEnC,QAOf,MAAQ,IAAM,CAEV,KAAK,4BAAoB,EAGzB,KAAK,oBAAsB,EAG3B,KAAK,MAAM,MAAM,CACrB,EAMA,WAAa,IACL,KAAK,qBAAuB,KAErB,KAAK,oBAAsB,KAAK,mBAIpC,GAMX,sBAAwB,IAAM,CAE1B,GAAI,KAAK,WAAa,KAClB,KAAK,mBAAqB,KAAK,iBACxB,KAAK,cAAgB,MAAQ,KAAK,cAAgB,KAAM,CAG/D,IAAMC,EAAS,OAAO,KAAK,QAAQ,QAAW,WAAa,KAAK,QAAQ,OAAS,KAAK,OAGtF,KAAK,mBAAqB,KAAK,MAC3BA,EAAO,GAAK,KAAK,YAAc,KAAK,YAAc,GAAK,KAAK,WAChE,CACJ,MACI,KAAK,mBAAqB,IAElC,CACJ,EChJA,IAAqBC,EAArB,cAAkCC,CAAU,CAMxC,YAAYC,EAAyBC,EAA+BC,EAAa,CAC7E,MAAM,OAAQF,EAAYC,EAASC,CAAK,CAC5C,CAMU,SAASC,EAAoB,EAE/B,KAAK,MAAM,SAAS,yBAAqB,KAAK,MAAM,SAAS,4BAE7D,KAAK,MAAM,OAAOA,CAAK,EAI3B,KAAK,SAAS,KAAK,MAAM,SAAS,CAAC,CACvC,CAKA,QAAU,IAAM,MACpB,EC7BA,IAAqBC,EAArB,cAAqCC,CAAU,CAM3C,YAAYC,EAAyBC,EAA+BC,EAAa,CAC7E,MAAM,UAAWF,EAAYC,EAASC,CAAK,CAC/C,CAMU,SAASC,EAAoB,CAOnC,QALI,KAAK,MAAM,SAAS,yBAAqB,KAAK,MAAM,SAAS,4BAC7D,KAAK,MAAM,OAAOA,CAAK,EAInB,KAAK,MAAM,SAAS,EAAG,CAC3B,0BACI,KAAK,8BAAsB,EAC3B,MAEJ,4BACA,yBACI,KAAK,gCAAwB,EAC7B,MAEJ,QACI,KAAK,4BAAoB,CACjC,CACJ,CAKA,QAAU,IAAM,SACpB,ECxBA,IAAqBC,EAArB,cAAoCC,CAAK,CAOrC,YACIC,EACAC,EACQC,EACDC,EACT,CACE,MAAM,SAAUH,EAAYC,CAAO,EAH3B,gBAAAC,EACD,qBAAAC,CAGX,CAKQ,qBAAuB,GAKvB,oBAAkD,KAMhD,SAASC,EAAoB,CAEnC,GAAI,KAAK,qBAAsB,CAE3B,GAAI,CAAC,KAAK,oBACN,OAGJ,GAAM,CAAE,WAAAC,EAAY,MAAAC,CAAM,EAAI,KAAK,oBAGnC,GAAID,EAAY,CAEZ,GAAIC,6BAA6BA,yBAC7B,MAAM,IAAI,MACN,qHACJ,EAIJ,KAAK,SAASA,CAAK,EAEnB,MACJ,KAEI,OAAM,IAAI,MAAM,oBAAoB,KAAK,sCAAsCA,IAAQ,CAE/F,CAGA,IAAMC,EAAoBC,EAAO,eAAeJ,EAAO,KAAK,UAAU,EAGtE,GAAIG,IAAsB,KACtB,MAAM,IAAI,MACN,4CAA4C,KAAK,8EACrD,EAGJ,IAAIE,EAEJ,GAAI,CAKAA,EAAuBF,EAAkB,KAAK,eAAe,CACjE,OAASG,EAAP,CAEE,MAAIA,aAAiB,MACX,IAAI,MAAM,oBAAoB,KAAK,sBAAsBA,EAAM,OAAO,EAEtE,IAAI,MAAM,oBAAoB,KAAK,sBAAsBA,GAAO,CAE9E,CAEID,aAAgC,SAChCA,EAAqB,KAChBE,GAAW,CAEJ,CAAC,KAAK,uBAKV,KAAK,oBAAsB,CACvB,WAAY,GACZ,MAAOA,CACX,EACJ,EACCC,GAAW,CAEJ,CAAC,KAAK,uBAKV,KAAK,oBAAsB,CACvB,WAAY,GACZ,MAAOA,CACX,EACJ,CACJ,EAGA,KAAK,8BAAsB,EAG3B,KAAK,qBAAuB,KAG5B,KAAK,qBAAqBH,CAAoB,EAG9C,KAAK,SAASA,wBAAqC,EAE3D,CAKA,QAAU,IAAM,KAAK,WAKrB,MAAQ,IAAM,CAEV,KAAK,4BAAoB,EAGzB,KAAK,qBAAuB,GAC5B,KAAK,oBAAsB,IAC/B,EAMO,YAA0B,CAC7B,MAAO,CACH,GAAG,MAAM,WAAW,EACpB,KAAM,KAAK,eACf,CACJ,CAMU,eAAeI,EAA4B,CACjD,KAAK,QAAQ,oBAAoB,CAC7B,GAAI,KAAK,IACT,KAAM,KAAK,QAAQ,EACnB,KAAM,KAAK,gBACX,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,KAAM,KAAK,WAAW,MAAM,WAAW,EACvC,KAAM,KAAK,WAAW,MAAM,WAAW,EACvC,cAAAA,EACA,MAAO,KAAK,SAAS,CACzB,CAAC,CACL,CAMQ,qBAAwBF,GAA0C,CACtE,OAAQA,EAAQ,CACZ,4BACA,yBACA,0BACA,KAAK,OACD,OACJ,QACI,MAAM,IAAI,MACN,6BAA6B,KAAK,yFAAyFA,IAC/H,CACR,CACJ,CACJ,EC/MA,IAAqBG,EAArB,cAAuCC,CAAK,CAOxC,YACIC,EACAC,EACQC,EACDC,EACT,CACE,MAAM,YAAaH,EAAYC,CAAO,EAH9B,mBAAAC,EACD,wBAAAC,CAGX,CAMU,SAASC,EAAoB,CAEnC,IAAMC,EAAuBC,EAAO,eAAeF,EAAO,KAAK,aAAa,EAG5E,GAAIC,IAAyB,KACzB,MAAM,IAAI,MACN,kDAAkD,KAAK,iFAC3D,EAGJ,IAAIE,EAEJ,GAAI,CAEAA,EAA0BF,EAAqB,KAAK,kBAAkB,CAC1E,OAASG,EAAP,CAEE,MAAIA,aAAiB,MACX,IAAI,MAAM,uBAAuB,KAAK,yBAAyBA,EAAM,OAAO,EAE5E,IAAI,MAAM,uBAAuB,KAAK,yBAAyBA,GAAO,CAEpF,CAGA,GAAI,OAAOD,GAA4B,UACnC,MAAM,IAAI,MACN,gCAAgC,KAAK,oDAAoDA,IAC7F,EAIJ,KAAK,SAASA,8CAAwD,CAC1E,CAKA,QAAU,IAAM,KAAK,cAMd,YAA0B,CAC7B,MAAO,CACH,GAAG,MAAM,WAAW,EACpB,KAAM,KAAK,kBACf,CACJ,CAMU,eAAeE,EAA4B,CACjD,KAAK,QAAQ,oBAAoB,CAC7B,GAAI,KAAK,IACT,KAAM,KAAK,QAAQ,EACnB,KAAM,KAAK,mBACX,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,MAAO,KAAK,WAAW,OAAO,WAAW,EACzC,KAAM,KAAK,WAAW,MAAM,WAAW,EACvC,KAAM,KAAK,WAAW,MAAM,WAAW,EACvC,cAAAA,EACA,MAAO,KAAK,SAAS,CACzB,CAAC,CACL,CACJ,EC5FA,IAAqBC,EAArB,cAAkCC,CAAK,CAQnC,YACIC,EACAC,EACQC,EACAC,EACAC,EACV,CACE,MAAM,OAAQJ,EAAYC,CAAO,EAJzB,cAAAC,EACA,iBAAAC,EACA,iBAAAC,CAGZ,CAKQ,kBAA4B,EAK5B,cAA+B,KAK/B,eAAyB,EAMvB,SAASC,EAAoB,CAEnC,GAAI,KAAK,sBAAc,EAAG,CAQtB,GANA,KAAK,kBAAoB,IAAI,KAAK,EAAE,QAAQ,EAG5C,KAAK,eAAiB,EAGlB,KAAK,WAAa,KAClB,KAAK,cAAgB,KAAK,iBACnB,KAAK,cAAgB,MAAQ,KAAK,cAAgB,KAAM,CAG/D,IAAMC,EAAS,OAAO,KAAK,QAAQ,QAAW,WAAa,KAAK,QAAQ,OAAS,KAAK,OAGtF,KAAK,cAAgB,KAAK,MACtBA,EAAO,GAAK,KAAK,YAAc,KAAK,YAAc,GAAK,KAAK,WAChE,CACJ,MACI,KAAK,cAAgB,KAIzB,KAAK,8BAAsB,CAC/B,CAGA,GAAI,KAAK,gBAAkB,KAK3B,IAAI,OAAO,KAAK,QAAQ,cAAiB,WAAY,CAEjD,IAAMC,EAAY,KAAK,QAAQ,aAAa,EAG5C,GAAI,OAAOA,GAAc,UAAY,MAAMA,CAAS,EAChD,MAAM,IAAI,MAAM,oDAAoD,EAIxE,KAAK,gBAAkBA,EAAY,GACvC,MAEI,KAAK,eAAiB,IAAI,KAAK,EAAE,QAAQ,EAAI,KAAK,kBAIlD,KAAK,gBAAkB,KAAK,eAE5B,KAAK,gCAAwB,EAErC,CAKA,QAAU,IACF,KAAK,WAAa,KACX,QAAQ,KAAK,aACb,KAAK,cAAgB,MAAQ,KAAK,cAAgB,KAClD,QAAQ,KAAK,iBAAiB,KAAK,gBAEnC,MAGnB,ECxGA,IAA8BC,EAA9B,KAAuG,CAKnG,YAAmBC,EAAqBC,EAAa,CAAlC,UAAAD,EAAqB,UAAAC,CAAc,CAM1D,ECVA,IAA8BC,EAA9B,cAA4CC,CAAiC,CAMzE,YAAYC,EAAcC,EAAqBC,EAAmB,CAC9D,MAAMF,EAAMC,CAAI,EAD2B,eAAAC,CAE/C,CAKA,aAAe,IAAM,KAAK,UAK1B,YAAoC,CAChC,MAAO,CACH,KAAM,KAAK,KACX,KAAM,KAAK,KACX,MAAO,KAAK,aAAa,CAC7B,CACJ,CAQJ,ECvCA,IAAqBC,EAArB,cAAmCC,CAAM,CAKrC,YAAYC,EAAmBC,EAAa,CACxC,MAAM,QAASA,EAAMD,CAAS,CAClC,CAOA,YAAeE,GAAiB,CAE5B,IAAMC,EAAuBC,EAAO,eAAeF,EAAO,KAAK,aAAa,CAAC,EAG7E,GAAIC,IAAyB,KACzB,MAAM,IAAI,MACN,gDAAgD,KAAK,aAAa,qEACtE,EAGJ,IAAIE,EAEJ,GAAI,CAEAA,EAA0BF,EAAqB,KAAK,IAAI,CAC5D,OAASG,EAAP,CAEE,MAAIA,aAAiB,MACX,IAAI,MAAM,6BAA6B,KAAK,aAAa,aAAaA,EAAM,OAAO,EAEnF,IAAI,MAAM,6BAA6B,KAAK,aAAa,aAAaA,GAAO,CAE3F,CAGA,GAAI,OAAOD,GAA4B,UACnC,MAAM,IAAI,MACN,sCAAsC,KAAK,aAAa,wCAAwCA,IACpG,EAIJ,OAAOA,CACX,CACJ,ECjDA,IAAqBE,EAArB,cAAmCC,CAAM,CAKrC,YAAYC,EAAmBC,EAAa,CACxC,MAAM,QAASA,EAAMD,CAAS,CAClC,CAOA,YAAeE,GAAiB,CAE5B,IAAMC,EAAuBC,EAAO,eAAeF,EAAO,KAAK,aAAa,CAAC,EAG7E,GAAIC,IAAyB,KACzB,MAAM,IAAI,MACN,gDAAgD,KAAK,aAAa,qEACtE,EAGJ,IAAIE,EAEJ,GAAI,CAEAA,EAA0BF,EAAqB,KAAK,IAAI,CAC5D,OAASG,EAAP,CAEE,MAAIA,aAAiB,MACX,IAAI,MAAM,6BAA6B,KAAK,aAAa,aAAaA,EAAM,OAAO,EAEnF,IAAI,MAAM,6BAA6B,KAAK,aAAa,aAAaA,GAAO,CAE3F,CAGA,GAAI,OAAOD,GAA4B,UACnC,MAAM,IAAI,MACN,sCAAsC,KAAK,aAAa,wCAAwCA,IACpG,EAIJ,MAAO,CAACA,CACZ,CACJ,EC1CA,IAA8BE,EAA9B,cAA+CC,CAAoC,CAM/E,YAAYC,EAAcC,EAAqBC,EAAsB,CACjE,MAAMF,EAAMC,CAAI,EAD2B,kBAAAC,CAE/C,CAKA,gBAAkB,IAAM,KAAK,aAK7B,YAAuC,CACnC,MAAO,CACH,KAAM,KAAK,KACX,KAAM,KAAK,KACX,MAAO,KAAK,gBAAgB,CAChC,CACJ,CAOJ,ECtCA,IAAqBC,EAArB,cAAmCC,CAAS,CAKxC,YAAYC,EAAsBC,EAAa,CAC3C,MAAM,QAASA,EAAMD,CAAY,CACrC,CAMA,kBAAqBE,GAAiB,CAElC,IAAMC,EAAsBC,EAAO,eAAeF,EAAO,KAAK,gBAAgB,CAAC,EAG/E,GAAIC,IAAwB,KACxB,MAAM,IAAI,MACN,+BAA+B,KAAK,gBAAgB,+DACxD,EAIJA,EAAoB,KAAK,IAAI,CACjC,CACJ,EC3BA,IAAqBE,EAArB,cAAkCC,CAAS,CAKvC,YAAYC,EAAsBC,EAAa,CAC3C,MAAM,OAAQA,EAAMD,CAAY,CACpC,CAMA,kBAAqBE,GAAiB,CAElC,IAAMC,EAAsBC,EAAO,eAAeF,EAAO,KAAK,gBAAgB,CAAC,EAG/E,GAAIC,IAAwB,KACxB,MAAM,IAAI,MACN,8BAA8B,KAAK,gBAAgB,+DACvD,EAIJA,EAAoB,KAAK,IAAI,CACjC,CACJ,EC3BA,IAAqBE,EAArB,cAAkCC,CAAS,CAKvC,YAAYC,EAAsBC,EAAa,CAC3C,MAAM,OAAQA,EAAMD,CAAY,CACpC,CAQA,kBAAoB,CAACE,EAAcC,EAAoBC,IAAuB,CAE1E,IAAMC,EAAsBC,EAAO,eAAeJ,EAAO,KAAK,gBAAgB,CAAC,EAG/E,GAAIG,IAAwB,KACxB,MAAM,IAAI,MACN,8BAA8B,KAAK,gBAAgB,+DACvD,EAIJA,EAAoB,CAAC,CAAE,UAAWF,EAAW,QAASC,CAAU,EAAG,GAAG,KAAK,IAAI,CAAC,CACpF,CACJ,ECyBA,IAAMG,GAAqB,OAAO,UAAU,EAQ7B,SAARC,GAA+BC,EAAkCC,EAAqC,CAEzG,IAAMC,EAAwBC,GAA4BH,CAAU,EAKpEI,GACI,CAACF,EAAsBJ,IAAqB,GAAG,OAAO,OAAOI,CAAqB,CAAC,EACnF,EACJ,EAGA,IAAMG,EAAWC,EAAYJ,EAAsBJ,IAAqBI,EAAuBD,CAAO,EAGtG,OAAAM,GAAwBF,CAAQ,EAGzBA,CACX,CASA,SAASC,EACLN,EACAE,EACAD,EACO,CAEP,IAAMO,EAAaC,GAAsBT,CAAU,EAGnD,OAAQA,EAAW,KAAM,CACrB,IAAK,OACD,OAAO,IAAIU,EAAKF,EAAYP,EAASK,EAAYN,EAAW,MAAOE,EAAuBD,CAAO,CAAC,EAEtG,IAAK,SAAU,CACX,IAAIU,EAA4B,KAC5BC,EAA+B,KAC/BC,EAA+B,KAEnC,OAAI,MAAM,QAAQb,EAAW,UAAU,GACnCY,EAAgBZ,EAAW,WAAW,GACtCa,EAAgBb,EAAW,WAAW,IAC/Bc,EAAUd,EAAW,UAAU,IACtCW,EAAaX,EAAW,YAGrB,IAAIe,EACPP,EACAP,EACAU,EACAC,EACAC,EACAP,EAAYN,EAAW,MAAOE,EAAuBD,CAAO,CAChE,CACJ,CAEA,IAAK,QAAS,CACV,IAAIe,EAA0B,KAC1BC,EAA6B,KAC7BC,EAA6B,KAEjC,OAAI,MAAM,QAAQlB,EAAW,QAAQ,GACjCiB,EAAcjB,EAAW,SAAS,GAClCkB,EAAclB,EAAW,SAAS,IAC3Bc,EAAUd,EAAW,QAAQ,IACpCgB,EAAWhB,EAAW,UAGnB,IAAImB,EACPX,EACAP,EACAe,EACAC,EACAC,EACAZ,EAAYN,EAAW,MAAOE,EAAuBD,CAAO,CAChE,CACJ,CAEA,IAAK,OACD,OAAO,IAAImB,EAAKZ,EAAYP,EAASK,EAAYN,EAAW,MAAOE,EAAuBD,CAAO,CAAC,EAEtG,IAAK,UACD,OAAO,IAAIoB,EAAQb,EAAYP,EAASK,EAAYN,EAAW,MAAOE,EAAuBD,CAAO,CAAC,EAEzG,IAAK,OACD,OAAO,IAAIqB,EAAKd,EAAYP,EAASK,EAAYN,EAAW,MAAOE,EAAuBD,CAAO,CAAC,EAEtG,IAAK,WACD,OAAO,IAAIsB,EACPf,EACAP,EACAD,EAAW,SAAS,IAAKwB,GAAUlB,EAAYkB,EAAOtB,EAAuBD,CAAO,CAAC,CACzF,EAEJ,IAAK,WACD,OAAO,IAAIwB,EACPjB,EACAP,EACAD,EAAW,SAAS,IAAKwB,GAAUlB,EAAYkB,EAAOtB,EAAuBD,CAAO,CAAC,CACzF,EAEJ,IAAK,WACD,OAAO,IAAIyB,EACPlB,EACAP,EACAD,EAAW,SAAS,IAAKwB,GAAUlB,EAAYkB,EAAOtB,EAAuBD,CAAO,CAAC,CACzF,EAEJ,IAAK,OACD,OAAO,IAAI0B,EACPnB,EACAP,EACAD,EAAW,SAAS,IAAKwB,GAAUlB,EAAYkB,EAAOtB,EAAuBD,CAAO,CAAC,CACzF,EAEJ,IAAK,MACD,OAAO,IAAI2B,EACPpB,EACAP,EACAD,EAAW,SAAS,IAAKwB,GAAUlB,EAAYkB,EAAOtB,EAAuBD,CAAO,CAAC,CACzF,EAEJ,IAAK,QACD,OAAO,IAAI4B,EACPrB,EACAP,EACAD,EAAW,QACXA,EAAW,SAAS,IAAKwB,GAAUlB,EAAYkB,EAAOtB,EAAuBD,CAAO,CAAC,CACzF,EAEJ,IAAK,SACD,OAAOK,EAAYJ,EAAsBF,EAAW,KAAK,MAAOE,EAAuBD,CAAO,EAElG,IAAK,SACD,OAAO,IAAI6B,EAAOtB,EAAYP,EAASD,EAAW,KAAMA,EAAW,MAAQ,CAAC,CAAC,EAEjF,IAAK,YACD,OAAO,IAAI+B,EAAUvB,EAAYP,EAASD,EAAW,KAAMA,EAAW,MAAQ,CAAC,CAAC,EAEpF,IAAK,OAAQ,CACT,IAAIgC,EAA0B,KAC1BC,EAA6B,KAC7BC,EAA6B,KAEjC,OAAI,MAAM,QAAQlC,EAAW,QAAQ,GACjCiC,EAAcjC,EAAW,SAAS,GAClCkC,EAAclC,EAAW,SAAS,IAC3Bc,EAAUd,EAAW,QAAQ,IACpCgC,EAAWhC,EAAW,UAGnB,IAAImC,EAAK3B,EAAYP,EAAS+B,EAAUC,EAAaC,CAAW,CAC3E,CACJ,CACJ,CAOA,SAASzB,GAAsBT,EAA4C,CACvE,IAAMQ,EAA0B,CAAC,EAEjC,OAAIR,EAAW,OACXQ,EAAW,KAAK,IAAI4B,EAAMpC,EAAW,MAAM,KAAMA,EAAW,MAAM,MAAQ,CAAC,CAAC,CAAC,EAG7EA,EAAW,OACXQ,EAAW,KAAK,IAAI6B,EAAMrC,EAAW,MAAM,KAAMA,EAAW,MAAM,MAAQ,CAAC,CAAC,CAAC,EAG7EA,EAAW,OACXQ,EAAW,KAAK,IAAI8B,EAAMtC,EAAW,MAAM,KAAMA,EAAW,MAAM,MAAQ,CAAC,CAAC,CAAC,EAG7EA,EAAW,MACXQ,EAAW,KAAK,IAAI+B,EAAKvC,EAAW,KAAK,KAAMA,EAAW,KAAK,MAAQ,CAAC,CAAC,CAAC,EAG1EA,EAAW,MACXQ,EAAW,KAAK,IAAIgC,EAAKxC,EAAW,KAAK,KAAMA,EAAW,KAAK,MAAQ,CAAC,CAAC,CAAC,EAGvEQ,CACX,CAOA,SAASL,GAA4BH,EAAyD,CAE1F,IAAMyC,EAAqC,CAAC,EAG5C,OAAW,CAACC,EAAMC,CAAkB,IAAK,OAAO,QAAQC,EAAO,YAAY,CAAC,EAExEH,EAAYC,GAAQ,CAAE,GAAGC,EAAoB,GAAID,CAAK,EAK1D,QAAWC,KAAsB3C,EAC7ByC,EAAYE,EAAmB,IAAM7C,IAAsB6C,EAG/D,OAAOF,CACX,CAMA,SAASlC,GAAwBsC,EAAY,CACzC,IAAMC,EAAsB,CAAC,EAEvBC,EAAgB,CAACC,EAAcC,IAAe,CAEhDD,EAAOA,EAAK,OAAOC,CAAI,EAGnBA,aAAgBC,EAChBJ,EAAU,KAAKE,CAAI,EAElBC,EAA+B,YAAY,EAAE,QAASzB,GAAUuB,EAAcC,EAAMxB,CAAK,CAAC,CAEnG,EAGAuB,EAAc,CAAC,EAAGF,CAAI,EAEtBC,EAAU,QAASE,GAAS,CAExB,QAASG,EAAQ,EAAGA,EAAQH,EAAK,OAAQG,IAAS,CAE9C,IAAMC,EAAcJ,EAAKG,GAGzB,GAAIC,EAAY,aAAa,EACzB,SAIJ,IAAMC,EAAY,IAAIC,EAClBN,EACK,MAAM,EAAGG,EAAQ,CAAC,EAClB,IAAoBF,IAAU,CAC3B,KAAAA,EACA,OAAQA,EAAK,cAAc,EAAE,OAAQM,GAAcA,aAAqBC,CAAK,CACjF,EAAE,EACD,OAAQC,GAAYA,EAAQ,OAAO,OAAS,CAAC,CACtD,EAGAL,EAAY,aAAaC,CAAS,CACtC,CACJ,CAAC,CACL,CCjUO,IAAMK,GAAN,KAAoB,CAYvB,YACIC,EACQC,EACAC,EAAgC,CAAC,EAC3C,CAFU,WAAAD,EACA,aAAAC,EAGR,GAAIC,GAAkBH,CAAU,EAC5B,MAAM,IAAI,MAAM,6BAA6B,EAIjD,GAAI,OAAOC,GAAU,UAAYA,IAAU,KACvC,MAAM,IAAI,MAAM,0CAA0C,EAI9D,GAAM,CAAE,UAAAG,EAAW,aAAAC,EAAc,KAAAC,CAAK,EAAIC,GAAmBP,CAAU,EAGvE,GAAI,CAACI,EACD,MAAM,IAAI,MAAM,uBAAuBC,GAAc,EAIzD,GAAI,CAACC,EACD,MAAM,IAAI,MACN,8FACJ,EAGJ,GAAI,CAEA,KAAK,UAAYE,GAAcF,EAAMJ,CAAO,CAChD,OAASO,EAAP,CAEE,MAAM,IAAI,MAAM,wBAAyBA,EAAoB,SAAS,CAC1E,CACJ,CA7CiB,UAmDV,WAAqB,CACxB,OAAO,KAAK,UAAU,SAAS,yBACnC,CAMO,UAAkB,CACrB,OAAO,KAAK,UAAU,SAAS,CACnC,CAUO,MAAa,EAEZ,KAAK,UAAU,SAAS,6BAAyB,KAAK,UAAU,SAAS,2BACzE,KAAK,UAAU,MAAM,EAGzB,GAAI,CACA,KAAK,UAAU,OAAO,KAAK,KAAK,CACpC,OAASA,EAAP,CACE,MAAM,IAAI,MAAM,wBAAyBA,EAAoB,SAAS,CAC1E,CACJ,CAKO,OAAc,CACjB,KAAK,UAAU,MAAM,CACzB,CAMO,oBAAkC,CACrC,OAAO,KAAK,UAAU,WAAW,CACrC,CAOA,OAAO,SAASC,EAAcC,EAAqD,CAE/E,GAAI,OAAOA,GAAU,WAAY,CAC7BC,EAAO,QAAQF,EAAMC,CAAK,EAC1B,MACJ,CAGA,GAAI,OAAOA,GAAU,SAAU,CAC3B,IAAIE,EAGJ,GAAI,CACAA,EAAsBC,EAAkBH,CAAK,CACjD,OAASF,EAAP,CACE,MAAM,IAAI,MAAM,+CAAgDA,EAAoB,SAAS,CACjG,CAGA,GAAII,EAAoB,QAAU,GAAK,OAAOA,EAAoB,GAAG,GAAO,IACxE,MAAM,IAAI,MAAM,mEAAmE,EAGvF,GAAI,CAEA,GAAM,CAAE,UAAAT,EAAW,aAAAC,CAAa,EAAIU,GAAuBF,EAAoB,EAAE,EAGjF,GAAI,CAACT,EACD,MAAM,IAAI,MAAMC,CAAY,CAEpC,OAASI,EAAP,CACE,MAAM,IAAI,MAAM,iCAAkCA,EAAoB,SAAS,CACnF,CAGAG,EAAO,WAAWF,EAAMG,EAAoB,EAAE,CAClD,SAAW,OAAOF,GAAU,UAAY,CAAC,MAAM,QAAQA,CAAK,EAAG,CAG3D,GAAI,CAEA,GAAM,CAAE,UAAAP,EAAW,aAAAC,CAAa,EAAIU,GAAuBJ,CAAK,EAGhE,GAAI,CAACP,EACD,MAAM,IAAI,MAAMC,CAAY,CAEpC,OAASI,EAAP,CACE,MAAM,IAAI,MAAM,iCAAkCA,EAAoB,SAAS,CACnF,CAGAG,EAAO,WAAWF,EAAMC,CAAK,CACjC,KACI,OAAM,IAAI,MAAM,0FAA0F,CAElH,CAMA,OAAO,WAAWD,EAAoB,CAClCE,EAAO,OAAOF,CAAI,CACtB,CAKA,OAAO,eAAsB,CACzBE,EAAO,MAAM,CACjB,CACJ", + "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", "isRootNodeDefinition", "node", "isBranchNodeDefinition", "isLeafNodeDefinition", "isDecoratorNodeDefinition", "isCompositeNodeDefinition", "flattenDefinition", "nodeDefinition", "nodes", "processNode", "currentNodeDefinition", "isInteger", "value", "isNullOrUndefined", "popAndCheck", "tokens", "expected", "popped", "expectedValues", "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", "isRootNodeDefinition", "topTreeStack", "topTreeStackTopNode", "isCompositeNodeDefinition", "isDecoratorNodeDefinition", "isLeafNodeDefinition", "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", "isBranchNodeDefinition", "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", "Leaf", "Node", "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", "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", "Leaf", "depth", "currentNode", "guardPath", "GuardPath", "attribute", "Guard", "details", "BehaviourTree", "definition", "agent", "options", "isNullOrUndefined", "succeeded", "errorMessage", "json", "validateDefinition", "buildRootNode", "exception", "name", "value", "Lookup", "rootNodeDefinitions", "convertMDSLToJSON", "validateJSONDefinition"] } diff --git a/dist/nodes/Node.d.ts b/dist/nodes/Node.d.ts index af0e7da..f7690a6 100644 --- a/dist/nodes/Node.d.ts +++ b/dist/nodes/Node.d.ts @@ -1,7 +1,6 @@ import { BehaviourTreeOptions } from "../BehaviourTreeOptions"; import State, { AnyState } from "../State"; import { Agent } from "../Agent"; -import Leaf from "./leaf/Leaf"; import Attribute from "../attributes/Attribute"; import Entry from "../attributes/callbacks/Entry"; import Exit from "../attributes/callbacks/Exit"; @@ -122,10 +121,6 @@ export default abstract class Node { * Gets the name of the node. */ abstract getName(): string; - /** - * Gets whether this node is a leaf node. - */ - abstract isLeafNode: () => this is Leaf; /** * Gets/Sets the state of the node. */ diff --git a/dist/nodes/composite/Composite.d.ts b/dist/nodes/composite/Composite.d.ts index 05f46fa..bdf5716 100644 --- a/dist/nodes/composite/Composite.d.ts +++ b/dist/nodes/composite/Composite.d.ts @@ -14,10 +14,6 @@ export default abstract class Composite extends Node { * @param children The child nodes. */ constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, children: Node[]); - /** - * Gets whether this node is a leaf node. - */ - isLeafNode: () => boolean; /** * Gets the children of this node. */ diff --git a/dist/nodes/decorator/Decorator.d.ts b/dist/nodes/decorator/Decorator.d.ts index 76df7e7..7d5accf 100644 --- a/dist/nodes/decorator/Decorator.d.ts +++ b/dist/nodes/decorator/Decorator.d.ts @@ -14,10 +14,6 @@ export default abstract class Decorator extends Node { * @param child The child node. */ constructor(type: string, attributes: Attribute[], options: BehaviourTreeOptions, child: Node); - /** - * Gets whether this node is a leaf node. - */ - isLeafNode: () => boolean; /** * Gets the children of this node. */ diff --git a/dist/nodes/leaf/Leaf.d.ts b/dist/nodes/leaf/Leaf.d.ts index c7e7109..869a000 100644 --- a/dist/nodes/leaf/Leaf.d.ts +++ b/dist/nodes/leaf/Leaf.d.ts @@ -3,8 +3,4 @@ import Node from "../Node"; * A leaf node. */ export default abstract class Leaf extends Node { - /** - * Gets whether this node is a leaf node. - */ - isLeafNode: () => boolean; } diff --git a/package-lock.json b/package-lock.json index 2e8a4a9..bd7786c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,8 @@ "lotto-draw": "^1.0.2" }, "devDependencies": { - "@types/chai": "^4.3.11", - "@types/mocha": "^10.0.6", + "@types/chai": "^4.3.16", + "@types/mocha": "^10.0.7", "@types/sinon": "^17.0.3", "@typescript-eslint/eslint-plugin": "^7.14.1", "@typescript-eslint/parser": "^7.14.1", @@ -21,56 +21,123 @@ "esbuild": "^0.15.18", "eslint": "^8.57.0", "expect": "^25.5.0", - "mocha": "^10.2.0", + "mocha": "^10.5.2", "npm-run-all": "^4.1.5", "prettier": "2.7.1", "should": "^1.3.0", "sinon": "^14.0.2", "ts-node": "^10.9.2", - "typescript": "^5.3.3" + "typescript": "^5.5.2" } }, "node_modules/@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.14.5" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -131,9 +198,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -162,6 +229,28 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { "version": "8.57.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", @@ -186,6 +275,28 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -221,21 +332,6 @@ "node": ">= 8.3" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/@jest/types/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -249,27 +345,6 @@ "node": ">=8" } }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -375,9 +450,9 @@ "dev": true }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", "dev": true }, "node_modules/@tsconfig/node12": { @@ -399,21 +474,21 @@ "dev": true }, "node_modules/@types/chai": { - "version": "4.3.11", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.11.tgz", - "integrity": "sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==", + "version": "4.3.16", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.16.tgz", + "integrity": "sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==", "dev": true }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" @@ -430,15 +505,15 @@ } }, "node_modules/@types/mocha": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", - "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.7.tgz", + "integrity": "sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==", "dev": true }, "node_modules/@types/node": { - "version": "20.11.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", - "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", + "version": "20.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", + "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", "dev": true, "peer": true, "dependencies": { @@ -467,18 +542,18 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "15.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", - "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -627,42 +702,6 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/utils": { "version": "7.14.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", @@ -709,9 +748,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -730,10 +769,13 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } @@ -773,32 +815,20 @@ } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-styles/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ansi-styles/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -824,6 +854,22 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -833,6 +879,28 @@ "node": ">=8" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -842,29 +910,46 @@ "node": "*" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -886,13 +971,19 @@ "dev": true }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -938,17 +1029,19 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/check-error": { @@ -964,16 +1057,10 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -986,10 +1073,25 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -1022,7 +1124,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "node_modules/create-require": { @@ -1032,25 +1134,74 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=4.8" + "node": ">= 8" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -1064,12 +1215,6 @@ } } }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", @@ -1083,9 +1228,9 @@ } }, "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, "dependencies": { "type-detect": "^4.0.0" @@ -1100,12 +1245,30 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/define-properties": { + "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -1174,35 +1337,57 @@ } }, "node_modules/es-abstract": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -1211,22 +1396,51 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { @@ -1604,21 +1818,24 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { @@ -1704,229 +1921,102 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": "*" } }, - "node_modules/eslint/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">= 8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "estraverse": "^5.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.10" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "is-glob": "^4.0.3" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=4.0" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/eslint/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/expect": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-25.5.0.tgz", + "integrity": "sha512-w7KAXo0+6qqZZhovCaBVPSIqQp7/UTcx4M9uKt2m6pd2VB1voyC8JizLRqeEqud3AAVP02g+hbErDu5gu64tlA==", "dev": true, "dependencies": { - "shebang-regex": "^3.0.0" + "@jest/types": "^25.5.0", + "ansi-styles": "^4.0.0", + "jest-get-type": "^25.2.6", + "jest-matcher-utils": "^25.5.0", + "jest-message-util": "^25.5.0", + "jest-regex-util": "^25.2.6" }, "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expect": { - "version": "25.5.0", - "integrity": "sha512-w7KAXo0+6qqZZhovCaBVPSIqQp7/UTcx4M9uKt2m6pd2VB1voyC8JizLRqeEqud3AAVP02g+hbErDu5gu64tlA==", - "dev": true, - "dependencies": { - "@jest/types": "^25.5.0", - "ansi-styles": "^4.0.0", - "jest-get-type": "^25.2.6", - "jest-matcher-utils": "^25.5.0", - "jest-message-util": "^25.5.0", - "jest-regex-util": "^25.2.6" - }, - "engines": { - "node": ">= 8.3" - } - }, - "node_modules/expect/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 8.3" } }, "node_modules/fast-deep-equal": { @@ -1951,6 +2041,18 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2041,6 +2143,15 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2048,9 +2159,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -2062,21 +2173,24 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -2113,27 +2227,33 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -2143,35 +2263,47 @@ } }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, "node_modules/globals": { @@ -2189,6 +2321,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -2209,10 +2357,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/graphemer": { @@ -2221,18 +2381,6 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -2243,21 +2391,33 @@ } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2276,12 +2436,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -2290,6 +2450,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2299,6 +2471,12 @@ "he": "bin/he" } }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -2337,6 +2515,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "dependencies": { "once": "^1.3.0", @@ -2350,19 +2529,35 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { "node": ">= 0.4" } }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -2422,12 +2617,30 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2479,9 +2692,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -2549,12 +2762,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2590,6 +2806,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -2615,15 +2846,15 @@ } }, "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "node_modules/jest-diff": { @@ -2641,21 +2872,6 @@ "node": ">= 8.3" } }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-diff/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -2669,27 +2885,6 @@ "node": ">=8" } }, - "node_modules/jest-diff/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-get-type": { "version": "25.2.6", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", @@ -2714,21 +2909,6 @@ "node": ">= 8.3" } }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-matcher-utils/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -2742,27 +2922,6 @@ "node": ">=8" } }, - "node_modules/jest-matcher-utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-message-util": { "version": "25.5.0", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.5.0.tgz", @@ -2782,21 +2941,6 @@ "node": ">= 8.3" } }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/jest-message-util/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -2810,27 +2954,6 @@ "node": ">=8" } }, - "node_modules/jest-message-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-regex-util": { "version": "25.2.6", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.2.6.tgz", @@ -2840,6 +2963,12 @@ "node": ">= 8.3" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2877,9 +3006,9 @@ "dev": true }, "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, "node_modules/keyv": { @@ -2919,19 +3048,6 @@ "node": ">=4" } }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2975,70 +3091,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/lotto-draw": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/lotto-draw/-/lotto-draw-1.0.2.tgz", "integrity": "sha512-1ih414A35BWpApfNlWAHBKOBLSxTj45crAJ+CMWF/kVY5nx6N22DA1OVF/FWW5WM5CGJbIMRh1O+xe8ukyoQ8Q==" }, "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "dependencies": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" } }, "node_modules/make-error": { @@ -3066,12 +3130,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -3079,37 +3143,39 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "version": "10.5.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.5.2.tgz", + "integrity": "sha512-9btlN3JKCefPf+vKd/kcKz2SXxi12z6JswkGfaAF0saQvnsqLJk504ZmbxhSoENge08E9dsymozKgFMTl5PQsA==", "dev": true, "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.3", + "chokidar": "^3.5.3", "debug": "4.3.4", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.2.0", + "glob": "8.1.0", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.3.3", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", @@ -3124,41 +3190,30 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/mocha/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, + "ms": "2.1.2" + }, "engines": { - "node": ">=10" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", @@ -3172,6 +3227,12 @@ "node": ">=10" } }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -3188,23 +3249,11 @@ } }, "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -3218,25 +3267,55 @@ "dev": true }, "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", + "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" + } + }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" } }, "node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0" + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" } }, "node_modules/normalize-path": { @@ -3273,55 +3352,174 @@ "node": ">= 4" } }, - "node_modules/npm-run-all/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "node_modules/npm-run-all/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" } }, - "node_modules/npm-run-all/node_modules/path-type": { + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/npm-run-all/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-all/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "pify": "^3.0.0" + "brace-expansion": "^1.1.7" }, + "engines": { + "node": "*" + } + }, + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, "engines": { "node": ">=4" } }, - "node_modules/npm-run-all/node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3335,6 +3533,24 @@ "node": ">= 0.4" } }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3403,6 +3619,19 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3422,12 +3651,12 @@ } }, "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/path-parse": { @@ -3437,13 +3666,10 @@ "dev": true }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "dependencies": { - "isarray": "0.0.1" - } + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -3463,6 +3689,12 @@ "node": "*" } }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -3496,6 +3728,15 @@ "node": ">=4" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3507,6 +3748,7 @@ }, "node_modules/prettier": { "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true, "bin": { @@ -3529,24 +3771,9 @@ "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^16.12.0" - }, - "engines": { - "node": ">= 8.3" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + }, + "engines": { + "node": ">= 8.3" } }, "node_modules/punycode": { @@ -3593,6 +3820,32 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3606,14 +3859,15 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -3632,12 +3886,12 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -3683,6 +3937,49 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3706,6 +4003,24 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3727,26 +4042,32 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/serialize-javascript": { @@ -3758,31 +4079,63 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/shell-quote": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.4.tgz", - "integrity": "sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3790,21 +4143,26 @@ }, "node_modules/should": { "version": "1.3.0", - "integrity": "sha1-ILcaCbXtFhRrkDAivTBu8zLv6HM=", + "resolved": "https://registry.npmjs.org/should/-/should-1.3.0.tgz", + "integrity": "sha512-jT7RMMj//A4Gx+1+D0IB/RF/k+3jWv9fUiGZbLqWHsnQ98aehwl31sc38dJwd/WnQQDYnzUt1WAJXVYNnYTIIQ==", "dev": true, "engines": { "node": ">= 0.2.0" } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3829,27 +4187,6 @@ "url": "https://opencollective.com/sinon" } }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -3860,9 +4197,9 @@ } }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -3870,9 +4207,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -3886,9 +4223,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", "dev": true }, "node_modules/stack-utils": { @@ -3927,14 +4264,33 @@ } }, "node_modules/string.prototype.padend": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz", - "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3944,28 +4300,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4005,15 +4364,15 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -4143,10 +4502,83 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", + "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -4204,15 +4636,18 @@ } }, "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { - "which": "bin/which" + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, "node_modules/which-boxed-primitive": { @@ -4231,6 +4666,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -4263,21 +4717,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 94e7dfe..c9bc459 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "dist/*" ], "devDependencies": { - "@types/chai": "^4.3.11", - "@types/mocha": "^10.0.6", + "@types/chai": "^4.3.16", + "@types/mocha": "^10.0.7", "@types/sinon": "^17.0.3", "@typescript-eslint/eslint-plugin": "^7.14.1", "@typescript-eslint/parser": "^7.14.1", @@ -17,13 +17,13 @@ "esbuild": "^0.15.18", "eslint": "^8.57.0", "expect": "^25.5.0", - "mocha": "^10.2.0", + "mocha": "^10.5.2", "npm-run-all": "^4.1.5", "prettier": "2.7.1", "should": "^1.3.0", "sinon": "^14.0.2", "ts-node": "^10.9.2", - "typescript": "^5.3.3" + "typescript": "^5.5.2" }, "scripts": { "build": "npm-run-all build:format build:node build:web build:web-minified build:typecheck", diff --git a/src/BehaviourTreeBuilder.ts b/src/BehaviourTreeBuilder.ts index 01c59db..1f37d96 100644 --- a/src/BehaviourTreeBuilder.ts +++ b/src/BehaviourTreeBuilder.ts @@ -3,6 +3,7 @@ import GuardPath, { GuardPathPart } from "./attributes/guards/GuardPath"; import { validateBranchSubtreeLinks } from "./BehaviourTreeDefinitionValidator"; import { isInteger } from "./BehaviourTreeDefinitionUtilities"; import Node from "./nodes/Node"; +import Leaf from "./nodes/leaf/Leaf"; import Composite from "./nodes/composite/Composite"; import Decorator from "./nodes/decorator/Decorator"; import Parallel from "./nodes/composite/Parallel"; @@ -297,7 +298,7 @@ function applyLeafNodeGuardPaths(root: Root) { path = path.concat(node); // Check whether the current node is a leaf node. - if (node.isLeafNode()) { + if (node instanceof Leaf) { nodePaths.push(path); } else { (node as Composite | Decorator).getChildren().forEach((child) => findLeafNodes(path, child)); @@ -324,7 +325,7 @@ function applyLeafNodeGuardPaths(root: Root) { .slice(0, depth + 1) .map((node) => ({ node, - guards: node.getAttributes().filter((attribute) => attribute.isGuard()) as Guard[] + guards: node.getAttributes().filter((attribute) => attribute instanceof Guard) })) .filter((details) => details.guards.length > 0) ); diff --git a/src/BehaviourTreeDefinitionUtilities.ts b/src/BehaviourTreeDefinitionUtilities.ts index 49012ba..04e4781 100644 --- a/src/BehaviourTreeDefinitionUtilities.ts +++ b/src/BehaviourTreeDefinitionUtilities.ts @@ -12,7 +12,7 @@ import { * @param node The node. * @returns A value of true if the specified node satisfies the RootNodeDefinition type. */ -export function isRootNode(node: NodeDefinition): node is RootNodeDefinition { +export function isRootNodeDefinition(node: NodeDefinition): node is RootNodeDefinition { return node.type === "root"; } @@ -21,7 +21,7 @@ export function isRootNode(node: NodeDefinition): node is RootNodeDefinition { * @param node The node. * @returns A value of true if the specified node satisfies the BranchNodeDefinition type. */ -export function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition { +export function isBranchNodeDefinition(node: NodeDefinition): node is BranchNodeDefinition { return node.type === "branch"; } @@ -30,7 +30,7 @@ export function isBranchNode(node: NodeDefinition): node is BranchNodeDefinition * @param node The node. * @returns A value of true if the specified node satisfies the NodeDefinition type. */ -export function isLeafNode(node: NodeDefinition): node is NodeDefinition { +export function isLeafNodeDefinition(node: NodeDefinition): node is NodeDefinition { return ["branch", "action", "condition", "wait"].includes(node.type); } @@ -39,7 +39,7 @@ export function isLeafNode(node: NodeDefinition): node is NodeDefinition { * @param node The node. * @returns A value of true if the specified node satisfies the DecoratorNodeDefinition type. */ -export function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefinition { +export function isDecoratorNodeDefinition(node: NodeDefinition): node is DecoratorNodeDefinition { return ["root", "repeat", "retry", "flip", "succeed", "fail"].includes(node.type); } @@ -48,7 +48,7 @@ export function isDecoratorNode(node: NodeDefinition): node is DecoratorNodeDefi * @param node The node. * @returns A value of true if the specified node satisfies the CompositeNodeDefinition type. */ -export function isCompositeNode(node: NodeDefinition): node is CompositeNodeDefinition { +export function isCompositeNodeDefinition(node: NodeDefinition): node is CompositeNodeDefinition { return ["sequence", "selector", "lotto", "parallel", "race", "all"].includes(node.type); } @@ -63,9 +63,9 @@ export function flattenDefinition(nodeDefinition: AnyNodeDefinition): AnyNodeDef const processNode = (currentNodeDefinition: AnyNodeDefinition) => { nodes.push(currentNodeDefinition); - if (isCompositeNode(currentNodeDefinition)) { + if (isCompositeNodeDefinition(currentNodeDefinition)) { currentNodeDefinition.children.forEach(processNode); - } else if (isDecoratorNode(currentNodeDefinition)) { + } else if (isDecoratorNodeDefinition(currentNodeDefinition)) { processNode(currentNodeDefinition.child); } }; diff --git a/src/BehaviourTreeDefinitionValidator.ts b/src/BehaviourTreeDefinitionValidator.ts index 6ed5de7..620d3f2 100644 --- a/src/BehaviourTreeDefinitionValidator.ts +++ b/src/BehaviourTreeDefinitionValidator.ts @@ -1,5 +1,5 @@ import { RootNodeDefinition } from "./BehaviourTreeDefinition"; -import { flattenDefinition, isBranchNode, isInteger } from "./BehaviourTreeDefinitionUtilities"; +import { flattenDefinition, isBranchNodeDefinition, isInteger } from "./BehaviourTreeDefinitionUtilities"; import { convertMDSLToJSON } from "./mdsl/MDSLDefinitionParser"; /** @@ -176,7 +176,7 @@ export function validateBranchSubtreeLinks(rootNodeDefinitions: RootNodeDefiniti (rootNodeDefinition) => ({ id: rootNodeDefinition.id, refs: flattenDefinition(rootNodeDefinition) - .filter(isBranchNode) + .filter(isBranchNodeDefinition) .map(({ ref }) => ref) }) ); diff --git a/src/attributes/Attribute.ts b/src/attributes/Attribute.ts index 82803f0..f892b55 100644 --- a/src/attributes/Attribute.ts +++ b/src/attributes/Attribute.ts @@ -22,9 +22,4 @@ export default abstract class Attribute this is Guard; } diff --git a/src/attributes/callbacks/Callback.ts b/src/attributes/callbacks/Callback.ts index 52b9f9d..e3e9d7f 100644 --- a/src/attributes/callbacks/Callback.ts +++ b/src/attributes/callbacks/Callback.ts @@ -27,11 +27,6 @@ export default abstract class Callback extends Attribute this.functionName; - /** - * Gets whether this attribute is a guard. - */ - isGuard = () => false; - /** * Gets the attribute details. */ diff --git a/src/attributes/guards/Guard.ts b/src/attributes/guards/Guard.ts index 9cca4ce..3fbfdb3 100644 --- a/src/attributes/guards/Guard.ts +++ b/src/attributes/guards/Guard.ts @@ -27,11 +27,6 @@ export default abstract class Guard extends Attribute { */ getCondition = () => this.condition; - /** - * Gets whether this attribute is a guard. - */ - isGuard = () => true; - /** * Gets the attribute details. */ diff --git a/src/mdsl/MDSLDefinitionParser.ts b/src/mdsl/MDSLDefinitionParser.ts index 2ba4e2a..618eff1 100644 --- a/src/mdsl/MDSLDefinitionParser.ts +++ b/src/mdsl/MDSLDefinitionParser.ts @@ -19,11 +19,11 @@ import { WaitNodeDefinition } from "../BehaviourTreeDefinition"; import { - isCompositeNode, - isDecoratorNode, - isLeafNode, + isCompositeNodeDefinition, + isDecoratorNodeDefinition, + isLeafNodeDefinition, isNullOrUndefined, - isRootNode + isRootNodeDefinition } from "../BehaviourTreeDefinitionUtilities"; import { parseArgumentTokens } from "./MDSLNodeArgumentParser"; import { parseAttributeTokens } from "./MDSLNodeAttributeParser"; @@ -84,7 +84,7 @@ function convertTokensToJSONDefinition( // A helper function used to push node definitions onto the tree stack. const pushNode = (node: AnyNodeDefinition) => { // If the node is a root node then we need to create a new tree stack array with the root node at the root. - if (isRootNode(node)) { + if (isRootNodeDefinition(node)) { // We need to double-check that this root node is not the child of another node. // We can do this by checking whether the top tree stack is not empty (contains an existing node) if (treeStacks[treeStacks.length - 1]?.length) { @@ -115,10 +115,10 @@ function convertTokensToJSONDefinition( // If the top-most node in the current root stack is a composite or decorator // node then the current node should be added as a child of the top-most node. - if (isCompositeNode(topTreeStackTopNode)) { + if (isCompositeNodeDefinition(topTreeStackTopNode)) { topTreeStackTopNode.children = topTreeStackTopNode.children || []; topTreeStackTopNode.children.push(node); - } else if (isDecoratorNode(topTreeStackTopNode)) { + } else if (isDecoratorNodeDefinition(topTreeStackTopNode)) { // If the top node already has a child node set then throw an error as a decorator should only have a single child. if (topTreeStackTopNode.child) { throw new Error("a decorator node must only have a single child node"); @@ -129,7 +129,7 @@ function convertTokensToJSONDefinition( // If the node we are adding is also a composite or decorator node, then we should push it // onto the current tree stack, as subsequent nodes will be added as its child/children. - if (!isLeafNode(node)) { + if (!isLeafNodeDefinition(node)) { topTreeStack.push(node); } }; @@ -788,12 +788,12 @@ function createBranchNode( */ function validatePoppedNode(definition: AnyNodeDefinition): void { // Decorators MUST have a child defined. - if (isDecoratorNode(definition) && isNullOrUndefined(definition.child)) { + if (isDecoratorNodeDefinition(definition) && isNullOrUndefined(definition.child)) { throw new Error(`a ${definition.type} node must have a single child node defined`); } // Composites MUST have at least one child defined. - if (isCompositeNode(definition) && !definition.children?.length) { + if (isCompositeNodeDefinition(definition) && !definition.children?.length) { throw new Error(`a ${definition.type} node must have at least a single child node defined`); } diff --git a/src/nodes/Node.ts b/src/nodes/Node.ts index 6e992d5..5e96eaf 100644 --- a/src/nodes/Node.ts +++ b/src/nodes/Node.ts @@ -141,11 +141,6 @@ export default abstract class Node { */ public abstract getName(): string; - /** - * Gets whether this node is a leaf node. - */ - public abstract isLeafNode: () => this is Leaf; - /** * Gets/Sets the state of the node. */ diff --git a/src/nodes/composite/Composite.ts b/src/nodes/composite/Composite.ts index 8ce5815..dc5f0da 100644 --- a/src/nodes/composite/Composite.ts +++ b/src/nodes/composite/Composite.ts @@ -18,11 +18,6 @@ export default abstract class Composite extends Node { super(type, attributes, options); } - /** - * Gets whether this node is a leaf node. - */ - isLeafNode = () => false; - /** * Gets the children of this node. */ diff --git a/src/nodes/decorator/Decorator.ts b/src/nodes/decorator/Decorator.ts index 56b8196..40450f3 100644 --- a/src/nodes/decorator/Decorator.ts +++ b/src/nodes/decorator/Decorator.ts @@ -18,11 +18,6 @@ export default abstract class Decorator extends Node { super(type, attributes, options); } - /** - * Gets whether this node is a leaf node. - */ - isLeafNode = () => false; - /** * Gets the children of this node. */ diff --git a/src/nodes/leaf/Leaf.ts b/src/nodes/leaf/Leaf.ts index a879a24..cce8f02 100644 --- a/src/nodes/leaf/Leaf.ts +++ b/src/nodes/leaf/Leaf.ts @@ -3,9 +3,4 @@ import Node from "../Node"; /** * A leaf node. */ -export default abstract class Leaf extends Node { - /** - * Gets whether this node is a leaf node. - */ - isLeafNode = () => true; -} +export default abstract class Leaf extends Node {} From 577705389ef87502bbc681576183c2827c8968eb Mon Sep 17 00:00:00 2001 From: Nikolas Howard Date: Fri, 28 Jun 2024 13:01:11 +0100 Subject: [PATCH 3/3] 4.1.1 --- README.md | 1 + package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 14e86c8..f3df68f 100644 --- a/README.md +++ b/README.md @@ -1431,6 +1431,7 @@ A practical look at behaviour trees and a good example of modelling behaviour fo ## Version History | Version | Notes | | -------------- |:----------------------------------------------------------------------------------------| +| 4.1.1 | Added linter and updated dependencies | | 4.1.0 | Added Race and All node types | | | Added onNodeStateChange callback to behaviour tree options | | | Added getTreeNodeDetails method to BehaviourTree | diff --git a/package-lock.json b/package-lock.json index bd7786c..6bdc524 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mistreevous", - "version": "4.1.0", + "version": "4.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mistreevous", - "version": "4.1.0", + "version": "4.1.1", "license": "MIT", "dependencies": { "lotto-draw": "^1.0.2" diff --git a/package.json b/package.json index c9bc459..edc3859 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mistreevous", - "version": "4.1.0", + "version": "4.1.1", "description": "A library to declaratively define, build and execute behaviour trees, written in TypeScript for Node and browsers", "main": "dist/index.js", "types": "dist/index.d.ts",