diff --git a/dist/bundle.js b/dist/bundle.js index c954fdc..7d3ef95 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -1960,7 +1960,18 @@ var mistreevous = (() => { `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered` ); } - return !!conditionFuncInvoker(this.args); + let conditionFunctionResult; + try { + conditionFunctionResult = conditionFuncInvoker(this.args); + } catch (error) { + throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`); + } + if (typeof conditionFunctionResult !== "boolean") { + throw new Error( + `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'` + ); + } + return conditionFunctionResult; }; }; @@ -1976,7 +1987,18 @@ var mistreevous = (() => { `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered` ); } - return !!!conditionFuncInvoker(this.args); + let conditionFunctionResult; + try { + conditionFunctionResult = conditionFuncInvoker(this.args); + } catch (error) { + throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`); + } + if (typeof conditionFunctionResult !== "boolean") { + throw new Error( + `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'` + ); + } + return !conditionFunctionResult; }; }; diff --git a/dist/bundle.js.map b/dist/bundle.js.map index 57837ad..afcf63b 100644 --- a/dist/bundle.js.map +++ b/dist/bundle.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/BehaviourTreeDefinitionUtilities.ts", "../src/mdsl/MDSLUtilities.ts", "../src/mdsl/MDSLNodeArgumentParser.ts", "../src/mdsl/MDSLNodeAttributeParser.ts", "../src/mdsl/MDSLDefinitionParser.ts", "../src/BehaviourTreeDefinitionValidator.ts", "../src/Lookup.ts", "../src/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/nodes/Node.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Parallel.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 { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { FlattenedTreeNode, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n READY = \"mistreevous.ready\",\n RUNNING = \"mistreevous.running\",\n SUCCEEDED = \"mistreevous.succeeded\",\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 {\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\"].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 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 \"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 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 // 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 \"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 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 { 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.map((arg) => arg.value));\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 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", "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 Guard from \"../attributes/guards/Guard\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node uid.\n */\n private readonly uid: string = createNodeUid();\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 args The node argument definitions.\n */\n constructor(private type: string, private attributes: Attribute[], private args: any[]) {}\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected abstract onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 this.state = value;\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 = () => this.attributes;\n\n /**\n * Gets the node arguments.\n */\n getArguments = () => this.args;\n\n /**\n * Gets the node attribute with the specified type, or null if it does not exist.\n */\n getAttribute(type: \"entry\" | \"ENTRY\"): Entry;\n getAttribute(type: \"exit\" | \"EXIT\"): Exit;\n getAttribute(type: \"step\" | \"STEP\"): Step;\n getAttribute(type: string): Attribute {\n return (\n this.getAttributes().filter((decorator) => decorator.type.toUpperCase() === type.toUpperCase())[0] || null\n );\n }\n\n /**\n * Gets the node attributes.\n */\n getGuardAttributes = (): Guard[] => this.getAttributes().filter((decorator) => decorator.isGuard()) as Guard[];\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.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n * @returns The result of the update.\n */\n public update(agent: Agent, options: BehaviourTreeOptions): 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.getAttribute(\"entry\")?.callAgentFunction(agent);\n }\n\n this.getAttribute(\"step\")?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent, options);\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.getAttribute(\"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/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nfunction createNodeUid(): 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 Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\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 children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], protected children: Node[]) {\n super(type, attributes, []);\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.getChildren().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.getChildren().forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\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 children The child nodes.\n */\n constructor(attributes: Attribute[], children: Node[]) {\n super(\"parallel\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): void {\n // Keep a count of the number of succeeded child nodes.\n let succeededCount = 0;\n\n let hasChildFailed = false;\n\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, options);\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 // The child node has succeeded, keep track of this to determine if all children have.\n succeededCount++;\n\n // The child node succeeded, but we have not finished checking every child node yet.\n continue;\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 hasChildFailed = true;\n\n // There is no need to check the rest of the children.\n break;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() !== State.RUNNING) {\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 if (hasChildFailed) {\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 } else {\n // If all children have succeeded then this node has also succeeded, otherwise it is still running.\n this.setState(succeededCount === this.children.length ? State.SUCCEEDED : State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\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 children The child nodes.\n */\n constructor(attributes: Attribute[], protected children: Node[]) {\n super(\"selector\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 children The child nodes.\n */\n constructor(attributes: Attribute[], protected children: Node[]) {\n super(\"sequence\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 weights The child node weights.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private weights: number[] | undefined, children: Node[]) {\n super(\"lotto\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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: 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, options);\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 from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\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 child The child node.\n */\n constructor(type: string, attributes: Attribute[], protected child: Node) {\n super(type, attributes, []);\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.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"fail\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"flip\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 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 private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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(options);\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, options);\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 * @param options The behaviour tree options object.\n */\n private setTargetIterationCount = (options: BehaviourTreeOptions) => {\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 options.random === \"function\" ? 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 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 private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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(options);\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, options);\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 * @param options The behaviour tree options object.\n */\n setTargetAttemptCount = (options: BehaviourTreeOptions) => {\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 options.random === \"function\" ? 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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"root\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"succeed\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 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 actionName The action name.\n * @param actionArguments The array of action argument definitions.\n */\n constructor(attributes: Attribute[], private actionName: string, private actionArguments: any[]) {\n super(\"action\", attributes, actionArguments);\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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 // The user was naughty and threw something.\n throw new Error(`action function '${this.actionName}' threw '${error}'`);\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 * 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 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 conditionName The name of the condition function.\n * @param conditionArguments The array of condition argument definitions.\n */\n constructor(attributes: Attribute[], private conditionName: string, private conditionArguments: any[]) {\n super(\"condition\", attributes, conditionArguments);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 // The user was naughty and threw something.\n throw new Error(`condition function '${this.conditionName}' threw '${error}'`);\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", "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 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 private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, []);\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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 options.random === \"function\" ? 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 options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = 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\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n condition: 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 condition: 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 // Call the condition function to determine whether this guard is satisfied.\n return !!conditionFuncInvoker(this.args);\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 // Call the condition function to determine whether this guard is satisfied.\n return !!!conditionFuncInvoker(this.args);\n };\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n functionName: 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 functionName: 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 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 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\";\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 | 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 * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[]): 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) 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 * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(definition: AnyNodeDefinition, rootNodeDefinitionMap: RootNodeDefinitionMap): 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, nodeFactory(definition.child, rootNodeDefinitionMap));\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 iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap)\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 attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap)\n );\n\n case \"flip\":\n return new Flip(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"succeed\":\n return new Succeed(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"fail\":\n return new Fail(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap);\n\n case \"action\":\n return new Action(attributes, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, 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, 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) => ({ node, guards: node.getGuardAttributes() }))\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 from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\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// Purely for outside inspection of the tree.\nexport type FlattenedTreeNode = {\n id: string;\n type: string;\n caption: string;\n state: AnyState;\n guards: GuardAttributeDetails[];\n callbacks: CallbackAttributeDetails[];\n args: any[];\n parentId: string | null;\n};\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);\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 isRunning() {\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 getState() {\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 step() {\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, this.options);\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 reset() {\n this._rootNode.reset();\n }\n\n /**\n * Gets the flattened details of every node in the tree.\n * @returns The flattened details of every node in the tree.\n */\n getFlattenedNodeDetails(): FlattenedTreeNode[] {\n // Create an empty flattened array of tree nodes.\n const flattenedTreeNodes: FlattenedTreeNode[] = [];\n\n /**\n * Helper function to process a node instance and push details into the flattened tree nodes array.\n * @param node The current node.\n * @param parentUid The UID of the node parent, or null if the node is the main root node.\n */\n const processNode = (node: Node, parentUid: string | null) => {\n // Get the guard and callback attribute details for this node.\n const guards = node\n .getAttributes()\n .filter((attribute) => attribute.isGuard())\n .map((attribute) => attribute.getDetails()) as GuardAttributeDetails[];\n const callbacks = node\n .getAttributes()\n .filter((attribute) => !attribute.isGuard())\n .map((attribute) => attribute.getDetails()) as CallbackAttributeDetails[];\n\n // Push the current node into the flattened nodes array.\n flattenedTreeNodes.push({\n id: node.getUid(),\n type: node.getType(),\n caption: node.getName(),\n state: node.getState(),\n guards,\n callbacks,\n args: node.getArguments(),\n parentId: parentUid\n });\n\n // Process each of the nodes children if it is not a leaf node.\n if (!node.isLeafNode()) {\n (node as Composite | Decorator)\n .getChildren()\n .forEach((child) => processNode(child, (node as Composite | Decorator).getUid()));\n }\n };\n\n // Convert the nested node structure into a flattened array of node details.\n processNode(this._rootNode, null);\n\n return flattenedTreeNodes;\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 || rootNodeDefinitions[0].id !== null) {\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 { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { FlattenedTreeNode, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n READY = \"mistreevous.ready\",\n RUNNING = \"mistreevous.running\",\n SUCCEEDED = \"mistreevous.succeeded\",\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 {\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\"].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 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 \"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 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 // 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 \"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 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 { 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.map((arg) => arg.value));\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 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", "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 Guard from \"../attributes/guards/Guard\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node uid.\n */\n private readonly uid: string = createNodeUid();\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 args The node argument definitions.\n */\n constructor(private type: string, private attributes: Attribute[], private args: any[]) {}\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected abstract onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 this.state = value;\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 = () => this.attributes;\n\n /**\n * Gets the node arguments.\n */\n getArguments = () => this.args;\n\n /**\n * Gets the node attribute with the specified type, or null if it does not exist.\n */\n getAttribute(type: \"entry\" | \"ENTRY\"): Entry;\n getAttribute(type: \"exit\" | \"EXIT\"): Exit;\n getAttribute(type: \"step\" | \"STEP\"): Step;\n getAttribute(type: string): Attribute {\n return (\n this.getAttributes().filter((decorator) => decorator.type.toUpperCase() === type.toUpperCase())[0] || null\n );\n }\n\n /**\n * Gets the node attributes.\n */\n getGuardAttributes = (): Guard[] => this.getAttributes().filter((decorator) => decorator.isGuard()) as Guard[];\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.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n * @returns The result of the update.\n */\n public update(agent: Agent, options: BehaviourTreeOptions): 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.getAttribute(\"entry\")?.callAgentFunction(agent);\n }\n\n this.getAttribute(\"step\")?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent, options);\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.getAttribute(\"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/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nfunction createNodeUid(): 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 Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\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 children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], protected children: Node[]) {\n super(type, attributes, []);\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.getChildren().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.getChildren().forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\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 children The child nodes.\n */\n constructor(attributes: Attribute[], children: Node[]) {\n super(\"parallel\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): void {\n // Keep a count of the number of succeeded child nodes.\n let succeededCount = 0;\n\n let hasChildFailed = false;\n\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, options);\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 // The child node has succeeded, keep track of this to determine if all children have.\n succeededCount++;\n\n // The child node succeeded, but we have not finished checking every child node yet.\n continue;\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 hasChildFailed = true;\n\n // There is no need to check the rest of the children.\n break;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() !== State.RUNNING) {\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 if (hasChildFailed) {\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 } else {\n // If all children have succeeded then this node has also succeeded, otherwise it is still running.\n this.setState(succeededCount === this.children.length ? State.SUCCEEDED : State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\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 children The child nodes.\n */\n constructor(attributes: Attribute[], protected children: Node[]) {\n super(\"selector\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 children The child nodes.\n */\n constructor(attributes: Attribute[], protected children: Node[]) {\n super(\"sequence\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 weights The child node weights.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private weights: number[] | undefined, children: Node[]) {\n super(\"lotto\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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: 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, options);\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 from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\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 child The child node.\n */\n constructor(type: string, attributes: Attribute[], protected child: Node) {\n super(type, attributes, []);\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.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"fail\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"flip\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 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 private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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(options);\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, options);\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 * @param options The behaviour tree options object.\n */\n private setTargetIterationCount = (options: BehaviourTreeOptions) => {\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 options.random === \"function\" ? 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 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 private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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(options);\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, options);\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 * @param options The behaviour tree options object.\n */\n setTargetAttemptCount = (options: BehaviourTreeOptions) => {\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 options.random === \"function\" ? 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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"root\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"succeed\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 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 actionName The action name.\n * @param actionArguments The array of action argument definitions.\n */\n constructor(attributes: Attribute[], private actionName: string, private actionArguments: any[]) {\n super(\"action\", attributes, actionArguments);\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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 // The user was naughty and threw something.\n throw new Error(`action function '${this.actionName}' threw '${error}'`);\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 * 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 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 conditionName The name of the condition function.\n * @param conditionArguments The array of condition argument definitions.\n */\n constructor(attributes: Attribute[], private conditionName: string, private conditionArguments: any[]) {\n super(\"condition\", attributes, conditionArguments);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 // The user was naughty and threw something.\n throw new Error(`condition function '${this.conditionName}' threw '${error}'`);\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", "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 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 private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, []);\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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 options.random === \"function\" ? 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 options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = 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\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n condition: 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 condition: 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 // The user was naughty and threw something.\n throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`);\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 // The user was naughty and threw something.\n throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`);\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\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n functionName: 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 functionName: 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 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 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\";\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 | 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 * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[]): 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) 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 * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(definition: AnyNodeDefinition, rootNodeDefinitionMap: RootNodeDefinitionMap): 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, nodeFactory(definition.child, rootNodeDefinitionMap));\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 iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap)\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 attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap)\n );\n\n case \"flip\":\n return new Flip(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"succeed\":\n return new Succeed(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"fail\":\n return new Fail(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap);\n\n case \"action\":\n return new Action(attributes, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, 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, 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) => ({ node, guards: node.getGuardAttributes() }))\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 from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\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// Purely for outside inspection of the tree.\nexport type FlattenedTreeNode = {\n id: string;\n type: string;\n caption: string;\n state: AnyState;\n guards: GuardAttributeDetails[];\n callbacks: CallbackAttributeDetails[];\n args: any[];\n parentId: string | null;\n};\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);\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 isRunning() {\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 getState() {\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 step() {\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, this.options);\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 reset() {\n this._rootNode.reset();\n }\n\n /**\n * Gets the flattened details of every node in the tree.\n * @returns The flattened details of every node in the tree.\n */\n getFlattenedNodeDetails(): FlattenedTreeNode[] {\n // Create an empty flattened array of tree nodes.\n const flattenedTreeNodes: FlattenedTreeNode[] = [];\n\n /**\n * Helper function to process a node instance and push details into the flattened tree nodes array.\n * @param node The current node.\n * @param parentUid The UID of the node parent, or null if the node is the main root node.\n */\n const processNode = (node: Node, parentUid: string | null) => {\n // Get the guard and callback attribute details for this node.\n const guards = node\n .getAttributes()\n .filter((attribute) => attribute.isGuard())\n .map((attribute) => attribute.getDetails()) as GuardAttributeDetails[];\n const callbacks = node\n .getAttributes()\n .filter((attribute) => !attribute.isGuard())\n .map((attribute) => attribute.getDetails()) as CallbackAttributeDetails[];\n\n // Push the current node into the flattened nodes array.\n flattenedTreeNodes.push({\n id: node.getUid(),\n type: node.getType(),\n caption: node.getName(),\n state: node.getState(),\n guards,\n callbacks,\n args: node.getArguments(),\n parentId: parentUid\n });\n\n // Process each of the nodes children if it is not a leaf node.\n if (!node.isLeafNode()) {\n (node as Composite | Decorator)\n .getChildren()\n .forEach((child) => processNode(child, (node as Composite | Decorator).getUid()));\n }\n };\n\n // Convert the nested node structure into a flattened array of node details.\n processNode(this._rootNode, null);\n\n return flattenedTreeNodes;\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 || rootNodeDefinitions[0].id !== null) {\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", "createLotto"] } diff --git a/dist/index.js b/dist/index.js index 80a508d..6169c18 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1960,7 +1960,18 @@ var While = class extends Guard { `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered` ); } - return !!conditionFuncInvoker(this.args); + let conditionFunctionResult; + try { + conditionFunctionResult = conditionFuncInvoker(this.args); + } catch (error) { + throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`); + } + if (typeof conditionFunctionResult !== "boolean") { + throw new Error( + `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'` + ); + } + return conditionFunctionResult; }; }; @@ -1976,7 +1987,18 @@ var Until = class extends Guard { `cannot evaluate node guard as the condition '${this.getCondition()}' function is not defined on the agent and has not been registered` ); } - return !!!conditionFuncInvoker(this.args); + let conditionFunctionResult; + try { + conditionFunctionResult = conditionFuncInvoker(this.args); + } catch (error) { + throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`); + } + if (typeof conditionFunctionResult !== "boolean") { + throw new Error( + `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'` + ); + } + return !conditionFunctionResult; }; }; diff --git a/dist/index.js.map b/dist/index.js.map index c80981e..f753e35 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/BehaviourTreeDefinitionUtilities.ts", "../src/mdsl/MDSLUtilities.ts", "../src/mdsl/MDSLNodeArgumentParser.ts", "../src/mdsl/MDSLNodeAttributeParser.ts", "../src/mdsl/MDSLDefinitionParser.ts", "../src/BehaviourTreeDefinitionValidator.ts", "../src/Lookup.ts", "../src/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/nodes/Node.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Parallel.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 { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { FlattenedTreeNode, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n READY = \"mistreevous.ready\",\n RUNNING = \"mistreevous.running\",\n SUCCEEDED = \"mistreevous.succeeded\",\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 {\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\"].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 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 \"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 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 // 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 \"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 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 { 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.map((arg) => arg.value));\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 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", "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 Guard from \"../attributes/guards/Guard\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node uid.\n */\n private readonly uid: string = createNodeUid();\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 args The node argument definitions.\n */\n constructor(private type: string, private attributes: Attribute[], private args: any[]) {}\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected abstract onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 this.state = value;\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 = () => this.attributes;\n\n /**\n * Gets the node arguments.\n */\n getArguments = () => this.args;\n\n /**\n * Gets the node attribute with the specified type, or null if it does not exist.\n */\n getAttribute(type: \"entry\" | \"ENTRY\"): Entry;\n getAttribute(type: \"exit\" | \"EXIT\"): Exit;\n getAttribute(type: \"step\" | \"STEP\"): Step;\n getAttribute(type: string): Attribute {\n return (\n this.getAttributes().filter((decorator) => decorator.type.toUpperCase() === type.toUpperCase())[0] || null\n );\n }\n\n /**\n * Gets the node attributes.\n */\n getGuardAttributes = (): Guard[] => this.getAttributes().filter((decorator) => decorator.isGuard()) as Guard[];\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.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n * @returns The result of the update.\n */\n public update(agent: Agent, options: BehaviourTreeOptions): 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.getAttribute(\"entry\")?.callAgentFunction(agent);\n }\n\n this.getAttribute(\"step\")?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent, options);\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.getAttribute(\"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/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nfunction createNodeUid(): 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 Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\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 children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], protected children: Node[]) {\n super(type, attributes, []);\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.getChildren().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.getChildren().forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\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 children The child nodes.\n */\n constructor(attributes: Attribute[], children: Node[]) {\n super(\"parallel\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): void {\n // Keep a count of the number of succeeded child nodes.\n let succeededCount = 0;\n\n let hasChildFailed = false;\n\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, options);\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 // The child node has succeeded, keep track of this to determine if all children have.\n succeededCount++;\n\n // The child node succeeded, but we have not finished checking every child node yet.\n continue;\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 hasChildFailed = true;\n\n // There is no need to check the rest of the children.\n break;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() !== State.RUNNING) {\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 if (hasChildFailed) {\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 } else {\n // If all children have succeeded then this node has also succeeded, otherwise it is still running.\n this.setState(succeededCount === this.children.length ? State.SUCCEEDED : State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\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 children The child nodes.\n */\n constructor(attributes: Attribute[], protected children: Node[]) {\n super(\"selector\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 children The child nodes.\n */\n constructor(attributes: Attribute[], protected children: Node[]) {\n super(\"sequence\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 weights The child node weights.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private weights: number[] | undefined, children: Node[]) {\n super(\"lotto\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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: 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, options);\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 from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\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 child The child node.\n */\n constructor(type: string, attributes: Attribute[], protected child: Node) {\n super(type, attributes, []);\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.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"fail\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"flip\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 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 private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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(options);\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, options);\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 * @param options The behaviour tree options object.\n */\n private setTargetIterationCount = (options: BehaviourTreeOptions) => {\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 options.random === \"function\" ? 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 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 private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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(options);\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, options);\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 * @param options The behaviour tree options object.\n */\n setTargetAttemptCount = (options: BehaviourTreeOptions) => {\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 options.random === \"function\" ? 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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"root\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"succeed\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 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 actionName The action name.\n * @param actionArguments The array of action argument definitions.\n */\n constructor(attributes: Attribute[], private actionName: string, private actionArguments: any[]) {\n super(\"action\", attributes, actionArguments);\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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 // The user was naughty and threw something.\n throw new Error(`action function '${this.actionName}' threw '${error}'`);\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 * 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 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 conditionName The name of the condition function.\n * @param conditionArguments The array of condition argument definitions.\n */\n constructor(attributes: Attribute[], private conditionName: string, private conditionArguments: any[]) {\n super(\"condition\", attributes, conditionArguments);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 // The user was naughty and threw something.\n throw new Error(`condition function '${this.conditionName}' threw '${error}'`);\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", "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 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 private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, []);\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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 options.random === \"function\" ? 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 options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = 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\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n condition: 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 condition: 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 // Call the condition function to determine whether this guard is satisfied.\n return !!conditionFuncInvoker(this.args);\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 // Call the condition function to determine whether this guard is satisfied.\n return !!!conditionFuncInvoker(this.args);\n };\n}\n", "import { Agent } from \"../../Agent\";\nimport Attribute, { AttributeDetails } from \"../Attribute\";\n\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n functionName: 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 functionName: 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 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 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\";\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 | 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 * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[]): 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) 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 * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(definition: AnyNodeDefinition, rootNodeDefinitionMap: RootNodeDefinitionMap): 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, nodeFactory(definition.child, rootNodeDefinitionMap));\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 iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap)\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 attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap)\n );\n\n case \"flip\":\n return new Flip(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"succeed\":\n return new Succeed(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"fail\":\n return new Fail(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap);\n\n case \"action\":\n return new Action(attributes, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, 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, 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) => ({ node, guards: node.getGuardAttributes() }))\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 from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\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// Purely for outside inspection of the tree.\nexport type FlattenedTreeNode = {\n id: string;\n type: string;\n caption: string;\n state: AnyState;\n guards: GuardAttributeDetails[];\n callbacks: CallbackAttributeDetails[];\n args: any[];\n parentId: string | null;\n};\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);\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 isRunning() {\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 getState() {\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 step() {\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, this.options);\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 reset() {\n this._rootNode.reset();\n }\n\n /**\n * Gets the flattened details of every node in the tree.\n * @returns The flattened details of every node in the tree.\n */\n getFlattenedNodeDetails(): FlattenedTreeNode[] {\n // Create an empty flattened array of tree nodes.\n const flattenedTreeNodes: FlattenedTreeNode[] = [];\n\n /**\n * Helper function to process a node instance and push details into the flattened tree nodes array.\n * @param node The current node.\n * @param parentUid The UID of the node parent, or null if the node is the main root node.\n */\n const processNode = (node: Node, parentUid: string | null) => {\n // Get the guard and callback attribute details for this node.\n const guards = node\n .getAttributes()\n .filter((attribute) => attribute.isGuard())\n .map((attribute) => attribute.getDetails()) as GuardAttributeDetails[];\n const callbacks = node\n .getAttributes()\n .filter((attribute) => !attribute.isGuard())\n .map((attribute) => attribute.getDetails()) as CallbackAttributeDetails[];\n\n // Push the current node into the flattened nodes array.\n flattenedTreeNodes.push({\n id: node.getUid(),\n type: node.getType(),\n caption: node.getName(),\n state: node.getState(),\n guards,\n callbacks,\n args: node.getArguments(),\n parentId: parentUid\n });\n\n // Process each of the nodes children if it is not a leaf node.\n if (!node.isLeafNode()) {\n (node as Composite | Decorator)\n .getChildren()\n .forEach((child) => processNode(child, (node as Composite | Decorator).getUid()));\n }\n };\n\n // Convert the nested node structure into a flattened array of node details.\n processNode(this._rootNode, null);\n\n return flattenedTreeNodes;\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 || rootNodeDefinitions[0].id !== null) {\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 { validateDefinition } from \"./BehaviourTreeDefinitionValidator\";\nimport { convertMDSLToJSON } from \"./mdsl/MDSLDefinitionParser\";\nimport { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport { BehaviourTreeOptions } from \"./BehaviourTreeOptions\";\n\nexport { BehaviourTree, State, convertMDSLToJSON, validateDefinition };\nexport type { FlattenedTreeNode, BehaviourTreeOptions };\n", "/**\n * Enumeration of node state types.\n */\nexport enum State {\n READY = \"mistreevous.ready\",\n RUNNING = \"mistreevous.running\",\n SUCCEEDED = \"mistreevous.succeeded\",\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 {\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\"].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 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 \"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 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 // 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 \"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 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 { 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.map((arg) => arg.value));\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 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", "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 Guard from \"../attributes/guards/Guard\";\nimport GuardPath from \"../attributes/guards/GuardPath\";\nimport GuardUnsatisifedException from \"../attributes/guards/GuardUnsatisifedException\";\n\n/**\n * A base node.\n */\nexport default abstract class Node {\n /**\n * The node uid.\n */\n private readonly uid: string = createNodeUid();\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 args The node argument definitions.\n */\n constructor(private type: string, private attributes: Attribute[], private args: any[]) {}\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected abstract onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 this.state = value;\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 = () => this.attributes;\n\n /**\n * Gets the node arguments.\n */\n getArguments = () => this.args;\n\n /**\n * Gets the node attribute with the specified type, or null if it does not exist.\n */\n getAttribute(type: \"entry\" | \"ENTRY\"): Entry;\n getAttribute(type: \"exit\" | \"EXIT\"): Exit;\n getAttribute(type: \"step\" | \"STEP\"): Step;\n getAttribute(type: string): Attribute {\n return (\n this.getAttributes().filter((decorator) => decorator.type.toUpperCase() === type.toUpperCase())[0] || null\n );\n }\n\n /**\n * Gets the node attributes.\n */\n getGuardAttributes = (): Guard[] => this.getAttributes().filter((decorator) => decorator.isGuard()) as Guard[];\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.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\n }\n\n /**\n * Update the node.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n * @returns The result of the update.\n */\n public update(agent: Agent, options: BehaviourTreeOptions): 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.getAttribute(\"entry\")?.callAgentFunction(agent);\n }\n\n this.getAttribute(\"step\")?.callAgentFunction(agent);\n\n // Do the actual update.\n this.onUpdate(agent, options);\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.getAttribute(\"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/**\n * Create a randomly generated node uid.\n * @returns A randomly generated node uid.\n */\nfunction createNodeUid(): 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 Node from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\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 children The child nodes.\n */\n constructor(type: string, attributes: Attribute[], protected children: Node[]) {\n super(type, attributes, []);\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.getChildren().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.getChildren().forEach((child) => child.abort(agent));\n\n // Reset the state of this node.\n this.reset();\n\n this.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\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 children The child nodes.\n */\n constructor(attributes: Attribute[], children: Node[]) {\n super(\"parallel\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): void {\n // Keep a count of the number of succeeded child nodes.\n let succeededCount = 0;\n\n let hasChildFailed = false;\n\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, options);\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 // The child node has succeeded, keep track of this to determine if all children have.\n succeededCount++;\n\n // The child node succeeded, but we have not finished checking every child node yet.\n continue;\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 hasChildFailed = true;\n\n // There is no need to check the rest of the children.\n break;\n }\n\n // The node should be in the 'RUNNING' state.\n if (child.getState() !== State.RUNNING) {\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 if (hasChildFailed) {\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 } else {\n // If all children have succeeded then this node has also succeeded, otherwise it is still running.\n this.setState(succeededCount === this.children.length ? State.SUCCEEDED : State.RUNNING);\n }\n }\n\n /**\n * Gets the name of the node.\n */\n getName = () => \"PARALLEL\";\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 children The child nodes.\n */\n constructor(attributes: Attribute[], protected children: Node[]) {\n super(\"selector\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 children The child nodes.\n */\n constructor(attributes: Attribute[], protected children: Node[]) {\n super(\"sequence\", attributes, children);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 weights The child node weights.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private weights: number[] | undefined, children: Node[]) {\n super(\"lotto\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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: 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, options);\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 from \"../Node\";\nimport State from \"../../State\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\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 child The child node.\n */\n constructor(type: string, attributes: Attribute[], protected child: Node) {\n super(type, attributes, []);\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.getAttribute(\"exit\")?.callAgentFunction(agent, false, true);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"fail\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"flip\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 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 private iterations: number | null,\n private iterationsMin: number | null,\n private iterationsMax: number | null,\n child: Node\n ) {\n super(\"repeat\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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(options);\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, options);\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 * @param options The behaviour tree options object.\n */\n private setTargetIterationCount = (options: BehaviourTreeOptions) => {\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 options.random === \"function\" ? 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 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 private attempts: number | null,\n private attemptsMin: number | null,\n private attemptsMax: number | null,\n child: Node\n ) {\n super(\"retry\", attributes, 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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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(options);\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, options);\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 * @param options The behaviour tree options object.\n */\n setTargetAttemptCount = (options: BehaviourTreeOptions) => {\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 options.random === \"function\" ? 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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"root\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 child The child node.\n */\n constructor(attributes: Attribute[], child: Node) {\n super(\"succeed\", attributes, child);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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, options);\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 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 actionName The action name.\n * @param actionArguments The array of action argument definitions.\n */\n constructor(attributes: Attribute[], private actionName: string, private actionArguments: any[]) {\n super(\"action\", attributes, actionArguments);\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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 // The user was naughty and threw something.\n throw new Error(`action function '${this.actionName}' threw '${error}'`);\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 * 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 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 conditionName The name of the condition function.\n * @param conditionArguments The array of condition argument definitions.\n */\n constructor(attributes: Attribute[], private conditionName: string, private conditionArguments: any[]) {\n super(\"condition\", attributes, conditionArguments);\n }\n\n /**\n * Called when the node is being updated.\n * @param agent The agent.\n * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 // The user was naughty and threw something.\n throw new Error(`condition function '${this.conditionName}' threw '${error}'`);\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", "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 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 private duration: number | null,\n private durationMin: number | null,\n private durationMax: number | null\n ) {\n super(\"wait\", attributes, []);\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 * @param options The behaviour tree options object.\n */\n protected onUpdate(agent: Agent, options: BehaviourTreeOptions): 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 options.random === \"function\" ? 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 options.getDeltaTime === \"function\") {\n // Get the delta time.\n const deltaTime = 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\nexport type GuardAttributeDetails = {\n /** The name of the condition function that determines whether the guard is satisfied. */\n condition: 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 condition: 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 // The user was naughty and threw something.\n throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`);\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 // The user was naughty and threw something.\n throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`);\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\nexport type CallbackAttributeDetails = {\n /** The name of the agent function that is called. */\n functionName: 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 functionName: 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 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 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\";\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 | 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 * @returns The built and populated root node definitions.\n */\nexport default function buildRootNode(definition: RootNodeDefinition[]): 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) 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 * @returns A node instance based on the specified definition.\n */\nfunction nodeFactory(definition: AnyNodeDefinition, rootNodeDefinitionMap: RootNodeDefinitionMap): 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, nodeFactory(definition.child, rootNodeDefinitionMap));\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 iterations,\n iterationsMin,\n iterationsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap)\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 attempts,\n attemptsMin,\n attemptsMax,\n nodeFactory(definition.child, rootNodeDefinitionMap)\n );\n\n case \"flip\":\n return new Flip(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"succeed\":\n return new Succeed(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"fail\":\n return new Fail(attributes, nodeFactory(definition.child, rootNodeDefinitionMap));\n\n case \"sequence\":\n return new Sequence(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"selector\":\n return new Selector(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"parallel\":\n return new Parallel(\n attributes,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"lotto\":\n return new Lotto(\n attributes,\n definition.weights,\n definition.children.map((child) => nodeFactory(child, rootNodeDefinitionMap))\n );\n\n case \"branch\":\n return nodeFactory(rootNodeDefinitionMap[definition.ref].child, rootNodeDefinitionMap);\n\n case \"action\":\n return new Action(attributes, definition.call, definition.args || []);\n\n case \"condition\":\n return new Condition(attributes, 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, 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) => ({ node, guards: node.getGuardAttributes() }))\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 from \"./nodes/Node\";\nimport Root from \"./nodes/decorator/Root\";\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// Purely for outside inspection of the tree.\nexport type FlattenedTreeNode = {\n id: string;\n type: string;\n caption: string;\n state: AnyState;\n guards: GuardAttributeDetails[];\n callbacks: CallbackAttributeDetails[];\n args: any[];\n parentId: string | null;\n};\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);\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 isRunning() {\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 getState() {\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 step() {\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, this.options);\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 reset() {\n this._rootNode.reset();\n }\n\n /**\n * Gets the flattened details of every node in the tree.\n * @returns The flattened details of every node in the tree.\n */\n getFlattenedNodeDetails(): FlattenedTreeNode[] {\n // Create an empty flattened array of tree nodes.\n const flattenedTreeNodes: FlattenedTreeNode[] = [];\n\n /**\n * Helper function to process a node instance and push details into the flattened tree nodes array.\n * @param node The current node.\n * @param parentUid The UID of the node parent, or null if the node is the main root node.\n */\n const processNode = (node: Node, parentUid: string | null) => {\n // Get the guard and callback attribute details for this node.\n const guards = node\n .getAttributes()\n .filter((attribute) => attribute.isGuard())\n .map((attribute) => attribute.getDetails()) as GuardAttributeDetails[];\n const callbacks = node\n .getAttributes()\n .filter((attribute) => !attribute.isGuard())\n .map((attribute) => attribute.getDetails()) as CallbackAttributeDetails[];\n\n // Push the current node into the flattened nodes array.\n flattenedTreeNodes.push({\n id: node.getUid(),\n type: node.getType(),\n caption: node.getName(),\n state: node.getState(),\n guards,\n callbacks,\n args: node.getArguments(),\n parentId: parentUid\n });\n\n // Process each of the nodes children if it is not a leaf node.\n if (!node.isLeafNode()) {\n (node as Composite | Decorator)\n .getChildren()\n .forEach((child) => processNode(child, (node as Composite | Decorator).getUid()));\n }\n };\n\n // Convert the nested node structure into a flattened array of node details.\n processNode(this._rootNode, null);\n\n return flattenedTreeNodes;\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 || rootNodeDefinitions[0].id !== null) {\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", "createLotto"] } diff --git a/src/attributes/guards/Until.ts b/src/attributes/guards/Until.ts index 4152bc9..542f2a8 100644 --- a/src/attributes/guards/Until.ts +++ b/src/attributes/guards/Until.ts @@ -30,7 +30,24 @@ export default class Until extends Guard { ); } - // Call the condition function to determine whether this guard is satisfied. - return !!!conditionFuncInvoker(this.args); + let conditionFunctionResult; + + try { + // Call the guard condition function to determine the state of this node, the result of which should be a boolean. + conditionFunctionResult = conditionFuncInvoker(this.args); + } catch (error) { + // The user was naughty and threw something. + throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`); + } + + // The result of calling the guard condition function must be a boolean value. + if (typeof conditionFunctionResult !== "boolean") { + throw new Error( + `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'` + ); + } + + // Return whether this guard is satisfied. + return !conditionFunctionResult; }; } diff --git a/src/attributes/guards/While.ts b/src/attributes/guards/While.ts index 13be8dc..c189891 100644 --- a/src/attributes/guards/While.ts +++ b/src/attributes/guards/While.ts @@ -30,7 +30,24 @@ export default class While extends Guard { ); } - // Call the condition function to determine whether this guard is satisfied. - return !!conditionFuncInvoker(this.args); + let conditionFunctionResult; + + try { + // Call the guard condition function to determine the state of this node, the result of which should be a boolean. + conditionFunctionResult = conditionFuncInvoker(this.args); + } catch (error) { + // The user was naughty and threw something. + throw new Error(`guard condition function '${this.getCondition()}' threw '${error}'`); + } + + // The result of calling the guard condition function must be a boolean value. + if (typeof conditionFunctionResult !== "boolean") { + throw new Error( + `expected guard condition function '${this.getCondition()}' to return a boolean but returned '${conditionFunctionResult}'` + ); + } + + // Return whether this guard is satisfied. + return conditionFunctionResult; }; } diff --git a/test/attributes/guards/Until.spec.ts b/test/attributes/guards/Until.spec.ts index 49bf92c..4c4f71e 100644 --- a/test/attributes/guards/Until.spec.ts +++ b/test/attributes/guards/Until.spec.ts @@ -1 +1,316 @@ -describe("An Until guard node attribute", () => {}); +import { assert } from "chai"; +import sinon from "sinon"; + +import { BehaviourTree, State } from "../../../src/index"; +import { RootNodeDefinition } from "../../../src/BehaviourTreeDefinition"; +import { findNode } from "../../TestUtilities"; + +describe("An Until guard node attribute", () => { + describe("on tree initialisation", () => { + describe("will error if no function name is defined", () => { + it("(MDSL)", () => { + const definition = "root { action [noop] until() }"; + assert.throws( + () => new BehaviourTree(definition, {}), + Error, + "invalid definition: expected agent function or registered function name identifier argument for attribute" + ); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "action", + call: "noop", + until: {} as any + } + }; + assert.throws( + () => new BehaviourTree(definition, {}), + Error, + "invalid definition: expected 'call' property for attribute 'until' to be a non-empty string for 'action' node at depth '1'" + ); + }); + }); + }); + + describe("when the node is updated as part of a tree step will call the guard function and", () => { + describe("abort the running node and an child nodes and move them to a FAILED state if the function returns a value of true", () => { + it("(MDSL)", () => { + const definition = `root { sequence until(someCondition, "condition-argument") { action [someAction] exit(onActionExit) } }`; + const agent = { + someAction: () => State.RUNNING, + someCondition: sinon.stub().returns(false), + onActionExit: sinon.stub() + }; + const tree = new BehaviourTree(definition, agent); + + tree.step(); + + assert.isTrue(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "sequence").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action").state, State.RUNNING); + + agent.someCondition.returns(true); + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.isTrue(agent.onActionExit.calledWith(sinon.match({ succeeded: false, aborted: true }))); + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "sequence").state, State.FAILED); + assert.strictEqual(findNode(tree, "action").state, State.READY); + + tree.reset(); + + assert.isFalse(tree.isRunning()); + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "sequence").state, State.READY); + assert.strictEqual(findNode(tree, "action").state, State.READY); + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "sequence").state, State.FAILED); + assert.strictEqual(findNode(tree, "action").state, State.READY); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "sequence", + until: { + call: "someCondition", + args: ["condition-argument"] + }, + children: [ + { + type: "action", + exit: { + call: "onActionExit" + }, + call: "someAction" + } + ] + } + }; + const agent = { + someAction: () => State.RUNNING, + someCondition: sinon.stub().returns(false), + onActionExit: sinon.stub() + }; + const tree = new BehaviourTree(definition, agent); + + tree.step(); + + assert.isTrue(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "sequence").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action").state, State.RUNNING); + + agent.someCondition.returns(true); + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.isTrue(agent.onActionExit.calledWith(sinon.match({ succeeded: false, aborted: true }))); + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "sequence").state, State.FAILED); + assert.strictEqual(findNode(tree, "action").state, State.READY); + + tree.reset(); + + assert.isFalse(tree.isRunning()); + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "sequence").state, State.READY); + assert.strictEqual(findNode(tree, "action").state, State.READY); + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "sequence").state, State.FAILED); + assert.strictEqual(findNode(tree, "action").state, State.READY); + }); + }); + + describe("does nothing if the function returns a value of false", () => { + it("(MDSL)", () => { + const definition = `root { sequence until(someCondition, "condition-argument") { action [someAction] } }`; + const agent = { + someAction: () => State.RUNNING, + someCondition: sinon.stub().returns(false) + }; + const tree = new BehaviourTree(definition, agent); + + tree.step(); + + assert.isTrue(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "sequence").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action").state, State.RUNNING); + + agent.someAction = () => State.SUCCEEDED; + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "sequence").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action").state, State.SUCCEEDED); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "sequence", + until: { + call: "someCondition", + args: ["condition-argument"] + }, + children: [ + { + type: "action", + call: "someAction" + } + ] + } + }; + const agent = { + someAction: () => State.RUNNING, + someCondition: sinon.stub().returns(false) + }; + const tree = new BehaviourTree(definition, agent); + + tree.step(); + + assert.isTrue(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "sequence").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action").state, State.RUNNING); + + agent.someAction = () => State.SUCCEEDED; + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "sequence").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action").state, State.SUCCEEDED); + }); + }); + + describe("throws an error if the guard condition function ", () => { + describe("does not return a boolean value", () => { + it("(MDSL)", () => { + const definition = `root { sequence until(someCondition, "condition-argument") { action [someAction] } }`; + const agent = { + someAction: () => State.RUNNING, + someCondition: () => "invalid-response" + }; + const tree = new BehaviourTree(definition, agent); + + assert.throws( + () => tree.step(), + Error, + "expected guard condition function 'someCondition' to return a boolean but returned 'invalid-response'" + ); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "sequence", + until: { + call: "someCondition", + args: ["condition-argument"] + }, + children: [ + { + type: "action", + call: "someAction" + } + ] + } + }; + const agent = { + someAction: () => State.RUNNING, + someCondition: () => "invalid-response" + }; + const tree = new BehaviourTree(definition, agent); + + assert.throws( + () => tree.step(), + Error, + "expected guard condition function 'someCondition' to return a boolean but returned 'invalid-response'" + ); + }); + }); + + describe("throws an exception", () => { + it("(MDSL)", () => { + const definition = `root { sequence until(someCondition, "condition-argument") { action [someAction] } }`; + const agent = { + someAction: () => State.RUNNING, + someCondition: () => { + throw new Error("some-error"); + } + }; + const tree = new BehaviourTree(definition, agent); + + assert.throws( + () => tree.step(), + Error, + "error stepping tree: guard condition function 'someCondition' threw 'Error: some-error'" + ); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "sequence", + until: { + call: "someCondition", + args: ["condition-argument"] + }, + children: [ + { + type: "action", + call: "someAction" + } + ] + } + }; + const agent = { + someAction: () => State.RUNNING, + someCondition: () => { + throw new Error("some-error"); + } + }; + const tree = new BehaviourTree(definition, agent); + + assert.throws( + () => tree.step(), + Error, + "error stepping tree: guard condition function 'someCondition' threw 'Error: some-error'" + ); + }); + }); + }); + }); +}); diff --git a/test/attributes/guards/While.spec.ts b/test/attributes/guards/While.spec.ts index 2575335..357ea59 100644 --- a/test/attributes/guards/While.spec.ts +++ b/test/attributes/guards/While.spec.ts @@ -1 +1,316 @@ -describe("A While guard node attribute", () => {}); +import { assert } from "chai"; +import sinon from "sinon"; + +import { BehaviourTree, State } from "../../../src/index"; +import { RootNodeDefinition } from "../../../src/BehaviourTreeDefinition"; +import { findNode } from "../../TestUtilities"; + +describe("A While guard node attribute", () => { + describe("on tree initialisation", () => { + describe("will error if no function name is defined", () => { + it("(MDSL)", () => { + const definition = "root { action [noop] while() }"; + assert.throws( + () => new BehaviourTree(definition, {}), + Error, + "invalid definition: expected agent function or registered function name identifier argument for attribute" + ); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "action", + call: "noop", + while: {} as any + } + }; + assert.throws( + () => new BehaviourTree(definition, {}), + Error, + "invalid definition: expected 'call' property for attribute 'while' to be a non-empty string for 'action' node at depth '1'" + ); + }); + }); + }); + + describe("when the node is updated as part of a tree step will call the guard function and", () => { + describe("abort the running node and an child nodes and move them to a FAILED state if the function returns a value of false", () => { + it("(MDSL)", () => { + const definition = `root { sequence while(someCondition, "condition-argument") { action [someAction] exit(onActionExit) } }`; + const agent = { + someAction: () => State.RUNNING, + someCondition: sinon.stub().returns(true), + onActionExit: sinon.stub() + }; + const tree = new BehaviourTree(definition, agent); + + tree.step(); + + assert.isTrue(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "sequence").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action").state, State.RUNNING); + + agent.someCondition.returns(false); + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.isTrue(agent.onActionExit.calledWith(sinon.match({ succeeded: false, aborted: true }))); + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "sequence").state, State.FAILED); + assert.strictEqual(findNode(tree, "action").state, State.READY); + + tree.reset(); + + assert.isFalse(tree.isRunning()); + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "sequence").state, State.READY); + assert.strictEqual(findNode(tree, "action").state, State.READY); + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "sequence").state, State.FAILED); + assert.strictEqual(findNode(tree, "action").state, State.READY); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "sequence", + while: { + call: "someCondition", + args: ["condition-argument"] + }, + children: [ + { + type: "action", + exit: { + call: "onActionExit" + }, + call: "someAction" + } + ] + } + }; + const agent = { + someAction: () => State.RUNNING, + someCondition: sinon.stub().returns(true), + onActionExit: sinon.stub() + }; + const tree = new BehaviourTree(definition, agent); + + tree.step(); + + assert.isTrue(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "sequence").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action").state, State.RUNNING); + + agent.someCondition.returns(false); + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.isTrue(agent.onActionExit.calledWith(sinon.match({ succeeded: false, aborted: true }))); + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "sequence").state, State.FAILED); + assert.strictEqual(findNode(tree, "action").state, State.READY); + + tree.reset(); + + assert.isFalse(tree.isRunning()); + assert.strictEqual(findNode(tree, "root").state, State.READY); + assert.strictEqual(findNode(tree, "sequence").state, State.READY); + assert.strictEqual(findNode(tree, "action").state, State.READY); + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.strictEqual(findNode(tree, "root").state, State.FAILED); + assert.strictEqual(findNode(tree, "sequence").state, State.FAILED); + assert.strictEqual(findNode(tree, "action").state, State.READY); + }); + }); + + describe("does nothing if the function returns a value of true", () => { + it("(MDSL)", () => { + const definition = `root { sequence while(someCondition, "condition-argument") { action [someAction] } }`; + const agent = { + someAction: () => State.RUNNING, + someCondition: sinon.stub().returns(true) + }; + const tree = new BehaviourTree(definition, agent); + + tree.step(); + + assert.isTrue(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "sequence").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action").state, State.RUNNING); + + agent.someAction = () => State.SUCCEEDED; + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "sequence").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action").state, State.SUCCEEDED); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "sequence", + while: { + call: "someCondition", + args: ["condition-argument"] + }, + children: [ + { + type: "action", + call: "someAction" + } + ] + } + }; + const agent = { + someAction: () => State.RUNNING, + someCondition: sinon.stub().returns(true) + }; + const tree = new BehaviourTree(definition, agent); + + tree.step(); + + assert.isTrue(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.RUNNING); + assert.strictEqual(findNode(tree, "sequence").state, State.RUNNING); + assert.strictEqual(findNode(tree, "action").state, State.RUNNING); + + agent.someAction = () => State.SUCCEEDED; + + tree.step(); + + assert.isFalse(tree.isRunning()); + assert.isTrue(agent.someCondition.calledWith("condition-argument")); + assert.strictEqual(findNode(tree, "root").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "sequence").state, State.SUCCEEDED); + assert.strictEqual(findNode(tree, "action").state, State.SUCCEEDED); + }); + }); + + describe("throws an error if the guard condition function ", () => { + describe("does not return a boolean value", () => { + it("(MDSL)", () => { + const definition = `root { sequence while(someCondition, "condition-argument") { action [someAction] } }`; + const agent = { + someAction: () => State.RUNNING, + someCondition: () => "invalid-response" + }; + const tree = new BehaviourTree(definition, agent); + + assert.throws( + () => tree.step(), + Error, + "expected guard condition function 'someCondition' to return a boolean but returned 'invalid-response'" + ); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "sequence", + while: { + call: "someCondition", + args: ["condition-argument"] + }, + children: [ + { + type: "action", + call: "someAction" + } + ] + } + }; + const agent = { + someAction: () => State.RUNNING, + someCondition: () => "invalid-response" + }; + const tree = new BehaviourTree(definition, agent); + + assert.throws( + () => tree.step(), + Error, + "expected guard condition function 'someCondition' to return a boolean but returned 'invalid-response'" + ); + }); + }); + + describe("throws an exception", () => { + it("(MDSL)", () => { + const definition = `root { sequence while(someCondition, "condition-argument") { action [someAction] } }`; + const agent = { + someAction: () => State.RUNNING, + someCondition: () => { + throw new Error("some-error"); + } + }; + const tree = new BehaviourTree(definition, agent); + + assert.throws( + () => tree.step(), + Error, + "error stepping tree: guard condition function 'someCondition' threw 'Error: some-error'" + ); + }); + + it("(JSON)", () => { + const definition: RootNodeDefinition = { + type: "root", + child: { + type: "sequence", + while: { + call: "someCondition", + args: ["condition-argument"] + }, + children: [ + { + type: "action", + call: "someAction" + } + ] + } + }; + const agent = { + someAction: () => State.RUNNING, + someCondition: () => { + throw new Error("some-error"); + } + }; + const tree = new BehaviourTree(definition, agent); + + assert.throws( + () => tree.step(), + Error, + "error stepping tree: guard condition function 'someCondition' threw 'Error: some-error'" + ); + }); + }); + }); + }); +}); diff --git a/test/nodes/leaf/Action.spec.ts b/test/nodes/leaf/Action.spec.ts index e0754a3..7c18e23 100644 --- a/test/nodes/leaf/Action.spec.ts +++ b/test/nodes/leaf/Action.spec.ts @@ -145,7 +145,7 @@ describe("An Action node", () => { const definition = "root { action [doAction] }"; const agent = { doAction: () => { - throw new Error("Disaster!"); + throw new Error("some-error"); } }; const tree = new BehaviourTree(definition, agent); @@ -153,7 +153,7 @@ describe("An Action node", () => { assert.throws( () => tree.step(), Error, - "error stepping tree: action function 'doAction' threw 'Error: Disaster!'" + "error stepping tree: action function 'doAction' threw 'Error: some-error'" ); }); @@ -167,7 +167,7 @@ describe("An Action node", () => { }; const agent = { doAction: () => { - throw new Error("Disaster!"); + throw new Error("some-error"); } }; const tree = new BehaviourTree(definition, agent); @@ -175,7 +175,7 @@ describe("An Action node", () => { assert.throws( () => tree.step(), Error, - "error stepping tree: action function 'doAction' threw 'Error: Disaster!'" + "error stepping tree: action function 'doAction' threw 'Error: some-error'" ); }); });