From acf882317944123a667bd377f14d2b2c4e968dda Mon Sep 17 00:00:00 2001 From: Nikolas Howard Date: Thu, 20 Apr 2023 13:59:05 +0100 Subject: [PATCH 1/4] Updated Wait.ts and added specs --- dist/{agent.d.ts => Agent.d.ts} | 0 ...{behaviourTree.d.ts => BehaviourTree.d.ts} | 0 ...Options.d.ts => BehaviourTreeOptions.d.ts} | 0 dist/{lookup.d.ts => Lookup.d.ts} | 0 ...sBuilder.d.ts => RootAstNodesBuilder.d.ts} | 3 +- dist/{state.d.ts => State.d.ts} | 0 .../{attribute.d.ts => Attribute.d.ts} | 0 .../{callback.d.ts => Callback.d.ts} | 0 .../callbacks/{entry.d.ts => Entry.d.ts} | 0 .../callbacks/{exit.d.ts => Exit.d.ts} | 0 .../callbacks/{step.d.ts => Step.d.ts} | 0 .../guards/{guard.d.ts => Guard.d.ts} | 0 .../guards/{guardPath.d.ts => GuardPath.d.ts} | 0 ...on.d.ts => GuardUnsatisifedException.d.ts} | 0 .../guards/{until.d.ts => Until.d.ts} | 0 .../guards/{while.d.ts => While.d.ts} | 0 dist/attributes/guards/timeout.d.ts | 20 ------ dist/bundle.js | 67 +++++++++++++------ dist/bundle.js.map | 4 +- dist/index.js | 67 +++++++++++++------ dist/index.js.map | 4 +- dist/nodes/{node.d.ts => Node.d.ts} | 0 .../{composite.d.ts => Composite.d.ts} | 0 .../composite/{lotto.d.ts => Lotto.d.ts} | 0 .../{parallel.d.ts => Parallel.d.ts} | 0 .../{selector.d.ts => Selector.d.ts} | 0 .../{sequence.d.ts => Sequence.d.ts} | 0 .../{decorator.d.ts => Decorator.d.ts} | 0 dist/nodes/decorator/{fail.d.ts => Fail.d.ts} | 0 dist/nodes/decorator/{flip.d.ts => Flip.d.ts} | 0 .../decorator/{repeat.d.ts => Repeat.d.ts} | 0 .../decorator/{retry.d.ts => Retry.d.ts} | 0 dist/nodes/decorator/{root.d.ts => Root.d.ts} | 0 .../decorator/{succeed.d.ts => Succeed.d.ts} | 0 dist/nodes/leaf/{action.d.ts => Action.d.ts} | 0 .../leaf/{condition.d.ts => Condition.d.ts} | 0 dist/nodes/leaf/{leaf.d.ts => Leaf.d.ts} | 0 dist/nodes/leaf/{wait.d.ts => Wait.d.ts} | 8 ++- src/RootAstNodesBuilder.ts | 60 +++++++++-------- src/nodes/leaf/Wait.ts | 43 +++++++++--- test/nodes/leaf/wait.test.js | 43 ++++++++++-- 41 files changed, 203 insertions(+), 116 deletions(-) rename dist/{agent.d.ts => Agent.d.ts} (100%) rename dist/{behaviourTree.d.ts => BehaviourTree.d.ts} (100%) rename dist/{behaviourTreeOptions.d.ts => BehaviourTreeOptions.d.ts} (100%) rename dist/{lookup.d.ts => Lookup.d.ts} (100%) rename dist/{rootAstNodesBuilder.d.ts => RootAstNodesBuilder.d.ts} (98%) rename dist/{state.d.ts => State.d.ts} (100%) rename dist/attributes/{attribute.d.ts => Attribute.d.ts} (100%) rename dist/attributes/callbacks/{callback.d.ts => Callback.d.ts} (100%) rename dist/attributes/callbacks/{entry.d.ts => Entry.d.ts} (100%) rename dist/attributes/callbacks/{exit.d.ts => Exit.d.ts} (100%) rename dist/attributes/callbacks/{step.d.ts => Step.d.ts} (100%) rename dist/attributes/guards/{guard.d.ts => Guard.d.ts} (100%) rename dist/attributes/guards/{guardPath.d.ts => GuardPath.d.ts} (100%) rename dist/attributes/guards/{guardUnsatisifedException.d.ts => GuardUnsatisifedException.d.ts} (100%) rename dist/attributes/guards/{until.d.ts => Until.d.ts} (100%) rename dist/attributes/guards/{while.d.ts => While.d.ts} (100%) delete mode 100644 dist/attributes/guards/timeout.d.ts rename dist/nodes/{node.d.ts => Node.d.ts} (100%) rename dist/nodes/composite/{composite.d.ts => Composite.d.ts} (100%) rename dist/nodes/composite/{lotto.d.ts => Lotto.d.ts} (100%) rename dist/nodes/composite/{parallel.d.ts => Parallel.d.ts} (100%) rename dist/nodes/composite/{selector.d.ts => Selector.d.ts} (100%) rename dist/nodes/composite/{sequence.d.ts => Sequence.d.ts} (100%) rename dist/nodes/decorator/{decorator.d.ts => Decorator.d.ts} (100%) rename dist/nodes/decorator/{fail.d.ts => Fail.d.ts} (100%) rename dist/nodes/decorator/{flip.d.ts => Flip.d.ts} (100%) rename dist/nodes/decorator/{repeat.d.ts => Repeat.d.ts} (100%) rename dist/nodes/decorator/{retry.d.ts => Retry.d.ts} (100%) rename dist/nodes/decorator/{root.d.ts => Root.d.ts} (100%) rename dist/nodes/decorator/{succeed.d.ts => Succeed.d.ts} (100%) rename dist/nodes/leaf/{action.d.ts => Action.d.ts} (100%) rename dist/nodes/leaf/{condition.d.ts => Condition.d.ts} (100%) rename dist/nodes/leaf/{leaf.d.ts => Leaf.d.ts} (100%) rename dist/nodes/leaf/{wait.d.ts => Wait.d.ts} (75%) diff --git a/dist/agent.d.ts b/dist/Agent.d.ts similarity index 100% rename from dist/agent.d.ts rename to dist/Agent.d.ts diff --git a/dist/behaviourTree.d.ts b/dist/BehaviourTree.d.ts similarity index 100% rename from dist/behaviourTree.d.ts rename to dist/BehaviourTree.d.ts diff --git a/dist/behaviourTreeOptions.d.ts b/dist/BehaviourTreeOptions.d.ts similarity index 100% rename from dist/behaviourTreeOptions.d.ts rename to dist/BehaviourTreeOptions.d.ts diff --git a/dist/lookup.d.ts b/dist/Lookup.d.ts similarity index 100% rename from dist/lookup.d.ts rename to dist/Lookup.d.ts diff --git a/dist/rootAstNodesBuilder.d.ts b/dist/RootAstNodesBuilder.d.ts similarity index 98% rename from dist/rootAstNodesBuilder.d.ts rename to dist/RootAstNodesBuilder.d.ts index 36f590a..d6973c6 100644 --- a/dist/rootAstNodesBuilder.d.ts +++ b/dist/RootAstNodesBuilder.d.ts @@ -84,7 +84,8 @@ export type ConditionAstNode = LeafAstNode & { export type WaitAstNode = LeafAstNode & { type: "wait"; duration: number | null; - longestDuration: number | null; + durationMin: number | null; + durationMax: number | null; }; export type AnyAstNode = BranchAstNode | CompositeAstNode | LottoAstNode | DecoratorAstNode | RootAstNode | IterableAstNode | LeafAstNode | ActionAstNode | ConditionAstNode | WaitAstNode; /** diff --git a/dist/state.d.ts b/dist/State.d.ts similarity index 100% rename from dist/state.d.ts rename to dist/State.d.ts diff --git a/dist/attributes/attribute.d.ts b/dist/attributes/Attribute.d.ts similarity index 100% rename from dist/attributes/attribute.d.ts rename to dist/attributes/Attribute.d.ts diff --git a/dist/attributes/callbacks/callback.d.ts b/dist/attributes/callbacks/Callback.d.ts similarity index 100% rename from dist/attributes/callbacks/callback.d.ts rename to dist/attributes/callbacks/Callback.d.ts diff --git a/dist/attributes/callbacks/entry.d.ts b/dist/attributes/callbacks/Entry.d.ts similarity index 100% rename from dist/attributes/callbacks/entry.d.ts rename to dist/attributes/callbacks/Entry.d.ts diff --git a/dist/attributes/callbacks/exit.d.ts b/dist/attributes/callbacks/Exit.d.ts similarity index 100% rename from dist/attributes/callbacks/exit.d.ts rename to dist/attributes/callbacks/Exit.d.ts diff --git a/dist/attributes/callbacks/step.d.ts b/dist/attributes/callbacks/Step.d.ts similarity index 100% rename from dist/attributes/callbacks/step.d.ts rename to dist/attributes/callbacks/Step.d.ts diff --git a/dist/attributes/guards/guard.d.ts b/dist/attributes/guards/Guard.d.ts similarity index 100% rename from dist/attributes/guards/guard.d.ts rename to dist/attributes/guards/Guard.d.ts diff --git a/dist/attributes/guards/guardPath.d.ts b/dist/attributes/guards/GuardPath.d.ts similarity index 100% rename from dist/attributes/guards/guardPath.d.ts rename to dist/attributes/guards/GuardPath.d.ts diff --git a/dist/attributes/guards/guardUnsatisifedException.d.ts b/dist/attributes/guards/GuardUnsatisifedException.d.ts similarity index 100% rename from dist/attributes/guards/guardUnsatisifedException.d.ts rename to dist/attributes/guards/GuardUnsatisifedException.d.ts diff --git a/dist/attributes/guards/until.d.ts b/dist/attributes/guards/Until.d.ts similarity index 100% rename from dist/attributes/guards/until.d.ts rename to dist/attributes/guards/Until.d.ts diff --git a/dist/attributes/guards/while.d.ts b/dist/attributes/guards/While.d.ts similarity index 100% rename from dist/attributes/guards/while.d.ts rename to dist/attributes/guards/While.d.ts diff --git a/dist/attributes/guards/timeout.d.ts b/dist/attributes/guards/timeout.d.ts deleted file mode 100644 index 80fd318..0000000 --- a/dist/attributes/guards/timeout.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Agent } from "../../agent"; -import { AnyArgument } from "../../rootAstNodesBuilder"; -import Guard from "./guard"; -/** - * A TIMEOUT guard which is satisfied as long as the given condition remains false. - */ -export default class Timeout extends Guard { - private duration; - /** - * @param duration The duration of the timeout. - * @param args The array of decorator argument definitions. - */ - constructor(duration: number, args: AnyArgument[]); - /** - * Gets whether the guard is satisfied. - * @param agent The agent. - * @returns Whether the guard is satisfied. - */ - isSatisfied: (agent: Agent) => never; -} diff --git a/dist/bundle.js b/dist/bundle.js index 01c25e1..48ac1ae 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -492,21 +492,33 @@ var mistreevous = (() => { // src/nodes/leaf/Wait.ts var Wait = class extends Leaf { - constructor(attributes, duration, longestDuration) { + constructor(attributes, duration, durationMin, durationMax) { super("wait", attributes, []); this.duration = duration; - this.longestDuration = longestDuration; + this.durationMin = durationMin; + this.durationMax = durationMax; } initialUpdateTime = 0; - totalDuration = 0; + totalDuration = null; waitedDuration = 0; onUpdate(agent, options) { if (this.is("mistreevous.ready" /* READY */)) { this.initialUpdateTime = new Date().getTime(); this.waitedDuration = 0; - this.totalDuration = this.longestDuration ? Math.floor(Math.random() * (this.longestDuration - this.duration + 1) + this.duration) : this.duration; + if (this.duration !== null) { + this.totalDuration = this.duration; + } else if (this.durationMin !== null && this.durationMax !== null) { + this.totalDuration = Math.floor( + Math.random() * (this.durationMax - this.durationMin + 1) + this.durationMin + ); + } else { + this.totalDuration = null; + } this.setState("mistreevous.running" /* RUNNING */); } + if (this.totalDuration === null) { + return; + } if (typeof options.getDeltaTime === "function") { const deltaTime = options.getDeltaTime(); if (typeof deltaTime !== "number" || isNaN(deltaTime)) { @@ -520,7 +532,15 @@ var mistreevous = (() => { this.setState("mistreevous.succeeded" /* SUCCEEDED */); } } - getName = () => `WAIT ${this.longestDuration ? this.duration + "ms-" + this.longestDuration + "ms" : this.duration + "ms"}`; + getName = () => { + if (this.duration !== null) { + return `WAIT ${this.duration}ms`; + } else if (this.durationMin !== null && this.durationMax !== null) { + return `WAIT ${this.durationMin}ms-${this.durationMax}ms`; + } else { + return "WAIT"; + } + }; }; // src/nodes/decorator/Decorator.ts @@ -1254,22 +1274,25 @@ var mistreevous = (() => { type: "wait", attributes: [], duration: null, - longestDuration: null, + durationMin: null, + durationMax: null, validate() { - if (this.duration < 0) { - throw new Error("a wait node must have a positive duration"); - } - if (this.longestDuration) { - if (this.longestDuration < 0) { - throw new Error("a wait node must have a positive longest duration if one is defined"); + if (this.duration !== null) { + if (this.duration < 0) { + throw new Error("a wait node must have a positive duration"); } - if (this.duration > this.longestDuration) { - throw new Error("a wait node must not have a shortest duration that exceeds the longest duration"); + } else if (this.durationMin !== null && this.durationMax !== null) { + if (this.durationMin < 0 || this.durationMax < 0) { + throw new Error("a wait node must have a positive minimum and maximum duration"); } + if (this.durationMin > this.durationMax) { + throw new Error("a wait node must not have a minimum duration that exceeds the maximum duration"); + } + } else { } }, createNodeInstance() { - return new Wait(this.attributes, this.duration, this.longestDuration); + return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax); } }), ACTION: () => ({ @@ -1428,18 +1451,18 @@ var mistreevous = (() => { case "WAIT": { const node = ASTNodeFactories.WAIT(); currentScope.push(node); - const durations = getArguments( + const nodeArguments = getArguments( tokens, placeholders, (arg) => arg.type === "number" && !!arg.isInteger, "wait node durations must be integer values" ).map((argument) => argument.value); - if (durations.length === 1) { - node.duration = durations[0]; - } else if (durations.length === 2) { - node.duration = durations[0]; - node.longestDuration = durations[1]; - } else { + if (nodeArguments.length === 1) { + node.duration = nodeArguments[0]; + } else if (nodeArguments.length === 2) { + node.durationMin = nodeArguments[0]; + node.durationMax = nodeArguments[1]; + } else if (nodeArguments.length > 2) { throw new Error("invalid number of wait node duration arguments defined"); } node.attributes = getAttributes(tokens, placeholders); diff --git a/dist/bundle.js.map b/dist/bundle.js.map index dbc2bda..0b4b4d2 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/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/State.ts", "../src/nodes/Node.ts", "../src/nodes/leaf/Leaf.ts", "../src/Lookup.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Parallel.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/Exit.ts", "../src/attributes/callbacks/Step.ts", "../src/RootAstNodesBuilder.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 { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport State from \"./State\";\n\nexport { BehaviourTree, State };\nexport type { FlattenedTreeNode };\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * 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 { Agent } from \"../Agent\";\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\";\nimport { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport { AnyArgument } from \"../RootAstNodesBuilder\";\nimport State, { AnyState } from \"../State\";\nimport Leaf from \"./leaf/Leaf\";\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: AnyArgument[]) {}\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.getType().toUpperCase() === type.toUpperCase())[0] ||\n 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\";\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 { ActionResult, Agent, ExitFunctionArg, FunctionArg, GlobalFunction } from \"./Agent\";\nimport { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\n\n// Exit callbacks receive their own special type of argument.\n// There's probably stricter ways to represent this but it feels overly complex right now.\ntype ExitResultArg = { value: ExitFunctionArg };\nexport type AnyExitArgument = AnyArgument | ExitResultArg;\n\nexport type InvokerFunction = (args: AnyExitArgument[]) => ActionResult;\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 functionTable: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered sub-trees keyed on tree name.\n */\n private static subtreeTable: { [key: string]: RootAstNode } = {};\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.functionTable[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.functionTable[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 foundOnAgent = agent[name];\n if (foundOnAgent && typeof foundOnAgent === \"function\") {\n return (args: AnyExitArgument[]): boolean | ActionResult =>\n foundOnAgent.apply(\n agent,\n args.map((arg) => arg.value)\n );\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.functionTable[name] && typeof this.functionTable[name] === \"function\") {\n return (args: AnyExitArgument[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets the subtree with the specified name.\n * @param name The name of the subtree.\n * @returns The subtree with the specified name.\n */\n static getSubtree(name: string): RootAstNode {\n return this.subtreeTable[name];\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: RootAstNode) {\n this.subtreeTable[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.functionTable[name];\n delete this.subtreeTable[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.functionTable = {};\n this.subtreeTable = {};\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State, { CompleteState } from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 updatePromiseStateResult: CompleteState | 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\n // it resolves, unless there has been a value set as a result of the update promise resolving.\n if (this.isUsingUpdatePromise) {\n // Check whether the update promise has resolved with a state value.\n if (this.updatePromiseStateResult) {\n // Set the state of this node to match the state returned by the promise.\n this.setState(this.updatePromiseStateResult);\n }\n\n return;\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 // 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 const updateResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n\n if (updateResult instanceof Promise) {\n updateResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Check to make sure the result is a valid finished state.\n if (result !== State.SUCCEEDED && result !== 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 pending update promise state result to be processed on next update.\n this.updatePromiseStateResult = result;\n },\n (reason) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Just throw whatever was returned as the rejection argument.\n throw new Error(reason);\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(updateResult);\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(updateResult || 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.updatePromiseStateResult = 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 | boolean) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case undefined:\n return;\n default:\n throw new Error(\n `action '${this.actionName}' 'onUpdate' returned an invalid response, expected an optional State.SUCCEEDED or State.FAILED value to be returned`\n );\n }\n };\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 // Call the condition function to determine the state of this node.\n this.setState(!!conditionFuncInvoker(this.conditionArguments) ? 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, or the earliest if longestDuration is defined.\n * @param longestDuration The longest possible duration in milliseconds that this node will wait to succeed.\n */\n constructor(attributes: Attribute[], private duration: number, private longestDuration: number) {\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 = 0;\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 // If a longestDuration value was defined then we will be randomly picking a duration between the\n // shortest and longest duration. If it was not defined, then we will be just using the duration.\n this.totalDuration = this.longestDuration\n ? Math.floor(Math.random() * (this.longestDuration - this.duration + 1) + this.duration)\n : this.duration;\n\n // The node is now running until we finish waiting.\n this.setState(State.RUNNING);\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 `WAIT ${this.longestDuration ? this.duration + \"ms-\" + this.longestDuration + \"ms\" : this.duration + \"ms\"}`;\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 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 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, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent, 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 ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default repeat node name.\n return \"REPEAT\";\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\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 iterations The number of iterations to repeat the child node, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: number | null,\n child: Node\n ) {\n super(\"retry\", 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the 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 iteration.\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 iteration.\n this.currentIterationCount += 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.iterations !== null) {\n return `RETRY ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default retry node name.\n return \"RETRY\";\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 canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\n } else {\n this.targetIterationCount = null;\n }\n };\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 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\";\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 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 tickets The child node tickets.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private tickets: number[], 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.tickets[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.tickets.length ? `LOTTO [${this.tickets.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 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 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 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 { AnyArgument } from \"../RootAstNodesBuilder\";\nimport Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: AnyArgument[];\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 argument definitions.\n */\n constructor(protected type: string, protected args: AnyArgument[]) {}\n\n /**\n * Gets the type of the attribute.\n */\n getType = () => this.type;\n\n /**\n * Gets the array of attribute argument definitions.\n */\n getArguments = () => this.args;\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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, { AnyExitArgument } from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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([{ value: { succeeded: isSuccess, aborted: isAborted } }, ...this.args]);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Root from \"./nodes/decorator/Root\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Node from \"./nodes/Node\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Callback from \"./attributes/callbacks/Callback\";\nimport Guard from \"./attributes/guards/Guard\";\nimport Attribute from \"./attributes/Attribute\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Leaf from \"./nodes/leaf/Leaf\";\n\nexport type Argument = {\n value: T;\n type: string; // Used for validation.\n};\ntype NullArgument = Argument & {\n type: \"null\";\n};\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\ntype NumberArgument = Argument & {\n type: \"number\";\n isInteger: boolean; // Used for validation.\n};\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\nexport type AnyArgument =\n | NullArgument\n | BooleanArgument\n | NumberArgument\n | StringPlaceholderArgument\n | IdentifierArgument;\n\n/**\n * The node attribute factories.\n */\nconst AttributeFactories: {\n [key: string]: (functionName: string, attributeArguments: AnyArgument[]) => Callback | Guard;\n} = {\n WHILE: (condition: string, attributeArguments: AnyArgument[]) => new While(condition, attributeArguments),\n UNTIL: (condition: string, attributeArguments: AnyArgument[]) => new Until(condition, attributeArguments),\n ENTRY: (functionName: string, attributeArguments: AnyArgument[]) => new Entry(functionName, attributeArguments),\n EXIT: (functionName: string, attributeArguments: AnyArgument[]) => new Exit(functionName, attributeArguments),\n STEP: (functionName: string, attributeArguments: AnyArgument[]) => new Step(functionName, attributeArguments)\n};\n\ntype Validatable = {\n children?: AstNode[];\n validate: (depth: number) => void;\n};\n\ntype NodeInstanceCreator = (\n namedRootNodeProvider: (name: string) => RootAstNode,\n visitedBranches: string[]\n) => T;\n\nexport type AstNode = Validatable & {\n type: string;\n createNodeInstance: NodeInstanceCreator;\n};\n\nexport type LeafAstNode = AstNode & {\n type: \"action\" | \"condition\" | \"wait\";\n attributes: Attribute[];\n};\n\nexport type CompositeAstNode = AstNode & {\n type: \"lotto\" | \"parallel\" | \"selector\" | \"sequence\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type DecoratorAstNode = AstNode & {\n type: \"fail\" | \"flip\" | \"repeat\" | \"retry\" | \"root\" | \"succeed\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type BranchAstNode = AstNode & {\n type: \"branch\";\n branchName: \"\" | string;\n};\n\nexport type LottoAstNode = CompositeAstNode & {\n type: \"lotto\";\n tickets: number[];\n};\n\nexport type RootAstNode = DecoratorAstNode & {\n type: \"root\";\n name: null | string;\n};\n\nexport type IterableAstNode = DecoratorAstNode & {\n type: \"repeat\" | \"retry\";\n iterations: null | number;\n maximumIterations: null | number;\n};\n\nexport type ActionAstNode = LeafAstNode & {\n type: \"action\";\n actionName: string;\n actionArguments: AnyArgument[];\n};\n\nexport type ConditionAstNode = LeafAstNode & {\n type: \"condition\";\n conditionName: string;\n conditionArguments: AnyArgument[];\n};\n\nexport type WaitAstNode = LeafAstNode & {\n type: \"wait\";\n duration: number | null;\n longestDuration: number | null;\n};\n\nexport type AnyAstNode =\n | BranchAstNode\n | CompositeAstNode\n | LottoAstNode\n | DecoratorAstNode\n | RootAstNode\n | IterableAstNode\n | LeafAstNode\n | ActionAstNode\n | ConditionAstNode\n | WaitAstNode;\n\n/**\n * The AST node factories.\n */\nconst ASTNodeFactories = {\n ROOT: (): RootAstNode => ({\n type: \"root\",\n attributes: [],\n name: null,\n children: [],\n validate(depth: number) {\n // A root node cannot be the child of another node.\n if (depth > 1) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // A root node must have a single child node.\n if (this.children.length !== 1) {\n throw new Error(\"a root node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Root(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n BRANCH: (): BranchAstNode => ({\n type: \"branch\",\n branchName: \"\",\n validate() {},\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n // Try to find the root node with a matching branch name.\n const targetRootNode = namedRootNodeProvider(this.branchName);\n\n // If we have already visited this branch then we have a circular dependency.\n if (visitedBranches.indexOf(this.branchName) !== -1) {\n throw new Error(`circular dependency found in branch node references for branch '${this.branchName}'`);\n }\n\n // If we have a target root node, then the node instance we want will be the first and only child of the referenced root node.\n if (targetRootNode) {\n return targetRootNode\n .createNodeInstance(namedRootNodeProvider, visitedBranches.concat(this.branchName))\n .getChildren()[0];\n } else {\n throw new Error(`branch references root node '${this.branchName}' which has not been defined`);\n }\n }\n }),\n SELECTOR: (): CompositeAstNode => ({\n type: \"selector\",\n attributes: [],\n children: [],\n validate() {\n // A selector node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a selector node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Selector(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n SEQUENCE: (): CompositeAstNode => ({\n type: \"sequence\",\n attributes: [],\n children: [],\n validate() {\n // A sequence node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a sequence node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Sequence(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n PARALLEL: (): CompositeAstNode => ({\n type: \"parallel\",\n attributes: [],\n children: [],\n validate() {\n // A parallel node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a parallel node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Parallel(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n LOTTO: (): LottoAstNode => ({\n type: \"lotto\",\n attributes: [],\n children: [],\n tickets: [],\n validate() {\n // A lotto node must have at least a single node.\n if (this.children!.length < 1) {\n throw new Error(\"a lotto node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Lotto(\n this.attributes,\n this.tickets!,\n this.children!.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n REPEAT: (): IterableAstNode => ({\n type: \"repeat\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A repeat node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a repeat node must have a single child\");\n }\n\n // A repeat node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A repeat node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a repeat node must have a positive maximum iterations count if defined\");\n }\n\n // A repeat node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a repeat node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Repeat(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n RETRY: (): IterableAstNode => ({\n type: \"retry\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A retry node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a retry node must have a single child\");\n }\n\n // A retry node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a retry node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A retry node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a retry node must have a positive maximum iterations count if defined\");\n }\n\n // A retry node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a retry node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Retry(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FLIP: (): DecoratorAstNode => ({\n type: \"flip\",\n attributes: [],\n children: [],\n validate() {\n // A flip node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a flip node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Flip(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n SUCCEED: (): DecoratorAstNode => ({\n type: \"succeed\",\n attributes: [],\n children: [],\n validate() {\n // A succeed node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a succeed node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Succeed(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FAIL: (): DecoratorAstNode => ({\n type: \"fail\",\n attributes: [],\n children: [],\n validate() {\n // A fail node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a fail node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Fail(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n WAIT: (): WaitAstNode => ({\n type: \"wait\",\n attributes: [],\n duration: null,\n longestDuration: null,\n validate() {\n // A wait node must have a positive duration.\n if (this.duration! < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.longestDuration) {\n // A wait node must have a positive longest duration.\n if (this.longestDuration < 0) {\n throw new Error(\"a wait node must have a positive longest duration if one is defined\");\n }\n\n // A wait node must not have a duration that exceeds the longest duration.\n if (this.duration! > this.longestDuration) {\n throw new Error(\"a wait node must not have a shortest duration that exceeds the longest duration\");\n }\n }\n },\n createNodeInstance() {\n return new Wait(this.attributes, this.duration!, this.longestDuration!);\n }\n }),\n ACTION: (): ActionAstNode => ({\n type: \"action\",\n attributes: [],\n actionName: \"\",\n actionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Action(this.attributes, this.actionName!, this.actionArguments!);\n }\n }),\n CONDITION: (): ConditionAstNode => ({\n type: \"condition\",\n attributes: [],\n conditionName: \"\",\n conditionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Condition(this.attributes, this.conditionName!, this.conditionArguments!);\n }\n })\n};\n\ntype OtherAstNodes = AstNode[];\n\n/**\n * Create an array of root AST nodes based on the given definition.\n * @param definition The definition to parse the AST nodes from.\n * @returns The base definition AST nodes.\n */\nexport default function buildRootASTNodes(definition: string): RootAstNode[] {\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 // Convert the processed definition (with substituted string literals) into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\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 a stack of node children arrays, starting with a definition scope.\n const stack: [RootAstNode[], ...OtherAstNodes[]] = [[]];\n const rootScope = stack[0];\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 const currentScope = stack[stack.length - 1] as OtherAstNodes;\n\n // How we create the next AST token depends on the current raw token value.\n switch (token!.toUpperCase()) {\n case \"ROOT\": {\n // Create a ROOT AST node.\n const node = ASTNodeFactories.ROOT();\n\n // Push the ROOT node into the current scope.\n rootScope.push(node);\n\n // We may have a root node name defined as an argument.\n if (tokens[0] === \"[\") {\n const rootArguments = getArguments(tokens, placeholders);\n\n // We should have only a single argument that is not an empty string for a root node, which is the root name identifier.\n if (rootArguments.length === 1 && rootArguments[0].type === \"identifier\") {\n // The root name will be the first and only node argument.\n node.name = rootArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new ROOT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"BRANCH\": {\n // Create a BRANCH AST node.\n const node = ASTNodeFactories.BRANCH();\n\n // Push the BRANCH node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a branch name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // The branch name will be defined as a node argument.\n const branchArguments = getArguments(tokens, placeholders);\n\n // We should have only a single identifer argument for a branch node, which is the branch name.\n if (branchArguments.length === 1 && branchArguments[0].type === \"identifier\") {\n // The branch name will be the first and only node argument.\n node.branchName = branchArguments[0].value as string;\n } else {\n throw new Error(\"expected single branch name argument\");\n }\n break;\n }\n\n case \"SELECTOR\": {\n // Create a SELECTOR AST node.\n const node = ASTNodeFactories.SELECTOR();\n\n // Push the SELECTOR node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SELECTOR nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SEQUENCE\": {\n // Create a SEQUENCE AST node.\n const node = ASTNodeFactories.SEQUENCE();\n\n // Push the SEQUENCE node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SEQUENCE nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"PARALLEL\": {\n // Create a PARALLEL AST node.\n const node = ASTNodeFactories.PARALLEL();\n\n // Push the PARALLEL node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new PARALLEL nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"LOTTO\": {\n // Create a LOTTO AST node.\n const node = ASTNodeFactories.LOTTO();\n\n // Push the LOTTO node into the current scope.\n currentScope.push(node);\n\n // If the next token is a '[' character then some ticket counts have been defined as arguments.\n if (tokens[0] === \"[\") {\n // Get the ticket count arguments, each argument must be a number.\n node.tickets = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"lotto node ticket counts must be integer values\"\n ).map((argument) => argument.value as number);\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new LOTTO nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"CONDITION\": {\n // Create a CONDITION AST node.\n const node = ASTNodeFactories.CONDITION();\n\n // Push the CONDITION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a condition function name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Grab the condition node arguments.\n const conditionArguments = getArguments(tokens, placeholders);\n\n // We should have at least a single identifier argument for a condition node, which is the condition function name.\n if (conditionArguments.length && conditionArguments[0].type === \"identifier\") {\n // The condition function name will be the first node argument.\n node.conditionName = conditionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n conditionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid condition node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the condition name identifier will be treated as condition function arguments.\n node.conditionArguments = conditionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"FLIP\": {\n // Create a FLIP AST node.\n const node = ASTNodeFactories.FLIP();\n\n // Push the Flip node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new FLIP nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SUCCEED\": {\n // Create a SUCCEED AST node.\n const node = ASTNodeFactories.SUCCEED();\n\n // Push the Succeed node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Succeed nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"FAIL\": {\n // Create a FAIL AST node.\n const node = ASTNodeFactories.FAIL();\n\n // Push the Fail node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Fail nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"WAIT\": {\n // Create a WAIT AST node.\n const node = ASTNodeFactories.WAIT();\n\n // Push the WAIT node into the current scope.\n currentScope.push(node);\n\n // Get the duration and potential longest duration of the wait.\n const durations = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"wait node durations must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two durations.\n if (durations.length === 1) {\n // A static duration was defined.\n node.duration = durations[0] as number;\n } else if (durations.length === 2) {\n // A shortest and longest duration was defined.\n node.duration = durations[0] as number;\n node.longestDuration = durations[1] as number;\n } else {\n // An incorrect number of durations was defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"REPEAT\": {\n // Create a REPEAT AST node.\n const node = ASTNodeFactories.REPEAT();\n\n // Push the REPEAT node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"repeat node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\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 // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new REPEAT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"RETRY\": {\n // Create a RETRY AST node.\n const node = ASTNodeFactories.RETRY();\n\n // Push the RETRY node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"retry node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of retry node iteration count arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new RETRY nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"ACTION\": {\n // Create a ACTION AST node.\n const node = ASTNodeFactories.ACTION();\n\n // Push the ACTION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require an action name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // The action name will be defined as a node argument.\n const actionArguments = getArguments(tokens, placeholders);\n\n // We should have at least one identifer argument for an action node, which is the action name.\n if (actionArguments.length && actionArguments[0].type === \"identifier\") {\n // The action name will be the first and only node argument.\n node.actionName = actionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n actionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid action node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the action name identifier will be treated as action function arguments.\n node.actionArguments = actionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope.\n stack.pop();\n break;\n }\n\n default: {\n throw new Error(\"unexpected token: \" + token);\n }\n }\n }\n\n // A function to recursively validate each of the nodes in the AST.\n const validateASTNode = (node: Validatable, depth: number): void => {\n // Validate the node.\n node.validate(depth);\n\n // Validate each child of the node.\n (node.children || []).forEach((child) => validateASTNode(child, depth + 1));\n };\n\n // Start node validation from the definition root.\n validateASTNode(\n {\n children: stack[0] as RootAstNode[],\n validate(this: { children: RootAstNode[] }) {\n // We must have at least one node defined as the definition scope, which should be a root node.\n if (this.children.length === 0) {\n throw new Error(\"expected root node to have been defined\");\n }\n\n // Each node at the base of the definition scope MUST be a root node.\n for (const definitionLevelNode of this.children) {\n if (definitionLevelNode.type !== \"root\") {\n throw new Error(\"expected root node at base of definition\");\n }\n }\n\n // Exactly one root node must not have a name defined. This will be the main root, others will have to be referenced via branch nodes.\n if (this.children.filter((definitionLevelNode) => definitionLevelNode.name === null).length !== 1) {\n throw new Error(\"expected single unnamed root node at base of definition to act as main root\");\n }\n\n // No two named root nodes can have matching names.\n const rootNodeNames: string[] = [];\n for (const definitionLevelNode of this.children) {\n if (rootNodeNames.indexOf(definitionLevelNode.name!) !== -1) {\n throw new Error(`multiple root nodes found with duplicate name '${definitionLevelNode.name}'`);\n } else {\n rootNodeNames.push(definitionLevelNode.name!);\n }\n }\n }\n },\n 0\n );\n\n // Return the root AST nodes.\n return stack[0];\n}\n\n/**\n * Pop the next raw token off of the stack and throw an error if it wasn't the expected one.\n * @param tokens The array of remaining 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 */\nfunction popAndCheck(tokens: string[], expected: string | string[]) {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token.\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 // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = ([] as string[])\n .concat(expected)\n .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 = ([] as string[])\n .concat(expected)\n .map((item) => \"'\" + item + \"'\")\n .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\ntype Placeholders = { [key: string]: string };\n\n/**\n * Pull an argument definition list off of the token stack.\n * @param tokens The array of remaining tokens.\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 The argument definition list.\n */\nfunction getArguments(\n tokens: string[],\n stringArgumentPlaceholders: Placeholders,\n argumentValidator?: (arg: AnyArgument) => boolean,\n validationFailedMessage?: string\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 closer = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n const argumentList: AnyArgument[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closer) {\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 // Try to validate the argument.\n if (argumentValidator && !argumentValidator(argumentDefinition)) {\n throw new Error(validationFailedMessage);\n }\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, closer);\n\n // Return the argument list.\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: Placeholders): 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\n/**\n * Pull any attributes off of the token stack.\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 array of attributes defined by any directly following tokens.\n */\nfunction getAttributes(tokens: string[], stringArgumentPlaceholders: Placeholders) {\n // Create an array to hold any attributes found.\n const attributes: Attribute[] = [];\n\n // Keep track of names of attribute that we have found on the token stack, as we cannot have duplicates.\n const attributesFound: string[] = [];\n\n // Try to get the attribute factory for the next token.\n let attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n\n // Pull attribute tokens off of the tokens stack until we have no more.\n while (attributeFactory) {\n // Check to make sure that we have not already created a attribute of this type for this node.\n if (attributesFound.indexOf(tokens[0].toUpperCase()) !== -1) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Add the current attribute type to our array of found attributes.\n attributesFound.push(tokens.shift()!.toUpperCase());\n\n // Grab any attribute arguments.\n const attributeArguments = getArguments(tokens, stringArgumentPlaceholders);\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeArguments.length === 0 || attributeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected agent function name identifier argument for attribute\");\n }\n\n // Grab the first attribute which is an identifier that will reference an agent function.\n const attributeFunctionName = attributeArguments.shift()! as IdentifierArgument;\n\n // Any remaining attribute arguments 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 and add it to the array of attributes found.\n attributes.push(attributeFactory(attributeFunctionName.value, attributeArguments));\n\n // Try to get the next attribute name token, as there could be multiple.\n attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n }\n\n return attributes;\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 */\nfunction substituteStringLiterals(definition: string): {\n placeholders: { [key: string]: string };\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: Placeholders = {};\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 */\nfunction 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 GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport buildRootASTNodes, { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\nimport 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\";\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: AnyArgument[];\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 public readonly rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition.\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(definition: string, private agent: Agent, private options: BehaviourTreeOptions = {}) {\n // The tree definition must be defined and a valid string.\n if (typeof definition !== \"string\") {\n throw new Error(\"the tree definition must be a string\");\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 defined and not null\");\n }\n\n // Parse the behaviour tree definition, create the populated tree of behaviour tree nodes, and get the root.\n this.rootNode = BehaviourTree.createRootNode(definition);\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) {\n if (typeof value === \"function\") {\n // We are going to register a action/condition/guard/callback function.\n Lookup.setFunc(name, value);\n } else if (typeof value === \"string\") {\n // We are going to register a subtree.\n let rootASTNodes: RootAstNode[];\n\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n rootASTNodes = buildRootASTNodes(value);\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error registering definition: ${(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 (rootASTNodes.length != 1 || rootASTNodes[0].name !== null) {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n Lookup.setSubtree(name, rootASTNodes[0]);\n } else {\n throw new Error(\"unexpected value, expected string 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 /**\n * Parses a behaviour tree definition and creates a tree of behaviour tree nodes.\n * @param {string} definition The behaviour tree definition.\n * @returns The root behaviour tree node.\n */\n private static createRootNode(definition: string): Root {\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n const rootASTNodes = buildRootASTNodes(definition);\n\n // Create a symbol to use as the main root key in our root node mapping.\n const mainRootNodeKey = Symbol(\"__root__\");\n\n // Create a mapping of root node names to root AST tokens. The main root node will have a key of Symbol(\"__root__\").\n const rootNodeMap: { [key: string | symbol]: RootAstNode } = {};\n for (const rootASTNode of rootASTNodes) {\n rootNodeMap[rootASTNode.name === null ? mainRootNodeKey : rootASTNode.name!] = rootASTNode;\n }\n\n // Convert the AST to our actual tree and get the root node.\n const rootNode: Root = rootNodeMap[mainRootNodeKey].createNodeInstance(\n // Create a provider for named root nodes that are part of our definition or have been registered. Prioritising the former.\n (name: string): RootAstNode => (rootNodeMap[name] ? rootNodeMap[name] : Lookup.getSubtree(name)),\n []\n );\n\n // Set a guard path on every leaf of the tree to evaluate as part of its update.\n BehaviourTree.applyLeafNodeGuardPaths(rootNode);\n\n // Return the root node.\n return rootNode;\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error parsing tree: ${(exception as Error).message}\\n${(exception as Error).stack}`);\n }\n }\n\n /**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param rootNode The main root tree node.\n */\n private static applyLeafNodeGuardPaths(rootNode: 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([], rootNode);\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}\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 { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport State from \"./State\";\n\nexport { BehaviourTree, State };\nexport type { FlattenedTreeNode };\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * 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 { Agent } from \"../Agent\";\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\";\nimport { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport { AnyArgument } from \"../RootAstNodesBuilder\";\nimport State, { AnyState } from \"../State\";\nimport Leaf from \"./leaf/Leaf\";\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: AnyArgument[]) {}\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.getType().toUpperCase() === type.toUpperCase())[0] ||\n 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\";\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 { ActionResult, Agent, ExitFunctionArg, FunctionArg, GlobalFunction } from \"./Agent\";\nimport { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\n\n// Exit callbacks receive their own special type of argument.\n// There's probably stricter ways to represent this but it feels overly complex right now.\ntype ExitResultArg = { value: ExitFunctionArg };\nexport type AnyExitArgument = AnyArgument | ExitResultArg;\n\nexport type InvokerFunction = (args: AnyExitArgument[]) => ActionResult;\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 functionTable: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered sub-trees keyed on tree name.\n */\n private static subtreeTable: { [key: string]: RootAstNode } = {};\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.functionTable[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.functionTable[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 foundOnAgent = agent[name];\n if (foundOnAgent && typeof foundOnAgent === \"function\") {\n return (args: AnyExitArgument[]): boolean | ActionResult =>\n foundOnAgent.apply(\n agent,\n args.map((arg) => arg.value)\n );\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.functionTable[name] && typeof this.functionTable[name] === \"function\") {\n return (args: AnyExitArgument[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets the subtree with the specified name.\n * @param name The name of the subtree.\n * @returns The subtree with the specified name.\n */\n static getSubtree(name: string): RootAstNode {\n return this.subtreeTable[name];\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: RootAstNode) {\n this.subtreeTable[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.functionTable[name];\n delete this.subtreeTable[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.functionTable = {};\n this.subtreeTable = {};\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State, { CompleteState } from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 updatePromiseStateResult: CompleteState | 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\n // it resolves, unless there has been a value set as a result of the update promise resolving.\n if (this.isUsingUpdatePromise) {\n // Check whether the update promise has resolved with a state value.\n if (this.updatePromiseStateResult) {\n // Set the state of this node to match the state returned by the promise.\n this.setState(this.updatePromiseStateResult);\n }\n\n return;\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 // 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 const updateResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n\n if (updateResult instanceof Promise) {\n updateResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Check to make sure the result is a valid finished state.\n if (result !== State.SUCCEEDED && result !== 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 pending update promise state result to be processed on next update.\n this.updatePromiseStateResult = result;\n },\n (reason) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Just throw whatever was returned as the rejection argument.\n throw new Error(reason);\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(updateResult);\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(updateResult || 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.updatePromiseStateResult = 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 | boolean) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case undefined:\n return;\n default:\n throw new Error(\n `action '${this.actionName}' 'onUpdate' returned an invalid response, expected an optional State.SUCCEEDED or State.FAILED value to be returned`\n );\n }\n };\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 // Call the condition function to determine the state of this node.\n this.setState(!!conditionFuncInvoker(this.conditionArguments) ? 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, or the earliest if longestDuration is defined.\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 this.totalDuration = Math.floor(\n Math.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 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 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 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, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent, 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 ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default repeat node name.\n return \"REPEAT\";\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\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 iterations The number of iterations to repeat the child node, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: number | null,\n child: Node\n ) {\n super(\"retry\", 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the 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 iteration.\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 iteration.\n this.currentIterationCount += 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.iterations !== null) {\n return `RETRY ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default retry node name.\n return \"RETRY\";\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 canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\n } else {\n this.targetIterationCount = null;\n }\n };\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 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\";\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 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 tickets The child node tickets.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private tickets: number[], 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.tickets[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.tickets.length ? `LOTTO [${this.tickets.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 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 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 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 { AnyArgument } from \"../RootAstNodesBuilder\";\nimport Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: AnyArgument[];\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 argument definitions.\n */\n constructor(protected type: string, protected args: AnyArgument[]) {}\n\n /**\n * Gets the type of the attribute.\n */\n getType = () => this.type;\n\n /**\n * Gets the array of attribute argument definitions.\n */\n getArguments = () => this.args;\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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, { AnyExitArgument } from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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([{ value: { succeeded: isSuccess, aborted: isAborted } }, ...this.args]);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Root from \"./nodes/decorator/Root\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Node from \"./nodes/Node\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Callback from \"./attributes/callbacks/Callback\";\nimport Guard from \"./attributes/guards/Guard\";\nimport Attribute from \"./attributes/Attribute\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Leaf from \"./nodes/leaf/Leaf\";\n\nexport type Argument = {\n value: T;\n type: string; // Used for validation.\n};\ntype NullArgument = Argument & {\n type: \"null\";\n};\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\ntype NumberArgument = Argument & {\n type: \"number\";\n isInteger: boolean; // Used for validation.\n};\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\nexport type AnyArgument =\n | NullArgument\n | BooleanArgument\n | NumberArgument\n | StringPlaceholderArgument\n | IdentifierArgument;\n\n/**\n * The node attribute factories.\n */\nconst AttributeFactories: {\n [key: string]: (functionName: string, attributeArguments: AnyArgument[]) => Callback | Guard;\n} = {\n WHILE: (condition: string, attributeArguments: AnyArgument[]) => new While(condition, attributeArguments),\n UNTIL: (condition: string, attributeArguments: AnyArgument[]) => new Until(condition, attributeArguments),\n ENTRY: (functionName: string, attributeArguments: AnyArgument[]) => new Entry(functionName, attributeArguments),\n EXIT: (functionName: string, attributeArguments: AnyArgument[]) => new Exit(functionName, attributeArguments),\n STEP: (functionName: string, attributeArguments: AnyArgument[]) => new Step(functionName, attributeArguments)\n};\n\ntype Validatable = {\n children?: AstNode[];\n validate: (depth: number) => void;\n};\n\ntype NodeInstanceCreator = (\n namedRootNodeProvider: (name: string) => RootAstNode,\n visitedBranches: string[]\n) => T;\n\nexport type AstNode = Validatable & {\n type: string;\n createNodeInstance: NodeInstanceCreator;\n};\n\nexport type LeafAstNode = AstNode & {\n type: \"action\" | \"condition\" | \"wait\";\n attributes: Attribute[];\n};\n\nexport type CompositeAstNode = AstNode & {\n type: \"lotto\" | \"parallel\" | \"selector\" | \"sequence\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type DecoratorAstNode = AstNode & {\n type: \"fail\" | \"flip\" | \"repeat\" | \"retry\" | \"root\" | \"succeed\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type BranchAstNode = AstNode & {\n type: \"branch\";\n branchName: \"\" | string;\n};\n\nexport type LottoAstNode = CompositeAstNode & {\n type: \"lotto\";\n tickets: number[];\n};\n\nexport type RootAstNode = DecoratorAstNode & {\n type: \"root\";\n name: null | string;\n};\n\nexport type IterableAstNode = DecoratorAstNode & {\n type: \"repeat\" | \"retry\";\n iterations: null | number;\n maximumIterations: null | number;\n};\n\nexport type ActionAstNode = LeafAstNode & {\n type: \"action\";\n actionName: string;\n actionArguments: AnyArgument[];\n};\n\nexport type ConditionAstNode = LeafAstNode & {\n type: \"condition\";\n conditionName: string;\n conditionArguments: AnyArgument[];\n};\n\nexport type WaitAstNode = LeafAstNode & {\n type: \"wait\";\n duration: number | null;\n durationMin: number | null;\n durationMax: number | null;\n};\n\nexport type AnyAstNode =\n | BranchAstNode\n | CompositeAstNode\n | LottoAstNode\n | DecoratorAstNode\n | RootAstNode\n | IterableAstNode\n | LeafAstNode\n | ActionAstNode\n | ConditionAstNode\n | WaitAstNode;\n\n/**\n * The AST node factories.\n */\nconst ASTNodeFactories = {\n ROOT: (): RootAstNode => ({\n type: \"root\",\n attributes: [],\n name: null,\n children: [],\n validate(depth: number) {\n // A root node cannot be the child of another node.\n if (depth > 1) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // A root node must have a single child node.\n if (this.children.length !== 1) {\n throw new Error(\"a root node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Root(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n BRANCH: (): BranchAstNode => ({\n type: \"branch\",\n branchName: \"\",\n validate() {},\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n // Try to find the root node with a matching branch name.\n const targetRootNode = namedRootNodeProvider(this.branchName);\n\n // If we have already visited this branch then we have a circular dependency.\n if (visitedBranches.indexOf(this.branchName) !== -1) {\n throw new Error(`circular dependency found in branch node references for branch '${this.branchName}'`);\n }\n\n // If we have a target root node, then the node instance we want will be the first and only child of the referenced root node.\n if (targetRootNode) {\n return targetRootNode\n .createNodeInstance(namedRootNodeProvider, visitedBranches.concat(this.branchName))\n .getChildren()[0];\n } else {\n throw new Error(`branch references root node '${this.branchName}' which has not been defined`);\n }\n }\n }),\n SELECTOR: (): CompositeAstNode => ({\n type: \"selector\",\n attributes: [],\n children: [],\n validate() {\n // A selector node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a selector node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Selector(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n SEQUENCE: (): CompositeAstNode => ({\n type: \"sequence\",\n attributes: [],\n children: [],\n validate() {\n // A sequence node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a sequence node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Sequence(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n PARALLEL: (): CompositeAstNode => ({\n type: \"parallel\",\n attributes: [],\n children: [],\n validate() {\n // A parallel node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a parallel node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Parallel(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n LOTTO: (): LottoAstNode => ({\n type: \"lotto\",\n attributes: [],\n children: [],\n tickets: [],\n validate() {\n // A lotto node must have at least a single node.\n if (this.children!.length < 1) {\n throw new Error(\"a lotto node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Lotto(\n this.attributes,\n this.tickets!,\n this.children!.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n REPEAT: (): IterableAstNode => ({\n type: \"repeat\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A repeat node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a repeat node must have a single child\");\n }\n\n // A repeat node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A repeat node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a repeat node must have a positive maximum iterations count if defined\");\n }\n\n // A repeat node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a repeat node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Repeat(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n RETRY: (): IterableAstNode => ({\n type: \"retry\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A retry node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a retry node must have a single child\");\n }\n\n // A retry node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a retry node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A retry node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a retry node must have a positive maximum iterations count if defined\");\n }\n\n // A retry node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a retry node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Retry(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FLIP: (): DecoratorAstNode => ({\n type: \"flip\",\n attributes: [],\n children: [],\n validate() {\n // A flip node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a flip node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Flip(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n SUCCEED: (): DecoratorAstNode => ({\n type: \"succeed\",\n attributes: [],\n children: [],\n validate() {\n // A succeed node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a succeed node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Succeed(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FAIL: (): DecoratorAstNode => ({\n type: \"fail\",\n attributes: [],\n children: [],\n validate() {\n // A fail node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a fail node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Fail(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n WAIT: (): WaitAstNode => ({\n type: \"wait\",\n attributes: [],\n duration: null,\n durationMin: null,\n durationMax: null,\n validate() {\n if (this.duration !== null) {\n // If an explict duration was defined then it must be a positive number.\n if (this.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // A wait node must have a positive min and max duration.\n if (this.durationMin < 0 || this.durationMax < 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 (this.durationMin > this.durationMax) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else {\n // If we have no explicit duration or duration bounds set then we are dealing with a wait node that waits indefinitely.\n }\n },\n createNodeInstance() {\n return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax);\n }\n }),\n ACTION: (): ActionAstNode => ({\n type: \"action\",\n attributes: [],\n actionName: \"\",\n actionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Action(this.attributes, this.actionName!, this.actionArguments!);\n }\n }),\n CONDITION: (): ConditionAstNode => ({\n type: \"condition\",\n attributes: [],\n conditionName: \"\",\n conditionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Condition(this.attributes, this.conditionName!, this.conditionArguments!);\n }\n })\n};\n\ntype OtherAstNodes = AstNode[];\n\n/**\n * Create an array of root AST nodes based on the given definition.\n * @param definition The definition to parse the AST nodes from.\n * @returns The base definition AST nodes.\n */\nexport default function buildRootASTNodes(definition: string): RootAstNode[] {\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 // Convert the processed definition (with substituted string literals) into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\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 a stack of node children arrays, starting with a definition scope.\n const stack: [RootAstNode[], ...OtherAstNodes[]] = [[]];\n const rootScope = stack[0];\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 const currentScope = stack[stack.length - 1] as OtherAstNodes;\n\n // How we create the next AST token depends on the current raw token value.\n switch (token!.toUpperCase()) {\n case \"ROOT\": {\n // Create a ROOT AST node.\n const node = ASTNodeFactories.ROOT();\n\n // Push the ROOT node into the current scope.\n rootScope.push(node);\n\n // We may have a root node name defined as an argument.\n if (tokens[0] === \"[\") {\n const rootArguments = getArguments(tokens, placeholders);\n\n // We should have only a single argument that is not an empty string for a root node, which is the root name identifier.\n if (rootArguments.length === 1 && rootArguments[0].type === \"identifier\") {\n // The root name will be the first and only node argument.\n node.name = rootArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new ROOT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"BRANCH\": {\n // Create a BRANCH AST node.\n const node = ASTNodeFactories.BRANCH();\n\n // Push the BRANCH node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a branch name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // The branch name will be defined as a node argument.\n const branchArguments = getArguments(tokens, placeholders);\n\n // We should have only a single identifer argument for a branch node, which is the branch name.\n if (branchArguments.length === 1 && branchArguments[0].type === \"identifier\") {\n // The branch name will be the first and only node argument.\n node.branchName = branchArguments[0].value as string;\n } else {\n throw new Error(\"expected single branch name argument\");\n }\n break;\n }\n\n case \"SELECTOR\": {\n // Create a SELECTOR AST node.\n const node = ASTNodeFactories.SELECTOR();\n\n // Push the SELECTOR node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SELECTOR nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SEQUENCE\": {\n // Create a SEQUENCE AST node.\n const node = ASTNodeFactories.SEQUENCE();\n\n // Push the SEQUENCE node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SEQUENCE nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"PARALLEL\": {\n // Create a PARALLEL AST node.\n const node = ASTNodeFactories.PARALLEL();\n\n // Push the PARALLEL node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new PARALLEL nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"LOTTO\": {\n // Create a LOTTO AST node.\n const node = ASTNodeFactories.LOTTO();\n\n // Push the LOTTO node into the current scope.\n currentScope.push(node);\n\n // If the next token is a '[' character then some ticket counts have been defined as arguments.\n if (tokens[0] === \"[\") {\n // Get the ticket count arguments, each argument must be a number.\n node.tickets = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"lotto node ticket counts must be integer values\"\n ).map((argument) => argument.value as number);\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new LOTTO nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"CONDITION\": {\n // Create a CONDITION AST node.\n const node = ASTNodeFactories.CONDITION();\n\n // Push the CONDITION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a condition function name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Grab the condition node arguments.\n const conditionArguments = getArguments(tokens, placeholders);\n\n // We should have at least a single identifier argument for a condition node, which is the condition function name.\n if (conditionArguments.length && conditionArguments[0].type === \"identifier\") {\n // The condition function name will be the first node argument.\n node.conditionName = conditionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n conditionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid condition node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the condition name identifier will be treated as condition function arguments.\n node.conditionArguments = conditionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"FLIP\": {\n // Create a FLIP AST node.\n const node = ASTNodeFactories.FLIP();\n\n // Push the Flip node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new FLIP nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SUCCEED\": {\n // Create a SUCCEED AST node.\n const node = ASTNodeFactories.SUCCEED();\n\n // Push the Succeed node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Succeed nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"FAIL\": {\n // Create a FAIL AST node.\n const node = ASTNodeFactories.FAIL();\n\n // Push the Fail node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Fail nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"WAIT\": {\n // Create a WAIT AST node.\n const node = ASTNodeFactories.WAIT();\n\n // Push the WAIT node into the current scope.\n currentScope.push(node);\n\n // Get the optional duration and longest duration of the wait.\n const nodeArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"wait node durations must be integer values\"\n ).map((argument) => argument.value);\n\n // 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 === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0] as number;\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.durationMin = nodeArguments[0] as number;\n node.durationMax = nodeArguments[1] as number;\n } else if (nodeArguments.length > 2) {\n // An incorrect number of durations was defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"REPEAT\": {\n // Create a REPEAT AST node.\n const node = ASTNodeFactories.REPEAT();\n\n // Push the REPEAT node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"repeat node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\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 // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new REPEAT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"RETRY\": {\n // Create a RETRY AST node.\n const node = ASTNodeFactories.RETRY();\n\n // Push the RETRY node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"retry node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of retry node iteration count arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new RETRY nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"ACTION\": {\n // Create a ACTION AST node.\n const node = ASTNodeFactories.ACTION();\n\n // Push the ACTION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require an action name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // The action name will be defined as a node argument.\n const actionArguments = getArguments(tokens, placeholders);\n\n // We should have at least one identifer argument for an action node, which is the action name.\n if (actionArguments.length && actionArguments[0].type === \"identifier\") {\n // The action name will be the first and only node argument.\n node.actionName = actionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n actionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid action node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the action name identifier will be treated as action function arguments.\n node.actionArguments = actionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope.\n stack.pop();\n break;\n }\n\n default: {\n throw new Error(\"unexpected token: \" + token);\n }\n }\n }\n\n // A function to recursively validate each of the nodes in the AST.\n const validateASTNode = (node: Validatable, depth: number): void => {\n // Validate the node.\n node.validate(depth);\n\n // Validate each child of the node.\n (node.children || []).forEach((child) => validateASTNode(child, depth + 1));\n };\n\n // Start node validation from the definition root.\n validateASTNode(\n {\n children: stack[0] as RootAstNode[],\n validate(this: { children: RootAstNode[] }) {\n // We must have at least one node defined as the definition scope, which should be a root node.\n if (this.children.length === 0) {\n throw new Error(\"expected root node to have been defined\");\n }\n\n // Each node at the base of the definition scope MUST be a root node.\n for (const definitionLevelNode of this.children) {\n if (definitionLevelNode.type !== \"root\") {\n throw new Error(\"expected root node at base of definition\");\n }\n }\n\n // Exactly one root node must not have a name defined. This will be the main root, others will have to be referenced via branch nodes.\n if (this.children.filter((definitionLevelNode) => definitionLevelNode.name === null).length !== 1) {\n throw new Error(\"expected single unnamed root node at base of definition to act as main root\");\n }\n\n // No two named root nodes can have matching names.\n const rootNodeNames: string[] = [];\n for (const definitionLevelNode of this.children) {\n if (rootNodeNames.indexOf(definitionLevelNode.name!) !== -1) {\n throw new Error(`multiple root nodes found with duplicate name '${definitionLevelNode.name}'`);\n } else {\n rootNodeNames.push(definitionLevelNode.name!);\n }\n }\n }\n },\n 0\n );\n\n // Return the root AST nodes.\n return stack[0];\n}\n\n/**\n * Pop the next raw token off of the stack and throw an error if it wasn't the expected one.\n * @param tokens The array of remaining 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 */\nfunction popAndCheck(tokens: string[], expected: string | string[]) {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token.\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 // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = ([] as string[])\n .concat(expected)\n .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 = ([] as string[])\n .concat(expected)\n .map((item) => \"'\" + item + \"'\")\n .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\ntype Placeholders = { [key: string]: string };\n\n/**\n * Pull an argument definition list off of the token stack.\n * @param tokens The array of remaining tokens.\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 The argument definition list.\n */\nfunction getArguments(\n tokens: string[],\n stringArgumentPlaceholders: Placeholders,\n argumentValidator?: (arg: AnyArgument) => boolean,\n validationFailedMessage?: string\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 closer = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n const argumentList: AnyArgument[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closer) {\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 // Try to validate the argument.\n if (argumentValidator && !argumentValidator(argumentDefinition)) {\n throw new Error(validationFailedMessage);\n }\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, closer);\n\n // Return the argument list.\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: Placeholders): 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\n/**\n * Pull any attributes off of the token stack.\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 array of attributes defined by any directly following tokens.\n */\nfunction getAttributes(tokens: string[], stringArgumentPlaceholders: Placeholders) {\n // Create an array to hold any attributes found.\n const attributes: Attribute[] = [];\n\n // Keep track of names of attribute that we have found on the token stack, as we cannot have duplicates.\n const attributesFound: string[] = [];\n\n // Try to get the attribute factory for the next token.\n let attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n\n // Pull attribute tokens off of the tokens stack until we have no more.\n while (attributeFactory) {\n // Check to make sure that we have not already created a attribute of this type for this node.\n if (attributesFound.indexOf(tokens[0].toUpperCase()) !== -1) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Add the current attribute type to our array of found attributes.\n attributesFound.push(tokens.shift()!.toUpperCase());\n\n // Grab any attribute arguments.\n const attributeArguments = getArguments(tokens, stringArgumentPlaceholders);\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeArguments.length === 0 || attributeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected agent function name identifier argument for attribute\");\n }\n\n // Grab the first attribute which is an identifier that will reference an agent function.\n const attributeFunctionName = attributeArguments.shift()! as IdentifierArgument;\n\n // Any remaining attribute arguments 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 and add it to the array of attributes found.\n attributes.push(attributeFactory(attributeFunctionName.value, attributeArguments));\n\n // Try to get the next attribute name token, as there could be multiple.\n attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n }\n\n return attributes;\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 */\nfunction substituteStringLiterals(definition: string): {\n placeholders: { [key: string]: string };\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: Placeholders = {};\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 */\nfunction 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 GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport buildRootASTNodes, { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\nimport 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\";\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: AnyArgument[];\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 public readonly rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition.\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(definition: string, private agent: Agent, private options: BehaviourTreeOptions = {}) {\n // The tree definition must be defined and a valid string.\n if (typeof definition !== \"string\") {\n throw new Error(\"the tree definition must be a string\");\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 defined and not null\");\n }\n\n // Parse the behaviour tree definition, create the populated tree of behaviour tree nodes, and get the root.\n this.rootNode = BehaviourTree.createRootNode(definition);\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) {\n if (typeof value === \"function\") {\n // We are going to register a action/condition/guard/callback function.\n Lookup.setFunc(name, value);\n } else if (typeof value === \"string\") {\n // We are going to register a subtree.\n let rootASTNodes: RootAstNode[];\n\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n rootASTNodes = buildRootASTNodes(value);\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error registering definition: ${(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 (rootASTNodes.length != 1 || rootASTNodes[0].name !== null) {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n Lookup.setSubtree(name, rootASTNodes[0]);\n } else {\n throw new Error(\"unexpected value, expected string 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 /**\n * Parses a behaviour tree definition and creates a tree of behaviour tree nodes.\n * @param {string} definition The behaviour tree definition.\n * @returns The root behaviour tree node.\n */\n private static createRootNode(definition: string): Root {\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n const rootASTNodes = buildRootASTNodes(definition);\n\n // Create a symbol to use as the main root key in our root node mapping.\n const mainRootNodeKey = Symbol(\"__root__\");\n\n // Create a mapping of root node names to root AST tokens. The main root node will have a key of Symbol(\"__root__\").\n const rootNodeMap: { [key: string | symbol]: RootAstNode } = {};\n for (const rootASTNode of rootASTNodes) {\n rootNodeMap[rootASTNode.name === null ? mainRootNodeKey : rootASTNode.name!] = rootASTNode;\n }\n\n // Convert the AST to our actual tree and get the root node.\n const rootNode: Root = rootNodeMap[mainRootNodeKey].createNodeInstance(\n // Create a provider for named root nodes that are part of our definition or have been registered. Prioritising the former.\n (name: string): RootAstNode => (rootNodeMap[name] ? rootNodeMap[name] : Lookup.getSubtree(name)),\n []\n );\n\n // Set a guard path on every leaf of the tree to evaluate as part of its update.\n BehaviourTree.applyLeafNodeGuardPaths(rootNode);\n\n // Return the root node.\n return rootNode;\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error parsing tree: ${(exception as Error).message}\\n${(exception as Error).stack}`);\n }\n }\n\n /**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param rootNode The main root tree node.\n */\n private static applyLeafNodeGuardPaths(rootNode: 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([], rootNode);\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}\n"], + "mappings": "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", "names": ["Participant", "Lotto", "createLotto", "State", "createLotto"] } diff --git a/dist/index.js b/dist/index.js index ea4c3c2..381bdf3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -492,21 +492,33 @@ var Condition = class extends Leaf { // src/nodes/leaf/Wait.ts var Wait = class extends Leaf { - constructor(attributes, duration, longestDuration) { + constructor(attributes, duration, durationMin, durationMax) { super("wait", attributes, []); this.duration = duration; - this.longestDuration = longestDuration; + this.durationMin = durationMin; + this.durationMax = durationMax; } initialUpdateTime = 0; - totalDuration = 0; + totalDuration = null; waitedDuration = 0; onUpdate(agent, options) { if (this.is("mistreevous.ready" /* READY */)) { this.initialUpdateTime = new Date().getTime(); this.waitedDuration = 0; - this.totalDuration = this.longestDuration ? Math.floor(Math.random() * (this.longestDuration - this.duration + 1) + this.duration) : this.duration; + if (this.duration !== null) { + this.totalDuration = this.duration; + } else if (this.durationMin !== null && this.durationMax !== null) { + this.totalDuration = Math.floor( + Math.random() * (this.durationMax - this.durationMin + 1) + this.durationMin + ); + } else { + this.totalDuration = null; + } this.setState("mistreevous.running" /* RUNNING */); } + if (this.totalDuration === null) { + return; + } if (typeof options.getDeltaTime === "function") { const deltaTime = options.getDeltaTime(); if (typeof deltaTime !== "number" || isNaN(deltaTime)) { @@ -520,7 +532,15 @@ var Wait = class extends Leaf { this.setState("mistreevous.succeeded" /* SUCCEEDED */); } } - getName = () => `WAIT ${this.longestDuration ? this.duration + "ms-" + this.longestDuration + "ms" : this.duration + "ms"}`; + getName = () => { + if (this.duration !== null) { + return `WAIT ${this.duration}ms`; + } else if (this.durationMin !== null && this.durationMax !== null) { + return `WAIT ${this.durationMin}ms-${this.durationMax}ms`; + } else { + return "WAIT"; + } + }; }; // src/nodes/decorator/Decorator.ts @@ -1254,22 +1274,25 @@ var ASTNodeFactories = { type: "wait", attributes: [], duration: null, - longestDuration: null, + durationMin: null, + durationMax: null, validate() { - if (this.duration < 0) { - throw new Error("a wait node must have a positive duration"); - } - if (this.longestDuration) { - if (this.longestDuration < 0) { - throw new Error("a wait node must have a positive longest duration if one is defined"); + if (this.duration !== null) { + if (this.duration < 0) { + throw new Error("a wait node must have a positive duration"); } - if (this.duration > this.longestDuration) { - throw new Error("a wait node must not have a shortest duration that exceeds the longest duration"); + } else if (this.durationMin !== null && this.durationMax !== null) { + if (this.durationMin < 0 || this.durationMax < 0) { + throw new Error("a wait node must have a positive minimum and maximum duration"); } + if (this.durationMin > this.durationMax) { + throw new Error("a wait node must not have a minimum duration that exceeds the maximum duration"); + } + } else { } }, createNodeInstance() { - return new Wait(this.attributes, this.duration, this.longestDuration); + return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax); } }), ACTION: () => ({ @@ -1428,18 +1451,18 @@ function buildRootASTNodes(definition) { case "WAIT": { const node = ASTNodeFactories.WAIT(); currentScope.push(node); - const durations = getArguments( + const nodeArguments = getArguments( tokens, placeholders, (arg) => arg.type === "number" && !!arg.isInteger, "wait node durations must be integer values" ).map((argument) => argument.value); - if (durations.length === 1) { - node.duration = durations[0]; - } else if (durations.length === 2) { - node.duration = durations[0]; - node.longestDuration = durations[1]; - } else { + if (nodeArguments.length === 1) { + node.duration = nodeArguments[0]; + } else if (nodeArguments.length === 2) { + node.durationMin = nodeArguments[0]; + node.durationMax = nodeArguments[1]; + } else if (nodeArguments.length > 2) { throw new Error("invalid number of wait node duration arguments defined"); } node.attributes = getAttributes(tokens, placeholders); diff --git a/dist/index.js.map b/dist/index.js.map index 49887ed..2fb4a39 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/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/State.ts", "../src/nodes/Node.ts", "../src/nodes/leaf/Leaf.ts", "../src/Lookup.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Parallel.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/Exit.ts", "../src/attributes/callbacks/Step.ts", "../src/RootAstNodesBuilder.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 { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport State from \"./State\";\n\nexport { BehaviourTree, State };\nexport type { FlattenedTreeNode };\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * 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 { Agent } from \"../Agent\";\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\";\nimport { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport { AnyArgument } from \"../RootAstNodesBuilder\";\nimport State, { AnyState } from \"../State\";\nimport Leaf from \"./leaf/Leaf\";\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: AnyArgument[]) {}\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.getType().toUpperCase() === type.toUpperCase())[0] ||\n 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\";\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 { ActionResult, Agent, ExitFunctionArg, FunctionArg, GlobalFunction } from \"./Agent\";\nimport { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\n\n// Exit callbacks receive their own special type of argument.\n// There's probably stricter ways to represent this but it feels overly complex right now.\ntype ExitResultArg = { value: ExitFunctionArg };\nexport type AnyExitArgument = AnyArgument | ExitResultArg;\n\nexport type InvokerFunction = (args: AnyExitArgument[]) => ActionResult;\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 functionTable: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered sub-trees keyed on tree name.\n */\n private static subtreeTable: { [key: string]: RootAstNode } = {};\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.functionTable[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.functionTable[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 foundOnAgent = agent[name];\n if (foundOnAgent && typeof foundOnAgent === \"function\") {\n return (args: AnyExitArgument[]): boolean | ActionResult =>\n foundOnAgent.apply(\n agent,\n args.map((arg) => arg.value)\n );\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.functionTable[name] && typeof this.functionTable[name] === \"function\") {\n return (args: AnyExitArgument[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets the subtree with the specified name.\n * @param name The name of the subtree.\n * @returns The subtree with the specified name.\n */\n static getSubtree(name: string): RootAstNode {\n return this.subtreeTable[name];\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: RootAstNode) {\n this.subtreeTable[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.functionTable[name];\n delete this.subtreeTable[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.functionTable = {};\n this.subtreeTable = {};\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State, { CompleteState } from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 updatePromiseStateResult: CompleteState | 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\n // it resolves, unless there has been a value set as a result of the update promise resolving.\n if (this.isUsingUpdatePromise) {\n // Check whether the update promise has resolved with a state value.\n if (this.updatePromiseStateResult) {\n // Set the state of this node to match the state returned by the promise.\n this.setState(this.updatePromiseStateResult);\n }\n\n return;\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 // 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 const updateResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n\n if (updateResult instanceof Promise) {\n updateResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Check to make sure the result is a valid finished state.\n if (result !== State.SUCCEEDED && result !== 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 pending update promise state result to be processed on next update.\n this.updatePromiseStateResult = result;\n },\n (reason) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Just throw whatever was returned as the rejection argument.\n throw new Error(reason);\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(updateResult);\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(updateResult || 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.updatePromiseStateResult = 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 | boolean) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case undefined:\n return;\n default:\n throw new Error(\n `action '${this.actionName}' 'onUpdate' returned an invalid response, expected an optional State.SUCCEEDED or State.FAILED value to be returned`\n );\n }\n };\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 // Call the condition function to determine the state of this node.\n this.setState(!!conditionFuncInvoker(this.conditionArguments) ? 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, or the earliest if longestDuration is defined.\n * @param longestDuration The longest possible duration in milliseconds that this node will wait to succeed.\n */\n constructor(attributes: Attribute[], private duration: number, private longestDuration: number) {\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 = 0;\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 // If a longestDuration value was defined then we will be randomly picking a duration between the\n // shortest and longest duration. If it was not defined, then we will be just using the duration.\n this.totalDuration = this.longestDuration\n ? Math.floor(Math.random() * (this.longestDuration - this.duration + 1) + this.duration)\n : this.duration;\n\n // The node is now running until we finish waiting.\n this.setState(State.RUNNING);\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 `WAIT ${this.longestDuration ? this.duration + \"ms-\" + this.longestDuration + \"ms\" : this.duration + \"ms\"}`;\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 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 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, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent, 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 ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default repeat node name.\n return \"REPEAT\";\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\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 iterations The number of iterations to repeat the child node, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: number | null,\n child: Node\n ) {\n super(\"retry\", 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the 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 iteration.\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 iteration.\n this.currentIterationCount += 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.iterations !== null) {\n return `RETRY ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default retry node name.\n return \"RETRY\";\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 canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\n } else {\n this.targetIterationCount = null;\n }\n };\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 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\";\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 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 tickets The child node tickets.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private tickets: number[], 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.tickets[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.tickets.length ? `LOTTO [${this.tickets.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 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 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 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 { AnyArgument } from \"../RootAstNodesBuilder\";\nimport Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: AnyArgument[];\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 argument definitions.\n */\n constructor(protected type: string, protected args: AnyArgument[]) {}\n\n /**\n * Gets the type of the attribute.\n */\n getType = () => this.type;\n\n /**\n * Gets the array of attribute argument definitions.\n */\n getArguments = () => this.args;\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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, { AnyExitArgument } from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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([{ value: { succeeded: isSuccess, aborted: isAborted } }, ...this.args]);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Root from \"./nodes/decorator/Root\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Node from \"./nodes/Node\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Callback from \"./attributes/callbacks/Callback\";\nimport Guard from \"./attributes/guards/Guard\";\nimport Attribute from \"./attributes/Attribute\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Leaf from \"./nodes/leaf/Leaf\";\n\nexport type Argument = {\n value: T;\n type: string; // Used for validation.\n};\ntype NullArgument = Argument & {\n type: \"null\";\n};\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\ntype NumberArgument = Argument & {\n type: \"number\";\n isInteger: boolean; // Used for validation.\n};\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\nexport type AnyArgument =\n | NullArgument\n | BooleanArgument\n | NumberArgument\n | StringPlaceholderArgument\n | IdentifierArgument;\n\n/**\n * The node attribute factories.\n */\nconst AttributeFactories: {\n [key: string]: (functionName: string, attributeArguments: AnyArgument[]) => Callback | Guard;\n} = {\n WHILE: (condition: string, attributeArguments: AnyArgument[]) => new While(condition, attributeArguments),\n UNTIL: (condition: string, attributeArguments: AnyArgument[]) => new Until(condition, attributeArguments),\n ENTRY: (functionName: string, attributeArguments: AnyArgument[]) => new Entry(functionName, attributeArguments),\n EXIT: (functionName: string, attributeArguments: AnyArgument[]) => new Exit(functionName, attributeArguments),\n STEP: (functionName: string, attributeArguments: AnyArgument[]) => new Step(functionName, attributeArguments)\n};\n\ntype Validatable = {\n children?: AstNode[];\n validate: (depth: number) => void;\n};\n\ntype NodeInstanceCreator = (\n namedRootNodeProvider: (name: string) => RootAstNode,\n visitedBranches: string[]\n) => T;\n\nexport type AstNode = Validatable & {\n type: string;\n createNodeInstance: NodeInstanceCreator;\n};\n\nexport type LeafAstNode = AstNode & {\n type: \"action\" | \"condition\" | \"wait\";\n attributes: Attribute[];\n};\n\nexport type CompositeAstNode = AstNode & {\n type: \"lotto\" | \"parallel\" | \"selector\" | \"sequence\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type DecoratorAstNode = AstNode & {\n type: \"fail\" | \"flip\" | \"repeat\" | \"retry\" | \"root\" | \"succeed\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type BranchAstNode = AstNode & {\n type: \"branch\";\n branchName: \"\" | string;\n};\n\nexport type LottoAstNode = CompositeAstNode & {\n type: \"lotto\";\n tickets: number[];\n};\n\nexport type RootAstNode = DecoratorAstNode & {\n type: \"root\";\n name: null | string;\n};\n\nexport type IterableAstNode = DecoratorAstNode & {\n type: \"repeat\" | \"retry\";\n iterations: null | number;\n maximumIterations: null | number;\n};\n\nexport type ActionAstNode = LeafAstNode & {\n type: \"action\";\n actionName: string;\n actionArguments: AnyArgument[];\n};\n\nexport type ConditionAstNode = LeafAstNode & {\n type: \"condition\";\n conditionName: string;\n conditionArguments: AnyArgument[];\n};\n\nexport type WaitAstNode = LeafAstNode & {\n type: \"wait\";\n duration: number | null;\n longestDuration: number | null;\n};\n\nexport type AnyAstNode =\n | BranchAstNode\n | CompositeAstNode\n | LottoAstNode\n | DecoratorAstNode\n | RootAstNode\n | IterableAstNode\n | LeafAstNode\n | ActionAstNode\n | ConditionAstNode\n | WaitAstNode;\n\n/**\n * The AST node factories.\n */\nconst ASTNodeFactories = {\n ROOT: (): RootAstNode => ({\n type: \"root\",\n attributes: [],\n name: null,\n children: [],\n validate(depth: number) {\n // A root node cannot be the child of another node.\n if (depth > 1) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // A root node must have a single child node.\n if (this.children.length !== 1) {\n throw new Error(\"a root node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Root(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n BRANCH: (): BranchAstNode => ({\n type: \"branch\",\n branchName: \"\",\n validate() {},\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n // Try to find the root node with a matching branch name.\n const targetRootNode = namedRootNodeProvider(this.branchName);\n\n // If we have already visited this branch then we have a circular dependency.\n if (visitedBranches.indexOf(this.branchName) !== -1) {\n throw new Error(`circular dependency found in branch node references for branch '${this.branchName}'`);\n }\n\n // If we have a target root node, then the node instance we want will be the first and only child of the referenced root node.\n if (targetRootNode) {\n return targetRootNode\n .createNodeInstance(namedRootNodeProvider, visitedBranches.concat(this.branchName))\n .getChildren()[0];\n } else {\n throw new Error(`branch references root node '${this.branchName}' which has not been defined`);\n }\n }\n }),\n SELECTOR: (): CompositeAstNode => ({\n type: \"selector\",\n attributes: [],\n children: [],\n validate() {\n // A selector node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a selector node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Selector(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n SEQUENCE: (): CompositeAstNode => ({\n type: \"sequence\",\n attributes: [],\n children: [],\n validate() {\n // A sequence node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a sequence node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Sequence(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n PARALLEL: (): CompositeAstNode => ({\n type: \"parallel\",\n attributes: [],\n children: [],\n validate() {\n // A parallel node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a parallel node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Parallel(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n LOTTO: (): LottoAstNode => ({\n type: \"lotto\",\n attributes: [],\n children: [],\n tickets: [],\n validate() {\n // A lotto node must have at least a single node.\n if (this.children!.length < 1) {\n throw new Error(\"a lotto node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Lotto(\n this.attributes,\n this.tickets!,\n this.children!.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n REPEAT: (): IterableAstNode => ({\n type: \"repeat\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A repeat node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a repeat node must have a single child\");\n }\n\n // A repeat node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A repeat node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a repeat node must have a positive maximum iterations count if defined\");\n }\n\n // A repeat node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a repeat node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Repeat(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n RETRY: (): IterableAstNode => ({\n type: \"retry\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A retry node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a retry node must have a single child\");\n }\n\n // A retry node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a retry node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A retry node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a retry node must have a positive maximum iterations count if defined\");\n }\n\n // A retry node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a retry node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Retry(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FLIP: (): DecoratorAstNode => ({\n type: \"flip\",\n attributes: [],\n children: [],\n validate() {\n // A flip node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a flip node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Flip(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n SUCCEED: (): DecoratorAstNode => ({\n type: \"succeed\",\n attributes: [],\n children: [],\n validate() {\n // A succeed node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a succeed node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Succeed(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FAIL: (): DecoratorAstNode => ({\n type: \"fail\",\n attributes: [],\n children: [],\n validate() {\n // A fail node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a fail node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Fail(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n WAIT: (): WaitAstNode => ({\n type: \"wait\",\n attributes: [],\n duration: null,\n longestDuration: null,\n validate() {\n // A wait node must have a positive duration.\n if (this.duration! < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.longestDuration) {\n // A wait node must have a positive longest duration.\n if (this.longestDuration < 0) {\n throw new Error(\"a wait node must have a positive longest duration if one is defined\");\n }\n\n // A wait node must not have a duration that exceeds the longest duration.\n if (this.duration! > this.longestDuration) {\n throw new Error(\"a wait node must not have a shortest duration that exceeds the longest duration\");\n }\n }\n },\n createNodeInstance() {\n return new Wait(this.attributes, this.duration!, this.longestDuration!);\n }\n }),\n ACTION: (): ActionAstNode => ({\n type: \"action\",\n attributes: [],\n actionName: \"\",\n actionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Action(this.attributes, this.actionName!, this.actionArguments!);\n }\n }),\n CONDITION: (): ConditionAstNode => ({\n type: \"condition\",\n attributes: [],\n conditionName: \"\",\n conditionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Condition(this.attributes, this.conditionName!, this.conditionArguments!);\n }\n })\n};\n\ntype OtherAstNodes = AstNode[];\n\n/**\n * Create an array of root AST nodes based on the given definition.\n * @param definition The definition to parse the AST nodes from.\n * @returns The base definition AST nodes.\n */\nexport default function buildRootASTNodes(definition: string): RootAstNode[] {\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 // Convert the processed definition (with substituted string literals) into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\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 a stack of node children arrays, starting with a definition scope.\n const stack: [RootAstNode[], ...OtherAstNodes[]] = [[]];\n const rootScope = stack[0];\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 const currentScope = stack[stack.length - 1] as OtherAstNodes;\n\n // How we create the next AST token depends on the current raw token value.\n switch (token!.toUpperCase()) {\n case \"ROOT\": {\n // Create a ROOT AST node.\n const node = ASTNodeFactories.ROOT();\n\n // Push the ROOT node into the current scope.\n rootScope.push(node);\n\n // We may have a root node name defined as an argument.\n if (tokens[0] === \"[\") {\n const rootArguments = getArguments(tokens, placeholders);\n\n // We should have only a single argument that is not an empty string for a root node, which is the root name identifier.\n if (rootArguments.length === 1 && rootArguments[0].type === \"identifier\") {\n // The root name will be the first and only node argument.\n node.name = rootArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new ROOT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"BRANCH\": {\n // Create a BRANCH AST node.\n const node = ASTNodeFactories.BRANCH();\n\n // Push the BRANCH node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a branch name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // The branch name will be defined as a node argument.\n const branchArguments = getArguments(tokens, placeholders);\n\n // We should have only a single identifer argument for a branch node, which is the branch name.\n if (branchArguments.length === 1 && branchArguments[0].type === \"identifier\") {\n // The branch name will be the first and only node argument.\n node.branchName = branchArguments[0].value as string;\n } else {\n throw new Error(\"expected single branch name argument\");\n }\n break;\n }\n\n case \"SELECTOR\": {\n // Create a SELECTOR AST node.\n const node = ASTNodeFactories.SELECTOR();\n\n // Push the SELECTOR node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SELECTOR nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SEQUENCE\": {\n // Create a SEQUENCE AST node.\n const node = ASTNodeFactories.SEQUENCE();\n\n // Push the SEQUENCE node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SEQUENCE nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"PARALLEL\": {\n // Create a PARALLEL AST node.\n const node = ASTNodeFactories.PARALLEL();\n\n // Push the PARALLEL node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new PARALLEL nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"LOTTO\": {\n // Create a LOTTO AST node.\n const node = ASTNodeFactories.LOTTO();\n\n // Push the LOTTO node into the current scope.\n currentScope.push(node);\n\n // If the next token is a '[' character then some ticket counts have been defined as arguments.\n if (tokens[0] === \"[\") {\n // Get the ticket count arguments, each argument must be a number.\n node.tickets = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"lotto node ticket counts must be integer values\"\n ).map((argument) => argument.value as number);\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new LOTTO nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"CONDITION\": {\n // Create a CONDITION AST node.\n const node = ASTNodeFactories.CONDITION();\n\n // Push the CONDITION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a condition function name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Grab the condition node arguments.\n const conditionArguments = getArguments(tokens, placeholders);\n\n // We should have at least a single identifier argument for a condition node, which is the condition function name.\n if (conditionArguments.length && conditionArguments[0].type === \"identifier\") {\n // The condition function name will be the first node argument.\n node.conditionName = conditionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n conditionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid condition node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the condition name identifier will be treated as condition function arguments.\n node.conditionArguments = conditionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"FLIP\": {\n // Create a FLIP AST node.\n const node = ASTNodeFactories.FLIP();\n\n // Push the Flip node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new FLIP nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SUCCEED\": {\n // Create a SUCCEED AST node.\n const node = ASTNodeFactories.SUCCEED();\n\n // Push the Succeed node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Succeed nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"FAIL\": {\n // Create a FAIL AST node.\n const node = ASTNodeFactories.FAIL();\n\n // Push the Fail node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Fail nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"WAIT\": {\n // Create a WAIT AST node.\n const node = ASTNodeFactories.WAIT();\n\n // Push the WAIT node into the current scope.\n currentScope.push(node);\n\n // Get the duration and potential longest duration of the wait.\n const durations = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"wait node durations must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two durations.\n if (durations.length === 1) {\n // A static duration was defined.\n node.duration = durations[0] as number;\n } else if (durations.length === 2) {\n // A shortest and longest duration was defined.\n node.duration = durations[0] as number;\n node.longestDuration = durations[1] as number;\n } else {\n // An incorrect number of durations was defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"REPEAT\": {\n // Create a REPEAT AST node.\n const node = ASTNodeFactories.REPEAT();\n\n // Push the REPEAT node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"repeat node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\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 // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new REPEAT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"RETRY\": {\n // Create a RETRY AST node.\n const node = ASTNodeFactories.RETRY();\n\n // Push the RETRY node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"retry node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of retry node iteration count arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new RETRY nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"ACTION\": {\n // Create a ACTION AST node.\n const node = ASTNodeFactories.ACTION();\n\n // Push the ACTION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require an action name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // The action name will be defined as a node argument.\n const actionArguments = getArguments(tokens, placeholders);\n\n // We should have at least one identifer argument for an action node, which is the action name.\n if (actionArguments.length && actionArguments[0].type === \"identifier\") {\n // The action name will be the first and only node argument.\n node.actionName = actionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n actionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid action node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the action name identifier will be treated as action function arguments.\n node.actionArguments = actionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope.\n stack.pop();\n break;\n }\n\n default: {\n throw new Error(\"unexpected token: \" + token);\n }\n }\n }\n\n // A function to recursively validate each of the nodes in the AST.\n const validateASTNode = (node: Validatable, depth: number): void => {\n // Validate the node.\n node.validate(depth);\n\n // Validate each child of the node.\n (node.children || []).forEach((child) => validateASTNode(child, depth + 1));\n };\n\n // Start node validation from the definition root.\n validateASTNode(\n {\n children: stack[0] as RootAstNode[],\n validate(this: { children: RootAstNode[] }) {\n // We must have at least one node defined as the definition scope, which should be a root node.\n if (this.children.length === 0) {\n throw new Error(\"expected root node to have been defined\");\n }\n\n // Each node at the base of the definition scope MUST be a root node.\n for (const definitionLevelNode of this.children) {\n if (definitionLevelNode.type !== \"root\") {\n throw new Error(\"expected root node at base of definition\");\n }\n }\n\n // Exactly one root node must not have a name defined. This will be the main root, others will have to be referenced via branch nodes.\n if (this.children.filter((definitionLevelNode) => definitionLevelNode.name === null).length !== 1) {\n throw new Error(\"expected single unnamed root node at base of definition to act as main root\");\n }\n\n // No two named root nodes can have matching names.\n const rootNodeNames: string[] = [];\n for (const definitionLevelNode of this.children) {\n if (rootNodeNames.indexOf(definitionLevelNode.name!) !== -1) {\n throw new Error(`multiple root nodes found with duplicate name '${definitionLevelNode.name}'`);\n } else {\n rootNodeNames.push(definitionLevelNode.name!);\n }\n }\n }\n },\n 0\n );\n\n // Return the root AST nodes.\n return stack[0];\n}\n\n/**\n * Pop the next raw token off of the stack and throw an error if it wasn't the expected one.\n * @param tokens The array of remaining 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 */\nfunction popAndCheck(tokens: string[], expected: string | string[]) {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token.\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 // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = ([] as string[])\n .concat(expected)\n .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 = ([] as string[])\n .concat(expected)\n .map((item) => \"'\" + item + \"'\")\n .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\ntype Placeholders = { [key: string]: string };\n\n/**\n * Pull an argument definition list off of the token stack.\n * @param tokens The array of remaining tokens.\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 The argument definition list.\n */\nfunction getArguments(\n tokens: string[],\n stringArgumentPlaceholders: Placeholders,\n argumentValidator?: (arg: AnyArgument) => boolean,\n validationFailedMessage?: string\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 closer = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n const argumentList: AnyArgument[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closer) {\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 // Try to validate the argument.\n if (argumentValidator && !argumentValidator(argumentDefinition)) {\n throw new Error(validationFailedMessage);\n }\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, closer);\n\n // Return the argument list.\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: Placeholders): 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\n/**\n * Pull any attributes off of the token stack.\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 array of attributes defined by any directly following tokens.\n */\nfunction getAttributes(tokens: string[], stringArgumentPlaceholders: Placeholders) {\n // Create an array to hold any attributes found.\n const attributes: Attribute[] = [];\n\n // Keep track of names of attribute that we have found on the token stack, as we cannot have duplicates.\n const attributesFound: string[] = [];\n\n // Try to get the attribute factory for the next token.\n let attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n\n // Pull attribute tokens off of the tokens stack until we have no more.\n while (attributeFactory) {\n // Check to make sure that we have not already created a attribute of this type for this node.\n if (attributesFound.indexOf(tokens[0].toUpperCase()) !== -1) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Add the current attribute type to our array of found attributes.\n attributesFound.push(tokens.shift()!.toUpperCase());\n\n // Grab any attribute arguments.\n const attributeArguments = getArguments(tokens, stringArgumentPlaceholders);\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeArguments.length === 0 || attributeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected agent function name identifier argument for attribute\");\n }\n\n // Grab the first attribute which is an identifier that will reference an agent function.\n const attributeFunctionName = attributeArguments.shift()! as IdentifierArgument;\n\n // Any remaining attribute arguments 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 and add it to the array of attributes found.\n attributes.push(attributeFactory(attributeFunctionName.value, attributeArguments));\n\n // Try to get the next attribute name token, as there could be multiple.\n attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n }\n\n return attributes;\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 */\nfunction substituteStringLiterals(definition: string): {\n placeholders: { [key: string]: string };\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: Placeholders = {};\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 */\nfunction 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 GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport buildRootASTNodes, { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\nimport 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\";\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: AnyArgument[];\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 public readonly rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition.\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(definition: string, private agent: Agent, private options: BehaviourTreeOptions = {}) {\n // The tree definition must be defined and a valid string.\n if (typeof definition !== \"string\") {\n throw new Error(\"the tree definition must be a string\");\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 defined and not null\");\n }\n\n // Parse the behaviour tree definition, create the populated tree of behaviour tree nodes, and get the root.\n this.rootNode = BehaviourTree.createRootNode(definition);\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) {\n if (typeof value === \"function\") {\n // We are going to register a action/condition/guard/callback function.\n Lookup.setFunc(name, value);\n } else if (typeof value === \"string\") {\n // We are going to register a subtree.\n let rootASTNodes: RootAstNode[];\n\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n rootASTNodes = buildRootASTNodes(value);\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error registering definition: ${(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 (rootASTNodes.length != 1 || rootASTNodes[0].name !== null) {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n Lookup.setSubtree(name, rootASTNodes[0]);\n } else {\n throw new Error(\"unexpected value, expected string 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 /**\n * Parses a behaviour tree definition and creates a tree of behaviour tree nodes.\n * @param {string} definition The behaviour tree definition.\n * @returns The root behaviour tree node.\n */\n private static createRootNode(definition: string): Root {\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n const rootASTNodes = buildRootASTNodes(definition);\n\n // Create a symbol to use as the main root key in our root node mapping.\n const mainRootNodeKey = Symbol(\"__root__\");\n\n // Create a mapping of root node names to root AST tokens. The main root node will have a key of Symbol(\"__root__\").\n const rootNodeMap: { [key: string | symbol]: RootAstNode } = {};\n for (const rootASTNode of rootASTNodes) {\n rootNodeMap[rootASTNode.name === null ? mainRootNodeKey : rootASTNode.name!] = rootASTNode;\n }\n\n // Convert the AST to our actual tree and get the root node.\n const rootNode: Root = rootNodeMap[mainRootNodeKey].createNodeInstance(\n // Create a provider for named root nodes that are part of our definition or have been registered. Prioritising the former.\n (name: string): RootAstNode => (rootNodeMap[name] ? rootNodeMap[name] : Lookup.getSubtree(name)),\n []\n );\n\n // Set a guard path on every leaf of the tree to evaluate as part of its update.\n BehaviourTree.applyLeafNodeGuardPaths(rootNode);\n\n // Return the root node.\n return rootNode;\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error parsing tree: ${(exception as Error).message}\\n${(exception as Error).stack}`);\n }\n }\n\n /**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param rootNode The main root tree node.\n */\n private static applyLeafNodeGuardPaths(rootNode: 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([], rootNode);\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}\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 { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport State from \"./State\";\n\nexport { BehaviourTree, State };\nexport type { FlattenedTreeNode };\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * 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 { Agent } from \"../Agent\";\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\";\nimport { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport { AnyArgument } from \"../RootAstNodesBuilder\";\nimport State, { AnyState } from \"../State\";\nimport Leaf from \"./leaf/Leaf\";\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: AnyArgument[]) {}\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.getType().toUpperCase() === type.toUpperCase())[0] ||\n 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\";\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 { ActionResult, Agent, ExitFunctionArg, FunctionArg, GlobalFunction } from \"./Agent\";\nimport { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\n\n// Exit callbacks receive their own special type of argument.\n// There's probably stricter ways to represent this but it feels overly complex right now.\ntype ExitResultArg = { value: ExitFunctionArg };\nexport type AnyExitArgument = AnyArgument | ExitResultArg;\n\nexport type InvokerFunction = (args: AnyExitArgument[]) => ActionResult;\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 functionTable: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered sub-trees keyed on tree name.\n */\n private static subtreeTable: { [key: string]: RootAstNode } = {};\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.functionTable[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.functionTable[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 foundOnAgent = agent[name];\n if (foundOnAgent && typeof foundOnAgent === \"function\") {\n return (args: AnyExitArgument[]): boolean | ActionResult =>\n foundOnAgent.apply(\n agent,\n args.map((arg) => arg.value)\n );\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.functionTable[name] && typeof this.functionTable[name] === \"function\") {\n return (args: AnyExitArgument[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets the subtree with the specified name.\n * @param name The name of the subtree.\n * @returns The subtree with the specified name.\n */\n static getSubtree(name: string): RootAstNode {\n return this.subtreeTable[name];\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: RootAstNode) {\n this.subtreeTable[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.functionTable[name];\n delete this.subtreeTable[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.functionTable = {};\n this.subtreeTable = {};\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State, { CompleteState } from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 updatePromiseStateResult: CompleteState | 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\n // it resolves, unless there has been a value set as a result of the update promise resolving.\n if (this.isUsingUpdatePromise) {\n // Check whether the update promise has resolved with a state value.\n if (this.updatePromiseStateResult) {\n // Set the state of this node to match the state returned by the promise.\n this.setState(this.updatePromiseStateResult);\n }\n\n return;\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 // 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 const updateResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n\n if (updateResult instanceof Promise) {\n updateResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Check to make sure the result is a valid finished state.\n if (result !== State.SUCCEEDED && result !== 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 pending update promise state result to be processed on next update.\n this.updatePromiseStateResult = result;\n },\n (reason) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Just throw whatever was returned as the rejection argument.\n throw new Error(reason);\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(updateResult);\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(updateResult || 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.updatePromiseStateResult = 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 | boolean) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case undefined:\n return;\n default:\n throw new Error(\n `action '${this.actionName}' 'onUpdate' returned an invalid response, expected an optional State.SUCCEEDED or State.FAILED value to be returned`\n );\n }\n };\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 // Call the condition function to determine the state of this node.\n this.setState(!!conditionFuncInvoker(this.conditionArguments) ? 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, or the earliest if longestDuration is defined.\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 this.totalDuration = Math.floor(\n Math.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 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 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 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, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent, 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 ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default repeat node name.\n return \"REPEAT\";\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\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 iterations The number of iterations to repeat the child node, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: number | null,\n child: Node\n ) {\n super(\"retry\", 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the 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 iteration.\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 iteration.\n this.currentIterationCount += 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.iterations !== null) {\n return `RETRY ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default retry node name.\n return \"RETRY\";\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 canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\n } else {\n this.targetIterationCount = null;\n }\n };\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 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\";\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 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 tickets The child node tickets.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private tickets: number[], 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.tickets[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.tickets.length ? `LOTTO [${this.tickets.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 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 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 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 { AnyArgument } from \"../RootAstNodesBuilder\";\nimport Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: AnyArgument[];\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 argument definitions.\n */\n constructor(protected type: string, protected args: AnyArgument[]) {}\n\n /**\n * Gets the type of the attribute.\n */\n getType = () => this.type;\n\n /**\n * Gets the array of attribute argument definitions.\n */\n getArguments = () => this.args;\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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, { AnyExitArgument } from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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([{ value: { succeeded: isSuccess, aborted: isAborted } }, ...this.args]);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Root from \"./nodes/decorator/Root\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Node from \"./nodes/Node\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Callback from \"./attributes/callbacks/Callback\";\nimport Guard from \"./attributes/guards/Guard\";\nimport Attribute from \"./attributes/Attribute\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Leaf from \"./nodes/leaf/Leaf\";\n\nexport type Argument = {\n value: T;\n type: string; // Used for validation.\n};\ntype NullArgument = Argument & {\n type: \"null\";\n};\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\ntype NumberArgument = Argument & {\n type: \"number\";\n isInteger: boolean; // Used for validation.\n};\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\nexport type AnyArgument =\n | NullArgument\n | BooleanArgument\n | NumberArgument\n | StringPlaceholderArgument\n | IdentifierArgument;\n\n/**\n * The node attribute factories.\n */\nconst AttributeFactories: {\n [key: string]: (functionName: string, attributeArguments: AnyArgument[]) => Callback | Guard;\n} = {\n WHILE: (condition: string, attributeArguments: AnyArgument[]) => new While(condition, attributeArguments),\n UNTIL: (condition: string, attributeArguments: AnyArgument[]) => new Until(condition, attributeArguments),\n ENTRY: (functionName: string, attributeArguments: AnyArgument[]) => new Entry(functionName, attributeArguments),\n EXIT: (functionName: string, attributeArguments: AnyArgument[]) => new Exit(functionName, attributeArguments),\n STEP: (functionName: string, attributeArguments: AnyArgument[]) => new Step(functionName, attributeArguments)\n};\n\ntype Validatable = {\n children?: AstNode[];\n validate: (depth: number) => void;\n};\n\ntype NodeInstanceCreator = (\n namedRootNodeProvider: (name: string) => RootAstNode,\n visitedBranches: string[]\n) => T;\n\nexport type AstNode = Validatable & {\n type: string;\n createNodeInstance: NodeInstanceCreator;\n};\n\nexport type LeafAstNode = AstNode & {\n type: \"action\" | \"condition\" | \"wait\";\n attributes: Attribute[];\n};\n\nexport type CompositeAstNode = AstNode & {\n type: \"lotto\" | \"parallel\" | \"selector\" | \"sequence\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type DecoratorAstNode = AstNode & {\n type: \"fail\" | \"flip\" | \"repeat\" | \"retry\" | \"root\" | \"succeed\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type BranchAstNode = AstNode & {\n type: \"branch\";\n branchName: \"\" | string;\n};\n\nexport type LottoAstNode = CompositeAstNode & {\n type: \"lotto\";\n tickets: number[];\n};\n\nexport type RootAstNode = DecoratorAstNode & {\n type: \"root\";\n name: null | string;\n};\n\nexport type IterableAstNode = DecoratorAstNode & {\n type: \"repeat\" | \"retry\";\n iterations: null | number;\n maximumIterations: null | number;\n};\n\nexport type ActionAstNode = LeafAstNode & {\n type: \"action\";\n actionName: string;\n actionArguments: AnyArgument[];\n};\n\nexport type ConditionAstNode = LeafAstNode & {\n type: \"condition\";\n conditionName: string;\n conditionArguments: AnyArgument[];\n};\n\nexport type WaitAstNode = LeafAstNode & {\n type: \"wait\";\n duration: number | null;\n durationMin: number | null;\n durationMax: number | null;\n};\n\nexport type AnyAstNode =\n | BranchAstNode\n | CompositeAstNode\n | LottoAstNode\n | DecoratorAstNode\n | RootAstNode\n | IterableAstNode\n | LeafAstNode\n | ActionAstNode\n | ConditionAstNode\n | WaitAstNode;\n\n/**\n * The AST node factories.\n */\nconst ASTNodeFactories = {\n ROOT: (): RootAstNode => ({\n type: \"root\",\n attributes: [],\n name: null,\n children: [],\n validate(depth: number) {\n // A root node cannot be the child of another node.\n if (depth > 1) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // A root node must have a single child node.\n if (this.children.length !== 1) {\n throw new Error(\"a root node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Root(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n BRANCH: (): BranchAstNode => ({\n type: \"branch\",\n branchName: \"\",\n validate() {},\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n // Try to find the root node with a matching branch name.\n const targetRootNode = namedRootNodeProvider(this.branchName);\n\n // If we have already visited this branch then we have a circular dependency.\n if (visitedBranches.indexOf(this.branchName) !== -1) {\n throw new Error(`circular dependency found in branch node references for branch '${this.branchName}'`);\n }\n\n // If we have a target root node, then the node instance we want will be the first and only child of the referenced root node.\n if (targetRootNode) {\n return targetRootNode\n .createNodeInstance(namedRootNodeProvider, visitedBranches.concat(this.branchName))\n .getChildren()[0];\n } else {\n throw new Error(`branch references root node '${this.branchName}' which has not been defined`);\n }\n }\n }),\n SELECTOR: (): CompositeAstNode => ({\n type: \"selector\",\n attributes: [],\n children: [],\n validate() {\n // A selector node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a selector node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Selector(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n SEQUENCE: (): CompositeAstNode => ({\n type: \"sequence\",\n attributes: [],\n children: [],\n validate() {\n // A sequence node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a sequence node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Sequence(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n PARALLEL: (): CompositeAstNode => ({\n type: \"parallel\",\n attributes: [],\n children: [],\n validate() {\n // A parallel node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a parallel node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Parallel(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n LOTTO: (): LottoAstNode => ({\n type: \"lotto\",\n attributes: [],\n children: [],\n tickets: [],\n validate() {\n // A lotto node must have at least a single node.\n if (this.children!.length < 1) {\n throw new Error(\"a lotto node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Lotto(\n this.attributes,\n this.tickets!,\n this.children!.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n REPEAT: (): IterableAstNode => ({\n type: \"repeat\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A repeat node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a repeat node must have a single child\");\n }\n\n // A repeat node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A repeat node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a repeat node must have a positive maximum iterations count if defined\");\n }\n\n // A repeat node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a repeat node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Repeat(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n RETRY: (): IterableAstNode => ({\n type: \"retry\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A retry node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a retry node must have a single child\");\n }\n\n // A retry node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a retry node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A retry node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a retry node must have a positive maximum iterations count if defined\");\n }\n\n // A retry node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a retry node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Retry(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FLIP: (): DecoratorAstNode => ({\n type: \"flip\",\n attributes: [],\n children: [],\n validate() {\n // A flip node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a flip node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Flip(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n SUCCEED: (): DecoratorAstNode => ({\n type: \"succeed\",\n attributes: [],\n children: [],\n validate() {\n // A succeed node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a succeed node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Succeed(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FAIL: (): DecoratorAstNode => ({\n type: \"fail\",\n attributes: [],\n children: [],\n validate() {\n // A fail node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a fail node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Fail(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n WAIT: (): WaitAstNode => ({\n type: \"wait\",\n attributes: [],\n duration: null,\n durationMin: null,\n durationMax: null,\n validate() {\n if (this.duration !== null) {\n // If an explict duration was defined then it must be a positive number.\n if (this.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // A wait node must have a positive min and max duration.\n if (this.durationMin < 0 || this.durationMax < 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 (this.durationMin > this.durationMax) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else {\n // If we have no explicit duration or duration bounds set then we are dealing with a wait node that waits indefinitely.\n }\n },\n createNodeInstance() {\n return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax);\n }\n }),\n ACTION: (): ActionAstNode => ({\n type: \"action\",\n attributes: [],\n actionName: \"\",\n actionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Action(this.attributes, this.actionName!, this.actionArguments!);\n }\n }),\n CONDITION: (): ConditionAstNode => ({\n type: \"condition\",\n attributes: [],\n conditionName: \"\",\n conditionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Condition(this.attributes, this.conditionName!, this.conditionArguments!);\n }\n })\n};\n\ntype OtherAstNodes = AstNode[];\n\n/**\n * Create an array of root AST nodes based on the given definition.\n * @param definition The definition to parse the AST nodes from.\n * @returns The base definition AST nodes.\n */\nexport default function buildRootASTNodes(definition: string): RootAstNode[] {\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 // Convert the processed definition (with substituted string literals) into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\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 a stack of node children arrays, starting with a definition scope.\n const stack: [RootAstNode[], ...OtherAstNodes[]] = [[]];\n const rootScope = stack[0];\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 const currentScope = stack[stack.length - 1] as OtherAstNodes;\n\n // How we create the next AST token depends on the current raw token value.\n switch (token!.toUpperCase()) {\n case \"ROOT\": {\n // Create a ROOT AST node.\n const node = ASTNodeFactories.ROOT();\n\n // Push the ROOT node into the current scope.\n rootScope.push(node);\n\n // We may have a root node name defined as an argument.\n if (tokens[0] === \"[\") {\n const rootArguments = getArguments(tokens, placeholders);\n\n // We should have only a single argument that is not an empty string for a root node, which is the root name identifier.\n if (rootArguments.length === 1 && rootArguments[0].type === \"identifier\") {\n // The root name will be the first and only node argument.\n node.name = rootArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new ROOT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"BRANCH\": {\n // Create a BRANCH AST node.\n const node = ASTNodeFactories.BRANCH();\n\n // Push the BRANCH node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a branch name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // The branch name will be defined as a node argument.\n const branchArguments = getArguments(tokens, placeholders);\n\n // We should have only a single identifer argument for a branch node, which is the branch name.\n if (branchArguments.length === 1 && branchArguments[0].type === \"identifier\") {\n // The branch name will be the first and only node argument.\n node.branchName = branchArguments[0].value as string;\n } else {\n throw new Error(\"expected single branch name argument\");\n }\n break;\n }\n\n case \"SELECTOR\": {\n // Create a SELECTOR AST node.\n const node = ASTNodeFactories.SELECTOR();\n\n // Push the SELECTOR node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SELECTOR nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SEQUENCE\": {\n // Create a SEQUENCE AST node.\n const node = ASTNodeFactories.SEQUENCE();\n\n // Push the SEQUENCE node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SEQUENCE nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"PARALLEL\": {\n // Create a PARALLEL AST node.\n const node = ASTNodeFactories.PARALLEL();\n\n // Push the PARALLEL node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new PARALLEL nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"LOTTO\": {\n // Create a LOTTO AST node.\n const node = ASTNodeFactories.LOTTO();\n\n // Push the LOTTO node into the current scope.\n currentScope.push(node);\n\n // If the next token is a '[' character then some ticket counts have been defined as arguments.\n if (tokens[0] === \"[\") {\n // Get the ticket count arguments, each argument must be a number.\n node.tickets = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"lotto node ticket counts must be integer values\"\n ).map((argument) => argument.value as number);\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new LOTTO nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"CONDITION\": {\n // Create a CONDITION AST node.\n const node = ASTNodeFactories.CONDITION();\n\n // Push the CONDITION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a condition function name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Grab the condition node arguments.\n const conditionArguments = getArguments(tokens, placeholders);\n\n // We should have at least a single identifier argument for a condition node, which is the condition function name.\n if (conditionArguments.length && conditionArguments[0].type === \"identifier\") {\n // The condition function name will be the first node argument.\n node.conditionName = conditionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n conditionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid condition node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the condition name identifier will be treated as condition function arguments.\n node.conditionArguments = conditionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"FLIP\": {\n // Create a FLIP AST node.\n const node = ASTNodeFactories.FLIP();\n\n // Push the Flip node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new FLIP nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SUCCEED\": {\n // Create a SUCCEED AST node.\n const node = ASTNodeFactories.SUCCEED();\n\n // Push the Succeed node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Succeed nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"FAIL\": {\n // Create a FAIL AST node.\n const node = ASTNodeFactories.FAIL();\n\n // Push the Fail node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Fail nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"WAIT\": {\n // Create a WAIT AST node.\n const node = ASTNodeFactories.WAIT();\n\n // Push the WAIT node into the current scope.\n currentScope.push(node);\n\n // Get the optional duration and longest duration of the wait.\n const nodeArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"wait node durations must be integer values\"\n ).map((argument) => argument.value);\n\n // 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 === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0] as number;\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.durationMin = nodeArguments[0] as number;\n node.durationMax = nodeArguments[1] as number;\n } else if (nodeArguments.length > 2) {\n // An incorrect number of durations was defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"REPEAT\": {\n // Create a REPEAT AST node.\n const node = ASTNodeFactories.REPEAT();\n\n // Push the REPEAT node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"repeat node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\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 // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new REPEAT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"RETRY\": {\n // Create a RETRY AST node.\n const node = ASTNodeFactories.RETRY();\n\n // Push the RETRY node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"retry node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of retry node iteration count arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new RETRY nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"ACTION\": {\n // Create a ACTION AST node.\n const node = ASTNodeFactories.ACTION();\n\n // Push the ACTION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require an action name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // The action name will be defined as a node argument.\n const actionArguments = getArguments(tokens, placeholders);\n\n // We should have at least one identifer argument for an action node, which is the action name.\n if (actionArguments.length && actionArguments[0].type === \"identifier\") {\n // The action name will be the first and only node argument.\n node.actionName = actionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n actionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid action node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the action name identifier will be treated as action function arguments.\n node.actionArguments = actionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope.\n stack.pop();\n break;\n }\n\n default: {\n throw new Error(\"unexpected token: \" + token);\n }\n }\n }\n\n // A function to recursively validate each of the nodes in the AST.\n const validateASTNode = (node: Validatable, depth: number): void => {\n // Validate the node.\n node.validate(depth);\n\n // Validate each child of the node.\n (node.children || []).forEach((child) => validateASTNode(child, depth + 1));\n };\n\n // Start node validation from the definition root.\n validateASTNode(\n {\n children: stack[0] as RootAstNode[],\n validate(this: { children: RootAstNode[] }) {\n // We must have at least one node defined as the definition scope, which should be a root node.\n if (this.children.length === 0) {\n throw new Error(\"expected root node to have been defined\");\n }\n\n // Each node at the base of the definition scope MUST be a root node.\n for (const definitionLevelNode of this.children) {\n if (definitionLevelNode.type !== \"root\") {\n throw new Error(\"expected root node at base of definition\");\n }\n }\n\n // Exactly one root node must not have a name defined. This will be the main root, others will have to be referenced via branch nodes.\n if (this.children.filter((definitionLevelNode) => definitionLevelNode.name === null).length !== 1) {\n throw new Error(\"expected single unnamed root node at base of definition to act as main root\");\n }\n\n // No two named root nodes can have matching names.\n const rootNodeNames: string[] = [];\n for (const definitionLevelNode of this.children) {\n if (rootNodeNames.indexOf(definitionLevelNode.name!) !== -1) {\n throw new Error(`multiple root nodes found with duplicate name '${definitionLevelNode.name}'`);\n } else {\n rootNodeNames.push(definitionLevelNode.name!);\n }\n }\n }\n },\n 0\n );\n\n // Return the root AST nodes.\n return stack[0];\n}\n\n/**\n * Pop the next raw token off of the stack and throw an error if it wasn't the expected one.\n * @param tokens The array of remaining 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 */\nfunction popAndCheck(tokens: string[], expected: string | string[]) {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token.\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 // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = ([] as string[])\n .concat(expected)\n .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 = ([] as string[])\n .concat(expected)\n .map((item) => \"'\" + item + \"'\")\n .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\ntype Placeholders = { [key: string]: string };\n\n/**\n * Pull an argument definition list off of the token stack.\n * @param tokens The array of remaining tokens.\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 The argument definition list.\n */\nfunction getArguments(\n tokens: string[],\n stringArgumentPlaceholders: Placeholders,\n argumentValidator?: (arg: AnyArgument) => boolean,\n validationFailedMessage?: string\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 closer = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n const argumentList: AnyArgument[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closer) {\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 // Try to validate the argument.\n if (argumentValidator && !argumentValidator(argumentDefinition)) {\n throw new Error(validationFailedMessage);\n }\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, closer);\n\n // Return the argument list.\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: Placeholders): 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\n/**\n * Pull any attributes off of the token stack.\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 array of attributes defined by any directly following tokens.\n */\nfunction getAttributes(tokens: string[], stringArgumentPlaceholders: Placeholders) {\n // Create an array to hold any attributes found.\n const attributes: Attribute[] = [];\n\n // Keep track of names of attribute that we have found on the token stack, as we cannot have duplicates.\n const attributesFound: string[] = [];\n\n // Try to get the attribute factory for the next token.\n let attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n\n // Pull attribute tokens off of the tokens stack until we have no more.\n while (attributeFactory) {\n // Check to make sure that we have not already created a attribute of this type for this node.\n if (attributesFound.indexOf(tokens[0].toUpperCase()) !== -1) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Add the current attribute type to our array of found attributes.\n attributesFound.push(tokens.shift()!.toUpperCase());\n\n // Grab any attribute arguments.\n const attributeArguments = getArguments(tokens, stringArgumentPlaceholders);\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeArguments.length === 0 || attributeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected agent function name identifier argument for attribute\");\n }\n\n // Grab the first attribute which is an identifier that will reference an agent function.\n const attributeFunctionName = attributeArguments.shift()! as IdentifierArgument;\n\n // Any remaining attribute arguments 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 and add it to the array of attributes found.\n attributes.push(attributeFactory(attributeFunctionName.value, attributeArguments));\n\n // Try to get the next attribute name token, as there could be multiple.\n attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n }\n\n return attributes;\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 */\nfunction substituteStringLiterals(definition: string): {\n placeholders: { [key: string]: string };\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: Placeholders = {};\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 */\nfunction 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 GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport buildRootASTNodes, { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\nimport 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\";\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: AnyArgument[];\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 public readonly rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition.\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(definition: string, private agent: Agent, private options: BehaviourTreeOptions = {}) {\n // The tree definition must be defined and a valid string.\n if (typeof definition !== \"string\") {\n throw new Error(\"the tree definition must be a string\");\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 defined and not null\");\n }\n\n // Parse the behaviour tree definition, create the populated tree of behaviour tree nodes, and get the root.\n this.rootNode = BehaviourTree.createRootNode(definition);\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) {\n if (typeof value === \"function\") {\n // We are going to register a action/condition/guard/callback function.\n Lookup.setFunc(name, value);\n } else if (typeof value === \"string\") {\n // We are going to register a subtree.\n let rootASTNodes: RootAstNode[];\n\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n rootASTNodes = buildRootASTNodes(value);\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error registering definition: ${(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 (rootASTNodes.length != 1 || rootASTNodes[0].name !== null) {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n Lookup.setSubtree(name, rootASTNodes[0]);\n } else {\n throw new Error(\"unexpected value, expected string 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 /**\n * Parses a behaviour tree definition and creates a tree of behaviour tree nodes.\n * @param {string} definition The behaviour tree definition.\n * @returns The root behaviour tree node.\n */\n private static createRootNode(definition: string): Root {\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n const rootASTNodes = buildRootASTNodes(definition);\n\n // Create a symbol to use as the main root key in our root node mapping.\n const mainRootNodeKey = Symbol(\"__root__\");\n\n // Create a mapping of root node names to root AST tokens. The main root node will have a key of Symbol(\"__root__\").\n const rootNodeMap: { [key: string | symbol]: RootAstNode } = {};\n for (const rootASTNode of rootASTNodes) {\n rootNodeMap[rootASTNode.name === null ? mainRootNodeKey : rootASTNode.name!] = rootASTNode;\n }\n\n // Convert the AST to our actual tree and get the root node.\n const rootNode: Root = rootNodeMap[mainRootNodeKey].createNodeInstance(\n // Create a provider for named root nodes that are part of our definition or have been registered. Prioritising the former.\n (name: string): RootAstNode => (rootNodeMap[name] ? rootNodeMap[name] : Lookup.getSubtree(name)),\n []\n );\n\n // Set a guard path on every leaf of the tree to evaluate as part of its update.\n BehaviourTree.applyLeafNodeGuardPaths(rootNode);\n\n // Return the root node.\n return rootNode;\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error parsing tree: ${(exception as Error).message}\\n${(exception as Error).stack}`);\n }\n }\n\n /**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param rootNode The main root tree node.\n */\n private static applyLeafNodeGuardPaths(rootNode: 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([], rootNode);\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}\n"], + "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AACA,WAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,YAAQ,cAAc;AAItB,QAAI,cAA6B,WAAY;AAMzC,eAASA,aAAY,aAAa,SAAS;AACvC,YAAI,YAAY,QAAQ;AAAE,oBAAU;AAAA,QAAG;AACvC,aAAK,eAAe;AACpB,aAAK,WAAW;AAAA,MACpB;AACA,aAAO,eAAeA,aAAY,WAAW,eAAe;AAAA,QAExD,KAAK,WAAY;AACb,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,MAClB,CAAC;AACD,aAAO,eAAeA,aAAY,WAAW,WAAW;AAAA,QAEpD,KAAK,WAAY;AACb,iBAAO,KAAK;AAAA,QAChB;AAAA,QACA,KAAK,SAAU,OAAO;AAClB,eAAK,WAAW;AAAA,QACpB;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,MAClB,CAAC;AACD,aAAOA;AAAA,IACX,EAAE;AACF,YAAQ,cAAc;AAAA;AAAA;;;ACtCtB;AAAA;AAAA;AACA,WAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,YAAQ,kBAAkB,QAAQ,oBAAoB;AAMtD,aAAS,kBAAkB,OAAO;AAC9B,aAAO,UAAU,QAAQ,UAAU;AAAA,IACvC;AACA,YAAQ,oBAAoB;AAM5B,aAAS,gBAAgB,OAAO;AAC5B,aAAO,OAAO,UAAU,YAAY,SAAS,KAAK,KAAK,MAAM,KAAK,MAAM;AAAA,IAC5E;AACA,YAAQ,kBAAkB;AAAA;AAAA;;;ACpB1B;AAAA;AAAA;AACA,WAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,YAAQ,QAAQ;AAChB,QAAI,gBAAgB;AACpB,QAAI,cAAc;AAIlB,QAAIC,SAAuB,WAAY;AAKnC,eAASA,OAAM,cAAc;AAEzB,aAAK,gBAAgB,CAAC;AACtB,aAAK,gBAAgB;AAAA,MACzB;AAOA,MAAAA,OAAM,UAAU,MAAM,SAAU,aAAa,SAAS;AAClD,YAAI,YAAY,QAAQ;AAAE,oBAAU;AAAA,QAAG;AAEvC,YAAI,EAAE,GAAG,YAAY,iBAAiB,OAAO,GAAG;AAC5C,gBAAM,IAAI,MAAM,wCAAwC;AAAA,QAC5D;AAEA,YAAI,sBAAsB,KAAK,cAAc,KAAK,SAAU,MAAM;AAAE,iBAAO,KAAK,gBAAgB;AAAA,QAAa,CAAC;AAC9G,YAAI,qBAAqB;AAErB,8BAAoB,WAAW;AAAA,QACnC,OACK;AAED,eAAK,cAAc,KAAK,IAAI,cAAc,YAAY,aAAa,OAAO,CAAC;AAAA,QAC/E;AACA,eAAO;AAAA,MACX;AAOA,MAAAA,OAAM,UAAU,SAAS,SAAU,aAAa,SAAS;AAErD,YAAI,sBAAsB,KAAK,cAAc,KAAK,SAAU,MAAM;AAAE,iBAAO,KAAK,gBAAgB;AAAA,QAAa,CAAC;AAE9G,YAAI,CAAC,qBAAqB;AACtB,iBAAO;AAAA,QACX;AAEA,YAAI,YAAY,QAAW;AAEvB,cAAI,EAAE,GAAG,YAAY,iBAAiB,OAAO,GAAG;AAC5C,kBAAM,IAAI,MAAM,wCAAwC;AAAA,UAC5D;AACA,8BAAoB,WAAW;AAE/B,cAAI,oBAAoB,UAAU,GAAG;AACjC,iBAAK,gBAAgB,KAAK,cAAc,OAAO,SAAU,MAAM;AAAE,qBAAO,SAAS;AAAA,YAAqB,CAAC;AAAA,UAC3G;AAAA,QACJ,OACK;AAED,eAAK,gBAAgB,KAAK,cAAc,OAAO,SAAU,MAAM;AAAE,mBAAO,SAAS;AAAA,UAAqB,CAAC;AAAA,QAC3G;AACA,eAAO;AAAA,MACX;AAMA,MAAAA,OAAM,UAAU,OAAO,SAAU,SAAS;AACtC,YAAI,YAAY,QAAQ;AAAE,oBAAU,CAAC;AAAA,QAAG;AAExC,YAAI,KAAK,cAAc,WAAW,GAAG;AACjC,iBAAO;AAAA,QACX;AACA,YAAI,cAAc,GAAG,YAAY,mBAAmB,QAAQ,UAAU,IAAI,OAAO,QAAQ;AACzF,YAAI,WAAW,CAAC;AAChB,aAAK,cAAc,QAAQ,SAAU,IAAI;AACrC,cAAI,cAAc,GAAG,aAAa,UAAU,GAAG;AAC/C,mBAAS,cAAc,GAAG,cAAc,SAAS,eAAe;AAC5D,qBAAS,KAAK,WAAW;AAAA,UAC7B;AAAA,QACJ,CAAC;AACD,YAAI;AAGJ,YAAI,KAAK,eAAe;AAEpB,mBAAS,KAAK,cAAc;AAE5B,cAAI,OAAO,WAAW,YAAY,SAAS,KAAK,UAAU,GAAG;AACzD,kBAAM,IAAI,MAAM,oFAAoF;AAAA,UACxG;AAAA,QACJ,OACK;AAED,mBAAS,KAAK,OAAO;AAAA,QACzB;AAEA,YAAI,SAAS,SAAS,KAAK,MAAM,SAAS,SAAS,MAAM;AAEzD,YAAI,CAAC,YAAY;AACb,eAAK,OAAO,QAAQ,CAAC;AAAA,QACzB;AAEA,eAAO;AAAA,MACX;AAOA,MAAAA,OAAM,UAAU,eAAe,SAAU,SAAS,SAAS;AACvD,YAAI,YAAY,QAAQ;AAAE,oBAAU,CAAC;AAAA,QAAG;AACxC,YAAI,iBAAiB,GAAG,YAAY,mBAAmB,QAAQ,MAAM,IAAI,QAAQ,QAAQ;AAEzF,YAAI,YAAY,GAAG;AACf,iBAAO,CAAC;AAAA,QACZ;AAEA,YAAI,EAAE,GAAG,YAAY,iBAAiB,OAAO,GAAG;AAC5C,gBAAM,IAAI,MAAM,wCAAwC;AAAA,QAC5D;AACA,YAAI,SAAS,CAAC;AAGd,eAAO,OAAO,SAAS,WAAW,KAAK,cAAc,SAAS,GAAG;AAC7D,iBAAO,KAAK,KAAK,KAAK,OAAO,CAAC;AAAA,QAClC;AAEA,YAAI,eAAe;AAEf,cAAI,SAAS,CAAC;AAEd,mBAAS,KAAK,GAAG,WAAW,QAAQ,KAAK,SAAS,QAAQ,MAAM;AAC5D,gBAAI,cAAc,SAAS;AAC3B,gBAAI,OAAO,QAAQ,WAAW,MAAM,IAAI;AACpC,qBAAO,KAAK,WAAW;AAAA,YAC3B;AAAA,UACJ;AACA,mBAAS;AAAA,QACb;AACA,eAAO;AAAA,MACX;AACA,aAAOA;AAAA,IACX,EAAE;AACF,YAAQ,QAAQA;AAAA;AAAA;;;AC5JhB;AAAA;AAAA;AACA,WAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,YAAQ,cAAc;AACtB,QAAI,UAAU;AAMd,aAASC,aAAY,uBAAuB;AAExC,UAAI,CAAC,uBAAuB;AACxB,eAAO,IAAI,QAAQ,MAAM;AAAA,MAC7B;AAEA,UAAI,MAAM,QAAQ,qBAAqB,GAAG;AAEtC,YAAI,eAAe;AACnB,YAAI,UAAU,IAAI,QAAQ,MAAM;AAEhC,qBAAa,QAAQ,SAAU,IAAI;AAC/B,cAAI,cAAc,GAAG,IAAI,SAAS,GAAG;AACrC,iBAAO,QAAQ,IAAI,aAAa,MAAM;AAAA,QAC1C,CAAC;AAED,eAAO;AAAA,MACX,OACK;AAED,YAAI,SAAS,sBAAsB,QAAQ,eAAe,sBAAsB;AAEhF,YAAI,UAAU,IAAI,QAAQ,MAAM,MAAM;AAEtC,YAAI,cAAc;AACd,uBAAa,QAAQ,SAAU,IAAI;AAC/B,gBAAI,cAAc,GAAG,IAAI,SAAS,GAAG;AACrC,mBAAO,QAAQ,IAAI,aAAa,MAAM;AAAA,UAC1C,CAAC;AAAA,QACL;AAEA,eAAO;AAAA,MACX;AAAA,IACJ;AACA,YAAQ,cAAcA;AAAA;AAAA;;;AC3CtB;AAAA;AAAA;AACA,WAAO,eAAe,SAAS,cAAc,EAAE,OAAO,KAAK,CAAC;AAC5D,QAAI,gBAAgB;AACpB,YAAQ,UAAU,cAAc;AAAA;AAAA;;;ACHhC;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,IAAqB,4BAArB,cAAuD,MAAM;AAAA,EAIzD,YAAoB,QAAc;AAC9B,UAAM,mCAAmC;AADzB;AAAA,EAEpB;AAAA,EAOA,eAAe,CAAC,SAAe,SAAS,KAAK;AACjD;;;ACNA,IAAqB,YAArB,MAA+B;AAAA,EAI3B,YAAoB,OAAwB;AAAxB;AAAA,EAAyB;AAAA,EAO7C,WAAW,CAAC,UAAiB;AAEzB,eAAW,WAAW,KAAK,OAAO;AAE9B,iBAAW,SAAS,QAAQ,QAAQ;AAEhC,YAAI,CAAC,MAAM,YAAY,KAAK,GAAG;AAC3B,gBAAM,IAAI,0BAA0B,QAAQ,IAAI;AAAA,QACpD;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AACJ;;;ACjCO,IAAK,QAAL,kBAAKC,WAAL;AACH,EAAAA,OAAA,WAAQ;AACR,EAAAA,OAAA,aAAU;AACV,EAAAA,OAAA,eAAY;AACZ,EAAAA,OAAA,YAAS;AAJD,SAAAA;AAAA,GAAA;;;ACaZ,IAA8B,OAA9B,MAAmC;AAAA,EAmB/B,YAAoB,MAAsB,YAAiC,MAAqB;AAA5E;AAAsB;AAAiC;AAAA,EAAsB;AAAA,EAfhF,MAAc,cAAc;AAAA,EAIrC;AAAA,EAIA;AAAA,EA6BR,WAAW,MAAgB,KAAK;AAAA,EAChC,WAAW,CAAC,UAA0B;AAClC,SAAK,QAAQ;AAAA,EACjB;AAAA,EAKA,SAAS,MAAM,KAAK;AAAA,EAKpB,UAAU,MAAM,KAAK;AAAA,EAKrB,gBAAgB,MAAM,KAAK;AAAA,EAK3B,eAAe,MAAM,KAAK;AAAA,EAQ1B,aAAa,MAAyB;AAClC,WACI,KAAK,cAAc,EAAE,OAAO,CAAC,cAAc,UAAU,QAAQ,EAAE,YAAY,MAAM,KAAK,YAAY,CAAC,EAAE,MACrG;AAAA,EAER;AAAA,EAKA,qBAAqB,MAAe,KAAK,cAAc,EAAE,OAAO,CAAC,cAAc,UAAU,QAAQ,CAAC;AAAA,EAKlG,eAAe,CAAC,UAAsB,KAAK,YAAY;AAAA,EAKvD,eAAe,MAAM,CAAC,CAAC,KAAK;AAAA,EAMrB,GAAG,OAA0B;AAChC,WAAO,KAAK,UAAU;AAAA,EAC1B;AAAA,EAKO,QAAc;AACjB,SAAK,wCAAoB;AAAA,EAC7B;AAAA,EAMO,MAAM,OAAoB;AAE7B,QAAI,CAAC,KAAK,sCAAgB,GAAG;AACzB;AAAA,IACJ;AAGA,SAAK,MAAM;AAEX,SAAK,aAAa,MAAM,GAAG,kBAAkB,OAAO,OAAO,IAAI;AAAA,EACnE;AAAA,EAQO,OAAO,OAAc,SAAqC;AAE7D,QAAI,KAAK,0CAAkB,KAAK,KAAK,oCAAe,GAAG;AACnD;AAAA,IACJ;AAEA,QAAI;AAEA,WAAK,UAAW,SAAS,KAAK;AAG9B,UAAI,KAAK,kCAAc,GAAG;AACtB,aAAK,aAAa,OAAO,GAAG,kBAAkB,KAAK;AAAA,MACvD;AAEA,WAAK,aAAa,MAAM,GAAG,kBAAkB,KAAK;AAGlD,WAAK,SAAS,OAAO,OAAO;AAG5B,UAAI,KAAK,0CAAkB,KAAK,KAAK,oCAAe,GAAG;AACnD,aAAK,aAAa,MAAM,GAAG,kBAAkB,OAAO,KAAK,0CAAkB,GAAG,KAAK;AAAA,MACvF;AAAA,IACJ,SAAS,OAAP;AAEE,UAAI,iBAAiB,6BAA6B,MAAM,aAAa,IAAI,GAAG;AAExE,aAAK,MAAM,KAAK;AAGhB,aAAK,0CAAqB;AAAA,MAC9B,OAAO;AACH,cAAM;AAAA,MACV;AAAA,IACJ;AAAA,EACJ;AACJ;AAMA,SAAS,gBAAwB;AAC7B,MAAI,KAAK,WAAY;AACjB,aAAU,IAAI,KAAK,OAAO,KAAK,QAAW,GAAG,SAAS,EAAE,EAAE,UAAU,CAAC;AAAA,EACzE;AACA,SAAO,GAAG,IAAI,GAAG,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,IAAI,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG;AACvF;;;AC9LA,IAA8B,OAA9B,cAA2C,KAAK;AAAA,EAI5C,aAAa,MAAM;AACvB;;;ACGA,IAAqB,SAArB,MAA4B;AAAA,EAexB,OAAc,QAAQ,MAA8B;AAChD,WAAO,KAAK,cAAc;AAAA,EAC9B;AAAA,EAOA,OAAc,QAAQ,MAAc,MAA4B;AAC5D,SAAK,cAAc,QAAQ;AAAA,EAC/B;AAAA,EAUA,OAAO,eAAe,OAAc,MAAsC;AAEtE,UAAM,eAAe,MAAM;AAC3B,QAAI,gBAAgB,OAAO,iBAAiB,YAAY;AACpD,aAAO,CAAC,SACJ,aAAa;AAAA,QACT;AAAA,QACA,KAAK,IAAI,CAAC,QAAQ,IAAI,KAAK;AAAA,MAC/B;AAAA,IACR;AAGA,QAAI,KAAK,cAAc,SAAS,OAAO,KAAK,cAAc,UAAU,YAAY;AAC5E,aAAO,CAAC,SAA4B,KAAK,cAAc,MAAM,OAAO,GAAG,KAAK,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC;AAAA,IACvG;AAGA,WAAO;AAAA,EACX;AAAA,EAOA,OAAO,WAAW,MAA2B;AACzC,WAAO,KAAK,aAAa;AAAA,EAC7B;AAAA,EAOA,OAAO,WAAW,MAAc,SAAsB;AAClD,SAAK,aAAa,QAAQ;AAAA,EAC9B;AAAA,EAMA,OAAO,OAAO,MAAc;AACxB,WAAO,KAAK,cAAc;AAC1B,WAAO,KAAK,aAAa;AAAA,EAC7B;AAAA,EAKA,OAAO,QAAQ;AACX,SAAK,gBAAgB,CAAC;AACtB,SAAK,eAAe,CAAC;AAAA,EACzB;AACJ;AAtFI,cAJiB,QAIF,iBAAmD,CAAC;AAInE,cARiB,QAQF,gBAA+C,CAAC;;;ACTnE,IAAqB,SAArB,cAAoC,KAAK;AAAA,EAMrC,YAAY,YAAiC,YAA4B,iBAAgC;AACrG,UAAM,UAAU,YAAY,eAAe;AADF;AAA4B;AAAA,EAEzE;AAAA,EAKQ,uBAAuB;AAAA,EAKvB,2BAAiD;AAAA,EAO/C,SAAS,OAAc,SAAqC;AAGlE,QAAI,KAAK,sBAAsB;AAE3B,UAAI,KAAK,0BAA0B;AAE/B,aAAK,SAAS,KAAK,wBAAwB;AAAA,MAC/C;AAEA;AAAA,IACJ;AAGA,UAAM,oBAAoB,OAAO,eAAe,OAAO,KAAK,UAAU;AAGtE,QAAI,sBAAsB,MAAM;AAC5B,YAAM,IAAI;AAAA,QACN,4CAA4C,KAAK;AAAA,MACrD;AAAA,IACJ;AAMA,UAAM,eAAe,kBAAkB,KAAK,eAAe;AAE3D,QAAI,wBAAwB,SAAS;AACjC,mBAAa;AAAA,QACT,CAAC,WAAW;AAER,cAAI,CAAC,KAAK,sBAAsB;AAC5B;AAAA,UACJ;AAGA,cAAI,sDAA8B,8CAAyB;AACvD,kBAAM,IAAI;AAAA,cACN;AAAA,YACJ;AAAA,UACJ;AAGA,eAAK,2BAA2B;AAAA,QACpC;AAAA,QACA,CAAC,WAAW;AAER,cAAI,CAAC,KAAK,sBAAsB;AAC5B;AAAA,UACJ;AAGA,gBAAM,IAAI,MAAM,MAAM;AAAA,QAC1B;AAAA,MACJ;AAGA,WAAK,4CAAsB;AAG3B,WAAK,uBAAuB;AAAA,IAChC,OAAO;AAEH,WAAK,qBAAqB,YAAY;AAGtC,WAAK,SAAS,mDAA6B;AAAA,IAC/C;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM,KAAK;AAAA,EAKrB,QAAQ,MAAM;AAEV,SAAK,wCAAoB;AAGzB,SAAK,uBAAuB;AAC5B,SAAK,2BAA2B;AAAA,EACpC;AAAA,EAMQ,uBAAuB,CAAC,WAAoC;AAChE,YAAQ,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA,KAAK;AACD;AAAA,MACJ;AACI,cAAM,IAAI;AAAA,UACN,WAAW,KAAK;AAAA,QACpB;AAAA,IACR;AAAA,EACJ;AACJ;;;AClIA,IAAqB,YAArB,cAAuC,KAAK;AAAA,EAMxC,YAAY,YAAiC,eAA+B,oBAAmC;AAC3G,UAAM,aAAa,YAAY,kBAAkB;AADR;AAA+B;AAAA,EAE5E;AAAA,EAOU,SAAS,OAAc,SAAqC;AAElE,UAAM,uBAAuB,OAAO,eAAe,OAAO,KAAK,aAAa;AAG5E,QAAI,yBAAyB,MAAM;AAC/B,YAAM,IAAI;AAAA,QACN,kDAAkD,KAAK;AAAA,MAC3D;AAAA,IACJ;AAGA,SAAK,SAAS,CAAC,CAAC,qBAAqB,KAAK,kBAAkB,+EAAkC;AAAA,EAClG;AAAA,EAKA,UAAU,MAAM,KAAK;AACzB;;;ACpCA,IAAqB,OAArB,cAAkC,KAAK;AAAA,EAOnC,YACI,YACQ,UACA,aACA,aACV;AACE,UAAM,QAAQ,YAAY,CAAC,CAAC;AAJpB;AACA;AACA;AAAA,EAGZ;AAAA,EAKQ,oBAA4B;AAAA,EAK5B,gBAA+B;AAAA,EAK/B,iBAAyB;AAAA,EAOvB,SAAS,OAAc,SAAqC;AAElE,QAAI,KAAK,kCAAc,GAAG;AAEtB,WAAK,oBAAoB,IAAI,KAAK,EAAE,QAAQ;AAG5C,WAAK,iBAAiB;AAGtB,UAAI,KAAK,aAAa,MAAM;AACxB,aAAK,gBAAgB,KAAK;AAAA,MAC9B,WAAW,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,MAAM;AAC/D,aAAK,gBAAgB,KAAK;AAAA,UACtB,KAAK,OAAO,KAAK,KAAK,cAAc,KAAK,cAAc,KAAK,KAAK;AAAA,QACrE;AAAA,MACJ,OAAO;AACH,aAAK,gBAAgB;AAAA,MACzB;AAGA,WAAK,4CAAsB;AAAA,IAC/B;AAGA,QAAI,KAAK,kBAAkB,MAAM;AAC7B;AAAA,IACJ;AAGA,QAAI,OAAO,QAAQ,iBAAiB,YAAY;AAE5C,YAAM,YAAY,QAAQ,aAAa;AAGvC,UAAI,OAAO,cAAc,YAAY,MAAM,SAAS,GAAG;AACnD,cAAM,IAAI,MAAM,oDAAoD;AAAA,MACxE;AAGA,WAAK,kBAAkB,YAAY;AAAA,IACvC,OAAO;AAEH,WAAK,iBAAiB,IAAI,KAAK,EAAE,QAAQ,IAAI,KAAK;AAAA,IACtD;AAGA,QAAI,KAAK,kBAAkB,KAAK,eAAe;AAE3C,WAAK,gDAAwB;AAAA,IACjC;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACZ,QAAI,KAAK,aAAa,MAAM;AACxB,aAAO,QAAQ,KAAK;AAAA,IACxB,WAAW,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,MAAM;AAC/D,aAAO,QAAQ,KAAK,iBAAiB,KAAK;AAAA,IAC9C,OAAO;AACH,aAAO;AAAA,IACX;AAAA,EACJ;AACJ;;;ACvGA,IAA8B,YAA9B,cAAgD,KAAK;AAAA,EAMjD,YAAY,MAAc,YAAmC,OAAa;AACtE,UAAM,MAAM,YAAY,CAAC,CAAC;AAD+B;AAAA,EAE7D;AAAA,EAKA,aAAa,MAAM;AAAA,EAKnB,cAAc,MAAM,CAAC,KAAK,KAAK;AAAA,EAK/B,QAAQ,MAAM;AAEV,SAAK,wCAAoB;AAGzB,SAAK,MAAM,MAAM;AAAA,EACrB;AAAA,EAMA,QAAQ,CAAC,UAAiB;AAEtB,QAAI,CAAC,KAAK,sCAAgB,GAAG;AACzB;AAAA,IACJ;AAGA,SAAK,MAAM,MAAM,KAAK;AAGtB,SAAK,MAAM;AAEX,SAAK,aAAa,MAAM,GAAG,kBAAkB,OAAO,OAAO,IAAI;AAAA,EACnE;AACJ;;;AC9CA,IAAqB,OAArB,cAAkC,UAAU;AAAA,EAKxC,YAAY,YAAyB,OAAa;AAC9C,UAAM,QAAQ,YAAY,KAAK;AAAA,EACnC;AAAA,EAOU,SAAS,OAAc,SAAqC;AAElE,QAAI,KAAK,MAAM,SAAS,yCAAqB,KAAK,MAAM,SAAS,2CAAqB;AAElF,WAAK,MAAM,OAAO,OAAO,OAAO;AAAA,IACpC;AAGA,SAAK,SAAS,KAAK,MAAM,SAAS,CAAC;AAAA,EACvC;AAAA,EAKA,UAAU,MAAM;AACpB;;;ACzBA,IAAqB,SAArB,cAAoC,UAAU;AAAA,EAO1C,YACI,YACQ,YACA,mBACR,OACF;AACE,UAAM,UAAU,YAAY,KAAK;AAJzB;AACA;AAAA,EAIZ;AAAA,EAKQ,uBAAsC;AAAA,EAKtC,wBAAgC;AAAA,EAO9B,SAAS,OAAc,SAAqC;AAElE,QAAI,KAAK,kCAAc,GAAG;AAEtB,WAAK,MAAM,MAAM;AAGjB,WAAK,wBAAwB;AAAA,IACjC;AAIA,QAAI,KAAK,WAAW,GAAG;AAEnB,WAAK,4CAAsB;AAI3B,UAAI,KAAK,MAAM,SAAS,+CAAuB;AAC3C,aAAK,MAAM,MAAM;AAAA,MACrB;AAGA,WAAK,MAAM,OAAO,OAAO,OAAO;AAIhC,UAAI,KAAK,MAAM,SAAS,yCAAoB;AAExC,aAAK,0CAAqB;AAE1B;AAAA,MACJ,WAAW,KAAK,MAAM,SAAS,+CAAuB;AAElD,aAAK,yBAAyB;AAAA,MAClC;AAAA,IACJ,OAAO;AAEH,WAAK,gDAAwB;AAAA,IACjC;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACZ,QAAI,KAAK,eAAe,MAAM;AAC1B,aAAO,UACH,KAAK,oBAAoB,KAAK,aAAa,OAAO,KAAK,oBAAoB,MAAM,KAAK,aAAa;AAAA,IAE3G;AAGA,WAAO;AAAA,EACX;AAAA,EAKA,QAAQ,MAAM;AAEV,SAAK,wCAAoB;AAGzB,SAAK,wBAAwB;AAG7B,SAAK,MAAM,MAAM;AAAA,EACrB;AAAA,EAMQ,aAAa,MAAM;AACvB,QAAI,KAAK,yBAAyB,MAAM;AAEpC,aAAO,KAAK,wBAAwB,KAAK;AAAA,IAC7C;AAGA,WAAO;AAAA,EACX;AAAA,EAKQ,0BAA0B,MAAM;AAEpC,QAAI,OAAO,KAAK,eAAe,UAAU;AAErC,WAAK,uBACD,OAAO,KAAK,sBAAsB,WAC5B,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,oBAAoB,KAAK,aAAa,KAAK,KAAK,UAAU,IAC3F,KAAK;AAAA,IACnB,OAAO;AACH,WAAK,uBAAuB;AAAA,IAChC;AAAA,EACJ;AACJ;;;AClIA,IAAqB,QAArB,cAAmC,UAAU;AAAA,EAOzC,YACI,YACQ,YACA,mBACR,OACF;AACE,UAAM,SAAS,YAAY,KAAK;AAJxB;AACA;AAAA,EAIZ;AAAA,EAKQ,uBAAsC;AAAA,EAKtC,wBAAgC;AAAA,EAO9B,SAAS,OAAc,SAAqC;AAElE,QAAI,KAAK,kCAAc,GAAG;AAEtB,WAAK,MAAM,MAAM;AAGjB,WAAK,wBAAwB;AAAA,IACjC;AAIA,QAAI,KAAK,WAAW,GAAG;AAEnB,WAAK,4CAAsB;AAI3B,UAAI,KAAK,MAAM,SAAS,yCAAoB;AACxC,aAAK,MAAM,MAAM;AAAA,MACrB;AAGA,WAAK,MAAM,OAAO,OAAO,OAAO;AAIhC,UAAI,KAAK,MAAM,SAAS,+CAAuB;AAE3C,aAAK,gDAAwB;AAE7B;AAAA,MACJ,WAAW,KAAK,MAAM,SAAS,yCAAoB;AAE/C,aAAK,yBAAyB;AAAA,MAClC;AAAA,IACJ,OAAO;AAEH,WAAK,0CAAqB;AAAA,IAC9B;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACZ,QAAI,KAAK,eAAe,MAAM;AAC1B,aAAO,SACH,KAAK,oBAAoB,KAAK,aAAa,OAAO,KAAK,oBAAoB,MAAM,KAAK,aAAa;AAAA,IAE3G;AAGA,WAAO;AAAA,EACX;AAAA,EAKA,QAAQ,MAAM;AAEV,SAAK,wCAAoB;AAGzB,SAAK,wBAAwB;AAG7B,SAAK,MAAM,MAAM;AAAA,EACrB;AAAA,EAMA,aAAa,MAAM;AACf,QAAI,KAAK,yBAAyB,MAAM;AAEpC,aAAO,KAAK,wBAAwB,KAAK;AAAA,IAC7C;AAGA,WAAO;AAAA,EACX;AAAA,EAKA,0BAA0B,MAAM;AAE5B,QAAI,OAAO,KAAK,eAAe,UAAU;AAErC,WAAK,uBACD,OAAO,KAAK,sBAAsB,WAC5B,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,oBAAoB,KAAK,aAAa,KAAK,KAAK,UAAU,IAC3F,KAAK;AAAA,IACnB,OAAO;AACH,WAAK,uBAAuB;AAAA,IAChC;AAAA,EACJ;AACJ;;;ACtIA,IAAqB,OAArB,cAAkC,UAAU;AAAA,EAKxC,YAAY,YAAyB,OAAa;AAC9C,UAAM,QAAQ,YAAY,KAAK;AAAA,EACnC;AAAA,EAOU,SAAS,OAAc,SAAqC;AAElE,QAAI,KAAK,MAAM,SAAS,yCAAqB,KAAK,MAAM,SAAS,2CAAqB;AAClF,WAAK,MAAM,OAAO,OAAO,OAAO;AAAA,IACpC;AAGA,YAAQ,KAAK,MAAM,SAAS,GAAG;AAAA,MAC3B;AACI,aAAK,4CAAsB;AAC3B;AAAA,MAEJ;AACI,aAAK,0CAAqB;AAC1B;AAAA,MAEJ;AACI,aAAK,gDAAwB;AAC7B;AAAA,MAEJ;AACI,aAAK,wCAAoB;AAAA,IACjC;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACpB;;;AC3CA,IAAqB,UAArB,cAAqC,UAAU;AAAA,EAK3C,YAAY,YAAyB,OAAa;AAC9C,UAAM,WAAW,YAAY,KAAK;AAAA,EACtC;AAAA,EAOU,SAAS,OAAc,SAAqC;AAElE,QAAI,KAAK,MAAM,SAAS,yCAAqB,KAAK,MAAM,SAAS,2CAAqB;AAClF,WAAK,MAAM,OAAO,OAAO,OAAO;AAAA,IACpC;AAGA,YAAQ,KAAK,MAAM,SAAS,GAAG;AAAA,MAC3B;AACI,aAAK,4CAAsB;AAC3B;AAAA,MAEJ;AAAA,MACA;AACI,aAAK,gDAAwB;AAC7B;AAAA,MAEJ;AACI,aAAK,wCAAoB;AAAA,IACjC;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACpB;;;ACxCA,IAAqB,OAArB,cAAkC,UAAU;AAAA,EAKxC,YAAY,YAAyB,OAAa;AAC9C,UAAM,QAAQ,YAAY,KAAK;AAAA,EACnC;AAAA,EAOU,SAAS,OAAc,SAAqC;AAElE,QAAI,KAAK,MAAM,SAAS,yCAAqB,KAAK,MAAM,SAAS,2CAAqB;AAClF,WAAK,MAAM,OAAO,OAAO,OAAO;AAAA,IACpC;AAGA,YAAQ,KAAK,MAAM,SAAS,GAAG;AAAA,MAC3B;AACI,aAAK,4CAAsB;AAC3B;AAAA,MAEJ;AAAA,MACA;AACI,aAAK,0CAAqB;AAC1B;AAAA,MAEJ;AACI,aAAK,wCAAoB;AAAA,IACjC;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACpB;;;ACnDA,wBAAwB;;;ACQxB,IAA8B,YAA9B,cAAgD,KAAK;AAAA,EAMjD,YAAY,MAAc,YAAmC,UAAkB;AAC3E,UAAM,MAAM,YAAY,CAAC,CAAC;AAD+B;AAAA,EAE7D;AAAA,EAKA,aAAa,MAAM;AAAA,EAKnB,cAAc,MAAM,KAAK;AAAA,EAKzB,QAAQ,MAAM;AAEV,SAAK,wCAAoB;AAGzB,SAAK,YAAY,EAAE,QAAQ,CAAC,UAAU,MAAM,MAAM,CAAC;AAAA,EACvD;AAAA,EAMA,QAAQ,CAAC,UAAiB;AAEtB,QAAI,CAAC,KAAK,sCAAgB,GAAG;AACzB;AAAA,IACJ;AAGA,SAAK,YAAY,EAAE,QAAQ,CAAC,UAAU,MAAM,MAAM,KAAK,CAAC;AAGxD,SAAK,MAAM;AAEX,SAAK,aAAa,MAAM,GAAG,kBAAkB,OAAO,OAAO,IAAI;AAAA,EACnE;AACJ;;;AD3CA,IAAqB,QAArB,cAAmC,UAAU;AAAA,EAMzC,YAAY,YAAiC,SAAmB,UAAkB;AAC9E,UAAM,SAAS,YAAY,QAAQ;AADM;AAAA,EAE7C;AAAA,EAKQ;AAAA,EAOE,SAAS,OAAc,SAAqC;AAElE,QAAI,KAAK,kCAAc,GAAG;AAEtB,YAAM,gBAAY,kBAAAC,SAAkB;AAAA,QAEhC,QAAQ,QAAQ;AAAA,QAEhB,cAAc,KAAK,SAAS,IAAI,CAAC,OAAO,UAAU,CAAC,OAAO,KAAK,QAAQ,UAAU,CAAC,CAAC;AAAA,MACvF,CAAC;AAGD,WAAK,gBAAgB,UAAU,KAAK,KAAK;AAAA,IAC7C;AAGA,QAAI,CAAC,KAAK,eAAe;AACrB,YAAM,IAAI,MAAM,uDAAuD;AAAA,IAC3E;AAGA,QAAI,KAAK,cAAc,SAAS,yCAAqB,KAAK,cAAc,SAAS,2CAAqB;AAClG,WAAK,cAAc,OAAO,OAAO,OAAO;AAAA,IAC5C;AAGA,SAAK,SAAS,KAAK,cAAc,SAAS,CAAC;AAAA,EAC/C;AAAA,EAKA,UAAU,MAAO,KAAK,QAAQ,SAAS,UAAU,KAAK,QAAQ,KAAK,GAAG,OAAO;AACjF;;;AExDA,IAAqB,WAArB,cAAsC,UAAU;AAAA,EAK5C,YAAY,YAAmC,UAAkB;AAC7D,UAAM,YAAY,YAAY,QAAQ;AADK;AAAA,EAE/C;AAAA,EAOU,SAAS,OAAc,SAAqC;AAElE,eAAW,SAAS,KAAK,UAAU;AAE/B,UAAI,MAAM,SAAS,yCAAqB,MAAM,SAAS,2CAAqB;AAExE,cAAM,OAAO,OAAO,OAAO;AAAA,MAC/B;AAGA,UAAI,MAAM,SAAS,+CAAuB;AAEtC,aAAK,gDAAwB;AAG7B;AAAA,MACJ;AAGA,UAAI,MAAM,SAAS,yCAAoB;AAGnC,YAAI,KAAK,SAAS,QAAQ,KAAK,MAAM,KAAK,SAAS,SAAS,GAAG;AAE3D,eAAK,0CAAqB;AAG1B;AAAA,QACJ,OAAO;AAEH;AAAA,QACJ;AAAA,MACJ;AAGA,UAAI,MAAM,SAAS,2CAAqB;AAEpC,aAAK,4CAAsB;AAG3B;AAAA,MACJ;AAGA,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC9D;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACpB;;;AClEA,IAAqB,WAArB,cAAsC,UAAU;AAAA,EAK5C,YAAY,YAAmC,UAAkB;AAC7D,UAAM,YAAY,YAAY,QAAQ;AADK;AAAA,EAE/C;AAAA,EAOU,SAAS,OAAc,SAAqC;AAElE,eAAW,SAAS,KAAK,UAAU;AAE/B,UAAI,MAAM,SAAS,yCAAqB,MAAM,SAAS,2CAAqB;AAExE,cAAM,OAAO,OAAO,OAAO;AAAA,MAC/B;AAGA,UAAI,MAAM,SAAS,+CAAuB;AAGtC,YAAI,KAAK,SAAS,QAAQ,KAAK,MAAM,KAAK,SAAS,SAAS,GAAG;AAE3D,eAAK,gDAAwB;AAG7B;AAAA,QACJ,OAAO;AAEH;AAAA,QACJ;AAAA,MACJ;AAGA,UAAI,MAAM,SAAS,yCAAoB;AAEnC,aAAK,0CAAqB;AAG1B;AAAA,MACJ;AAGA,UAAI,MAAM,SAAS,2CAAqB;AAEpC,aAAK,4CAAsB;AAG3B;AAAA,MACJ;AAGA,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC9D;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACpB;;;AClEA,IAAqB,WAArB,cAAsC,UAAU;AAAA,EAK5C,YAAY,YAAyB,UAAkB;AACnD,UAAM,YAAY,YAAY,QAAQ;AAAA,EAC1C;AAAA,EAOU,SAAS,OAAc,SAAqC;AAElE,QAAI,iBAAiB;AAErB,QAAI,iBAAiB;AAGrB,eAAW,SAAS,KAAK,UAAU;AAE/B,UAAI,MAAM,SAAS,yCAAqB,MAAM,SAAS,2CAAqB;AAExE,cAAM,OAAO,OAAO,OAAO;AAAA,MAC/B;AAGA,UAAI,MAAM,SAAS,+CAAuB;AAEtC;AAGA;AAAA,MACJ;AAGA,UAAI,MAAM,SAAS,yCAAoB;AACnC,yBAAiB;AAGjB;AAAA,MACJ;AAGA,UAAI,MAAM,SAAS,2CAAqB;AAEpC,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC9D;AAAA,IACJ;AAEA,QAAI,gBAAgB;AAEhB,WAAK,0CAAqB;AAG1B,iBAAW,SAAS,KAAK,UAAU;AAC/B,YAAI,MAAM,SAAS,2CAAqB;AACpC,gBAAM,MAAM,KAAK;AAAA,QACrB;AAAA,MACJ;AAAA,IACJ,OAAO;AAEH,WAAK,SAAS,mBAAmB,KAAK,SAAS,sFAAwC;AAAA,IAC3F;AAAA,EACJ;AAAA,EAKA,UAAU,MAAM;AACpB;;;ACrEA,IAA8B,YAA9B,MAAuG;AAAA,EAKnG,YAAsB,MAAwB,MAAqB;AAA7C;AAAwB;AAAA,EAAsB;AAAA,EAKpE,UAAU,MAAM,KAAK;AAAA,EAKrB,eAAe,MAAM,KAAK;AAW9B;;;AC5BA,IAA8B,QAA9B,cAA4C,UAAiC;AAAA,EAMzE,YAAY,MAAc,MAA6B,WAAmB;AACtE,UAAM,MAAM,IAAI;AADmC;AAAA,EAEvD;AAAA,EAKA,eAAe,MAAM,KAAK;AAAA,EAK1B,UAAU,MAAM;AAAA,EAKhB,aAAoC;AAChC,WAAO;AAAA,MACH,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,KAAK,aAAa;AAAA,MACxB,WAAW,KAAK,aAAa;AAAA,IACjC;AAAA,EACJ;AAQJ;;;ACzCA,IAAqB,QAArB,cAAmC,MAAM;AAAA,EAKrC,YAAY,WAAmB,MAAqB;AAChD,UAAM,SAAS,MAAM,SAAS;AAAA,EAClC;AAAA,EAOA,cAAc,CAAC,UAAiB;AAE5B,UAAM,uBAAuB,OAAO,eAAe,OAAO,KAAK,aAAa,CAAC;AAG7E,QAAI,yBAAyB,MAAM;AAC/B,YAAM,IAAI;AAAA,QACN,gDAAgD,KAAK,aAAa;AAAA,MACtE;AAAA,IACJ;AAGA,WAAO,CAAC,CAAC,qBAAqB,KAAK,IAAI;AAAA,EAC3C;AACJ;;;AC5BA,IAAqB,QAArB,cAAmC,MAAM;AAAA,EAKrC,YAAY,WAAmB,MAAqB;AAChD,UAAM,SAAS,MAAM,SAAS;AAAA,EAClC;AAAA,EAOA,cAAc,CAAC,UAAiB;AAE5B,UAAM,uBAAuB,OAAO,eAAe,OAAO,KAAK,aAAa,CAAC;AAG7E,QAAI,yBAAyB,MAAM;AAC/B,YAAM,IAAI;AAAA,QACN,gDAAgD,KAAK,aAAa;AAAA,MACtE;AAAA,IACJ;AAGA,WAAO,CAAC,CAAC,CAAC,qBAAqB,KAAK,IAAI;AAAA,EAC5C;AACJ;;;ACxBA,IAA8B,WAA9B,cAA+C,UAAoC;AAAA,EAM/E,YAAY,MAAc,MAA6B,cAAsB;AACzE,UAAM,MAAM,IAAI;AADmC;AAAA,EAEvD;AAAA,EAKA,kBAAkB,MAAM,KAAK;AAAA,EAK7B,UAAU,MAAM;AAAA,EAKhB,aAAuC;AACnC,WAAO;AAAA,MACH,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,KAAK,aAAa;AAAA,MACxB,cAAc,KAAK,gBAAgB;AAAA,IACvC;AAAA,EACJ;AAOJ;;;ACxCA,IAAqB,QAArB,cAAmC,SAAS;AAAA,EAKxC,YAAY,cAAsB,MAAqB;AACnD,UAAM,SAAS,MAAM,YAAY;AAAA,EACrC;AAAA,EAMA,oBAAoB,CAAC,UAAiB;AAElC,UAAM,sBAAsB,OAAO,eAAe,OAAO,KAAK,gBAAgB,CAAC;AAG/E,QAAI,wBAAwB,MAAM;AAC9B,YAAM,IAAI;AAAA,QACN,+BAA+B,KAAK,gBAAgB;AAAA,MACxD;AAAA,IACJ;AAGA,wBAAoB,KAAK,IAAI;AAAA,EACjC;AACJ;;;AC3BA,IAAqB,OAArB,cAAkC,SAAS;AAAA,EAKvC,YAAY,cAAsB,MAAqB;AACnD,UAAM,QAAQ,MAAM,YAAY;AAAA,EACpC;AAAA,EAQA,oBAAoB,CAAC,OAAc,WAAoB,cAAuB;AAE1E,UAAM,sBAAsB,OAAO,eAAe,OAAO,KAAK,gBAAgB,CAAC;AAG/E,QAAI,wBAAwB,MAAM;AAC9B,YAAM,IAAI;AAAA,QACN,8BAA8B,KAAK,gBAAgB;AAAA,MACvD;AAAA,IACJ;AAGA,wBAAoB,CAAC,EAAE,OAAO,EAAE,WAAW,WAAW,SAAS,UAAU,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC;AAAA,EAC/F;AACJ;;;AC7BA,IAAqB,OAArB,cAAkC,SAAS;AAAA,EAKvC,YAAY,cAAsB,MAAqB;AACnD,UAAM,QAAQ,MAAM,YAAY;AAAA,EACpC;AAAA,EAMA,oBAAoB,CAAC,UAAiB;AAElC,UAAM,sBAAsB,OAAO,eAAe,OAAO,KAAK,gBAAgB,CAAC;AAG/E,QAAI,wBAAwB,MAAM;AAC9B,YAAM,IAAI;AAAA,QACN,8BAA8B,KAAK,gBAAgB;AAAA,MACvD;AAAA,IACJ;AAGA,wBAAoB,KAAK,IAAI;AAAA,EACjC;AACJ;;;ACqBA,IAAM,qBAEF;AAAA,EACA,OAAO,CAAC,WAAmB,uBAAsC,IAAI,MAAM,WAAW,kBAAkB;AAAA,EACxG,OAAO,CAAC,WAAmB,uBAAsC,IAAI,MAAM,WAAW,kBAAkB;AAAA,EACxG,OAAO,CAAC,cAAsB,uBAAsC,IAAI,MAAM,cAAc,kBAAkB;AAAA,EAC9G,MAAM,CAAC,cAAsB,uBAAsC,IAAI,KAAK,cAAc,kBAAkB;AAAA,EAC5G,MAAM,CAAC,cAAsB,uBAAsC,IAAI,KAAK,cAAc,kBAAkB;AAChH;AAyFA,IAAM,mBAAmB;AAAA,EACrB,MAAM,OAAoB;AAAA,IACtB,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC;AAAA,IACX,SAAS,OAAe;AAEpB,UAAI,QAAQ,GAAG;AACX,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACrE;AAGA,UAAI,KAAK,SAAS,WAAW,GAAG;AAC5B,cAAM,IAAI,MAAM,sCAAsC;AAAA,MAC1D;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK,SAAU,GAAG,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC;AAAA,MACvF;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,QAAQ,OAAsB;AAAA,IAC1B,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,WAAW;AAAA,IAAC;AAAA,IACZ,mBAAmB,uBAAuB,iBAAiB;AAEvD,YAAM,iBAAiB,sBAAsB,KAAK,UAAU;AAG5D,UAAI,gBAAgB,QAAQ,KAAK,UAAU,MAAM,IAAI;AACjD,cAAM,IAAI,MAAM,mEAAmE,KAAK,aAAa;AAAA,MACzG;AAGA,UAAI,gBAAgB;AAChB,eAAO,eACF,mBAAmB,uBAAuB,gBAAgB,OAAO,KAAK,UAAU,CAAC,EACjF,YAAY,EAAE;AAAA,MACvB,OAAO;AACH,cAAM,IAAI,MAAM,gCAAgC,KAAK,wCAAwC;AAAA,MACjG;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,UAAU,OAAyB;AAAA,IAC/B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,IACX,WAAW;AAEP,UAAI,KAAK,SAAS,SAAS,GAAG;AAC1B,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACvE;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK,SAAS,IAAI,CAAC,UAAU,MAAM,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC,CAAC;AAAA,MACzG;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,UAAU,OAAyB;AAAA,IAC/B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,IACX,WAAW;AAEP,UAAI,KAAK,SAAS,SAAS,GAAG;AAC1B,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACvE;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK,SAAS,IAAI,CAAC,UAAU,MAAM,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC,CAAC;AAAA,MACzG;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,UAAU,OAAyB;AAAA,IAC/B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,IACX,WAAW;AAEP,UAAI,KAAK,SAAS,SAAS,GAAG;AAC1B,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACvE;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK,SAAS,IAAI,CAAC,UAAU,MAAM,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC,CAAC;AAAA,MACzG;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,OAAO,OAAqB;AAAA,IACxB,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,WAAW;AAEP,UAAI,KAAK,SAAU,SAAS,GAAG;AAC3B,cAAM,IAAI,MAAM,gDAAgD;AAAA,MACpE;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK,SAAU,IAAI,CAAC,UAAU,MAAM,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC,CAAC;AAAA,MAC1G;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,QAAQ,OAAwB;AAAA,IAC5B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,UAAU,CAAC;AAAA,IACX,WAAW;AAEP,UAAI,KAAK,SAAU,WAAW,GAAG;AAC7B,cAAM,IAAI,MAAM,wCAAwC;AAAA,MAC5D;AAGA,UAAI,KAAK,eAAe,QAAQ,KAAK,aAAc,GAAG;AAClD,cAAM,IAAI,MAAM,oEAAoE;AAAA,MACxF;AAGA,UAAI,KAAK,sBAAsB,MAAM;AAEjC,YAAI,KAAK,oBAAqB,GAAG;AAC7B,gBAAM,IAAI,MAAM,wEAAwE;AAAA,QAC5F;AAGA,YAAI,KAAK,aAAc,KAAK,mBAAoB;AAC5C,gBAAM,IAAI;AAAA,YACN;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK,SAAU,GAAG,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC;AAAA,MACvF;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,OAAO,OAAwB;AAAA,IAC3B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,YAAY;AAAA,IACZ,mBAAmB;AAAA,IACnB,UAAU,CAAC;AAAA,IACX,WAAW;AAEP,UAAI,KAAK,SAAU,WAAW,GAAG;AAC7B,cAAM,IAAI,MAAM,uCAAuC;AAAA,MAC3D;AAGA,UAAI,KAAK,eAAe,QAAQ,KAAK,aAAc,GAAG;AAClD,cAAM,IAAI,MAAM,mEAAmE;AAAA,MACvF;AAGA,UAAI,KAAK,sBAAsB,MAAM;AAEjC,YAAI,KAAK,oBAAqB,GAAG;AAC7B,gBAAM,IAAI,MAAM,uEAAuE;AAAA,QAC3F;AAGA,YAAI,KAAK,aAAc,KAAK,mBAAoB;AAC5C,gBAAM,IAAI;AAAA,YACN;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK,SAAU,GAAG,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC;AAAA,MACvF;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,MAAM,OAAyB;AAAA,IAC3B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,IACX,WAAW;AAEP,UAAI,KAAK,SAAU,WAAW,GAAG;AAC7B,cAAM,IAAI,MAAM,sCAAsC;AAAA,MAC1D;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK,SAAU,GAAG,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC;AAAA,MACvF;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,SAAS,OAAyB;AAAA,IAC9B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,IACX,WAAW;AAEP,UAAI,KAAK,SAAU,WAAW,GAAG;AAC7B,cAAM,IAAI,MAAM,yCAAyC;AAAA,MAC7D;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK,SAAU,GAAG,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC;AAAA,MACvF;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,MAAM,OAAyB;AAAA,IAC3B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,UAAU,CAAC;AAAA,IACX,WAAW;AAEP,UAAI,KAAK,SAAU,WAAW,GAAG;AAC7B,cAAM,IAAI,MAAM,sCAAsC;AAAA,MAC1D;AAAA,IACJ;AAAA,IACA,mBAAmB,uBAAuB,iBAAiB;AACvD,aAAO,IAAI;AAAA,QACP,KAAK;AAAA,QACL,KAAK,SAAU,GAAG,mBAAmB,uBAAuB,gBAAgB,MAAM,CAAC;AAAA,MACvF;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,MAAM,OAAoB;AAAA,IACtB,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,WAAW;AACP,UAAI,KAAK,aAAa,MAAM;AAExB,YAAI,KAAK,WAAW,GAAG;AACnB,gBAAM,IAAI,MAAM,2CAA2C;AAAA,QAC/D;AAAA,MACJ,WAAW,KAAK,gBAAgB,QAAQ,KAAK,gBAAgB,MAAM;AAE/D,YAAI,KAAK,cAAc,KAAK,KAAK,cAAc,GAAG;AAC9C,gBAAM,IAAI,MAAM,+DAA+D;AAAA,QACnF;AAGA,YAAI,KAAK,cAAc,KAAK,aAAa;AACrC,gBAAM,IAAI,MAAM,gFAAgF;AAAA,QACpG;AAAA,MACJ,OAAO;AAAA,MAEP;AAAA,IACJ;AAAA,IACA,qBAAqB;AACjB,aAAO,IAAI,KAAK,KAAK,YAAY,KAAK,UAAU,KAAK,aAAa,KAAK,WAAW;AAAA,IACtF;AAAA,EACJ;AAAA,EACA,QAAQ,OAAsB;AAAA,IAC1B,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,YAAY;AAAA,IACZ,iBAAiB,CAAC;AAAA,IAClB,WAAW;AAAA,IAAC;AAAA,IACZ,qBAAqB;AACjB,aAAO,IAAI,OAAO,KAAK,YAAY,KAAK,YAAa,KAAK,eAAgB;AAAA,IAC9E;AAAA,EACJ;AAAA,EACA,WAAW,OAAyB;AAAA,IAChC,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,IACb,eAAe;AAAA,IACf,oBAAoB,CAAC;AAAA,IACrB,WAAW;AAAA,IAAC;AAAA,IACZ,qBAAqB;AACjB,aAAO,IAAI,UAAU,KAAK,YAAY,KAAK,eAAgB,KAAK,kBAAmB;AAAA,IACvF;AAAA,EACJ;AACJ;AASe,SAAR,kBAAmC,YAAmC;AAEzE,QAAM,EAAE,cAAc,oBAAoB,IAAI,yBAAyB,UAAU;AAGjF,QAAM,SAAS,0BAA0B,mBAAmB;AAG5D,MAAI,OAAO,SAAS,GAAG;AACnB,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACzC;AAGA,MAAI,OAAO,OAAO,CAAC,UAAU,UAAU,GAAG,EAAE,WAAW,OAAO,OAAO,CAAC,UAAU,UAAU,GAAG,EAAE,QAAQ;AACnG,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC9C;AAGA,QAAM,QAA6C,CAAC,CAAC,CAAC;AACtD,QAAM,YAAY,MAAM;AAGxB,SAAO,OAAO,QAAQ;AAElB,UAAM,QAAQ,OAAO,MAAM;AAE3B,UAAM,eAAe,MAAM,MAAM,SAAS;AAG1C,YAAQ,MAAO,YAAY,GAAG;AAAA,MAC1B,KAAK,QAAQ;AAET,cAAM,OAAO,iBAAiB,KAAK;AAGnC,kBAAU,KAAK,IAAI;AAGnB,YAAI,OAAO,OAAO,KAAK;AACnB,gBAAM,gBAAgB,aAAa,QAAQ,YAAY;AAGvD,cAAI,cAAc,WAAW,KAAK,cAAc,GAAG,SAAS,cAAc;AAEtE,iBAAK,OAAO,cAAc,GAAG;AAAA,UACjC,OAAO;AACH,kBAAM,IAAI,MAAM,oCAAoC;AAAA,UACxD;AAAA,QACJ;AAGA,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,UAAU;AAEX,cAAM,OAAO,iBAAiB,OAAO;AAGrC,qBAAa,KAAK,IAAI;AAGtB,YAAI,OAAO,OAAO,KAAK;AACnB,gBAAM,IAAI,MAAM,sCAAsC;AAAA,QAC1D;AAGA,cAAM,kBAAkB,aAAa,QAAQ,YAAY;AAGzD,YAAI,gBAAgB,WAAW,KAAK,gBAAgB,GAAG,SAAS,cAAc;AAE1E,eAAK,aAAa,gBAAgB,GAAG;AAAA,QACzC,OAAO;AACH,gBAAM,IAAI,MAAM,sCAAsC;AAAA,QAC1D;AACA;AAAA,MACJ;AAAA,MAEA,KAAK,YAAY;AAEb,cAAM,OAAO,iBAAiB,SAAS;AAGvC,qBAAa,KAAK,IAAI;AAGtB,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,YAAY;AAEb,cAAM,OAAO,iBAAiB,SAAS;AAGvC,qBAAa,KAAK,IAAI;AAGtB,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,YAAY;AAEb,cAAM,OAAO,iBAAiB,SAAS;AAGvC,qBAAa,KAAK,IAAI;AAGtB,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,SAAS;AAEV,cAAM,OAAO,iBAAiB,MAAM;AAGpC,qBAAa,KAAK,IAAI;AAGtB,YAAI,OAAO,OAAO,KAAK;AAEnB,eAAK,UAAU;AAAA,YACX;AAAA,YACA;AAAA,YACA,CAAC,QAAQ,IAAI,SAAS,YAAY,CAAC,CAAC,IAAI;AAAA,YACxC;AAAA,UACJ,EAAE,IAAI,CAAC,aAAa,SAAS,KAAe;AAAA,QAChD;AAGA,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,aAAa;AAEd,cAAM,OAAO,iBAAiB,UAAU;AAGxC,qBAAa,KAAK,IAAI;AAGtB,YAAI,OAAO,OAAO,KAAK;AACnB,gBAAM,IAAI,MAAM,6CAA6C;AAAA,QACjE;AAGA,cAAM,qBAAqB,aAAa,QAAQ,YAAY;AAG5D,YAAI,mBAAmB,UAAU,mBAAmB,GAAG,SAAS,cAAc;AAE1E,eAAK,gBAAgB,mBAAmB,MAAM,EAAG;AAAA,QACrD,OAAO;AACH,gBAAM,IAAI,MAAM,6CAA6C;AAAA,QACjE;AAGA,2BACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,EACzC,QAAQ,CAAC,QAAQ;AACd,gBAAM,IAAI;AAAA,YACN,4CACI,IAAI,QACJ;AAAA,UACR;AAAA,QACJ,CAAC;AAGL,aAAK,qBAAqB;AAG1B,aAAK,aAAa,cAAc,QAAQ,YAAY;AACpD;AAAA,MACJ;AAAA,MAEA,KAAK,QAAQ;AAET,cAAM,OAAO,iBAAiB,KAAK;AAGnC,qBAAa,KAAK,IAAI;AAGtB,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,WAAW;AAEZ,cAAM,OAAO,iBAAiB,QAAQ;AAGtC,qBAAa,KAAK,IAAI;AAGtB,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,QAAQ;AAET,cAAM,OAAO,iBAAiB,KAAK;AAGnC,qBAAa,KAAK,IAAI;AAGtB,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,QAAQ;AAET,cAAM,OAAO,iBAAiB,KAAK;AAGnC,qBAAa,KAAK,IAAI;AAGtB,cAAM,gBAAgB;AAAA,UAClB;AAAA,UACA;AAAA,UACA,CAAC,QAAQ,IAAI,SAAS,YAAY,CAAC,CAAC,IAAI;AAAA,UACxC;AAAA,QACJ,EAAE,IAAI,CAAC,aAAa,SAAS,KAAK;AAMlC,YAAI,cAAc,WAAW,GAAG;AAE5B,eAAK,WAAW,cAAc;AAAA,QAClC,WAAW,cAAc,WAAW,GAAG;AAEnC,eAAK,cAAc,cAAc;AACjC,eAAK,cAAc,cAAc;AAAA,QACrC,WAAW,cAAc,SAAS,GAAG;AAEjC,gBAAM,IAAI,MAAM,wDAAwD;AAAA,QAC5E;AAGA,aAAK,aAAa,cAAc,QAAQ,YAAY;AACpD;AAAA,MACJ;AAAA,MAEA,KAAK,UAAU;AAEX,cAAM,OAAO,iBAAiB,OAAO;AAGrC,qBAAa,KAAK,IAAI;AAGtB,YAAI,OAAO,OAAO,KAAK;AAEnB,gBAAM,qBAAqB;AAAA,YACvB;AAAA,YACA;AAAA,YACA,CAAC,QAAQ,IAAI,SAAS,YAAY,CAAC,CAAC,IAAI;AAAA,YACxC;AAAA,UACJ,EAAE,IAAI,CAAC,aAAa,SAAS,KAAK;AAGlC,cAAI,mBAAmB,WAAW,GAAG;AAEjC,iBAAK,aAAa,mBAAmB;AAAA,UACzC,WAAW,mBAAmB,WAAW,GAAG;AAExC,iBAAK,aAAa,mBAAmB;AACrC,iBAAK,oBAAoB,mBAAmB;AAAA,UAChD,OAAO;AAEH,kBAAM,IAAI,MAAM,iEAAiE;AAAA,UACrF;AAAA,QACJ;AAGA,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,SAAS;AAEV,cAAM,OAAO,iBAAiB,MAAM;AAGpC,qBAAa,KAAK,IAAI;AAGtB,YAAI,OAAO,OAAO,KAAK;AAEnB,gBAAM,qBAAqB;AAAA,YACvB;AAAA,YACA;AAAA,YACA,CAAC,QAAQ,IAAI,SAAS,YAAY,CAAC,CAAC,IAAI;AAAA,YACxC;AAAA,UACJ,EAAE,IAAI,CAAC,aAAa,SAAS,KAAK;AAGlC,cAAI,mBAAmB,WAAW,GAAG;AAEjC,iBAAK,aAAa,mBAAmB;AAAA,UACzC,WAAW,mBAAmB,WAAW,GAAG;AAExC,iBAAK,aAAa,mBAAmB;AACrC,iBAAK,oBAAoB,mBAAmB;AAAA,UAChD,OAAO;AAEH,kBAAM,IAAI,MAAM,gEAAgE;AAAA,UACpF;AAAA,QACJ;AAGA,aAAK,aAAa,cAAc,QAAQ,YAAY;AAEpD,oBAAY,QAAQ,GAAG;AAGvB,cAAM,KAAK,KAAK,QAAS;AACzB;AAAA,MACJ;AAAA,MAEA,KAAK,UAAU;AAEX,cAAM,OAAO,iBAAiB,OAAO;AAGrC,qBAAa,KAAK,IAAI;AAGtB,YAAI,OAAO,OAAO,KAAK;AACnB,gBAAM,IAAI,MAAM,0CAA0C;AAAA,QAC9D;AAGA,cAAM,kBAAkB,aAAa,QAAQ,YAAY;AAGzD,YAAI,gBAAgB,UAAU,gBAAgB,GAAG,SAAS,cAAc;AAEpE,eAAK,aAAa,gBAAgB,MAAM,EAAG;AAAA,QAC/C,OAAO;AACH,gBAAM,IAAI,MAAM,0CAA0C;AAAA,QAC9D;AAGA,wBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,EACzC,QAAQ,CAAC,QAAQ;AACd,gBAAM,IAAI;AAAA,YACN,yCACI,IAAI,QACJ;AAAA,UACR;AAAA,QACJ,CAAC;AAGL,aAAK,kBAAkB;AAGvB,aAAK,aAAa,cAAc,QAAQ,YAAY;AACpD;AAAA,MACJ;AAAA,MAEA,KAAK,KAAK;AAEN,cAAM,IAAI;AACV;AAAA,MACJ;AAAA,MAEA,SAAS;AACL,cAAM,IAAI,MAAM,uBAAuB,KAAK;AAAA,MAChD;AAAA,IACJ;AAAA,EACJ;AAGA,QAAM,kBAAkB,CAAC,MAAmB,UAAwB;AAEhE,SAAK,SAAS,KAAK;AAGnB,KAAC,KAAK,YAAY,CAAC,GAAG,QAAQ,CAAC,UAAU,gBAAgB,OAAO,QAAQ,CAAC,CAAC;AAAA,EAC9E;AAGA;AAAA,IACI;AAAA,MACI,UAAU,MAAM;AAAA,MAChB,WAA4C;AAExC,YAAI,KAAK,SAAS,WAAW,GAAG;AAC5B,gBAAM,IAAI,MAAM,yCAAyC;AAAA,QAC7D;AAGA,mBAAW,uBAAuB,KAAK,UAAU;AAC7C,cAAI,oBAAoB,SAAS,QAAQ;AACrC,kBAAM,IAAI,MAAM,0CAA0C;AAAA,UAC9D;AAAA,QACJ;AAGA,YAAI,KAAK,SAAS,OAAO,CAAC,wBAAwB,oBAAoB,SAAS,IAAI,EAAE,WAAW,GAAG;AAC/F,gBAAM,IAAI,MAAM,6EAA6E;AAAA,QACjG;AAGA,cAAM,gBAA0B,CAAC;AACjC,mBAAW,uBAAuB,KAAK,UAAU;AAC7C,cAAI,cAAc,QAAQ,oBAAoB,IAAK,MAAM,IAAI;AACzD,kBAAM,IAAI,MAAM,kDAAkD,oBAAoB,OAAO;AAAA,UACjG,OAAO;AACH,0BAAc,KAAK,oBAAoB,IAAK;AAAA,UAChD;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAAA,IACA;AAAA,EACJ;AAGA,SAAO,MAAM;AACjB;AAQA,SAAS,YAAY,QAAkB,UAA6B;AAEhE,QAAM,SAAS,OAAO,MAAM;AAG5B,MAAI,WAAW,QAAW;AACtB,UAAM,IAAI,MAAM,8BAA8B;AAAA,EAClD;AAGA,MAAI,aAAa,QAAW;AAExB,QAAI,0BAA2B,CAAC,EAC3B,OAAO,QAAQ,EACf,KAAK,CAAC,SAAS,OAAO,YAAY,MAAM,KAAK,YAAY,CAAC;AAG/D,QAAI,CAAC,yBAAyB;AAC1B,YAAM,oBAAqB,CAAC,EACvB,OAAO,QAAQ,EACf,IAAI,CAAC,SAAS,MAAM,OAAO,GAAG,EAC9B,KAAK,MAAM;AAChB,YAAM,IAAI,MAAM,sCAAsC,oBAAoB,eAAe,SAAS,GAAG;AAAA,IACzG;AAAA,EACJ;AAGA,SAAO;AACX;AAYA,SAAS,aACL,QACA,4BACA,mBACA,yBACF;AAGE,QAAM,SAAS,YAAY,QAAQ,CAAC,KAAK,GAAG,CAAC,MAAM,MAAM,MAAM;AAE/D,QAAM,qBAA+B,CAAC;AACtC,QAAM,eAA8B,CAAC;AAGrC,SAAO,OAAO,UAAU,OAAO,OAAO,QAAQ;AAE1C,uBAAmB,KAAK,OAAO,MAAM,CAAE;AAAA,EAC3C;AAGA,qBAAmB,QAAQ,CAAC,OAAO,UAAU;AAEzC,UAAM,wBAAwB,EAAE,QAAQ;AAGxC,QAAI,uBAAuB;AAEvB,YAAM,qBAAqB,sBAAsB,OAAQ,0BAA0B;AAGnF,UAAI,qBAAqB,CAAC,kBAAkB,kBAAkB,GAAG;AAC7D,cAAM,IAAI,MAAM,uBAAuB;AAAA,MAC3C;AAGA,mBAAa,KAAK,kBAAkB;AAAA,IACxC,OAAO;AAEH,UAAI,UAAU,KAAK;AACf,cAAM,IAAI,MAAM,uDAAuD,QAAQ;AAAA,MACnF;AAAA,IACJ;AAAA,EACJ,CAAC;AAGD,cAAY,QAAQ,MAAM;AAG1B,SAAO;AACX;AAQA,SAAS,sBAAsB,OAAe,4BAAuD;AAEjG,MAAI,UAAU,QAAQ;AAClB,WAAO;AAAA,MACH,OAAO;AAAA,MACP,MAAM;AAAA,IACV;AAAA,EACJ;AAGA,MAAI,UAAU,UAAU,UAAU,SAAS;AACvC,WAAO;AAAA,MACH,OAAO,UAAU;AAAA,MACjB,MAAM;AAAA,IACV;AAAA,EACJ;AAKA,MAAI,CAAC,MAAM,KAAY,GAAG;AACtB,WAAO;AAAA,MACH,OAAO,WAAW,KAAK;AAAA,MACvB,WAAW,WAAW,KAAK,MAAM,SAAS,OAAO,EAAE;AAAA,MACnD,MAAM;AAAA,IACV;AAAA,EACJ;AAGA,MAAI,MAAM,MAAM,YAAY,GAAG;AAC3B,WAAO;AAAA,MACH,OAAO,2BAA2B,OAAO,QAAQ,OAAO,GAAG;AAAA,MAC3D,MAAM;AAAA,IACV;AAAA,EACJ;AAGA,SAAO;AAAA,IACH,OAAO;AAAA,IACP,MAAM;AAAA,EACV;AACJ;AAQA,SAAS,cAAc,QAAkB,4BAA0C;AAE/E,QAAM,aAA0B,CAAC;AAGjC,QAAM,kBAA4B,CAAC;AAGnC,MAAI,mBAAmB,oBAAoB,OAAO,MAAM,IAAI,YAAY;AAGxE,SAAO,kBAAkB;AAErB,QAAI,gBAAgB,QAAQ,OAAO,GAAG,YAAY,CAAC,MAAM,IAAI;AACzD,YAAM,IAAI,MAAM,wBAAwB,OAAO,GAAG,YAAY,mBAAmB;AAAA,IACrF;AAGA,oBAAgB,KAAK,OAAO,MAAM,EAAG,YAAY,CAAC;AAGlD,UAAM,qBAAqB,aAAa,QAAQ,0BAA0B;AAG1E,QAAI,mBAAmB,WAAW,KAAK,mBAAmB,GAAG,SAAS,cAAc;AAChF,YAAM,IAAI,MAAM,gEAAgE;AAAA,IACpF;AAGA,UAAM,wBAAwB,mBAAmB,MAAM;AAGvD,uBACK,OAAO,CAAC,QAAQ,IAAI,SAAS,YAAY,EACzC,QAAQ,CAAC,QAAQ;AACd,YAAM,IAAI;AAAA,QACN,uCAAuC,IAAI,QAAQ;AAAA,MACvD;AAAA,IACJ,CAAC;AAGL,eAAW,KAAK,iBAAiB,sBAAsB,OAAO,kBAAkB,CAAC;AAGjF,uBAAmB,oBAAoB,OAAO,MAAM,IAAI,YAAY;AAAA,EACxE;AAEA,SAAO;AACX;AAOA,SAAS,yBAAyB,YAGhC;AAEE,QAAM,eAA6B,CAAC;AAGpC,QAAM,sBAAsB,WAAW,QAAQ,sBAAsB,CAAC,UAAU;AAC5E,QAAI,gBAAgB,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC;AACvD,QAAI,cAAc,OAAO,KAAK,YAAY,EAAE,KAAK,CAAC,QAAQ,aAAa,SAAS,aAAa;AAG7F,QAAI,CAAC,aAAa;AACd,oBAAc,KAAK,OAAO,KAAK,YAAY,EAAE;AAC7C,mBAAa,eAAe;AAAA,IAChC;AAEA,WAAO;AAAA,EACX,CAAC;AAED,SAAO,EAAE,cAAc,oBAAoB;AAC/C;AAOA,SAAS,0BAA0B,YAA8B;AAE7D,eAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,eAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,eAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,eAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,eAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,eAAa,WAAW,QAAQ,OAAO,KAAK;AAC5C,eAAa,WAAW,QAAQ,OAAO,KAAK;AAG5C,SAAO,WAAW,QAAQ,QAAQ,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG;AAC3D;;;ACxoCO,IAAM,gBAAN,MAAoB;AAAA,EAYvB,YAAY,YAA4B,OAAsB,UAAgC,CAAC,GAAG;AAA1D;AAAsB;AAE1D,QAAI,OAAO,eAAe,UAAU;AAChC,YAAM,IAAI,MAAM,sCAAsC;AAAA,IAC1D;AAGA,QAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC7C,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC5D;AAGA,SAAK,WAAW,cAAc,eAAe,UAAU;AAAA,EAC3D;AAAA,EArBgB;AAAA,EA2BhB,YAAY;AACR,WAAO,KAAK,SAAS,SAAS;AAAA,EAClC;AAAA,EAMA,WAAW;AACP,WAAO,KAAK,SAAS,SAAS;AAAA,EAClC;AAAA,EAUA,OAAO;AAEH,QAAI,KAAK,SAAS,SAAS,iDAAyB,KAAK,SAAS,SAAS,yCAAoB;AAC3F,WAAK,SAAS,MAAM;AAAA,IACxB;AAEA,QAAI;AACA,WAAK,SAAS,OAAO,KAAK,OAAO,KAAK,OAAO;AAAA,IACjD,SAAS,WAAP;AACE,YAAM,IAAI,MAAM,wBAAyB,UAAoB,SAAS;AAAA,IAC1E;AAAA,EACJ;AAAA,EAKA,QAAQ;AACJ,SAAK,SAAS,MAAM;AAAA,EACxB;AAAA,EAMA,0BAA+C;AAE3C,UAAM,qBAA0C,CAAC;AAOjD,UAAM,cAAc,CAAC,MAAY,cAA6B;AAE1D,YAAM,SAAS,KACV,cAAc,EACd,OAAO,CAAC,cAAc,UAAU,QAAQ,CAAC,EACzC,IAAI,CAAC,cAAc,UAAU,WAAW,CAAC;AAC9C,YAAM,YAAY,KACb,cAAc,EACd,OAAO,CAAC,cAAc,CAAC,UAAU,QAAQ,CAAC,EAC1C,IAAI,CAAC,cAAc,UAAU,WAAW,CAAC;AAG9C,yBAAmB,KAAK;AAAA,QACpB,IAAI,KAAK,OAAO;AAAA,QAChB,MAAM,KAAK,QAAQ;AAAA,QACnB,SAAS,KAAK,QAAQ;AAAA,QACtB,OAAO,KAAK,SAAS;AAAA,QACrB;AAAA,QACA;AAAA,QACA,MAAM,KAAK,aAAa;AAAA,QACxB,UAAU;AAAA,MACd,CAAC;AAGD,UAAI,CAAC,KAAK,WAAW,GAAG;AACpB,QAAC,KACI,YAAY,EACZ,QAAQ,CAAC,UAAU,YAAY,OAAQ,KAA+B,OAAO,CAAC,CAAC;AAAA,MACxF;AAAA,IACJ;AAGA,gBAAY,KAAK,UAAU,IAAI;AAE/B,WAAO;AAAA,EACX;AAAA,EAOA,OAAO,SAAS,MAAc,OAAgC;AAC1D,QAAI,OAAO,UAAU,YAAY;AAE7B,aAAO,QAAQ,MAAM,KAAK;AAAA,IAC9B,WAAW,OAAO,UAAU,UAAU;AAElC,UAAI;AAEJ,UAAI;AAEA,uBAAe,kBAAkB,KAAK;AAAA,MAC1C,SAAS,WAAP;AAEE,cAAM,IAAI,MAAM,iCAAkC,UAAoB,SAAS;AAAA,MACnF;AAGA,UAAI,aAAa,UAAU,KAAK,aAAa,GAAG,SAAS,MAAM;AAC3D,cAAM,IAAI,MAAM,mEAAmE;AAAA,MACvF;AAEA,aAAO,WAAW,MAAM,aAAa,EAAE;AAAA,IAC3C,OAAO;AACH,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC9E;AAAA,EACJ;AAAA,EAMA,OAAO,WAAW,MAAoB;AAClC,WAAO,OAAO,IAAI;AAAA,EACtB;AAAA,EAKA,OAAO,gBAAsB;AACzB,WAAO,MAAM;AAAA,EACjB;AAAA,EAOA,OAAe,eAAe,YAA0B;AACpD,QAAI;AAEA,YAAM,eAAe,kBAAkB,UAAU;AAGjD,YAAM,kBAAkB,OAAO,UAAU;AAGzC,YAAM,cAAuD,CAAC;AAC9D,iBAAW,eAAe,cAAc;AACpC,oBAAY,YAAY,SAAS,OAAO,kBAAkB,YAAY,QAAS;AAAA,MACnF;AAGA,YAAM,WAAiB,YAAY,iBAAiB;AAAA,QAEhD,CAAC,SAA+B,YAAY,QAAQ,YAAY,QAAQ,OAAO,WAAW,IAAI;AAAA,QAC9F,CAAC;AAAA,MACL;AAGA,oBAAc,wBAAwB,QAAQ;AAG9C,aAAO;AAAA,IACX,SAAS,WAAP;AAEE,YAAM,IAAI,MAAM,uBAAwB,UAAoB;AAAA,EAAa,UAAoB,OAAO;AAAA,IACxG;AAAA,EACJ;AAAA,EAMA,OAAe,wBAAwB,UAAgB;AACnD,UAAM,YAAsB,CAAC;AAE7B,UAAM,gBAAgB,CAAC,MAAc,SAAe;AAEhD,aAAO,KAAK,OAAO,IAAI;AAGvB,UAAI,KAAK,WAAW,GAAG;AACnB,kBAAU,KAAK,IAAI;AAAA,MACvB,OAAO;AACH,QAAC,KAA+B,YAAY,EAAE,QAAQ,CAAC,UAAU,cAAc,MAAM,KAAK,CAAC;AAAA,MAC/F;AAAA,IACJ;AAGA,kBAAc,CAAC,GAAG,QAAQ;AAE1B,cAAU,QAAQ,CAAC,SAAS;AAExB,eAAS,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;AAE9C,cAAM,cAAc,KAAK;AAGzB,YAAI,YAAY,aAAa,GAAG;AAC5B;AAAA,QACJ;AAGA,cAAM,YAAY,IAAI;AAAA,UAClB,KACK,MAAM,GAAG,QAAQ,CAAC,EAClB,IAAmB,CAAC,UAAU,EAAE,MAAM,QAAQ,KAAK,mBAAmB,EAAE,EAAE,EAC1E,OAAO,CAAC,YAAY,QAAQ,OAAO,SAAS,CAAC;AAAA,QACtD;AAGA,oBAAY,aAAa,SAAS;AAAA,MACtC;AAAA,IACJ,CAAC;AAAA,EACL;AACJ;", "names": ["Participant", "Lotto", "createLotto", "State", "createLotto"] } diff --git a/dist/nodes/node.d.ts b/dist/nodes/Node.d.ts similarity index 100% rename from dist/nodes/node.d.ts rename to dist/nodes/Node.d.ts diff --git a/dist/nodes/composite/composite.d.ts b/dist/nodes/composite/Composite.d.ts similarity index 100% rename from dist/nodes/composite/composite.d.ts rename to dist/nodes/composite/Composite.d.ts diff --git a/dist/nodes/composite/lotto.d.ts b/dist/nodes/composite/Lotto.d.ts similarity index 100% rename from dist/nodes/composite/lotto.d.ts rename to dist/nodes/composite/Lotto.d.ts diff --git a/dist/nodes/composite/parallel.d.ts b/dist/nodes/composite/Parallel.d.ts similarity index 100% rename from dist/nodes/composite/parallel.d.ts rename to dist/nodes/composite/Parallel.d.ts diff --git a/dist/nodes/composite/selector.d.ts b/dist/nodes/composite/Selector.d.ts similarity index 100% rename from dist/nodes/composite/selector.d.ts rename to dist/nodes/composite/Selector.d.ts diff --git a/dist/nodes/composite/sequence.d.ts b/dist/nodes/composite/Sequence.d.ts similarity index 100% rename from dist/nodes/composite/sequence.d.ts rename to dist/nodes/composite/Sequence.d.ts diff --git a/dist/nodes/decorator/decorator.d.ts b/dist/nodes/decorator/Decorator.d.ts similarity index 100% rename from dist/nodes/decorator/decorator.d.ts rename to dist/nodes/decorator/Decorator.d.ts diff --git a/dist/nodes/decorator/fail.d.ts b/dist/nodes/decorator/Fail.d.ts similarity index 100% rename from dist/nodes/decorator/fail.d.ts rename to dist/nodes/decorator/Fail.d.ts diff --git a/dist/nodes/decorator/flip.d.ts b/dist/nodes/decorator/Flip.d.ts similarity index 100% rename from dist/nodes/decorator/flip.d.ts rename to dist/nodes/decorator/Flip.d.ts diff --git a/dist/nodes/decorator/repeat.d.ts b/dist/nodes/decorator/Repeat.d.ts similarity index 100% rename from dist/nodes/decorator/repeat.d.ts rename to dist/nodes/decorator/Repeat.d.ts diff --git a/dist/nodes/decorator/retry.d.ts b/dist/nodes/decorator/Retry.d.ts similarity index 100% rename from dist/nodes/decorator/retry.d.ts rename to dist/nodes/decorator/Retry.d.ts diff --git a/dist/nodes/decorator/root.d.ts b/dist/nodes/decorator/Root.d.ts similarity index 100% rename from dist/nodes/decorator/root.d.ts rename to dist/nodes/decorator/Root.d.ts diff --git a/dist/nodes/decorator/succeed.d.ts b/dist/nodes/decorator/Succeed.d.ts similarity index 100% rename from dist/nodes/decorator/succeed.d.ts rename to dist/nodes/decorator/Succeed.d.ts diff --git a/dist/nodes/leaf/action.d.ts b/dist/nodes/leaf/Action.d.ts similarity index 100% rename from dist/nodes/leaf/action.d.ts rename to dist/nodes/leaf/Action.d.ts diff --git a/dist/nodes/leaf/condition.d.ts b/dist/nodes/leaf/Condition.d.ts similarity index 100% rename from dist/nodes/leaf/condition.d.ts rename to dist/nodes/leaf/Condition.d.ts diff --git a/dist/nodes/leaf/leaf.d.ts b/dist/nodes/leaf/Leaf.d.ts similarity index 100% rename from dist/nodes/leaf/leaf.d.ts rename to dist/nodes/leaf/Leaf.d.ts diff --git a/dist/nodes/leaf/wait.d.ts b/dist/nodes/leaf/Wait.d.ts similarity index 75% rename from dist/nodes/leaf/wait.d.ts rename to dist/nodes/leaf/Wait.d.ts index d9fccdc..78f16a0 100644 --- a/dist/nodes/leaf/wait.d.ts +++ b/dist/nodes/leaf/Wait.d.ts @@ -8,13 +8,15 @@ import { BehaviourTreeOptions } from "../../BehaviourTreeOptions"; */ export default class Wait extends Leaf { private duration; - private longestDuration; + private durationMin; + private durationMax; /** * @param attributes The node attributes. * @param duration The duration that this node will wait to succeed in milliseconds, or the earliest if longestDuration is defined. - * @param longestDuration The longest possible duration in milliseconds that this node will wait to succeed. + * @param durationMin The minimum possible duration in milliseconds that this node will wait to succeed. + * @param durationMax The maximum possible duration in milliseconds that this node will wait to succeed. */ - constructor(attributes: Attribute[], duration: number, longestDuration: number); + constructor(attributes: Attribute[], duration: number | null, durationMin: number | null, durationMax: number | null); /** * The time in milliseconds at which this node was first updated. */ diff --git a/src/RootAstNodesBuilder.ts b/src/RootAstNodesBuilder.ts index 150b692..02f1f77 100644 --- a/src/RootAstNodesBuilder.ts +++ b/src/RootAstNodesBuilder.ts @@ -132,7 +132,8 @@ export type ConditionAstNode = LeafAstNode & { export type WaitAstNode = LeafAstNode & { type: "wait"; duration: number | null; - longestDuration: number | null; + durationMin: number | null; + durationMax: number | null; }; export type AnyAstNode = @@ -404,28 +405,30 @@ const ASTNodeFactories = { type: "wait", attributes: [], duration: null, - longestDuration: null, + durationMin: null, + durationMax: null, validate() { - // A wait node must have a positive duration. - if (this.duration! < 0) { - throw new Error("a wait node must have a positive duration"); - } - - // There is validation to carry out if a longest duration was defined. - if (this.longestDuration) { - // A wait node must have a positive longest duration. - if (this.longestDuration < 0) { - throw new Error("a wait node must have a positive longest duration if one is defined"); + if (this.duration !== null) { + // If an explict duration was defined then it must be a positive number. + if (this.duration < 0) { + throw new Error("a wait node must have a positive duration"); + } + } else if (this.durationMin !== null && this.durationMax !== null) { + // A wait node must have a positive min and max duration. + if (this.durationMin < 0 || this.durationMax < 0) { + throw new Error("a wait node must have a positive minimum and maximum duration"); } - // A wait node must not have a duration that exceeds the longest duration. - if (this.duration! > this.longestDuration) { - throw new Error("a wait node must not have a shortest duration that exceeds the longest duration"); + // A wait node must not have a minimum duration that exceeds the maximum duration. + if (this.durationMin > this.durationMax) { + throw new Error("a wait node must not have a minimum duration that exceeds the maximum duration"); } + } else { + // If we have no explicit duration or duration bounds set then we are dealing with a wait node that waits indefinitely. } }, createNodeInstance() { - return new Wait(this.attributes, this.duration!, this.longestDuration!); + return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax); } }), ACTION: (): ActionAstNode => ({ @@ -721,23 +724,26 @@ export default function buildRootASTNodes(definition: string): RootAstNode[] { // Push the WAIT node into the current scope. currentScope.push(node); - // Get the duration and potential longest duration of the wait. - const durations = getArguments( + // Get the optional duration and longest duration of the wait. + const nodeArguments = getArguments( tokens, placeholders, (arg) => arg.type === "number" && !!arg.isInteger, "wait node durations must be integer values" ).map((argument) => argument.value); - // We should have got one or two durations. - if (durations.length === 1) { - // A static duration was defined. - node.duration = durations[0] as number; - } else if (durations.length === 2) { - // A shortest and longest duration was defined. - node.duration = durations[0] as number; - node.longestDuration = durations[1] as number; - } else { + // We may have: + // - No node arguments, in which case the wait will be indefinite until it is aborted. + // - One node argument which will be the explicit duration of the wait. + // - Two node arguments which define the min and max duration bounds from which a random duration will be picked. + if (nodeArguments.length === 1) { + // An explicit duration was defined. + node.duration = nodeArguments[0] as number; + } else if (nodeArguments.length === 2) { + // Min and max duration bounds were defined from which a random duration will be picked. + node.durationMin = nodeArguments[0] as number; + node.durationMax = nodeArguments[1] as number; + } else if (nodeArguments.length > 2) { // An incorrect number of durations was defined. throw new Error("invalid number of wait node duration arguments defined"); } diff --git a/src/nodes/leaf/Wait.ts b/src/nodes/leaf/Wait.ts index f727922..1beea16 100644 --- a/src/nodes/leaf/Wait.ts +++ b/src/nodes/leaf/Wait.ts @@ -12,9 +12,15 @@ export default class Wait extends Leaf { /** * @param attributes The node attributes. * @param duration The duration that this node will wait to succeed in milliseconds, or the earliest if longestDuration is defined. - * @param longestDuration The longest possible duration in milliseconds that this node will wait to succeed. + * @param durationMin The minimum possible duration in milliseconds that this node will wait to succeed. + * @param durationMax The maximum possible duration in milliseconds that this node will wait to succeed. */ - constructor(attributes: Attribute[], private duration: number, private longestDuration: number) { + constructor( + attributes: Attribute[], + private duration: number | null, + private durationMin: number | null, + private durationMax: number | null + ) { super("wait", attributes, []); } @@ -26,7 +32,7 @@ export default class Wait extends Leaf { /** * The total duration in milliseconds that this node will be waiting for. */ - private totalDuration: number = 0; + private totalDuration: number | null = null; /** * The duration in milliseconds that this node has been waiting for. @@ -47,16 +53,26 @@ export default class Wait extends Leaf { // Set the initial waited duration. this.waitedDuration = 0; - // If a longestDuration value was defined then we will be randomly picking a duration between the - // shortest and longest duration. If it was not defined, then we will be just using the duration. - this.totalDuration = this.longestDuration - ? Math.floor(Math.random() * (this.longestDuration - this.duration + 1) + this.duration) - : this.duration; + // Are we dealing with an explicit duration or will we be randomly picking a duration between the min and max duration. + if (this.duration !== null) { + this.totalDuration = this.duration; + } else if (this.durationMin !== null && this.durationMax !== null) { + this.totalDuration = Math.floor( + Math.random() * (this.durationMax - this.durationMin + 1) + this.durationMin + ); + } else { + this.totalDuration = null; + } // The node is now running until we finish waiting. this.setState(State.RUNNING); } + // If we have no total duration then this wait node will wait indefinitely until it is aborted. + if (this.totalDuration === null) { + return; + } + // 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. if (typeof options.getDeltaTime === "function") { // Get the delta time. @@ -84,6 +100,13 @@ export default class Wait extends Leaf { /** * Gets the name of the node. */ - getName = () => - `WAIT ${this.longestDuration ? this.duration + "ms-" + this.longestDuration + "ms" : this.duration + "ms"}`; + getName = () => { + if (this.duration !== null) { + return `WAIT ${this.duration}ms`; + } else if (this.durationMin !== null && this.durationMax !== null) { + return `WAIT ${this.durationMin}ms-${this.durationMax}ms`; + } else { + return "WAIT"; + } + }; } diff --git a/test/nodes/leaf/wait.test.js b/test/nodes/leaf/wait.test.js index dc45c08..967a48e 100644 --- a/test/nodes/leaf/wait.test.js +++ b/test/nodes/leaf/wait.test.js @@ -9,13 +9,42 @@ const findNode = (tree, type, caption) => describe("A Wait node", () => { describe("on tree initialisation", () => { - it("will error if a duration is not provided", () => { - const definition = "root { wait [] }"; - assert.throws( - () => new mistreevous.BehaviourTree(definition, {}), - Error, - "error parsing tree: invalid number of wait node duration arguments defined" - ); + describe("will error if", () => { + it("the defined node arguments are not integers", () => { + const definition = "root { wait ['not', 'integers'] }"; + assert.throws( + () => new mistreevous.BehaviourTree(definition, {}), + Error, + "error parsing tree: wait node durations must be integer values" + ); + }); + + it("a negative duration node argument was defined", () => { + const definition = "root { wait [-1] }"; + assert.throws( + () => new mistreevous.BehaviourTree(definition, {}), + Error, + "error parsing tree: a wait node must have a positive duration" + ); + }); + + it("more than two node arguments are defined", () => { + const definition = "root { wait [0, 1000, 4000] }"; + assert.throws( + () => new mistreevous.BehaviourTree(definition, {}), + Error, + "error parsing tree: invalid number of wait node duration arguments defined" + ); + }); + + it("a minimum duration bound niode argument is defined that is greater than the maximum duration bound node argument", () => { + const definition = "root { wait [1000, 500] }"; + assert.throws( + () => new mistreevous.BehaviourTree(definition, {}), + Error, + "error parsing tree: a wait node must not have a minimum duration that exceeds the maximum duration" + ); + }); }); }); From 915deaafbd2f1da110d7cca2dc710e9011d7c6f9 Mon Sep 17 00:00:00 2001 From: Nikolas Howard Date: Mon, 1 May 2023 13:52:08 +0100 Subject: [PATCH 2/4] options.random is used for duration selection and added specs --- README.md | 2 +- dist/bundle.js | 31 +++++---- dist/bundle.js.map | 4 +- dist/index.js | 31 +++++---- dist/index.js.map | 4 +- src/RootAstNodesBuilder.ts | 46 ++++++++------ src/nodes/leaf/Wait.ts | 7 +- test/nodes/leaf/action.test.js | 2 +- test/nodes/leaf/wait.test.js | 113 ++++++++++++++++++++++++++++++--- 9 files changed, 177 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index c7e3a6f..84e77a4 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ The `BehaviourTree` constructor can take an options object as an argument, the p | Option |Type | Description | | :--------------------|:- |:- | | getDeltaTime |() => number| A function returning a delta time in seconds that is used to calculate the elapsed duration of any `wait` nodes. If this function is not defined then `Date().getTime()` is used instead by default. | -| random |() => number| A function returning a floating-point number between 0 (inclusive) and 1 (exclusive). If defined, this function is used to source a pseudo-random number to use in the selection of active children for any `lotto` nodes. If not defined then `Math.random` will be used instead by default. This function can be useful in seeding all random numbers used in the running of a tree instance to make any behaviour completely deterministic. | +| random |() => number| A function returning a floating-point number between 0 (inclusive) and 1 (exclusive). If defined, this function is used to source a pseudo-random number to use in operations such as the selection of active children for any `lotto` nodes and the selection of durations for `wait` nodes when minimum and maximum durations are defined. If not defined then `Math.random` will be used instead by default. This function can be useful in seeding all random numbers used in the running of a tree instance to make any behaviour completely deterministic. | # Nodes diff --git a/dist/bundle.js b/dist/bundle.js index 48ac1ae..9ee6013 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -508,8 +508,9 @@ var mistreevous = (() => { if (this.duration !== null) { this.totalDuration = this.duration; } else if (this.durationMin !== null && this.durationMax !== null) { + const random = typeof options.random === "function" ? options.random : Math.random; this.totalDuration = Math.floor( - Math.random() * (this.durationMax - this.durationMin + 1) + this.durationMin + random() * (this.durationMax - this.durationMin + 1) + this.durationMin ); } else { this.totalDuration = null; @@ -1451,19 +1452,21 @@ var mistreevous = (() => { case "WAIT": { const node = ASTNodeFactories.WAIT(); currentScope.push(node); - const nodeArguments = getArguments( - tokens, - placeholders, - (arg) => arg.type === "number" && !!arg.isInteger, - "wait node durations must be integer values" - ).map((argument) => argument.value); - if (nodeArguments.length === 1) { - node.duration = nodeArguments[0]; - } else if (nodeArguments.length === 2) { - node.durationMin = nodeArguments[0]; - node.durationMax = nodeArguments[1]; - } else if (nodeArguments.length > 2) { - throw new Error("invalid number of wait node duration arguments defined"); + if (tokens[0] === "[") { + const nodeArguments = getArguments( + tokens, + placeholders, + (arg) => arg.type === "number" && !!arg.isInteger, + "wait node durations must be integer values" + ).map((argument) => argument.value); + if (nodeArguments.length === 1) { + node.duration = nodeArguments[0]; + } else if (nodeArguments.length === 2) { + node.durationMin = nodeArguments[0]; + node.durationMax = nodeArguments[1]; + } else if (nodeArguments.length > 2) { + throw new Error("invalid number of wait node duration arguments defined"); + } } node.attributes = getAttributes(tokens, placeholders); break; diff --git a/dist/bundle.js.map b/dist/bundle.js.map index 0b4b4d2..788cf5e 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/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/State.ts", "../src/nodes/Node.ts", "../src/nodes/leaf/Leaf.ts", "../src/Lookup.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Parallel.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/Exit.ts", "../src/attributes/callbacks/Step.ts", "../src/RootAstNodesBuilder.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 { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport State from \"./State\";\n\nexport { BehaviourTree, State };\nexport type { FlattenedTreeNode };\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * 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 { Agent } from \"../Agent\";\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\";\nimport { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport { AnyArgument } from \"../RootAstNodesBuilder\";\nimport State, { AnyState } from \"../State\";\nimport Leaf from \"./leaf/Leaf\";\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: AnyArgument[]) {}\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.getType().toUpperCase() === type.toUpperCase())[0] ||\n 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\";\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 { ActionResult, Agent, ExitFunctionArg, FunctionArg, GlobalFunction } from \"./Agent\";\nimport { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\n\n// Exit callbacks receive their own special type of argument.\n// There's probably stricter ways to represent this but it feels overly complex right now.\ntype ExitResultArg = { value: ExitFunctionArg };\nexport type AnyExitArgument = AnyArgument | ExitResultArg;\n\nexport type InvokerFunction = (args: AnyExitArgument[]) => ActionResult;\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 functionTable: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered sub-trees keyed on tree name.\n */\n private static subtreeTable: { [key: string]: RootAstNode } = {};\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.functionTable[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.functionTable[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 foundOnAgent = agent[name];\n if (foundOnAgent && typeof foundOnAgent === \"function\") {\n return (args: AnyExitArgument[]): boolean | ActionResult =>\n foundOnAgent.apply(\n agent,\n args.map((arg) => arg.value)\n );\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.functionTable[name] && typeof this.functionTable[name] === \"function\") {\n return (args: AnyExitArgument[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets the subtree with the specified name.\n * @param name The name of the subtree.\n * @returns The subtree with the specified name.\n */\n static getSubtree(name: string): RootAstNode {\n return this.subtreeTable[name];\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: RootAstNode) {\n this.subtreeTable[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.functionTable[name];\n delete this.subtreeTable[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.functionTable = {};\n this.subtreeTable = {};\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State, { CompleteState } from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 updatePromiseStateResult: CompleteState | 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\n // it resolves, unless there has been a value set as a result of the update promise resolving.\n if (this.isUsingUpdatePromise) {\n // Check whether the update promise has resolved with a state value.\n if (this.updatePromiseStateResult) {\n // Set the state of this node to match the state returned by the promise.\n this.setState(this.updatePromiseStateResult);\n }\n\n return;\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 // 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 const updateResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n\n if (updateResult instanceof Promise) {\n updateResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Check to make sure the result is a valid finished state.\n if (result !== State.SUCCEEDED && result !== 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 pending update promise state result to be processed on next update.\n this.updatePromiseStateResult = result;\n },\n (reason) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Just throw whatever was returned as the rejection argument.\n throw new Error(reason);\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(updateResult);\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(updateResult || 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.updatePromiseStateResult = 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 | boolean) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case undefined:\n return;\n default:\n throw new Error(\n `action '${this.actionName}' 'onUpdate' returned an invalid response, expected an optional State.SUCCEEDED or State.FAILED value to be returned`\n );\n }\n };\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 // Call the condition function to determine the state of this node.\n this.setState(!!conditionFuncInvoker(this.conditionArguments) ? 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, or the earliest if longestDuration is defined.\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 this.totalDuration = Math.floor(\n Math.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 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 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 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, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent, 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 ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default repeat node name.\n return \"REPEAT\";\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\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 iterations The number of iterations to repeat the child node, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: number | null,\n child: Node\n ) {\n super(\"retry\", 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the 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 iteration.\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 iteration.\n this.currentIterationCount += 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.iterations !== null) {\n return `RETRY ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default retry node name.\n return \"RETRY\";\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 canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\n } else {\n this.targetIterationCount = null;\n }\n };\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 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\";\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 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 tickets The child node tickets.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private tickets: number[], 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.tickets[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.tickets.length ? `LOTTO [${this.tickets.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 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 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 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 { AnyArgument } from \"../RootAstNodesBuilder\";\nimport Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: AnyArgument[];\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 argument definitions.\n */\n constructor(protected type: string, protected args: AnyArgument[]) {}\n\n /**\n * Gets the type of the attribute.\n */\n getType = () => this.type;\n\n /**\n * Gets the array of attribute argument definitions.\n */\n getArguments = () => this.args;\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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, { AnyExitArgument } from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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([{ value: { succeeded: isSuccess, aborted: isAborted } }, ...this.args]);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Root from \"./nodes/decorator/Root\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Node from \"./nodes/Node\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Callback from \"./attributes/callbacks/Callback\";\nimport Guard from \"./attributes/guards/Guard\";\nimport Attribute from \"./attributes/Attribute\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Leaf from \"./nodes/leaf/Leaf\";\n\nexport type Argument = {\n value: T;\n type: string; // Used for validation.\n};\ntype NullArgument = Argument & {\n type: \"null\";\n};\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\ntype NumberArgument = Argument & {\n type: \"number\";\n isInteger: boolean; // Used for validation.\n};\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\nexport type AnyArgument =\n | NullArgument\n | BooleanArgument\n | NumberArgument\n | StringPlaceholderArgument\n | IdentifierArgument;\n\n/**\n * The node attribute factories.\n */\nconst AttributeFactories: {\n [key: string]: (functionName: string, attributeArguments: AnyArgument[]) => Callback | Guard;\n} = {\n WHILE: (condition: string, attributeArguments: AnyArgument[]) => new While(condition, attributeArguments),\n UNTIL: (condition: string, attributeArguments: AnyArgument[]) => new Until(condition, attributeArguments),\n ENTRY: (functionName: string, attributeArguments: AnyArgument[]) => new Entry(functionName, attributeArguments),\n EXIT: (functionName: string, attributeArguments: AnyArgument[]) => new Exit(functionName, attributeArguments),\n STEP: (functionName: string, attributeArguments: AnyArgument[]) => new Step(functionName, attributeArguments)\n};\n\ntype Validatable = {\n children?: AstNode[];\n validate: (depth: number) => void;\n};\n\ntype NodeInstanceCreator = (\n namedRootNodeProvider: (name: string) => RootAstNode,\n visitedBranches: string[]\n) => T;\n\nexport type AstNode = Validatable & {\n type: string;\n createNodeInstance: NodeInstanceCreator;\n};\n\nexport type LeafAstNode = AstNode & {\n type: \"action\" | \"condition\" | \"wait\";\n attributes: Attribute[];\n};\n\nexport type CompositeAstNode = AstNode & {\n type: \"lotto\" | \"parallel\" | \"selector\" | \"sequence\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type DecoratorAstNode = AstNode & {\n type: \"fail\" | \"flip\" | \"repeat\" | \"retry\" | \"root\" | \"succeed\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type BranchAstNode = AstNode & {\n type: \"branch\";\n branchName: \"\" | string;\n};\n\nexport type LottoAstNode = CompositeAstNode & {\n type: \"lotto\";\n tickets: number[];\n};\n\nexport type RootAstNode = DecoratorAstNode & {\n type: \"root\";\n name: null | string;\n};\n\nexport type IterableAstNode = DecoratorAstNode & {\n type: \"repeat\" | \"retry\";\n iterations: null | number;\n maximumIterations: null | number;\n};\n\nexport type ActionAstNode = LeafAstNode & {\n type: \"action\";\n actionName: string;\n actionArguments: AnyArgument[];\n};\n\nexport type ConditionAstNode = LeafAstNode & {\n type: \"condition\";\n conditionName: string;\n conditionArguments: AnyArgument[];\n};\n\nexport type WaitAstNode = LeafAstNode & {\n type: \"wait\";\n duration: number | null;\n durationMin: number | null;\n durationMax: number | null;\n};\n\nexport type AnyAstNode =\n | BranchAstNode\n | CompositeAstNode\n | LottoAstNode\n | DecoratorAstNode\n | RootAstNode\n | IterableAstNode\n | LeafAstNode\n | ActionAstNode\n | ConditionAstNode\n | WaitAstNode;\n\n/**\n * The AST node factories.\n */\nconst ASTNodeFactories = {\n ROOT: (): RootAstNode => ({\n type: \"root\",\n attributes: [],\n name: null,\n children: [],\n validate(depth: number) {\n // A root node cannot be the child of another node.\n if (depth > 1) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // A root node must have a single child node.\n if (this.children.length !== 1) {\n throw new Error(\"a root node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Root(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n BRANCH: (): BranchAstNode => ({\n type: \"branch\",\n branchName: \"\",\n validate() {},\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n // Try to find the root node with a matching branch name.\n const targetRootNode = namedRootNodeProvider(this.branchName);\n\n // If we have already visited this branch then we have a circular dependency.\n if (visitedBranches.indexOf(this.branchName) !== -1) {\n throw new Error(`circular dependency found in branch node references for branch '${this.branchName}'`);\n }\n\n // If we have a target root node, then the node instance we want will be the first and only child of the referenced root node.\n if (targetRootNode) {\n return targetRootNode\n .createNodeInstance(namedRootNodeProvider, visitedBranches.concat(this.branchName))\n .getChildren()[0];\n } else {\n throw new Error(`branch references root node '${this.branchName}' which has not been defined`);\n }\n }\n }),\n SELECTOR: (): CompositeAstNode => ({\n type: \"selector\",\n attributes: [],\n children: [],\n validate() {\n // A selector node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a selector node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Selector(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n SEQUENCE: (): CompositeAstNode => ({\n type: \"sequence\",\n attributes: [],\n children: [],\n validate() {\n // A sequence node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a sequence node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Sequence(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n PARALLEL: (): CompositeAstNode => ({\n type: \"parallel\",\n attributes: [],\n children: [],\n validate() {\n // A parallel node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a parallel node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Parallel(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n LOTTO: (): LottoAstNode => ({\n type: \"lotto\",\n attributes: [],\n children: [],\n tickets: [],\n validate() {\n // A lotto node must have at least a single node.\n if (this.children!.length < 1) {\n throw new Error(\"a lotto node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Lotto(\n this.attributes,\n this.tickets!,\n this.children!.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n REPEAT: (): IterableAstNode => ({\n type: \"repeat\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A repeat node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a repeat node must have a single child\");\n }\n\n // A repeat node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A repeat node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a repeat node must have a positive maximum iterations count if defined\");\n }\n\n // A repeat node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a repeat node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Repeat(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n RETRY: (): IterableAstNode => ({\n type: \"retry\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A retry node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a retry node must have a single child\");\n }\n\n // A retry node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a retry node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A retry node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a retry node must have a positive maximum iterations count if defined\");\n }\n\n // A retry node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a retry node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Retry(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FLIP: (): DecoratorAstNode => ({\n type: \"flip\",\n attributes: [],\n children: [],\n validate() {\n // A flip node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a flip node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Flip(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n SUCCEED: (): DecoratorAstNode => ({\n type: \"succeed\",\n attributes: [],\n children: [],\n validate() {\n // A succeed node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a succeed node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Succeed(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FAIL: (): DecoratorAstNode => ({\n type: \"fail\",\n attributes: [],\n children: [],\n validate() {\n // A fail node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a fail node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Fail(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n WAIT: (): WaitAstNode => ({\n type: \"wait\",\n attributes: [],\n duration: null,\n durationMin: null,\n durationMax: null,\n validate() {\n if (this.duration !== null) {\n // If an explict duration was defined then it must be a positive number.\n if (this.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // A wait node must have a positive min and max duration.\n if (this.durationMin < 0 || this.durationMax < 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 (this.durationMin > this.durationMax) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else {\n // If we have no explicit duration or duration bounds set then we are dealing with a wait node that waits indefinitely.\n }\n },\n createNodeInstance() {\n return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax);\n }\n }),\n ACTION: (): ActionAstNode => ({\n type: \"action\",\n attributes: [],\n actionName: \"\",\n actionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Action(this.attributes, this.actionName!, this.actionArguments!);\n }\n }),\n CONDITION: (): ConditionAstNode => ({\n type: \"condition\",\n attributes: [],\n conditionName: \"\",\n conditionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Condition(this.attributes, this.conditionName!, this.conditionArguments!);\n }\n })\n};\n\ntype OtherAstNodes = AstNode[];\n\n/**\n * Create an array of root AST nodes based on the given definition.\n * @param definition The definition to parse the AST nodes from.\n * @returns The base definition AST nodes.\n */\nexport default function buildRootASTNodes(definition: string): RootAstNode[] {\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 // Convert the processed definition (with substituted string literals) into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\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 a stack of node children arrays, starting with a definition scope.\n const stack: [RootAstNode[], ...OtherAstNodes[]] = [[]];\n const rootScope = stack[0];\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 const currentScope = stack[stack.length - 1] as OtherAstNodes;\n\n // How we create the next AST token depends on the current raw token value.\n switch (token!.toUpperCase()) {\n case \"ROOT\": {\n // Create a ROOT AST node.\n const node = ASTNodeFactories.ROOT();\n\n // Push the ROOT node into the current scope.\n rootScope.push(node);\n\n // We may have a root node name defined as an argument.\n if (tokens[0] === \"[\") {\n const rootArguments = getArguments(tokens, placeholders);\n\n // We should have only a single argument that is not an empty string for a root node, which is the root name identifier.\n if (rootArguments.length === 1 && rootArguments[0].type === \"identifier\") {\n // The root name will be the first and only node argument.\n node.name = rootArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new ROOT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"BRANCH\": {\n // Create a BRANCH AST node.\n const node = ASTNodeFactories.BRANCH();\n\n // Push the BRANCH node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a branch name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // The branch name will be defined as a node argument.\n const branchArguments = getArguments(tokens, placeholders);\n\n // We should have only a single identifer argument for a branch node, which is the branch name.\n if (branchArguments.length === 1 && branchArguments[0].type === \"identifier\") {\n // The branch name will be the first and only node argument.\n node.branchName = branchArguments[0].value as string;\n } else {\n throw new Error(\"expected single branch name argument\");\n }\n break;\n }\n\n case \"SELECTOR\": {\n // Create a SELECTOR AST node.\n const node = ASTNodeFactories.SELECTOR();\n\n // Push the SELECTOR node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SELECTOR nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SEQUENCE\": {\n // Create a SEQUENCE AST node.\n const node = ASTNodeFactories.SEQUENCE();\n\n // Push the SEQUENCE node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SEQUENCE nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"PARALLEL\": {\n // Create a PARALLEL AST node.\n const node = ASTNodeFactories.PARALLEL();\n\n // Push the PARALLEL node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new PARALLEL nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"LOTTO\": {\n // Create a LOTTO AST node.\n const node = ASTNodeFactories.LOTTO();\n\n // Push the LOTTO node into the current scope.\n currentScope.push(node);\n\n // If the next token is a '[' character then some ticket counts have been defined as arguments.\n if (tokens[0] === \"[\") {\n // Get the ticket count arguments, each argument must be a number.\n node.tickets = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"lotto node ticket counts must be integer values\"\n ).map((argument) => argument.value as number);\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new LOTTO nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"CONDITION\": {\n // Create a CONDITION AST node.\n const node = ASTNodeFactories.CONDITION();\n\n // Push the CONDITION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a condition function name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Grab the condition node arguments.\n const conditionArguments = getArguments(tokens, placeholders);\n\n // We should have at least a single identifier argument for a condition node, which is the condition function name.\n if (conditionArguments.length && conditionArguments[0].type === \"identifier\") {\n // The condition function name will be the first node argument.\n node.conditionName = conditionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n conditionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid condition node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the condition name identifier will be treated as condition function arguments.\n node.conditionArguments = conditionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"FLIP\": {\n // Create a FLIP AST node.\n const node = ASTNodeFactories.FLIP();\n\n // Push the Flip node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new FLIP nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SUCCEED\": {\n // Create a SUCCEED AST node.\n const node = ASTNodeFactories.SUCCEED();\n\n // Push the Succeed node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Succeed nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"FAIL\": {\n // Create a FAIL AST node.\n const node = ASTNodeFactories.FAIL();\n\n // Push the Fail node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Fail nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"WAIT\": {\n // Create a WAIT AST node.\n const node = ASTNodeFactories.WAIT();\n\n // Push the WAIT node into the current scope.\n currentScope.push(node);\n\n // Get the optional duration and longest duration of the wait.\n const nodeArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"wait node durations must be integer values\"\n ).map((argument) => argument.value);\n\n // 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 === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0] as number;\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.durationMin = nodeArguments[0] as number;\n node.durationMax = nodeArguments[1] as number;\n } else if (nodeArguments.length > 2) {\n // An incorrect number of durations was defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"REPEAT\": {\n // Create a REPEAT AST node.\n const node = ASTNodeFactories.REPEAT();\n\n // Push the REPEAT node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"repeat node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\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 // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new REPEAT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"RETRY\": {\n // Create a RETRY AST node.\n const node = ASTNodeFactories.RETRY();\n\n // Push the RETRY node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"retry node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of retry node iteration count arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new RETRY nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"ACTION\": {\n // Create a ACTION AST node.\n const node = ASTNodeFactories.ACTION();\n\n // Push the ACTION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require an action name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // The action name will be defined as a node argument.\n const actionArguments = getArguments(tokens, placeholders);\n\n // We should have at least one identifer argument for an action node, which is the action name.\n if (actionArguments.length && actionArguments[0].type === \"identifier\") {\n // The action name will be the first and only node argument.\n node.actionName = actionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n actionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid action node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the action name identifier will be treated as action function arguments.\n node.actionArguments = actionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope.\n stack.pop();\n break;\n }\n\n default: {\n throw new Error(\"unexpected token: \" + token);\n }\n }\n }\n\n // A function to recursively validate each of the nodes in the AST.\n const validateASTNode = (node: Validatable, depth: number): void => {\n // Validate the node.\n node.validate(depth);\n\n // Validate each child of the node.\n (node.children || []).forEach((child) => validateASTNode(child, depth + 1));\n };\n\n // Start node validation from the definition root.\n validateASTNode(\n {\n children: stack[0] as RootAstNode[],\n validate(this: { children: RootAstNode[] }) {\n // We must have at least one node defined as the definition scope, which should be a root node.\n if (this.children.length === 0) {\n throw new Error(\"expected root node to have been defined\");\n }\n\n // Each node at the base of the definition scope MUST be a root node.\n for (const definitionLevelNode of this.children) {\n if (definitionLevelNode.type !== \"root\") {\n throw new Error(\"expected root node at base of definition\");\n }\n }\n\n // Exactly one root node must not have a name defined. This will be the main root, others will have to be referenced via branch nodes.\n if (this.children.filter((definitionLevelNode) => definitionLevelNode.name === null).length !== 1) {\n throw new Error(\"expected single unnamed root node at base of definition to act as main root\");\n }\n\n // No two named root nodes can have matching names.\n const rootNodeNames: string[] = [];\n for (const definitionLevelNode of this.children) {\n if (rootNodeNames.indexOf(definitionLevelNode.name!) !== -1) {\n throw new Error(`multiple root nodes found with duplicate name '${definitionLevelNode.name}'`);\n } else {\n rootNodeNames.push(definitionLevelNode.name!);\n }\n }\n }\n },\n 0\n );\n\n // Return the root AST nodes.\n return stack[0];\n}\n\n/**\n * Pop the next raw token off of the stack and throw an error if it wasn't the expected one.\n * @param tokens The array of remaining 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 */\nfunction popAndCheck(tokens: string[], expected: string | string[]) {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token.\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 // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = ([] as string[])\n .concat(expected)\n .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 = ([] as string[])\n .concat(expected)\n .map((item) => \"'\" + item + \"'\")\n .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\ntype Placeholders = { [key: string]: string };\n\n/**\n * Pull an argument definition list off of the token stack.\n * @param tokens The array of remaining tokens.\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 The argument definition list.\n */\nfunction getArguments(\n tokens: string[],\n stringArgumentPlaceholders: Placeholders,\n argumentValidator?: (arg: AnyArgument) => boolean,\n validationFailedMessage?: string\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 closer = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n const argumentList: AnyArgument[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closer) {\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 // Try to validate the argument.\n if (argumentValidator && !argumentValidator(argumentDefinition)) {\n throw new Error(validationFailedMessage);\n }\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, closer);\n\n // Return the argument list.\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: Placeholders): 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\n/**\n * Pull any attributes off of the token stack.\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 array of attributes defined by any directly following tokens.\n */\nfunction getAttributes(tokens: string[], stringArgumentPlaceholders: Placeholders) {\n // Create an array to hold any attributes found.\n const attributes: Attribute[] = [];\n\n // Keep track of names of attribute that we have found on the token stack, as we cannot have duplicates.\n const attributesFound: string[] = [];\n\n // Try to get the attribute factory for the next token.\n let attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n\n // Pull attribute tokens off of the tokens stack until we have no more.\n while (attributeFactory) {\n // Check to make sure that we have not already created a attribute of this type for this node.\n if (attributesFound.indexOf(tokens[0].toUpperCase()) !== -1) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Add the current attribute type to our array of found attributes.\n attributesFound.push(tokens.shift()!.toUpperCase());\n\n // Grab any attribute arguments.\n const attributeArguments = getArguments(tokens, stringArgumentPlaceholders);\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeArguments.length === 0 || attributeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected agent function name identifier argument for attribute\");\n }\n\n // Grab the first attribute which is an identifier that will reference an agent function.\n const attributeFunctionName = attributeArguments.shift()! as IdentifierArgument;\n\n // Any remaining attribute arguments 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 and add it to the array of attributes found.\n attributes.push(attributeFactory(attributeFunctionName.value, attributeArguments));\n\n // Try to get the next attribute name token, as there could be multiple.\n attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n }\n\n return attributes;\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 */\nfunction substituteStringLiterals(definition: string): {\n placeholders: { [key: string]: string };\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: Placeholders = {};\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 */\nfunction 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 GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport buildRootASTNodes, { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\nimport 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\";\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: AnyArgument[];\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 public readonly rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition.\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(definition: string, private agent: Agent, private options: BehaviourTreeOptions = {}) {\n // The tree definition must be defined and a valid string.\n if (typeof definition !== \"string\") {\n throw new Error(\"the tree definition must be a string\");\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 defined and not null\");\n }\n\n // Parse the behaviour tree definition, create the populated tree of behaviour tree nodes, and get the root.\n this.rootNode = BehaviourTree.createRootNode(definition);\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) {\n if (typeof value === \"function\") {\n // We are going to register a action/condition/guard/callback function.\n Lookup.setFunc(name, value);\n } else if (typeof value === \"string\") {\n // We are going to register a subtree.\n let rootASTNodes: RootAstNode[];\n\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n rootASTNodes = buildRootASTNodes(value);\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error registering definition: ${(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 (rootASTNodes.length != 1 || rootASTNodes[0].name !== null) {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n Lookup.setSubtree(name, rootASTNodes[0]);\n } else {\n throw new Error(\"unexpected value, expected string 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 /**\n * Parses a behaviour tree definition and creates a tree of behaviour tree nodes.\n * @param {string} definition The behaviour tree definition.\n * @returns The root behaviour tree node.\n */\n private static createRootNode(definition: string): Root {\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n const rootASTNodes = buildRootASTNodes(definition);\n\n // Create a symbol to use as the main root key in our root node mapping.\n const mainRootNodeKey = Symbol(\"__root__\");\n\n // Create a mapping of root node names to root AST tokens. The main root node will have a key of Symbol(\"__root__\").\n const rootNodeMap: { [key: string | symbol]: RootAstNode } = {};\n for (const rootASTNode of rootASTNodes) {\n rootNodeMap[rootASTNode.name === null ? mainRootNodeKey : rootASTNode.name!] = rootASTNode;\n }\n\n // Convert the AST to our actual tree and get the root node.\n const rootNode: Root = rootNodeMap[mainRootNodeKey].createNodeInstance(\n // Create a provider for named root nodes that are part of our definition or have been registered. Prioritising the former.\n (name: string): RootAstNode => (rootNodeMap[name] ? rootNodeMap[name] : Lookup.getSubtree(name)),\n []\n );\n\n // Set a guard path on every leaf of the tree to evaluate as part of its update.\n BehaviourTree.applyLeafNodeGuardPaths(rootNode);\n\n // Return the root node.\n return rootNode;\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error parsing tree: ${(exception as Error).message}\\n${(exception as Error).stack}`);\n }\n }\n\n /**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param rootNode The main root tree node.\n */\n private static applyLeafNodeGuardPaths(rootNode: 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([], rootNode);\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}\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 { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport State from \"./State\";\n\nexport { BehaviourTree, State };\nexport type { FlattenedTreeNode };\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * 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 { Agent } from \"../Agent\";\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\";\nimport { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport { AnyArgument } from \"../RootAstNodesBuilder\";\nimport State, { AnyState } from \"../State\";\nimport Leaf from \"./leaf/Leaf\";\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: AnyArgument[]) {}\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.getType().toUpperCase() === type.toUpperCase())[0] ||\n 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\";\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 { ActionResult, Agent, ExitFunctionArg, FunctionArg, GlobalFunction } from \"./Agent\";\nimport { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\n\n// Exit callbacks receive their own special type of argument.\n// There's probably stricter ways to represent this but it feels overly complex right now.\ntype ExitResultArg = { value: ExitFunctionArg };\nexport type AnyExitArgument = AnyArgument | ExitResultArg;\n\nexport type InvokerFunction = (args: AnyExitArgument[]) => ActionResult;\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 functionTable: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered sub-trees keyed on tree name.\n */\n private static subtreeTable: { [key: string]: RootAstNode } = {};\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.functionTable[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.functionTable[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 foundOnAgent = agent[name];\n if (foundOnAgent && typeof foundOnAgent === \"function\") {\n return (args: AnyExitArgument[]): boolean | ActionResult =>\n foundOnAgent.apply(\n agent,\n args.map((arg) => arg.value)\n );\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.functionTable[name] && typeof this.functionTable[name] === \"function\") {\n return (args: AnyExitArgument[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets the subtree with the specified name.\n * @param name The name of the subtree.\n * @returns The subtree with the specified name.\n */\n static getSubtree(name: string): RootAstNode {\n return this.subtreeTable[name];\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: RootAstNode) {\n this.subtreeTable[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.functionTable[name];\n delete this.subtreeTable[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.functionTable = {};\n this.subtreeTable = {};\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State, { CompleteState } from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 updatePromiseStateResult: CompleteState | 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\n // it resolves, unless there has been a value set as a result of the update promise resolving.\n if (this.isUsingUpdatePromise) {\n // Check whether the update promise has resolved with a state value.\n if (this.updatePromiseStateResult) {\n // Set the state of this node to match the state returned by the promise.\n this.setState(this.updatePromiseStateResult);\n }\n\n return;\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 // 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 const updateResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n\n if (updateResult instanceof Promise) {\n updateResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Check to make sure the result is a valid finished state.\n if (result !== State.SUCCEEDED && result !== 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 pending update promise state result to be processed on next update.\n this.updatePromiseStateResult = result;\n },\n (reason) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Just throw whatever was returned as the rejection argument.\n throw new Error(reason);\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(updateResult);\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(updateResult || 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.updatePromiseStateResult = 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 | boolean) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case undefined:\n return;\n default:\n throw new Error(\n `action '${this.actionName}' 'onUpdate' returned an invalid response, expected an optional State.SUCCEEDED or State.FAILED value to be returned`\n );\n }\n };\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 // Call the condition function to determine the state of this node.\n this.setState(!!conditionFuncInvoker(this.conditionArguments) ? 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, or the earliest if longestDuration is defined.\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 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 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 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 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, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent, 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 ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default repeat node name.\n return \"REPEAT\";\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\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 iterations The number of iterations to repeat the child node, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: number | null,\n child: Node\n ) {\n super(\"retry\", 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the 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 iteration.\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 iteration.\n this.currentIterationCount += 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.iterations !== null) {\n return `RETRY ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default retry node name.\n return \"RETRY\";\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 canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\n } else {\n this.targetIterationCount = null;\n }\n };\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 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\";\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 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 tickets The child node tickets.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private tickets: number[], 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.tickets[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.tickets.length ? `LOTTO [${this.tickets.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 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 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 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 { AnyArgument } from \"../RootAstNodesBuilder\";\nimport Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: AnyArgument[];\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 argument definitions.\n */\n constructor(protected type: string, protected args: AnyArgument[]) {}\n\n /**\n * Gets the type of the attribute.\n */\n getType = () => this.type;\n\n /**\n * Gets the array of attribute argument definitions.\n */\n getArguments = () => this.args;\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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, { AnyExitArgument } from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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([{ value: { succeeded: isSuccess, aborted: isAborted } }, ...this.args]);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Root from \"./nodes/decorator/Root\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Node from \"./nodes/Node\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Callback from \"./attributes/callbacks/Callback\";\nimport Guard from \"./attributes/guards/Guard\";\nimport Attribute from \"./attributes/Attribute\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Leaf from \"./nodes/leaf/Leaf\";\n\nexport type Argument = {\n value: T;\n type: string; // Used for validation.\n};\ntype NullArgument = Argument & {\n type: \"null\";\n};\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\ntype NumberArgument = Argument & {\n type: \"number\";\n isInteger: boolean; // Used for validation.\n};\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\nexport type AnyArgument =\n | NullArgument\n | BooleanArgument\n | NumberArgument\n | StringPlaceholderArgument\n | IdentifierArgument;\n\n/**\n * The node attribute factories.\n */\nconst AttributeFactories: {\n [key: string]: (functionName: string, attributeArguments: AnyArgument[]) => Callback | Guard;\n} = {\n WHILE: (condition: string, attributeArguments: AnyArgument[]) => new While(condition, attributeArguments),\n UNTIL: (condition: string, attributeArguments: AnyArgument[]) => new Until(condition, attributeArguments),\n ENTRY: (functionName: string, attributeArguments: AnyArgument[]) => new Entry(functionName, attributeArguments),\n EXIT: (functionName: string, attributeArguments: AnyArgument[]) => new Exit(functionName, attributeArguments),\n STEP: (functionName: string, attributeArguments: AnyArgument[]) => new Step(functionName, attributeArguments)\n};\n\ntype Validatable = {\n children?: AstNode[];\n validate: (depth: number) => void;\n};\n\ntype NodeInstanceCreator = (\n namedRootNodeProvider: (name: string) => RootAstNode,\n visitedBranches: string[]\n) => T;\n\nexport type AstNode = Validatable & {\n type: string;\n createNodeInstance: NodeInstanceCreator;\n};\n\nexport type LeafAstNode = AstNode & {\n type: \"action\" | \"condition\" | \"wait\";\n attributes: Attribute[];\n};\n\nexport type CompositeAstNode = AstNode & {\n type: \"lotto\" | \"parallel\" | \"selector\" | \"sequence\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type DecoratorAstNode = AstNode & {\n type: \"fail\" | \"flip\" | \"repeat\" | \"retry\" | \"root\" | \"succeed\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type BranchAstNode = AstNode & {\n type: \"branch\";\n branchName: \"\" | string;\n};\n\nexport type LottoAstNode = CompositeAstNode & {\n type: \"lotto\";\n tickets: number[];\n};\n\nexport type RootAstNode = DecoratorAstNode & {\n type: \"root\";\n name: null | string;\n};\n\nexport type IterableAstNode = DecoratorAstNode & {\n type: \"repeat\" | \"retry\";\n iterations: null | number;\n maximumIterations: null | number;\n};\n\nexport type ActionAstNode = LeafAstNode & {\n type: \"action\";\n actionName: string;\n actionArguments: AnyArgument[];\n};\n\nexport type ConditionAstNode = LeafAstNode & {\n type: \"condition\";\n conditionName: string;\n conditionArguments: AnyArgument[];\n};\n\nexport type WaitAstNode = LeafAstNode & {\n type: \"wait\";\n duration: number | null;\n durationMin: number | null;\n durationMax: number | null;\n};\n\nexport type AnyAstNode =\n | BranchAstNode\n | CompositeAstNode\n | LottoAstNode\n | DecoratorAstNode\n | RootAstNode\n | IterableAstNode\n | LeafAstNode\n | ActionAstNode\n | ConditionAstNode\n | WaitAstNode;\n\n/**\n * The AST node factories.\n */\nconst ASTNodeFactories = {\n ROOT: (): RootAstNode => ({\n type: \"root\",\n attributes: [],\n name: null,\n children: [],\n validate(depth: number) {\n // A root node cannot be the child of another node.\n if (depth > 1) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // A root node must have a single child node.\n if (this.children.length !== 1) {\n throw new Error(\"a root node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Root(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n BRANCH: (): BranchAstNode => ({\n type: \"branch\",\n branchName: \"\",\n validate() {},\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n // Try to find the root node with a matching branch name.\n const targetRootNode = namedRootNodeProvider(this.branchName);\n\n // If we have already visited this branch then we have a circular dependency.\n if (visitedBranches.indexOf(this.branchName) !== -1) {\n throw new Error(`circular dependency found in branch node references for branch '${this.branchName}'`);\n }\n\n // If we have a target root node, then the node instance we want will be the first and only child of the referenced root node.\n if (targetRootNode) {\n return targetRootNode\n .createNodeInstance(namedRootNodeProvider, visitedBranches.concat(this.branchName))\n .getChildren()[0];\n } else {\n throw new Error(`branch references root node '${this.branchName}' which has not been defined`);\n }\n }\n }),\n SELECTOR: (): CompositeAstNode => ({\n type: \"selector\",\n attributes: [],\n children: [],\n validate() {\n // A selector node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a selector node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Selector(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n SEQUENCE: (): CompositeAstNode => ({\n type: \"sequence\",\n attributes: [],\n children: [],\n validate() {\n // A sequence node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a sequence node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Sequence(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n PARALLEL: (): CompositeAstNode => ({\n type: \"parallel\",\n attributes: [],\n children: [],\n validate() {\n // A parallel node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a parallel node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Parallel(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n LOTTO: (): LottoAstNode => ({\n type: \"lotto\",\n attributes: [],\n children: [],\n tickets: [],\n validate() {\n // A lotto node must have at least a single node.\n if (this.children!.length < 1) {\n throw new Error(\"a lotto node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Lotto(\n this.attributes,\n this.tickets!,\n this.children!.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n REPEAT: (): IterableAstNode => ({\n type: \"repeat\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A repeat node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a repeat node must have a single child\");\n }\n\n // A repeat node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A repeat node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a repeat node must have a positive maximum iterations count if defined\");\n }\n\n // A repeat node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a repeat node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Repeat(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n RETRY: (): IterableAstNode => ({\n type: \"retry\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A retry node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a retry node must have a single child\");\n }\n\n // A retry node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a retry node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A retry node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a retry node must have a positive maximum iterations count if defined\");\n }\n\n // A retry node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a retry node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Retry(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FLIP: (): DecoratorAstNode => ({\n type: \"flip\",\n attributes: [],\n children: [],\n validate() {\n // A flip node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a flip node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Flip(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n SUCCEED: (): DecoratorAstNode => ({\n type: \"succeed\",\n attributes: [],\n children: [],\n validate() {\n // A succeed node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a succeed node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Succeed(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FAIL: (): DecoratorAstNode => ({\n type: \"fail\",\n attributes: [],\n children: [],\n validate() {\n // A fail node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a fail node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Fail(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n WAIT: (): WaitAstNode => ({\n type: \"wait\",\n attributes: [],\n duration: null,\n durationMin: null,\n durationMax: null,\n validate() {\n if (this.duration !== null) {\n // If an explict duration was defined then it must be a positive number.\n if (this.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // A wait node must have a positive min and max duration.\n if (this.durationMin < 0 || this.durationMax < 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 (this.durationMin > this.durationMax) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else {\n // If we have no explicit duration or duration bounds set then we are dealing with a wait node that waits indefinitely.\n }\n },\n createNodeInstance() {\n return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax);\n }\n }),\n ACTION: (): ActionAstNode => ({\n type: \"action\",\n attributes: [],\n actionName: \"\",\n actionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Action(this.attributes, this.actionName!, this.actionArguments!);\n }\n }),\n CONDITION: (): ConditionAstNode => ({\n type: \"condition\",\n attributes: [],\n conditionName: \"\",\n conditionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Condition(this.attributes, this.conditionName!, this.conditionArguments!);\n }\n })\n};\n\ntype OtherAstNodes = AstNode[];\n\n/**\n * Create an array of root AST nodes based on the given definition.\n * @param definition The definition to parse the AST nodes from.\n * @returns The base definition AST nodes.\n */\nexport default function buildRootASTNodes(definition: string): RootAstNode[] {\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 // Convert the processed definition (with substituted string literals) into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\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 a stack of node children arrays, starting with a definition scope.\n const stack: [RootAstNode[], ...OtherAstNodes[]] = [[]];\n const rootScope = stack[0];\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 const currentScope = stack[stack.length - 1] as OtherAstNodes;\n\n // How we create the next AST token depends on the current raw token value.\n switch (token!.toUpperCase()) {\n case \"ROOT\": {\n // Create a ROOT AST node.\n const node = ASTNodeFactories.ROOT();\n\n // Push the ROOT node into the current scope.\n rootScope.push(node);\n\n // We may have a root node name defined as an argument.\n if (tokens[0] === \"[\") {\n const rootArguments = getArguments(tokens, placeholders);\n\n // We should have only a single argument that is not an empty string for a root node, which is the root name identifier.\n if (rootArguments.length === 1 && rootArguments[0].type === \"identifier\") {\n // The root name will be the first and only node argument.\n node.name = rootArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new ROOT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"BRANCH\": {\n // Create a BRANCH AST node.\n const node = ASTNodeFactories.BRANCH();\n\n // Push the BRANCH node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a branch name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // The branch name will be defined as a node argument.\n const branchArguments = getArguments(tokens, placeholders);\n\n // We should have only a single identifer argument for a branch node, which is the branch name.\n if (branchArguments.length === 1 && branchArguments[0].type === \"identifier\") {\n // The branch name will be the first and only node argument.\n node.branchName = branchArguments[0].value as string;\n } else {\n throw new Error(\"expected single branch name argument\");\n }\n break;\n }\n\n case \"SELECTOR\": {\n // Create a SELECTOR AST node.\n const node = ASTNodeFactories.SELECTOR();\n\n // Push the SELECTOR node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SELECTOR nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SEQUENCE\": {\n // Create a SEQUENCE AST node.\n const node = ASTNodeFactories.SEQUENCE();\n\n // Push the SEQUENCE node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SEQUENCE nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"PARALLEL\": {\n // Create a PARALLEL AST node.\n const node = ASTNodeFactories.PARALLEL();\n\n // Push the PARALLEL node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new PARALLEL nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"LOTTO\": {\n // Create a LOTTO AST node.\n const node = ASTNodeFactories.LOTTO();\n\n // Push the LOTTO node into the current scope.\n currentScope.push(node);\n\n // If the next token is a '[' character then some ticket counts have been defined as arguments.\n if (tokens[0] === \"[\") {\n // Get the ticket count arguments, each argument must be a number.\n node.tickets = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"lotto node ticket counts must be integer values\"\n ).map((argument) => argument.value as number);\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new LOTTO nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"CONDITION\": {\n // Create a CONDITION AST node.\n const node = ASTNodeFactories.CONDITION();\n\n // Push the CONDITION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a condition function name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Grab the condition node arguments.\n const conditionArguments = getArguments(tokens, placeholders);\n\n // We should have at least a single identifier argument for a condition node, which is the condition function name.\n if (conditionArguments.length && conditionArguments[0].type === \"identifier\") {\n // The condition function name will be the first node argument.\n node.conditionName = conditionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n conditionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid condition node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the condition name identifier will be treated as condition function arguments.\n node.conditionArguments = conditionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"FLIP\": {\n // Create a FLIP AST node.\n const node = ASTNodeFactories.FLIP();\n\n // Push the Flip node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new FLIP nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SUCCEED\": {\n // Create a SUCCEED AST node.\n const node = ASTNodeFactories.SUCCEED();\n\n // Push the Succeed node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Succeed nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"FAIL\": {\n // Create a FAIL AST node.\n const node = ASTNodeFactories.FAIL();\n\n // Push the Fail node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Fail nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"WAIT\": {\n // Create a WAIT AST node.\n const node = ASTNodeFactories.WAIT();\n\n // Push the WAIT node into the current scope.\n currentScope.push(node);\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 (tokens[0] === \"[\") {\n // Get the optional duration and longest duration of the wait.\n const nodeArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"wait node durations must be integer values\"\n ).map((argument) => argument.value);\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] as number;\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.durationMin = nodeArguments[0] as number;\n node.durationMax = nodeArguments[1] as number;\n } else if (nodeArguments.length > 2) {\n // An incorrect number of durations was defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"REPEAT\": {\n // Create a REPEAT AST node.\n const node = ASTNodeFactories.REPEAT();\n\n // Push the REPEAT node into the current scope.\n currentScope.push(node);\n\n // Check for iteration count node arguments ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"repeat node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\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 // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new REPEAT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"RETRY\": {\n // Create a RETRY AST node.\n const node = ASTNodeFactories.RETRY();\n\n // Push the RETRY node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"retry node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of retry node iteration count arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new RETRY nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"ACTION\": {\n // Create a ACTION AST node.\n const node = ASTNodeFactories.ACTION();\n\n // Push the ACTION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require an action name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // The action name will be defined as a node argument.\n const actionArguments = getArguments(tokens, placeholders);\n\n // We should have at least one identifer argument for an action node, which is the action name.\n if (actionArguments.length && actionArguments[0].type === \"identifier\") {\n // The action name will be the first and only node argument.\n node.actionName = actionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n actionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid action node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the action name identifier will be treated as action function arguments.\n node.actionArguments = actionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope.\n stack.pop();\n break;\n }\n\n default: {\n throw new Error(\"unexpected token: \" + token);\n }\n }\n }\n\n // A function to recursively validate each of the nodes in the AST.\n const validateASTNode = (node: Validatable, depth: number): void => {\n // Validate the node.\n node.validate(depth);\n\n // Validate each child of the node.\n (node.children || []).forEach((child) => validateASTNode(child, depth + 1));\n };\n\n // Start node validation from the definition root.\n validateASTNode(\n {\n children: stack[0] as RootAstNode[],\n validate(this: { children: RootAstNode[] }) {\n // We must have at least one node defined as the definition scope, which should be a root node.\n if (this.children.length === 0) {\n throw new Error(\"expected root node to have been defined\");\n }\n\n // Each node at the base of the definition scope MUST be a root node.\n for (const definitionLevelNode of this.children) {\n if (definitionLevelNode.type !== \"root\") {\n throw new Error(\"expected root node at base of definition\");\n }\n }\n\n // Exactly one root node must not have a name defined. This will be the main root, others will have to be referenced via branch nodes.\n if (this.children.filter((definitionLevelNode) => definitionLevelNode.name === null).length !== 1) {\n throw new Error(\"expected single unnamed root node at base of definition to act as main root\");\n }\n\n // No two named root nodes can have matching names.\n const rootNodeNames: string[] = [];\n for (const definitionLevelNode of this.children) {\n if (rootNodeNames.indexOf(definitionLevelNode.name!) !== -1) {\n throw new Error(`multiple root nodes found with duplicate name '${definitionLevelNode.name}'`);\n } else {\n rootNodeNames.push(definitionLevelNode.name!);\n }\n }\n }\n },\n 0\n );\n\n // Return the root AST nodes.\n return stack[0];\n}\n\n/**\n * Pop the next raw token off of the stack and throw an error if it wasn't the expected one.\n * @param tokens The array of remaining 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 */\nfunction popAndCheck(tokens: string[], expected: string | string[]) {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token.\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 // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = ([] as string[])\n .concat(expected)\n .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 = ([] as string[])\n .concat(expected)\n .map((item) => \"'\" + item + \"'\")\n .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\ntype Placeholders = { [key: string]: string };\n\n/**\n * Pull an argument definition list off of the token stack.\n * @param tokens The array of remaining tokens.\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 The argument definition list.\n */\nfunction getArguments(\n tokens: string[],\n stringArgumentPlaceholders: Placeholders,\n argumentValidator?: (arg: AnyArgument) => boolean,\n validationFailedMessage?: string\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 closer = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n const argumentList: AnyArgument[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closer) {\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 // Try to validate the argument.\n if (argumentValidator && !argumentValidator(argumentDefinition)) {\n throw new Error(validationFailedMessage);\n }\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, closer);\n\n // Return the argument list.\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: Placeholders): 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\n/**\n * Pull any attributes off of the token stack.\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 array of attributes defined by any directly following tokens.\n */\nfunction getAttributes(tokens: string[], stringArgumentPlaceholders: Placeholders) {\n // Create an array to hold any attributes found.\n const attributes: Attribute[] = [];\n\n // Keep track of names of attribute that we have found on the token stack, as we cannot have duplicates.\n const attributesFound: string[] = [];\n\n // Try to get the attribute factory for the next token.\n let attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n\n // Pull attribute tokens off of the tokens stack until we have no more.\n while (attributeFactory) {\n // Check to make sure that we have not already created a attribute of this type for this node.\n if (attributesFound.indexOf(tokens[0].toUpperCase()) !== -1) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Add the current attribute type to our array of found attributes.\n attributesFound.push(tokens.shift()!.toUpperCase());\n\n // Grab any attribute arguments.\n const attributeArguments = getArguments(tokens, stringArgumentPlaceholders);\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeArguments.length === 0 || attributeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected agent function name identifier argument for attribute\");\n }\n\n // Grab the first attribute which is an identifier that will reference an agent function.\n const attributeFunctionName = attributeArguments.shift()! as IdentifierArgument;\n\n // Any remaining attribute arguments 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 and add it to the array of attributes found.\n attributes.push(attributeFactory(attributeFunctionName.value, attributeArguments));\n\n // Try to get the next attribute name token, as there could be multiple.\n attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n }\n\n return attributes;\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 */\nfunction substituteStringLiterals(definition: string): {\n placeholders: { [key: string]: string };\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: Placeholders = {};\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 */\nfunction 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 GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport buildRootASTNodes, { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\nimport 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\";\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: AnyArgument[];\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 public readonly rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition.\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(definition: string, private agent: Agent, private options: BehaviourTreeOptions = {}) {\n // The tree definition must be defined and a valid string.\n if (typeof definition !== \"string\") {\n throw new Error(\"the tree definition must be a string\");\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 defined and not null\");\n }\n\n // Parse the behaviour tree definition, create the populated tree of behaviour tree nodes, and get the root.\n this.rootNode = BehaviourTree.createRootNode(definition);\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) {\n if (typeof value === \"function\") {\n // We are going to register a action/condition/guard/callback function.\n Lookup.setFunc(name, value);\n } else if (typeof value === \"string\") {\n // We are going to register a subtree.\n let rootASTNodes: RootAstNode[];\n\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n rootASTNodes = buildRootASTNodes(value);\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error registering definition: ${(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 (rootASTNodes.length != 1 || rootASTNodes[0].name !== null) {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n Lookup.setSubtree(name, rootASTNodes[0]);\n } else {\n throw new Error(\"unexpected value, expected string 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 /**\n * Parses a behaviour tree definition and creates a tree of behaviour tree nodes.\n * @param {string} definition The behaviour tree definition.\n * @returns The root behaviour tree node.\n */\n private static createRootNode(definition: string): Root {\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n const rootASTNodes = buildRootASTNodes(definition);\n\n // Create a symbol to use as the main root key in our root node mapping.\n const mainRootNodeKey = Symbol(\"__root__\");\n\n // Create a mapping of root node names to root AST tokens. The main root node will have a key of Symbol(\"__root__\").\n const rootNodeMap: { [key: string | symbol]: RootAstNode } = {};\n for (const rootASTNode of rootASTNodes) {\n rootNodeMap[rootASTNode.name === null ? mainRootNodeKey : rootASTNode.name!] = rootASTNode;\n }\n\n // Convert the AST to our actual tree and get the root node.\n const rootNode: Root = rootNodeMap[mainRootNodeKey].createNodeInstance(\n // Create a provider for named root nodes that are part of our definition or have been registered. Prioritising the former.\n (name: string): RootAstNode => (rootNodeMap[name] ? rootNodeMap[name] : Lookup.getSubtree(name)),\n []\n );\n\n // Set a guard path on every leaf of the tree to evaluate as part of its update.\n BehaviourTree.applyLeafNodeGuardPaths(rootNode);\n\n // Return the root node.\n return rootNode;\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error parsing tree: ${(exception as Error).message}\\n${(exception as Error).stack}`);\n }\n }\n\n /**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param rootNode The main root tree node.\n */\n private static applyLeafNodeGuardPaths(rootNode: 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([], rootNode);\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}\n"], + "mappings": "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", "names": ["Participant", "Lotto", "createLotto", "State", "createLotto"] } diff --git a/dist/index.js b/dist/index.js index 381bdf3..c2c0040 100644 --- a/dist/index.js +++ b/dist/index.js @@ -508,8 +508,9 @@ var Wait = class extends Leaf { if (this.duration !== null) { this.totalDuration = this.duration; } else if (this.durationMin !== null && this.durationMax !== null) { + const random = typeof options.random === "function" ? options.random : Math.random; this.totalDuration = Math.floor( - Math.random() * (this.durationMax - this.durationMin + 1) + this.durationMin + random() * (this.durationMax - this.durationMin + 1) + this.durationMin ); } else { this.totalDuration = null; @@ -1451,19 +1452,21 @@ function buildRootASTNodes(definition) { case "WAIT": { const node = ASTNodeFactories.WAIT(); currentScope.push(node); - const nodeArguments = getArguments( - tokens, - placeholders, - (arg) => arg.type === "number" && !!arg.isInteger, - "wait node durations must be integer values" - ).map((argument) => argument.value); - if (nodeArguments.length === 1) { - node.duration = nodeArguments[0]; - } else if (nodeArguments.length === 2) { - node.durationMin = nodeArguments[0]; - node.durationMax = nodeArguments[1]; - } else if (nodeArguments.length > 2) { - throw new Error("invalid number of wait node duration arguments defined"); + if (tokens[0] === "[") { + const nodeArguments = getArguments( + tokens, + placeholders, + (arg) => arg.type === "number" && !!arg.isInteger, + "wait node durations must be integer values" + ).map((argument) => argument.value); + if (nodeArguments.length === 1) { + node.duration = nodeArguments[0]; + } else if (nodeArguments.length === 2) { + node.durationMin = nodeArguments[0]; + node.durationMax = nodeArguments[1]; + } else if (nodeArguments.length > 2) { + throw new Error("invalid number of wait node duration arguments defined"); + } } node.attributes = getAttributes(tokens, placeholders); break; diff --git a/dist/index.js.map b/dist/index.js.map index 2fb4a39..bde8841 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/attributes/guards/GuardUnsatisifedException.ts", "../src/attributes/guards/GuardPath.ts", "../src/State.ts", "../src/nodes/Node.ts", "../src/nodes/leaf/Leaf.ts", "../src/Lookup.ts", "../src/nodes/leaf/Action.ts", "../src/nodes/leaf/Condition.ts", "../src/nodes/leaf/Wait.ts", "../src/nodes/decorator/Decorator.ts", "../src/nodes/decorator/Root.ts", "../src/nodes/decorator/Repeat.ts", "../src/nodes/decorator/Retry.ts", "../src/nodes/decorator/Flip.ts", "../src/nodes/decorator/Succeed.ts", "../src/nodes/decorator/Fail.ts", "../src/nodes/composite/Lotto.ts", "../src/nodes/composite/Composite.ts", "../src/nodes/composite/Selector.ts", "../src/nodes/composite/Sequence.ts", "../src/nodes/composite/Parallel.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/Exit.ts", "../src/attributes/callbacks/Step.ts", "../src/RootAstNodesBuilder.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 { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport State from \"./State\";\n\nexport { BehaviourTree, State };\nexport type { FlattenedTreeNode };\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * 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 { Agent } from \"../Agent\";\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\";\nimport { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport { AnyArgument } from \"../RootAstNodesBuilder\";\nimport State, { AnyState } from \"../State\";\nimport Leaf from \"./leaf/Leaf\";\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: AnyArgument[]) {}\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.getType().toUpperCase() === type.toUpperCase())[0] ||\n 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\";\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 { ActionResult, Agent, ExitFunctionArg, FunctionArg, GlobalFunction } from \"./Agent\";\nimport { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\n\n// Exit callbacks receive their own special type of argument.\n// There's probably stricter ways to represent this but it feels overly complex right now.\ntype ExitResultArg = { value: ExitFunctionArg };\nexport type AnyExitArgument = AnyArgument | ExitResultArg;\n\nexport type InvokerFunction = (args: AnyExitArgument[]) => ActionResult;\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 functionTable: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered sub-trees keyed on tree name.\n */\n private static subtreeTable: { [key: string]: RootAstNode } = {};\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.functionTable[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.functionTable[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 foundOnAgent = agent[name];\n if (foundOnAgent && typeof foundOnAgent === \"function\") {\n return (args: AnyExitArgument[]): boolean | ActionResult =>\n foundOnAgent.apply(\n agent,\n args.map((arg) => arg.value)\n );\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.functionTable[name] && typeof this.functionTable[name] === \"function\") {\n return (args: AnyExitArgument[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets the subtree with the specified name.\n * @param name The name of the subtree.\n * @returns The subtree with the specified name.\n */\n static getSubtree(name: string): RootAstNode {\n return this.subtreeTable[name];\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: RootAstNode) {\n this.subtreeTable[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.functionTable[name];\n delete this.subtreeTable[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.functionTable = {};\n this.subtreeTable = {};\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State, { CompleteState } from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 updatePromiseStateResult: CompleteState | 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\n // it resolves, unless there has been a value set as a result of the update promise resolving.\n if (this.isUsingUpdatePromise) {\n // Check whether the update promise has resolved with a state value.\n if (this.updatePromiseStateResult) {\n // Set the state of this node to match the state returned by the promise.\n this.setState(this.updatePromiseStateResult);\n }\n\n return;\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 // 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 const updateResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n\n if (updateResult instanceof Promise) {\n updateResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Check to make sure the result is a valid finished state.\n if (result !== State.SUCCEEDED && result !== 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 pending update promise state result to be processed on next update.\n this.updatePromiseStateResult = result;\n },\n (reason) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Just throw whatever was returned as the rejection argument.\n throw new Error(reason);\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(updateResult);\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(updateResult || 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.updatePromiseStateResult = 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 | boolean) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case undefined:\n return;\n default:\n throw new Error(\n `action '${this.actionName}' 'onUpdate' returned an invalid response, expected an optional State.SUCCEEDED or State.FAILED value to be returned`\n );\n }\n };\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 // Call the condition function to determine the state of this node.\n this.setState(!!conditionFuncInvoker(this.conditionArguments) ? 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, or the earliest if longestDuration is defined.\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 this.totalDuration = Math.floor(\n Math.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 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 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 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, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent, 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 ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default repeat node name.\n return \"REPEAT\";\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\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 iterations The number of iterations to repeat the child node, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: number | null,\n child: Node\n ) {\n super(\"retry\", 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the 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 iteration.\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 iteration.\n this.currentIterationCount += 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.iterations !== null) {\n return `RETRY ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default retry node name.\n return \"RETRY\";\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 canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\n } else {\n this.targetIterationCount = null;\n }\n };\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 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\";\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 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 tickets The child node tickets.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private tickets: number[], 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.tickets[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.tickets.length ? `LOTTO [${this.tickets.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 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 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 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 { AnyArgument } from \"../RootAstNodesBuilder\";\nimport Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: AnyArgument[];\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 argument definitions.\n */\n constructor(protected type: string, protected args: AnyArgument[]) {}\n\n /**\n * Gets the type of the attribute.\n */\n getType = () => this.type;\n\n /**\n * Gets the array of attribute argument definitions.\n */\n getArguments = () => this.args;\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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, { AnyExitArgument } from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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([{ value: { succeeded: isSuccess, aborted: isAborted } }, ...this.args]);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Root from \"./nodes/decorator/Root\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Node from \"./nodes/Node\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Callback from \"./attributes/callbacks/Callback\";\nimport Guard from \"./attributes/guards/Guard\";\nimport Attribute from \"./attributes/Attribute\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Leaf from \"./nodes/leaf/Leaf\";\n\nexport type Argument = {\n value: T;\n type: string; // Used for validation.\n};\ntype NullArgument = Argument & {\n type: \"null\";\n};\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\ntype NumberArgument = Argument & {\n type: \"number\";\n isInteger: boolean; // Used for validation.\n};\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\nexport type AnyArgument =\n | NullArgument\n | BooleanArgument\n | NumberArgument\n | StringPlaceholderArgument\n | IdentifierArgument;\n\n/**\n * The node attribute factories.\n */\nconst AttributeFactories: {\n [key: string]: (functionName: string, attributeArguments: AnyArgument[]) => Callback | Guard;\n} = {\n WHILE: (condition: string, attributeArguments: AnyArgument[]) => new While(condition, attributeArguments),\n UNTIL: (condition: string, attributeArguments: AnyArgument[]) => new Until(condition, attributeArguments),\n ENTRY: (functionName: string, attributeArguments: AnyArgument[]) => new Entry(functionName, attributeArguments),\n EXIT: (functionName: string, attributeArguments: AnyArgument[]) => new Exit(functionName, attributeArguments),\n STEP: (functionName: string, attributeArguments: AnyArgument[]) => new Step(functionName, attributeArguments)\n};\n\ntype Validatable = {\n children?: AstNode[];\n validate: (depth: number) => void;\n};\n\ntype NodeInstanceCreator = (\n namedRootNodeProvider: (name: string) => RootAstNode,\n visitedBranches: string[]\n) => T;\n\nexport type AstNode = Validatable & {\n type: string;\n createNodeInstance: NodeInstanceCreator;\n};\n\nexport type LeafAstNode = AstNode & {\n type: \"action\" | \"condition\" | \"wait\";\n attributes: Attribute[];\n};\n\nexport type CompositeAstNode = AstNode & {\n type: \"lotto\" | \"parallel\" | \"selector\" | \"sequence\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type DecoratorAstNode = AstNode & {\n type: \"fail\" | \"flip\" | \"repeat\" | \"retry\" | \"root\" | \"succeed\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type BranchAstNode = AstNode & {\n type: \"branch\";\n branchName: \"\" | string;\n};\n\nexport type LottoAstNode = CompositeAstNode & {\n type: \"lotto\";\n tickets: number[];\n};\n\nexport type RootAstNode = DecoratorAstNode & {\n type: \"root\";\n name: null | string;\n};\n\nexport type IterableAstNode = DecoratorAstNode & {\n type: \"repeat\" | \"retry\";\n iterations: null | number;\n maximumIterations: null | number;\n};\n\nexport type ActionAstNode = LeafAstNode & {\n type: \"action\";\n actionName: string;\n actionArguments: AnyArgument[];\n};\n\nexport type ConditionAstNode = LeafAstNode & {\n type: \"condition\";\n conditionName: string;\n conditionArguments: AnyArgument[];\n};\n\nexport type WaitAstNode = LeafAstNode & {\n type: \"wait\";\n duration: number | null;\n durationMin: number | null;\n durationMax: number | null;\n};\n\nexport type AnyAstNode =\n | BranchAstNode\n | CompositeAstNode\n | LottoAstNode\n | DecoratorAstNode\n | RootAstNode\n | IterableAstNode\n | LeafAstNode\n | ActionAstNode\n | ConditionAstNode\n | WaitAstNode;\n\n/**\n * The AST node factories.\n */\nconst ASTNodeFactories = {\n ROOT: (): RootAstNode => ({\n type: \"root\",\n attributes: [],\n name: null,\n children: [],\n validate(depth: number) {\n // A root node cannot be the child of another node.\n if (depth > 1) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // A root node must have a single child node.\n if (this.children.length !== 1) {\n throw new Error(\"a root node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Root(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n BRANCH: (): BranchAstNode => ({\n type: \"branch\",\n branchName: \"\",\n validate() {},\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n // Try to find the root node with a matching branch name.\n const targetRootNode = namedRootNodeProvider(this.branchName);\n\n // If we have already visited this branch then we have a circular dependency.\n if (visitedBranches.indexOf(this.branchName) !== -1) {\n throw new Error(`circular dependency found in branch node references for branch '${this.branchName}'`);\n }\n\n // If we have a target root node, then the node instance we want will be the first and only child of the referenced root node.\n if (targetRootNode) {\n return targetRootNode\n .createNodeInstance(namedRootNodeProvider, visitedBranches.concat(this.branchName))\n .getChildren()[0];\n } else {\n throw new Error(`branch references root node '${this.branchName}' which has not been defined`);\n }\n }\n }),\n SELECTOR: (): CompositeAstNode => ({\n type: \"selector\",\n attributes: [],\n children: [],\n validate() {\n // A selector node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a selector node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Selector(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n SEQUENCE: (): CompositeAstNode => ({\n type: \"sequence\",\n attributes: [],\n children: [],\n validate() {\n // A sequence node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a sequence node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Sequence(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n PARALLEL: (): CompositeAstNode => ({\n type: \"parallel\",\n attributes: [],\n children: [],\n validate() {\n // A parallel node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a parallel node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Parallel(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n LOTTO: (): LottoAstNode => ({\n type: \"lotto\",\n attributes: [],\n children: [],\n tickets: [],\n validate() {\n // A lotto node must have at least a single node.\n if (this.children!.length < 1) {\n throw new Error(\"a lotto node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Lotto(\n this.attributes,\n this.tickets!,\n this.children!.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n REPEAT: (): IterableAstNode => ({\n type: \"repeat\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A repeat node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a repeat node must have a single child\");\n }\n\n // A repeat node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A repeat node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a repeat node must have a positive maximum iterations count if defined\");\n }\n\n // A repeat node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a repeat node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Repeat(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n RETRY: (): IterableAstNode => ({\n type: \"retry\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A retry node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a retry node must have a single child\");\n }\n\n // A retry node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a retry node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A retry node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a retry node must have a positive maximum iterations count if defined\");\n }\n\n // A retry node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a retry node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Retry(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FLIP: (): DecoratorAstNode => ({\n type: \"flip\",\n attributes: [],\n children: [],\n validate() {\n // A flip node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a flip node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Flip(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n SUCCEED: (): DecoratorAstNode => ({\n type: \"succeed\",\n attributes: [],\n children: [],\n validate() {\n // A succeed node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a succeed node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Succeed(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FAIL: (): DecoratorAstNode => ({\n type: \"fail\",\n attributes: [],\n children: [],\n validate() {\n // A fail node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a fail node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Fail(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n WAIT: (): WaitAstNode => ({\n type: \"wait\",\n attributes: [],\n duration: null,\n durationMin: null,\n durationMax: null,\n validate() {\n if (this.duration !== null) {\n // If an explict duration was defined then it must be a positive number.\n if (this.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // A wait node must have a positive min and max duration.\n if (this.durationMin < 0 || this.durationMax < 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 (this.durationMin > this.durationMax) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else {\n // If we have no explicit duration or duration bounds set then we are dealing with a wait node that waits indefinitely.\n }\n },\n createNodeInstance() {\n return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax);\n }\n }),\n ACTION: (): ActionAstNode => ({\n type: \"action\",\n attributes: [],\n actionName: \"\",\n actionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Action(this.attributes, this.actionName!, this.actionArguments!);\n }\n }),\n CONDITION: (): ConditionAstNode => ({\n type: \"condition\",\n attributes: [],\n conditionName: \"\",\n conditionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Condition(this.attributes, this.conditionName!, this.conditionArguments!);\n }\n })\n};\n\ntype OtherAstNodes = AstNode[];\n\n/**\n * Create an array of root AST nodes based on the given definition.\n * @param definition The definition to parse the AST nodes from.\n * @returns The base definition AST nodes.\n */\nexport default function buildRootASTNodes(definition: string): RootAstNode[] {\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 // Convert the processed definition (with substituted string literals) into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\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 a stack of node children arrays, starting with a definition scope.\n const stack: [RootAstNode[], ...OtherAstNodes[]] = [[]];\n const rootScope = stack[0];\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 const currentScope = stack[stack.length - 1] as OtherAstNodes;\n\n // How we create the next AST token depends on the current raw token value.\n switch (token!.toUpperCase()) {\n case \"ROOT\": {\n // Create a ROOT AST node.\n const node = ASTNodeFactories.ROOT();\n\n // Push the ROOT node into the current scope.\n rootScope.push(node);\n\n // We may have a root node name defined as an argument.\n if (tokens[0] === \"[\") {\n const rootArguments = getArguments(tokens, placeholders);\n\n // We should have only a single argument that is not an empty string for a root node, which is the root name identifier.\n if (rootArguments.length === 1 && rootArguments[0].type === \"identifier\") {\n // The root name will be the first and only node argument.\n node.name = rootArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new ROOT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"BRANCH\": {\n // Create a BRANCH AST node.\n const node = ASTNodeFactories.BRANCH();\n\n // Push the BRANCH node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a branch name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // The branch name will be defined as a node argument.\n const branchArguments = getArguments(tokens, placeholders);\n\n // We should have only a single identifer argument for a branch node, which is the branch name.\n if (branchArguments.length === 1 && branchArguments[0].type === \"identifier\") {\n // The branch name will be the first and only node argument.\n node.branchName = branchArguments[0].value as string;\n } else {\n throw new Error(\"expected single branch name argument\");\n }\n break;\n }\n\n case \"SELECTOR\": {\n // Create a SELECTOR AST node.\n const node = ASTNodeFactories.SELECTOR();\n\n // Push the SELECTOR node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SELECTOR nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SEQUENCE\": {\n // Create a SEQUENCE AST node.\n const node = ASTNodeFactories.SEQUENCE();\n\n // Push the SEQUENCE node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SEQUENCE nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"PARALLEL\": {\n // Create a PARALLEL AST node.\n const node = ASTNodeFactories.PARALLEL();\n\n // Push the PARALLEL node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new PARALLEL nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"LOTTO\": {\n // Create a LOTTO AST node.\n const node = ASTNodeFactories.LOTTO();\n\n // Push the LOTTO node into the current scope.\n currentScope.push(node);\n\n // If the next token is a '[' character then some ticket counts have been defined as arguments.\n if (tokens[0] === \"[\") {\n // Get the ticket count arguments, each argument must be a number.\n node.tickets = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"lotto node ticket counts must be integer values\"\n ).map((argument) => argument.value as number);\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new LOTTO nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"CONDITION\": {\n // Create a CONDITION AST node.\n const node = ASTNodeFactories.CONDITION();\n\n // Push the CONDITION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a condition function name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Grab the condition node arguments.\n const conditionArguments = getArguments(tokens, placeholders);\n\n // We should have at least a single identifier argument for a condition node, which is the condition function name.\n if (conditionArguments.length && conditionArguments[0].type === \"identifier\") {\n // The condition function name will be the first node argument.\n node.conditionName = conditionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n conditionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid condition node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the condition name identifier will be treated as condition function arguments.\n node.conditionArguments = conditionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"FLIP\": {\n // Create a FLIP AST node.\n const node = ASTNodeFactories.FLIP();\n\n // Push the Flip node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new FLIP nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SUCCEED\": {\n // Create a SUCCEED AST node.\n const node = ASTNodeFactories.SUCCEED();\n\n // Push the Succeed node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Succeed nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"FAIL\": {\n // Create a FAIL AST node.\n const node = ASTNodeFactories.FAIL();\n\n // Push the Fail node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Fail nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"WAIT\": {\n // Create a WAIT AST node.\n const node = ASTNodeFactories.WAIT();\n\n // Push the WAIT node into the current scope.\n currentScope.push(node);\n\n // Get the optional duration and longest duration of the wait.\n const nodeArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"wait node durations must be integer values\"\n ).map((argument) => argument.value);\n\n // 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 === 1) {\n // An explicit duration was defined.\n node.duration = nodeArguments[0] as number;\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.durationMin = nodeArguments[0] as number;\n node.durationMax = nodeArguments[1] as number;\n } else if (nodeArguments.length > 2) {\n // An incorrect number of durations was defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"REPEAT\": {\n // Create a REPEAT AST node.\n const node = ASTNodeFactories.REPEAT();\n\n // Push the REPEAT node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"repeat node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\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 // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new REPEAT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"RETRY\": {\n // Create a RETRY AST node.\n const node = ASTNodeFactories.RETRY();\n\n // Push the RETRY node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"retry node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of retry node iteration count arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new RETRY nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"ACTION\": {\n // Create a ACTION AST node.\n const node = ASTNodeFactories.ACTION();\n\n // Push the ACTION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require an action name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // The action name will be defined as a node argument.\n const actionArguments = getArguments(tokens, placeholders);\n\n // We should have at least one identifer argument for an action node, which is the action name.\n if (actionArguments.length && actionArguments[0].type === \"identifier\") {\n // The action name will be the first and only node argument.\n node.actionName = actionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n actionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid action node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the action name identifier will be treated as action function arguments.\n node.actionArguments = actionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope.\n stack.pop();\n break;\n }\n\n default: {\n throw new Error(\"unexpected token: \" + token);\n }\n }\n }\n\n // A function to recursively validate each of the nodes in the AST.\n const validateASTNode = (node: Validatable, depth: number): void => {\n // Validate the node.\n node.validate(depth);\n\n // Validate each child of the node.\n (node.children || []).forEach((child) => validateASTNode(child, depth + 1));\n };\n\n // Start node validation from the definition root.\n validateASTNode(\n {\n children: stack[0] as RootAstNode[],\n validate(this: { children: RootAstNode[] }) {\n // We must have at least one node defined as the definition scope, which should be a root node.\n if (this.children.length === 0) {\n throw new Error(\"expected root node to have been defined\");\n }\n\n // Each node at the base of the definition scope MUST be a root node.\n for (const definitionLevelNode of this.children) {\n if (definitionLevelNode.type !== \"root\") {\n throw new Error(\"expected root node at base of definition\");\n }\n }\n\n // Exactly one root node must not have a name defined. This will be the main root, others will have to be referenced via branch nodes.\n if (this.children.filter((definitionLevelNode) => definitionLevelNode.name === null).length !== 1) {\n throw new Error(\"expected single unnamed root node at base of definition to act as main root\");\n }\n\n // No two named root nodes can have matching names.\n const rootNodeNames: string[] = [];\n for (const definitionLevelNode of this.children) {\n if (rootNodeNames.indexOf(definitionLevelNode.name!) !== -1) {\n throw new Error(`multiple root nodes found with duplicate name '${definitionLevelNode.name}'`);\n } else {\n rootNodeNames.push(definitionLevelNode.name!);\n }\n }\n }\n },\n 0\n );\n\n // Return the root AST nodes.\n return stack[0];\n}\n\n/**\n * Pop the next raw token off of the stack and throw an error if it wasn't the expected one.\n * @param tokens The array of remaining 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 */\nfunction popAndCheck(tokens: string[], expected: string | string[]) {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token.\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 // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = ([] as string[])\n .concat(expected)\n .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 = ([] as string[])\n .concat(expected)\n .map((item) => \"'\" + item + \"'\")\n .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\ntype Placeholders = { [key: string]: string };\n\n/**\n * Pull an argument definition list off of the token stack.\n * @param tokens The array of remaining tokens.\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 The argument definition list.\n */\nfunction getArguments(\n tokens: string[],\n stringArgumentPlaceholders: Placeholders,\n argumentValidator?: (arg: AnyArgument) => boolean,\n validationFailedMessage?: string\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 closer = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n const argumentList: AnyArgument[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closer) {\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 // Try to validate the argument.\n if (argumentValidator && !argumentValidator(argumentDefinition)) {\n throw new Error(validationFailedMessage);\n }\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, closer);\n\n // Return the argument list.\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: Placeholders): 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\n/**\n * Pull any attributes off of the token stack.\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 array of attributes defined by any directly following tokens.\n */\nfunction getAttributes(tokens: string[], stringArgumentPlaceholders: Placeholders) {\n // Create an array to hold any attributes found.\n const attributes: Attribute[] = [];\n\n // Keep track of names of attribute that we have found on the token stack, as we cannot have duplicates.\n const attributesFound: string[] = [];\n\n // Try to get the attribute factory for the next token.\n let attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n\n // Pull attribute tokens off of the tokens stack until we have no more.\n while (attributeFactory) {\n // Check to make sure that we have not already created a attribute of this type for this node.\n if (attributesFound.indexOf(tokens[0].toUpperCase()) !== -1) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Add the current attribute type to our array of found attributes.\n attributesFound.push(tokens.shift()!.toUpperCase());\n\n // Grab any attribute arguments.\n const attributeArguments = getArguments(tokens, stringArgumentPlaceholders);\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeArguments.length === 0 || attributeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected agent function name identifier argument for attribute\");\n }\n\n // Grab the first attribute which is an identifier that will reference an agent function.\n const attributeFunctionName = attributeArguments.shift()! as IdentifierArgument;\n\n // Any remaining attribute arguments 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 and add it to the array of attributes found.\n attributes.push(attributeFactory(attributeFunctionName.value, attributeArguments));\n\n // Try to get the next attribute name token, as there could be multiple.\n attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n }\n\n return attributes;\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 */\nfunction substituteStringLiterals(definition: string): {\n placeholders: { [key: string]: string };\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: Placeholders = {};\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 */\nfunction 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 GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport buildRootASTNodes, { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\nimport 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\";\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: AnyArgument[];\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 public readonly rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition.\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(definition: string, private agent: Agent, private options: BehaviourTreeOptions = {}) {\n // The tree definition must be defined and a valid string.\n if (typeof definition !== \"string\") {\n throw new Error(\"the tree definition must be a string\");\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 defined and not null\");\n }\n\n // Parse the behaviour tree definition, create the populated tree of behaviour tree nodes, and get the root.\n this.rootNode = BehaviourTree.createRootNode(definition);\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) {\n if (typeof value === \"function\") {\n // We are going to register a action/condition/guard/callback function.\n Lookup.setFunc(name, value);\n } else if (typeof value === \"string\") {\n // We are going to register a subtree.\n let rootASTNodes: RootAstNode[];\n\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n rootASTNodes = buildRootASTNodes(value);\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error registering definition: ${(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 (rootASTNodes.length != 1 || rootASTNodes[0].name !== null) {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n Lookup.setSubtree(name, rootASTNodes[0]);\n } else {\n throw new Error(\"unexpected value, expected string 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 /**\n * Parses a behaviour tree definition and creates a tree of behaviour tree nodes.\n * @param {string} definition The behaviour tree definition.\n * @returns The root behaviour tree node.\n */\n private static createRootNode(definition: string): Root {\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n const rootASTNodes = buildRootASTNodes(definition);\n\n // Create a symbol to use as the main root key in our root node mapping.\n const mainRootNodeKey = Symbol(\"__root__\");\n\n // Create a mapping of root node names to root AST tokens. The main root node will have a key of Symbol(\"__root__\").\n const rootNodeMap: { [key: string | symbol]: RootAstNode } = {};\n for (const rootASTNode of rootASTNodes) {\n rootNodeMap[rootASTNode.name === null ? mainRootNodeKey : rootASTNode.name!] = rootASTNode;\n }\n\n // Convert the AST to our actual tree and get the root node.\n const rootNode: Root = rootNodeMap[mainRootNodeKey].createNodeInstance(\n // Create a provider for named root nodes that are part of our definition or have been registered. Prioritising the former.\n (name: string): RootAstNode => (rootNodeMap[name] ? rootNodeMap[name] : Lookup.getSubtree(name)),\n []\n );\n\n // Set a guard path on every leaf of the tree to evaluate as part of its update.\n BehaviourTree.applyLeafNodeGuardPaths(rootNode);\n\n // Return the root node.\n return rootNode;\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error parsing tree: ${(exception as Error).message}\\n${(exception as Error).stack}`);\n }\n }\n\n /**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param rootNode The main root tree node.\n */\n private static applyLeafNodeGuardPaths(rootNode: 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([], rootNode);\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}\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 { BehaviourTree, FlattenedTreeNode } from \"./BehaviourTree\";\nimport State from \"./State\";\n\nexport { BehaviourTree, State };\nexport type { FlattenedTreeNode };\n", "import Node from \"../../nodes/Node\";\n\n/**\n * An exception thrown when evaluating node guard path conditions and a conditions fails.\n */\nexport default class GuardUnsatisifedException extends Error {\n /**\n * @param source The node at which a guard condition failed.\n */\n constructor(private source: Node) {\n super(\"A guard path condition has failed\");\n }\n\n /**\n * Gets whether the specified node is the node at which a guard condition failed.\n * @param node The node to check against the source node.\n * @returns Whether the specified node is the node at which a guard condition failed.\n */\n isSourceNode = (node: Node) => node === this.source;\n}\n", "import { Agent } from \"../../Agent\";\nimport Guard from \"./Guard\";\nimport Node from \"../../nodes/Node\";\nimport GuardUnsatisifedException from \"./GuardUnsatisifedException\";\n\nexport type GuardPathPart = {\n node: Node;\n guards: Guard[];\n};\n\n/**\n * Represents a path of node guards along a root-to-leaf tree path.\n */\nexport default class GuardPath {\n /**\n * @param nodes An array of objects defining a node instance -> guard link, ordered by node depth.\n */\n constructor(private nodes: GuardPathPart[]) {}\n\n /**\n * Evaluate guard conditions for all guards in the tree path, moving outwards from the root.\n * @param agent The agent, required for guard evaluation.\n * @returns An evaluation results object.\n */\n evaluate = (agent: Agent) => {\n // We need to evaluate guard conditions for nodes up the tree, moving outwards from the root.\n for (const details of this.nodes) {\n // There can be multiple guards per node.\n for (const guard of details.guards) {\n // Check whether the guard condition passes, and throw an exception if not.\n if (!guard.isSatisfied(agent)) {\n throw new GuardUnsatisifedException(details.node);\n }\n }\n }\n };\n}\n", "/**\n * 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 { Agent } from \"../Agent\";\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\";\nimport { BehaviourTreeOptions } from \"../BehaviourTreeOptions\";\nimport { AnyArgument } from \"../RootAstNodesBuilder\";\nimport State, { AnyState } from \"../State\";\nimport Leaf from \"./leaf/Leaf\";\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: AnyArgument[]) {}\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.getType().toUpperCase() === type.toUpperCase())[0] ||\n 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\";\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 { ActionResult, Agent, ExitFunctionArg, FunctionArg, GlobalFunction } from \"./Agent\";\nimport { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\n\n// Exit callbacks receive their own special type of argument.\n// There's probably stricter ways to represent this but it feels overly complex right now.\ntype ExitResultArg = { value: ExitFunctionArg };\nexport type AnyExitArgument = AnyArgument | ExitResultArg;\n\nexport type InvokerFunction = (args: AnyExitArgument[]) => ActionResult;\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 functionTable: { [key: string]: GlobalFunction } = {};\n /**\n * The object holding any registered sub-trees keyed on tree name.\n */\n private static subtreeTable: { [key: string]: RootAstNode } = {};\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.functionTable[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.functionTable[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 foundOnAgent = agent[name];\n if (foundOnAgent && typeof foundOnAgent === \"function\") {\n return (args: AnyExitArgument[]): boolean | ActionResult =>\n foundOnAgent.apply(\n agent,\n args.map((arg) => arg.value)\n );\n }\n\n // The agent does not contain the specified function but it may have been registered at some point.\n if (this.functionTable[name] && typeof this.functionTable[name] === \"function\") {\n return (args: AnyExitArgument[]) => this.functionTable[name](agent, ...args.map((arg) => arg.value));\n }\n\n // We have no function to invoke.\n return null;\n }\n\n /**\n * Gets the subtree with the specified name.\n * @param name The name of the subtree.\n * @returns The subtree with the specified name.\n */\n static getSubtree(name: string): RootAstNode {\n return this.subtreeTable[name];\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: RootAstNode) {\n this.subtreeTable[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.functionTable[name];\n delete this.subtreeTable[name];\n }\n\n /**\n * Remove all registered functions and subtrees.\n */\n static empty() {\n this.functionTable = {};\n this.subtreeTable = {};\n }\n}\n", "import Leaf from \"./Leaf\";\nimport State, { CompleteState } from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 updatePromiseStateResult: CompleteState | 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\n // it resolves, unless there has been a value set as a result of the update promise resolving.\n if (this.isUsingUpdatePromise) {\n // Check whether the update promise has resolved with a state value.\n if (this.updatePromiseStateResult) {\n // Set the state of this node to match the state returned by the promise.\n this.setState(this.updatePromiseStateResult);\n }\n\n return;\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 // 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 const updateResult = actionFuncInvoker(this.actionArguments) as CompleteState | Promise;\n\n if (updateResult instanceof Promise) {\n updateResult.then(\n (result) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Check to make sure the result is a valid finished state.\n if (result !== State.SUCCEEDED && result !== 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 pending update promise state result to be processed on next update.\n this.updatePromiseStateResult = result;\n },\n (reason) => {\n // If 'isUpdatePromisePending' is null then the promise was cleared as it was resolving, probably via an abort of reset.\n if (!this.isUsingUpdatePromise) {\n return;\n }\n\n // Just throw whatever was returned as the rejection argument.\n throw new Error(reason);\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(updateResult);\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(updateResult || 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.updatePromiseStateResult = 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 | boolean) => {\n switch (result) {\n case State.SUCCEEDED:\n case State.FAILED:\n case undefined:\n return;\n default:\n throw new Error(\n `action '${this.actionName}' 'onUpdate' returned an invalid response, expected an optional State.SUCCEEDED or State.FAILED value to be returned`\n );\n }\n };\n}\n", "import Leaf from \"./Leaf\";\nimport State from \"../../State\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport Attribute from \"../../attributes/Attribute\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\nimport { BehaviourTreeOptions } from \"../../BehaviourTreeOptions\";\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: AnyArgument[]) {\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 // Call the condition function to determine the state of this node.\n this.setState(!!conditionFuncInvoker(this.conditionArguments) ? 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, or the earliest if longestDuration is defined.\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 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 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 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 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, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the SUCCEEDED state.\n // If this is the case then we will have to reset the child node now.\n if (this.child.getState() === State.SUCCEEDED) {\n this.child.reset();\n }\n\n // Update the child of this node.\n this.child.update(agent, 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 ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default repeat node name.\n return \"REPEAT\";\n };\n\n /**\n * Reset the state of the node.\n */\n reset = () => {\n // Reset the state of this node.\n this.setState(State.READY);\n\n // Reset the current iteration count.\n this.currentIterationCount = 0;\n\n // Reset the child node.\n this.child.reset();\n };\n\n /**\n * Gets whether an iteration can be made.\n * @returns Whether an iteration can be made.\n */\n private canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n private setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\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 iterations The number of iterations to repeat the child node, or the minimum number of iterations if maximumIterations is defined.\n * @param maximumIterations The maximum 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 maximumIterations: number | null,\n child: Node\n ) {\n super(\"retry\", 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 // Set the target iteration count.\n this.setTargetIterationCount();\n }\n\n // Do a check to see if we can iterate. If we can then this node will move into the 'RUNNING' state.\n // If we cannot iterate then we have hit our target iteration count, which means that the node has succeeded.\n if (this.canIterate()) {\n // This node is in the running state and can do its initial iteration.\n this.setState(State.RUNNING);\n\n // We may have already completed an iteration, meaning that the child node will be in the 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 iteration.\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 iteration.\n this.currentIterationCount += 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.iterations !== null) {\n return `RETRY ${\n this.maximumIterations ? this.iterations + \"x-\" + this.maximumIterations + \"x\" : this.iterations + \"x\"\n }`;\n }\n\n // Return the default retry node name.\n return \"RETRY\";\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 canIterate = () => {\n if (this.targetIterationCount !== null) {\n // We can iterate as long as we have not reached our target iteration count.\n return this.currentIterationCount < this.targetIterationCount;\n }\n\n // If neither an iteration count or a condition function were defined then we can iterate indefinitely.\n return true;\n };\n\n /**\n * Sets the target iteration count.\n */\n setTargetIterationCount = () => {\n // Are we dealing with a finite number of iterations?\n if (typeof this.iterations === \"number\") {\n // If we have maximumIterations defined then we will want a random iteration count bounded by iterations and maximumIterations.\n this.targetIterationCount =\n typeof this.maximumIterations === \"number\"\n ? Math.floor(Math.random() * (this.maximumIterations - this.iterations + 1) + this.iterations)\n : this.iterations;\n } else {\n this.targetIterationCount = null;\n }\n };\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 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\";\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 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 tickets The child node tickets.\n * @param children The child nodes.\n */\n constructor(attributes: Attribute[], private tickets: number[], 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.tickets[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.tickets.length ? `LOTTO [${this.tickets.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 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 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 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 { AnyArgument } from \"../RootAstNodesBuilder\";\nimport Guard from \"./guards/Guard\";\n\nexport type AttributeDetails = {\n /** The attribute type. */\n type: string;\n\n /** The attribute arguments. */\n args: AnyArgument[];\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 argument definitions.\n */\n constructor(protected type: string, protected args: AnyArgument[]) {}\n\n /**\n * Gets the type of the attribute.\n */\n getType = () => this.type;\n\n /**\n * Gets the array of attribute argument definitions.\n */\n getArguments = () => this.args;\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[], 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.getType(),\n args: this.getArguments(),\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\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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, { AnyExitArgument } from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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([{ value: { succeeded: isSuccess, aborted: isAborted } }, ...this.args]);\n };\n}\n", "import Callback from \"./Callback\";\nimport Lookup from \"../../Lookup\";\nimport { Agent } from \"../../Agent\";\nimport { AnyArgument } from \"../../RootAstNodesBuilder\";\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: AnyArgument[]) {\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 Action from \"./nodes/leaf/Action\";\nimport Condition from \"./nodes/leaf/Condition\";\nimport Wait from \"./nodes/leaf/Wait\";\nimport Root from \"./nodes/decorator/Root\";\nimport Repeat from \"./nodes/decorator/Repeat\";\nimport Retry from \"./nodes/decorator/Retry\";\nimport Flip from \"./nodes/decorator/Flip\";\nimport Succeed from \"./nodes/decorator/Succeed\";\nimport Fail from \"./nodes/decorator/Fail\";\nimport Lotto from \"./nodes/composite/Lotto\";\nimport Selector from \"./nodes/composite/Selector\";\nimport Sequence from \"./nodes/composite/Sequence\";\nimport Parallel from \"./nodes/composite/Parallel\";\nimport Node from \"./nodes/Node\";\nimport While from \"./attributes/guards/While\";\nimport Until from \"./attributes/guards/Until\";\nimport Entry from \"./attributes/callbacks/Entry\";\nimport Exit from \"./attributes/callbacks/Exit\";\nimport Step from \"./attributes/callbacks/Step\";\nimport Callback from \"./attributes/callbacks/Callback\";\nimport Guard from \"./attributes/guards/Guard\";\nimport Attribute from \"./attributes/Attribute\";\nimport Composite from \"./nodes/composite/Composite\";\nimport Decorator from \"./nodes/decorator/Decorator\";\nimport Leaf from \"./nodes/leaf/Leaf\";\n\nexport type Argument = {\n value: T;\n type: string; // Used for validation.\n};\ntype NullArgument = Argument & {\n type: \"null\";\n};\ntype BooleanArgument = Argument & {\n type: \"boolean\";\n};\ntype NumberArgument = Argument & {\n type: \"number\";\n isInteger: boolean; // Used for validation.\n};\ntype StringPlaceholderArgument = Argument & {\n type: \"string\";\n};\ntype IdentifierArgument = Argument & {\n type: \"identifier\";\n};\nexport type AnyArgument =\n | NullArgument\n | BooleanArgument\n | NumberArgument\n | StringPlaceholderArgument\n | IdentifierArgument;\n\n/**\n * The node attribute factories.\n */\nconst AttributeFactories: {\n [key: string]: (functionName: string, attributeArguments: AnyArgument[]) => Callback | Guard;\n} = {\n WHILE: (condition: string, attributeArguments: AnyArgument[]) => new While(condition, attributeArguments),\n UNTIL: (condition: string, attributeArguments: AnyArgument[]) => new Until(condition, attributeArguments),\n ENTRY: (functionName: string, attributeArguments: AnyArgument[]) => new Entry(functionName, attributeArguments),\n EXIT: (functionName: string, attributeArguments: AnyArgument[]) => new Exit(functionName, attributeArguments),\n STEP: (functionName: string, attributeArguments: AnyArgument[]) => new Step(functionName, attributeArguments)\n};\n\ntype Validatable = {\n children?: AstNode[];\n validate: (depth: number) => void;\n};\n\ntype NodeInstanceCreator = (\n namedRootNodeProvider: (name: string) => RootAstNode,\n visitedBranches: string[]\n) => T;\n\nexport type AstNode = Validatable & {\n type: string;\n createNodeInstance: NodeInstanceCreator;\n};\n\nexport type LeafAstNode = AstNode & {\n type: \"action\" | \"condition\" | \"wait\";\n attributes: Attribute[];\n};\n\nexport type CompositeAstNode = AstNode & {\n type: \"lotto\" | \"parallel\" | \"selector\" | \"sequence\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type DecoratorAstNode = AstNode & {\n type: \"fail\" | \"flip\" | \"repeat\" | \"retry\" | \"root\" | \"succeed\";\n attributes: Attribute[];\n children: AstNode[];\n};\n\nexport type BranchAstNode = AstNode & {\n type: \"branch\";\n branchName: \"\" | string;\n};\n\nexport type LottoAstNode = CompositeAstNode & {\n type: \"lotto\";\n tickets: number[];\n};\n\nexport type RootAstNode = DecoratorAstNode & {\n type: \"root\";\n name: null | string;\n};\n\nexport type IterableAstNode = DecoratorAstNode & {\n type: \"repeat\" | \"retry\";\n iterations: null | number;\n maximumIterations: null | number;\n};\n\nexport type ActionAstNode = LeafAstNode & {\n type: \"action\";\n actionName: string;\n actionArguments: AnyArgument[];\n};\n\nexport type ConditionAstNode = LeafAstNode & {\n type: \"condition\";\n conditionName: string;\n conditionArguments: AnyArgument[];\n};\n\nexport type WaitAstNode = LeafAstNode & {\n type: \"wait\";\n duration: number | null;\n durationMin: number | null;\n durationMax: number | null;\n};\n\nexport type AnyAstNode =\n | BranchAstNode\n | CompositeAstNode\n | LottoAstNode\n | DecoratorAstNode\n | RootAstNode\n | IterableAstNode\n | LeafAstNode\n | ActionAstNode\n | ConditionAstNode\n | WaitAstNode;\n\n/**\n * The AST node factories.\n */\nconst ASTNodeFactories = {\n ROOT: (): RootAstNode => ({\n type: \"root\",\n attributes: [],\n name: null,\n children: [],\n validate(depth: number) {\n // A root node cannot be the child of another node.\n if (depth > 1) {\n throw new Error(\"a root node cannot be the child of another node\");\n }\n\n // A root node must have a single child node.\n if (this.children.length !== 1) {\n throw new Error(\"a root node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Root(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n BRANCH: (): BranchAstNode => ({\n type: \"branch\",\n branchName: \"\",\n validate() {},\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n // Try to find the root node with a matching branch name.\n const targetRootNode = namedRootNodeProvider(this.branchName);\n\n // If we have already visited this branch then we have a circular dependency.\n if (visitedBranches.indexOf(this.branchName) !== -1) {\n throw new Error(`circular dependency found in branch node references for branch '${this.branchName}'`);\n }\n\n // If we have a target root node, then the node instance we want will be the first and only child of the referenced root node.\n if (targetRootNode) {\n return targetRootNode\n .createNodeInstance(namedRootNodeProvider, visitedBranches.concat(this.branchName))\n .getChildren()[0];\n } else {\n throw new Error(`branch references root node '${this.branchName}' which has not been defined`);\n }\n }\n }),\n SELECTOR: (): CompositeAstNode => ({\n type: \"selector\",\n attributes: [],\n children: [],\n validate() {\n // A selector node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a selector node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Selector(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n SEQUENCE: (): CompositeAstNode => ({\n type: \"sequence\",\n attributes: [],\n children: [],\n validate() {\n // A sequence node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a sequence node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Sequence(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n PARALLEL: (): CompositeAstNode => ({\n type: \"parallel\",\n attributes: [],\n children: [],\n validate() {\n // A parallel node must have at least a single node.\n if (this.children.length < 1) {\n throw new Error(\"a parallel node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Parallel(\n this.attributes,\n this.children.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n LOTTO: (): LottoAstNode => ({\n type: \"lotto\",\n attributes: [],\n children: [],\n tickets: [],\n validate() {\n // A lotto node must have at least a single node.\n if (this.children!.length < 1) {\n throw new Error(\"a lotto node must have at least a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Lotto(\n this.attributes,\n this.tickets!,\n this.children!.map((child) => child.createNodeInstance(namedRootNodeProvider, visitedBranches.slice()))\n );\n }\n }),\n REPEAT: (): IterableAstNode => ({\n type: \"repeat\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A repeat node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a repeat node must have a single child\");\n }\n\n // A repeat node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a repeat node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A repeat node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a repeat node must have a positive maximum iterations count if defined\");\n }\n\n // A repeat node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a repeat node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Repeat(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n RETRY: (): IterableAstNode => ({\n type: \"retry\",\n attributes: [],\n iterations: null,\n maximumIterations: null,\n children: [],\n validate() {\n // A retry node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a retry node must have a single child\");\n }\n\n // A retry node must have a positive number of iterations if defined.\n if (this.iterations !== null && this.iterations! < 0) {\n throw new Error(\"a retry node must have a positive number of iterations if defined\");\n }\n\n // There is validation to carry out if a longest duration was defined.\n if (this.maximumIterations !== null) {\n // A retry node must have a positive maximum iterations count if defined.\n if (this.maximumIterations! < 0) {\n throw new Error(\"a retry node must have a positive maximum iterations count if defined\");\n }\n\n // A retry node must not have an iteration count that exceeds the maximum iteration count.\n if (this.iterations! > this.maximumIterations!) {\n throw new Error(\n \"a retry node must not have an iteration count that exceeds the maximum iteration count\"\n );\n }\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Retry(\n this.attributes,\n this.iterations!,\n this.maximumIterations!,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FLIP: (): DecoratorAstNode => ({\n type: \"flip\",\n attributes: [],\n children: [],\n validate() {\n // A flip node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a flip node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Flip(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n SUCCEED: (): DecoratorAstNode => ({\n type: \"succeed\",\n attributes: [],\n children: [],\n validate() {\n // A succeed node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a succeed node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Succeed(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n FAIL: (): DecoratorAstNode => ({\n type: \"fail\",\n attributes: [],\n children: [],\n validate() {\n // A fail node must have a single node.\n if (this.children!.length !== 1) {\n throw new Error(\"a fail node must have a single child\");\n }\n },\n createNodeInstance(namedRootNodeProvider, visitedBranches) {\n return new Fail(\n this.attributes,\n this.children![0].createNodeInstance(namedRootNodeProvider, visitedBranches.slice())\n );\n }\n }),\n WAIT: (): WaitAstNode => ({\n type: \"wait\",\n attributes: [],\n duration: null,\n durationMin: null,\n durationMax: null,\n validate() {\n if (this.duration !== null) {\n // If an explict duration was defined then it must be a positive number.\n if (this.duration < 0) {\n throw new Error(\"a wait node must have a positive duration\");\n }\n } else if (this.durationMin !== null && this.durationMax !== null) {\n // A wait node must have a positive min and max duration.\n if (this.durationMin < 0 || this.durationMax < 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 (this.durationMin > this.durationMax) {\n throw new Error(\"a wait node must not have a minimum duration that exceeds the maximum duration\");\n }\n } else {\n // If we have no explicit duration or duration bounds set then we are dealing with a wait node that waits indefinitely.\n }\n },\n createNodeInstance() {\n return new Wait(this.attributes, this.duration, this.durationMin, this.durationMax);\n }\n }),\n ACTION: (): ActionAstNode => ({\n type: \"action\",\n attributes: [],\n actionName: \"\",\n actionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Action(this.attributes, this.actionName!, this.actionArguments!);\n }\n }),\n CONDITION: (): ConditionAstNode => ({\n type: \"condition\",\n attributes: [],\n conditionName: \"\",\n conditionArguments: [],\n validate() {},\n createNodeInstance() {\n return new Condition(this.attributes, this.conditionName!, this.conditionArguments!);\n }\n })\n};\n\ntype OtherAstNodes = AstNode[];\n\n/**\n * Create an array of root AST nodes based on the given definition.\n * @param definition The definition to parse the AST nodes from.\n * @returns The base definition AST nodes.\n */\nexport default function buildRootASTNodes(definition: string): RootAstNode[] {\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 // Convert the processed definition (with substituted string literals) into an array of raw tokens.\n const tokens = parseTokensFromDefinition(processedDefinition);\n\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 a stack of node children arrays, starting with a definition scope.\n const stack: [RootAstNode[], ...OtherAstNodes[]] = [[]];\n const rootScope = stack[0];\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 const currentScope = stack[stack.length - 1] as OtherAstNodes;\n\n // How we create the next AST token depends on the current raw token value.\n switch (token!.toUpperCase()) {\n case \"ROOT\": {\n // Create a ROOT AST node.\n const node = ASTNodeFactories.ROOT();\n\n // Push the ROOT node into the current scope.\n rootScope.push(node);\n\n // We may have a root node name defined as an argument.\n if (tokens[0] === \"[\") {\n const rootArguments = getArguments(tokens, placeholders);\n\n // We should have only a single argument that is not an empty string for a root node, which is the root name identifier.\n if (rootArguments.length === 1 && rootArguments[0].type === \"identifier\") {\n // The root name will be the first and only node argument.\n node.name = rootArguments[0].value as string;\n } else {\n throw new Error(\"expected single root name argument\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new ROOT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"BRANCH\": {\n // Create a BRANCH AST node.\n const node = ASTNodeFactories.BRANCH();\n\n // Push the BRANCH node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a branch name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected single branch name argument\");\n }\n\n // The branch name will be defined as a node argument.\n const branchArguments = getArguments(tokens, placeholders);\n\n // We should have only a single identifer argument for a branch node, which is the branch name.\n if (branchArguments.length === 1 && branchArguments[0].type === \"identifier\") {\n // The branch name will be the first and only node argument.\n node.branchName = branchArguments[0].value as string;\n } else {\n throw new Error(\"expected single branch name argument\");\n }\n break;\n }\n\n case \"SELECTOR\": {\n // Create a SELECTOR AST node.\n const node = ASTNodeFactories.SELECTOR();\n\n // Push the SELECTOR node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SELECTOR nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SEQUENCE\": {\n // Create a SEQUENCE AST node.\n const node = ASTNodeFactories.SEQUENCE();\n\n // Push the SEQUENCE node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new SEQUENCE nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"PARALLEL\": {\n // Create a PARALLEL AST node.\n const node = ASTNodeFactories.PARALLEL();\n\n // Push the PARALLEL node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new PARALLEL nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"LOTTO\": {\n // Create a LOTTO AST node.\n const node = ASTNodeFactories.LOTTO();\n\n // Push the LOTTO node into the current scope.\n currentScope.push(node);\n\n // If the next token is a '[' character then some ticket counts have been defined as arguments.\n if (tokens[0] === \"[\") {\n // Get the ticket count arguments, each argument must be a number.\n node.tickets = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"lotto node ticket counts must be integer values\"\n ).map((argument) => argument.value as number);\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new LOTTO nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"CONDITION\": {\n // Create a CONDITION AST node.\n const node = ASTNodeFactories.CONDITION();\n\n // Push the CONDITION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require a condition function name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Grab the condition node arguments.\n const conditionArguments = getArguments(tokens, placeholders);\n\n // We should have at least a single identifier argument for a condition node, which is the condition function name.\n if (conditionArguments.length && conditionArguments[0].type === \"identifier\") {\n // The condition function name will be the first node argument.\n node.conditionName = conditionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected condition name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n conditionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid condition node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the condition name identifier will be treated as condition function arguments.\n node.conditionArguments = conditionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"FLIP\": {\n // Create a FLIP AST node.\n const node = ASTNodeFactories.FLIP();\n\n // Push the Flip node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new FLIP nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"SUCCEED\": {\n // Create a SUCCEED AST node.\n const node = ASTNodeFactories.SUCCEED();\n\n // Push the Succeed node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Succeed nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"FAIL\": {\n // Create a FAIL AST node.\n const node = ASTNodeFactories.FAIL();\n\n // Push the Fail node into the current scope.\n currentScope.push(node);\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new Fail nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"WAIT\": {\n // Create a WAIT AST node.\n const node = ASTNodeFactories.WAIT();\n\n // Push the WAIT node into the current scope.\n currentScope.push(node);\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 (tokens[0] === \"[\") {\n // Get the optional duration and longest duration of the wait.\n const nodeArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"wait node durations must be integer values\"\n ).map((argument) => argument.value);\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] as number;\n } else if (nodeArguments.length === 2) {\n // Min and max duration bounds were defined from which a random duration will be picked.\n node.durationMin = nodeArguments[0] as number;\n node.durationMax = nodeArguments[1] as number;\n } else if (nodeArguments.length > 2) {\n // An incorrect number of durations was defined.\n throw new Error(\"invalid number of wait node duration arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"REPEAT\": {\n // Create a REPEAT AST node.\n const node = ASTNodeFactories.REPEAT();\n\n // Push the REPEAT node into the current scope.\n currentScope.push(node);\n\n // Check for iteration count node arguments ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"repeat node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\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 // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new REPEAT nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"RETRY\": {\n // Create a RETRY AST node.\n const node = ASTNodeFactories.RETRY();\n\n // Push the RETRY node into the current scope.\n currentScope.push(node);\n\n // Check for iteration counts ([])\n if (tokens[0] === \"[\") {\n // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait.\n const iterationArguments = getArguments(\n tokens,\n placeholders,\n (arg) => arg.type === \"number\" && !!arg.isInteger,\n \"retry node iteration counts must be integer values\"\n ).map((argument) => argument.value);\n\n // We should have got one or two iteration counts.\n if (iterationArguments.length === 1) {\n // A static iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n } else if (iterationArguments.length === 2) {\n // A minimum and maximum iteration count was defined.\n node.iterations = iterationArguments[0] as number;\n node.maximumIterations = iterationArguments[1] as number;\n } else {\n // An incorrect number of iteration counts was defined.\n throw new Error(\"invalid number of retry node iteration count arguments defined\");\n }\n }\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n\n popAndCheck(tokens, \"{\");\n\n // The new scope is that of the new RETRY nodes children.\n stack.push(node.children!);\n break;\n }\n\n case \"ACTION\": {\n // Create a ACTION AST node.\n const node = ASTNodeFactories.ACTION();\n\n // Push the ACTION node into the current scope.\n currentScope.push(node);\n\n // We must have arguments defined, as we require an action name argument.\n if (tokens[0] !== \"[\") {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // The action name will be defined as a node argument.\n const actionArguments = getArguments(tokens, placeholders);\n\n // We should have at least one identifer argument for an action node, which is the action name.\n if (actionArguments.length && actionArguments[0].type === \"identifier\") {\n // The action name will be the first and only node argument.\n node.actionName = actionArguments.shift()!.value as string;\n } else {\n throw new Error(\"expected action name identifier argument\");\n }\n\n // Only the first argument should have been an identifier, all following arguments must be string, number, boolean or null.\n actionArguments\n .filter((arg) => arg.type === \"identifier\")\n .forEach((arg) => {\n throw new Error(\n \"invalid action node argument value '\" +\n arg.value +\n \"', must be string, number, boolean or null\"\n );\n });\n\n // Any node arguments that follow the action name identifier will be treated as action function arguments.\n node.actionArguments = actionArguments;\n\n // Try to pick any attributes off of the token stack.\n node.attributes = getAttributes(tokens, placeholders);\n break;\n }\n\n case \"}\": {\n // The '}' character closes the current scope.\n stack.pop();\n break;\n }\n\n default: {\n throw new Error(\"unexpected token: \" + token);\n }\n }\n }\n\n // A function to recursively validate each of the nodes in the AST.\n const validateASTNode = (node: Validatable, depth: number): void => {\n // Validate the node.\n node.validate(depth);\n\n // Validate each child of the node.\n (node.children || []).forEach((child) => validateASTNode(child, depth + 1));\n };\n\n // Start node validation from the definition root.\n validateASTNode(\n {\n children: stack[0] as RootAstNode[],\n validate(this: { children: RootAstNode[] }) {\n // We must have at least one node defined as the definition scope, which should be a root node.\n if (this.children.length === 0) {\n throw new Error(\"expected root node to have been defined\");\n }\n\n // Each node at the base of the definition scope MUST be a root node.\n for (const definitionLevelNode of this.children) {\n if (definitionLevelNode.type !== \"root\") {\n throw new Error(\"expected root node at base of definition\");\n }\n }\n\n // Exactly one root node must not have a name defined. This will be the main root, others will have to be referenced via branch nodes.\n if (this.children.filter((definitionLevelNode) => definitionLevelNode.name === null).length !== 1) {\n throw new Error(\"expected single unnamed root node at base of definition to act as main root\");\n }\n\n // No two named root nodes can have matching names.\n const rootNodeNames: string[] = [];\n for (const definitionLevelNode of this.children) {\n if (rootNodeNames.indexOf(definitionLevelNode.name!) !== -1) {\n throw new Error(`multiple root nodes found with duplicate name '${definitionLevelNode.name}'`);\n } else {\n rootNodeNames.push(definitionLevelNode.name!);\n }\n }\n }\n },\n 0\n );\n\n // Return the root AST nodes.\n return stack[0];\n}\n\n/**\n * Pop the next raw token off of the stack and throw an error if it wasn't the expected one.\n * @param tokens The array of remaining 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 */\nfunction popAndCheck(tokens: string[], expected: string | string[]) {\n // Get and remove the next token.\n const popped = tokens.shift();\n\n // We were expecting another token.\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 // Check whether the popped token matches at least one of our expected items.\n var tokenMatchesExpectation = ([] as string[])\n .concat(expected)\n .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 = ([] as string[])\n .concat(expected)\n .map((item) => \"'\" + item + \"'\")\n .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\ntype Placeholders = { [key: string]: string };\n\n/**\n * Pull an argument definition list off of the token stack.\n * @param tokens The array of remaining tokens.\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 The argument definition list.\n */\nfunction getArguments(\n tokens: string[],\n stringArgumentPlaceholders: Placeholders,\n argumentValidator?: (arg: AnyArgument) => boolean,\n validationFailedMessage?: string\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 closer = popAndCheck(tokens, [\"[\", \"(\"]) === \"[\" ? \"]\" : \")\";\n\n const argumentListTokens: string[] = [];\n const argumentList: AnyArgument[] = [];\n\n // Grab all tokens between the '[' and ']' or '(' and ')'.\n while (tokens.length && tokens[0] !== closer) {\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 // Try to validate the argument.\n if (argumentValidator && !argumentValidator(argumentDefinition)) {\n throw new Error(validationFailedMessage);\n }\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, closer);\n\n // Return the argument list.\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: Placeholders): 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\n/**\n * Pull any attributes off of the token stack.\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 array of attributes defined by any directly following tokens.\n */\nfunction getAttributes(tokens: string[], stringArgumentPlaceholders: Placeholders) {\n // Create an array to hold any attributes found.\n const attributes: Attribute[] = [];\n\n // Keep track of names of attribute that we have found on the token stack, as we cannot have duplicates.\n const attributesFound: string[] = [];\n\n // Try to get the attribute factory for the next token.\n let attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n\n // Pull attribute tokens off of the tokens stack until we have no more.\n while (attributeFactory) {\n // Check to make sure that we have not already created a attribute of this type for this node.\n if (attributesFound.indexOf(tokens[0].toUpperCase()) !== -1) {\n throw new Error(`duplicate attribute '${tokens[0].toUpperCase()}' found for node`);\n }\n\n // Add the current attribute type to our array of found attributes.\n attributesFound.push(tokens.shift()!.toUpperCase());\n\n // Grab any attribute arguments.\n const attributeArguments = getArguments(tokens, stringArgumentPlaceholders);\n\n // The first attribute argument has to be an identifer, this will reference an agent function.\n if (attributeArguments.length === 0 || attributeArguments[0].type !== \"identifier\") {\n throw new Error(\"expected agent function name identifier argument for attribute\");\n }\n\n // Grab the first attribute which is an identifier that will reference an agent function.\n const attributeFunctionName = attributeArguments.shift()! as IdentifierArgument;\n\n // Any remaining attribute arguments 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 and add it to the array of attributes found.\n attributes.push(attributeFactory(attributeFunctionName.value, attributeArguments));\n\n // Try to get the next attribute name token, as there could be multiple.\n attributeFactory = AttributeFactories[(tokens[0] || \"\").toUpperCase()];\n }\n\n return attributes;\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 */\nfunction substituteStringLiterals(definition: string): {\n placeholders: { [key: string]: string };\n processedDefinition: string;\n} {\n // Create an object to hold the mapping of placeholders to original string values.\n const placeholders: Placeholders = {};\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 */\nfunction 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 GuardPath, { GuardPathPart } from \"./attributes/guards/GuardPath\";\nimport buildRootASTNodes, { AnyArgument, RootAstNode } from \"./RootAstNodesBuilder\";\nimport 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\";\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: AnyArgument[];\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 public readonly rootNode: Root;\n\n /**\n * Creates a new instance of the BehaviourTree class.\n * @param definition The behaviour tree definition.\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(definition: string, private agent: Agent, private options: BehaviourTreeOptions = {}) {\n // The tree definition must be defined and a valid string.\n if (typeof definition !== \"string\") {\n throw new Error(\"the tree definition must be a string\");\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 defined and not null\");\n }\n\n // Parse the behaviour tree definition, create the populated tree of behaviour tree nodes, and get the root.\n this.rootNode = BehaviourTree.createRootNode(definition);\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) {\n if (typeof value === \"function\") {\n // We are going to register a action/condition/guard/callback function.\n Lookup.setFunc(name, value);\n } else if (typeof value === \"string\") {\n // We are going to register a subtree.\n let rootASTNodes: RootAstNode[];\n\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n rootASTNodes = buildRootASTNodes(value);\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error registering definition: ${(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 (rootASTNodes.length != 1 || rootASTNodes[0].name !== null) {\n throw new Error(\"error registering definition: expected a single unnamed root node\");\n }\n\n Lookup.setSubtree(name, rootASTNodes[0]);\n } else {\n throw new Error(\"unexpected value, expected string 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 /**\n * Parses a behaviour tree definition and creates a tree of behaviour tree nodes.\n * @param {string} definition The behaviour tree definition.\n * @returns The root behaviour tree node.\n */\n private static createRootNode(definition: string): Root {\n try {\n // Try to create the behaviour tree AST based on the definition provided, this could fail if the definition is invalid.\n const rootASTNodes = buildRootASTNodes(definition);\n\n // Create a symbol to use as the main root key in our root node mapping.\n const mainRootNodeKey = Symbol(\"__root__\");\n\n // Create a mapping of root node names to root AST tokens. The main root node will have a key of Symbol(\"__root__\").\n const rootNodeMap: { [key: string | symbol]: RootAstNode } = {};\n for (const rootASTNode of rootASTNodes) {\n rootNodeMap[rootASTNode.name === null ? mainRootNodeKey : rootASTNode.name!] = rootASTNode;\n }\n\n // Convert the AST to our actual tree and get the root node.\n const rootNode: Root = rootNodeMap[mainRootNodeKey].createNodeInstance(\n // Create a provider for named root nodes that are part of our definition or have been registered. Prioritising the former.\n (name: string): RootAstNode => (rootNodeMap[name] ? rootNodeMap[name] : Lookup.getSubtree(name)),\n []\n );\n\n // Set a guard path on every leaf of the tree to evaluate as part of its update.\n BehaviourTree.applyLeafNodeGuardPaths(rootNode);\n\n // Return the root node.\n return rootNode;\n } catch (exception) {\n // There was an issue in trying to parse and build the tree definition.\n throw new Error(`error parsing tree: ${(exception as Error).message}\\n${(exception as Error).stack}`);\n }\n }\n\n /**\n * Applies a guard path to every leaf of the tree to evaluate as part of each update.\n * @param rootNode The main root tree node.\n */\n private static applyLeafNodeGuardPaths(rootNode: 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([], rootNode);\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}\n"], + "mappings": "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", "names": ["Participant", "Lotto", "createLotto", "State", "createLotto"] } diff --git a/src/RootAstNodesBuilder.ts b/src/RootAstNodesBuilder.ts index 02f1f77..bafd329 100644 --- a/src/RootAstNodesBuilder.ts +++ b/src/RootAstNodesBuilder.ts @@ -724,28 +724,34 @@ export default function buildRootASTNodes(definition: string): RootAstNode[] { // Push the WAIT node into the current scope. currentScope.push(node); - // Get the optional duration and longest duration of the wait. - const nodeArguments = getArguments( - tokens, - placeholders, - (arg) => arg.type === "number" && !!arg.isInteger, - "wait node durations must be integer values" - ).map((argument) => argument.value); - - // We may have: + // The arguments of a wait node are optional. We may have: // - No node arguments, in which case the wait will be indefinite until it is aborted. // - One node argument which will be the explicit duration of the wait. // - Two node arguments which define the min and max duration bounds from which a random duration will be picked. - if (nodeArguments.length === 1) { - // An explicit duration was defined. - node.duration = nodeArguments[0] as number; - } else if (nodeArguments.length === 2) { - // Min and max duration bounds were defined from which a random duration will be picked. - node.durationMin = nodeArguments[0] as number; - node.durationMax = nodeArguments[1] as number; - } else if (nodeArguments.length > 2) { - // An incorrect number of durations was defined. - throw new Error("invalid number of wait node duration arguments defined"); + if (tokens[0] === "[") { + // Get the optional duration and longest duration of the wait. + const nodeArguments = getArguments( + tokens, + placeholders, + (arg) => arg.type === "number" && !!arg.isInteger, + "wait node durations must be integer values" + ).map((argument) => argument.value); + + // We may have: + // - One node argument which will be the explicit duration of the wait. + // - Two node arguments which define the min and max duration bounds from which a random duration will be picked. + // - Too many arguments, which is not valid. + if (nodeArguments.length === 1) { + // An explicit duration was defined. + node.duration = nodeArguments[0] as number; + } else if (nodeArguments.length === 2) { + // Min and max duration bounds were defined from which a random duration will be picked. + node.durationMin = nodeArguments[0] as number; + node.durationMax = nodeArguments[1] as number; + } else if (nodeArguments.length > 2) { + // An incorrect number of durations was defined. + throw new Error("invalid number of wait node duration arguments defined"); + } } // Try to pick any attributes off of the token stack. @@ -760,7 +766,7 @@ export default function buildRootASTNodes(definition: string): RootAstNode[] { // Push the REPEAT node into the current scope. currentScope.push(node); - // Check for iteration counts ([]) + // Check for iteration count node arguments ([]) if (tokens[0] === "[") { // An iteration count has been defined. Get the iteration and potential maximum iteration of the wait. const iterationArguments = getArguments( diff --git a/src/nodes/leaf/Wait.ts b/src/nodes/leaf/Wait.ts index 1beea16..854682a 100644 --- a/src/nodes/leaf/Wait.ts +++ b/src/nodes/leaf/Wait.ts @@ -57,8 +57,13 @@ export default class Wait extends Leaf { if (this.duration !== null) { this.totalDuration = this.duration; } else if (this.durationMin !== null && this.durationMax !== null) { + // We will be picking a random duration between a min and max duration, if the optional 'random' behaviour tree + // function option is defined then we will be using that, otherwise we will fall back to using Math.random. + const random = typeof options.random === "function" ? options.random : Math.random; + + // Pick a random duration a min and max duration. this.totalDuration = Math.floor( - Math.random() * (this.durationMax - this.durationMin + 1) + this.durationMin + random() * (this.durationMax - this.durationMin + 1) + this.durationMin ); } else { this.totalDuration = null; diff --git a/test/nodes/leaf/action.test.js b/test/nodes/leaf/action.test.js index 2507426..c4f274d 100644 --- a/test/nodes/leaf/action.test.js +++ b/test/nodes/leaf/action.test.js @@ -54,7 +54,7 @@ describe("An Action node", () => { assert.throws( () => tree.step(), Error, - "error stepping tree: cannot update action node as the action 'DoTheThing' function is not defined on the agent and has not been registere" + "error stepping tree: cannot update action node as the action 'DoTheThing' function is not defined on the agent and has not been registered" ); }); diff --git a/test/nodes/leaf/wait.test.js b/test/nodes/leaf/wait.test.js index 967a48e..0dc3e1b 100644 --- a/test/nodes/leaf/wait.test.js +++ b/test/nodes/leaf/wait.test.js @@ -37,7 +37,7 @@ describe("A Wait node", () => { ); }); - it("a minimum duration bound niode argument is defined that is greater than the maximum duration bound node argument", () => { + it("a minimum duration bound node argument is defined that is greater than the maximum duration bound node argument", () => { const definition = "root { wait [1000, 500] }"; assert.throws( () => new mistreevous.BehaviourTree(definition, {}), @@ -50,13 +50,49 @@ describe("A Wait node", () => { describe("when updated as part of a tree step", () => { var clock; + var sandbox; - beforeEach(() => (clock = sinon.useFakeTimers())); - afterEach(() => clock.restore()); + beforeEach(() => { + clock = sinon.useFakeTimers(); + sandbox = sinon.createSandbox(); + sandbox.replace(globalThis.Math, "random", () => 0.5); + }); + + afterEach(() => { + clock.restore(); + sandbox.restore(); + }); + + it("and an explicit duration was defined will move to the SUCCEEDED state if the duration has expired", () => { + const definition = "root { wait [100] }"; + const tree = new mistreevous.BehaviourTree(definition, {}); + + let node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.READY); + + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.RUNNING); + + clock.tick(99); + + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.RUNNING); + + clock.tick(1); - describe("and an explicit duration was defined", () => { - it("will move to the SUCCEEDED state if the duration has expired", () => { - const definition = "root { wait [100] }"; + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.SUCCEEDED); + }); + + describe("and min and max durations were defined", () => { + it("will select a random duration between the min and max durations and move to the SUCCEEDED state if the duration has expired", () => { + const definition = "root { wait [5000, 10000] }"; const tree = new mistreevous.BehaviourTree(definition, {}); let node = findNode(tree, "wait"); @@ -67,7 +103,41 @@ describe("A Wait node", () => { node = findNode(tree, "wait"); assert.strictEqual(node.state, mistreevous.State.RUNNING); - clock.tick(99); + // We have spied on Math.random to always return 0.5 for the sake of this test, so our actual duration 'should' be 7500ms. + clock.tick(7499); + + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.RUNNING); + + clock.tick(1); + + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.SUCCEEDED); + }); + + it("will use the 'random' function to select the duration between the min and max durations if it was defined as a behaviour tree option and move to the SUCCEEDED state if the duration has expired", () => { + const definition = "root { wait [5000, 10000] }"; + const options = { + // Usually this would return a new pseudo-random number each time, but for the sake of this test we + // just want to make sure that the number we return actually has an impact on which duration is picked. + random: () => 0.2 + }; + const tree = new mistreevous.BehaviourTree(definition, {}, options); + + let node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.READY); + + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.RUNNING); + + // Our 'random' function option will always return 0.2 for the sake of this test, so our actual duration 'should' be 6000ms. + clock.tick(5999); tree.step(); @@ -83,7 +153,34 @@ describe("A Wait node", () => { }); }); - describe("and an explicit duration was not defined", () => {}); + it("and an explicit duration or min and max durations were not defined will stay in the RUNNING state until aborted", () => { + const definition = "root { wait while(CanWait) }"; + let canWait = true; + const agent = { CanWait: () => canWait }; + const tree = new mistreevous.BehaviourTree(definition, agent); + + let node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.READY); + + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.RUNNING); + + clock.tick(1000000); + + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.RUNNING); + + canWait = false; + + tree.step(); + + node = findNode(tree, "wait"); + assert.strictEqual(node.state, mistreevous.State.FAILED); + }); it("will use the 'getDeltaTime' function to update the elapsed duration if it was defined as a behaviour tree option", () => { const definition = "root { wait [1000] }"; From e3e070b7c39210cb2af7c7ecfbb5c883500d02cb Mon Sep 17 00:00:00 2001 From: Nikolas Howard Date: Wed, 3 May 2023 09:06:03 +0100 Subject: [PATCH 3/4] Updated README --- README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 84e77a4..dcbb07b 100644 --- a/README.md +++ b/README.md @@ -442,7 +442,7 @@ root { In the above example, we are using a wait node to wait 2 seconds between each run of the **FireWeapon** action. The duration to wait in milliseconds can also be selected at random within a lower and upper bound if these are defined as two integer node arguments. In the example below, we would run the **PickUpProjectile** action and then wait for 2 to 8 seconds before running the **ThrowProjectile** action. -[Example](https://nikkorn.github.io/mistreevous-visualiser/index.html?example=wait-one-to-five-seconds) +[Example](https://nikkorn.github.io/mistreevous-visualiser/index.html?example=wait) ``` root { @@ -454,6 +454,15 @@ root { } ``` +If no node arguments are defined then the wait node will remain in the running state indefinitely until it is aborted. +[Example](https://nikkorn.github.io/mistreevous-visualiser/index.html?example=wait) + +``` +root { + wait +} +``` + ### Branch Named root nodes can be referenced using the **branch** node. This node acts as a placeholder that will be replaced by the child node of the referenced root node. The two definitions below are synonymous. @@ -531,14 +540,14 @@ root { ``` ## Guards -A guard defines a condition that must be met in order for the node to remain active. Any running nodes will have their guard condition evaluated for each leaf node update, and will move to a failed state if the guard condition is not met. +A guard defines a condition that must be met in order for the associated node to remain active. Any running nodes will have their guard condition evaluated for each leaf node update, and will move to a failed state if the guard condition is not met. [Example](https://nikkorn.github.io/mistreevous-visualiser/index.html?example=guards) This functionality is useful as a means of aborting long running actions or branches that span across multiple steps of the tree. ``` root { - wait [10000] while(CanWait) + wait while(CanWait) } ``` From 12177feb7001c804c9725e80a0d585538e9a1a26 Mon Sep 17 00:00:00 2001 From: Nikolas Howard Date: Wed, 10 May 2023 08:25:12 +0100 Subject: [PATCH 4/4] npm update --- package-lock.json | 286 +++++++++++++++++++++++----------------------- package.json | 6 +- 2 files changed, 146 insertions(+), 146 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9ead6f0..34c2177 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,16 +39,16 @@ } }, "@esbuild/android-arm": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.14.tgz", - "integrity": "sha512-+Rb20XXxRGisNu2WmNKk+scpanb7nL5yhuI1KR9wQFiC43ddPj/V1fmNyzlFC9bKiG4mYzxW7egtoHVcynr+OA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.14.tgz", - "integrity": "sha512-eQi9rosGNVQFJyJWV0HCA5WZae/qWIQME7s8/j8DMvnylfBv62Pbu+zJ2eUDqNf2O4u3WB+OEXyfkpBoe194sg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", "dev": true, "optional": true }, @@ -231,9 +231,9 @@ } }, "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -306,15 +306,16 @@ "dev": true }, "chai": { - "version": "4.3.4", - "resolved": false, - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", + "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" } @@ -333,7 +334,7 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", "dev": true }, "chokidar": { @@ -414,10 +415,16 @@ } } }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -518,172 +525,172 @@ } }, "esbuild": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.14.tgz", - "integrity": "sha512-pJN8j42fvWLFWwSMG4luuupl2Me7mxciUOsMegKvwCmhEbJ2covUdFnihxm0FMIBV+cbwbtMoHgMCCI+pj1btQ==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.15.14", - "@esbuild/linux-loong64": "0.15.14", - "esbuild-android-64": "0.15.14", - "esbuild-android-arm64": "0.15.14", - "esbuild-darwin-64": "0.15.14", - "esbuild-darwin-arm64": "0.15.14", - "esbuild-freebsd-64": "0.15.14", - "esbuild-freebsd-arm64": "0.15.14", - "esbuild-linux-32": "0.15.14", - "esbuild-linux-64": "0.15.14", - "esbuild-linux-arm": "0.15.14", - "esbuild-linux-arm64": "0.15.14", - "esbuild-linux-mips64le": "0.15.14", - "esbuild-linux-ppc64le": "0.15.14", - "esbuild-linux-riscv64": "0.15.14", - "esbuild-linux-s390x": "0.15.14", - "esbuild-netbsd-64": "0.15.14", - "esbuild-openbsd-64": "0.15.14", - "esbuild-sunos-64": "0.15.14", - "esbuild-windows-32": "0.15.14", - "esbuild-windows-64": "0.15.14", - "esbuild-windows-arm64": "0.15.14" + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" } }, "esbuild-android-64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.14.tgz", - "integrity": "sha512-HuilVIb4rk9abT4U6bcFdU35UHOzcWVGLSjEmC58OVr96q5UiRqzDtWjPlCMugjhgUGKEs8Zf4ueIvYbOStbIg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", "dev": true, "optional": true }, "esbuild-android-arm64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.14.tgz", - "integrity": "sha512-/QnxRVxsR2Vtf3XottAHj7hENAMW2wCs6S+OZcAbc/8nlhbAL/bCQRCVD78VtI5mdwqWkVi3wMqM94kScQCgqg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", "dev": true, "optional": true }, "esbuild-darwin-64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.14.tgz", - "integrity": "sha512-ToNuf1uifu8hhwWvoZJGCdLIX/1zpo8cOGnT0XAhDQXiKOKYaotVNx7pOVB1f+wHoWwTLInrOmh3EmA7Fd+8Vg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", "dev": true, "optional": true }, "esbuild-darwin-arm64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.14.tgz", - "integrity": "sha512-KgGP+y77GszfYJgceO0Wi/PiRtYo5y2Xo9rhBUpxTPaBgWDJ14gqYN0+NMbu+qC2fykxXaipHxN4Scaj9tUS1A==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", "dev": true, "optional": true }, "esbuild-freebsd-64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.14.tgz", - "integrity": "sha512-xr0E2n5lyWw3uFSwwUXHc0EcaBDtsal/iIfLioflHdhAe10KSctV978Te7YsfnsMKzcoGeS366+tqbCXdqDHQA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", "dev": true, "optional": true }, "esbuild-freebsd-arm64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.14.tgz", - "integrity": "sha512-8XH96sOQ4b1LhMlO10eEWOjEngmZ2oyw3pW4o8kvBcpF6pULr56eeYVP5radtgw54g3T8nKHDHYEI5AItvskZg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", "dev": true, "optional": true }, "esbuild-linux-32": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.14.tgz", - "integrity": "sha512-6ssnvwaTAi8AzKN8By2V0nS+WF5jTP7SfuK6sStGnDP7MCJo/4zHgM9oE1eQTS2jPmo3D673rckuCzRlig+HMA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", "dev": true, "optional": true }, "esbuild-linux-64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.14.tgz", - "integrity": "sha512-ONySx3U0wAJOJuxGUlXBWxVKFVpWv88JEv0NZ6NlHknmDd1yCbf4AEdClSgLrqKQDXYywmw4gYDvdLsS6z0hcw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", "dev": true, "optional": true }, "esbuild-linux-arm": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.14.tgz", - "integrity": "sha512-D2LImAIV3QzL7lHURyCHBkycVFbKwkDb1XEUWan+2fb4qfW7qAeUtul7ZIcIwFKZgPcl+6gKZmvLgPSj26RQ2Q==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", "dev": true, "optional": true }, "esbuild-linux-arm64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.14.tgz", - "integrity": "sha512-kle2Ov6a1e5AjlHlMQl1e+c4myGTeggrRzArQFmWp6O6JoqqB9hT+B28EW4tjFWgV/NxUq46pWYpgaWXsXRPAg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", "dev": true, "optional": true }, "esbuild-linux-mips64le": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.14.tgz", - "integrity": "sha512-FVdMYIzOLXUq+OE7XYKesuEAqZhmAIV6qOoYahvUp93oXy0MOVTP370ECbPfGXXUdlvc0TNgkJa3YhEwyZ6MRA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", "dev": true, "optional": true }, "esbuild-linux-ppc64le": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.14.tgz", - "integrity": "sha512-2NzH+iuzMDA+jjtPjuIz/OhRDf8tzbQ1tRZJI//aT25o1HKc0reMMXxKIYq/8nSHXiJSnYV4ODzTiv45s+h73w==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", "dev": true, "optional": true }, "esbuild-linux-riscv64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.14.tgz", - "integrity": "sha512-VqxvutZNlQxmUNS7Ac+aczttLEoHBJ9e3OYGqnULrfipRvG97qLrAv9EUY9iSrRKBqeEbSvS9bSfstZqwz0T4Q==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", "dev": true, "optional": true }, "esbuild-linux-s390x": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.14.tgz", - "integrity": "sha512-+KVHEUshX5n6VP6Vp/AKv9fZIl5kr2ph8EUFmQUJnDpHwcfTSn2AQgYYm0HTBR2Mr4d0Wlr0FxF/Cs5pbFgiOw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", "dev": true, "optional": true }, "esbuild-netbsd-64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.14.tgz", - "integrity": "sha512-6D/dr17piEgevIm1xJfZP2SjB9Z+g8ERhNnBdlZPBWZl+KSPUKLGF13AbvC+nzGh8IxOH2TyTIdRMvKMP0nEzQ==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", "dev": true, "optional": true }, "esbuild-openbsd-64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.14.tgz", - "integrity": "sha512-rREQBIlMibBetgr2E9Lywt2Qxv2ZdpmYahR4IUlAQ1Efv/A5gYdO0/VIN3iowDbCNTLxp0bb57Vf0LFcffD6kA==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", "dev": true, "optional": true }, "esbuild-sunos-64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.14.tgz", - "integrity": "sha512-DNVjSp/BY4IfwtdUAvWGIDaIjJXY5KI4uD82+15v6k/w7px9dnaDaJJ2R6Mu+KCgr5oklmFc0KjBjh311Gxl9Q==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", "dev": true, "optional": true }, "esbuild-windows-32": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.14.tgz", - "integrity": "sha512-pHBWrcA+/oLgvViuG9FO3kNPO635gkoVrRQwe6ZY1S0jdET07xe2toUvQoJQ8KT3/OkxqUasIty5hpuKFLD+eg==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", "dev": true, "optional": true }, "esbuild-windows-64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.14.tgz", - "integrity": "sha512-CszIGQVk/P8FOS5UgAH4hKc9zOaFo69fe+k1rqgBHx3CSK3Opyk5lwYriIamaWOVjBt7IwEP6NALz+tkVWdFog==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", "dev": true, "optional": true }, "esbuild-windows-arm64": { - "version": "0.15.14", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.14.tgz", - "integrity": "sha512-KW9W4psdZceaS9A7Jsgl4WialOznSURvqX/oHZk3gOP7KbjtHLSsnmSvNdzagGJfxbAe30UVGXRe8q8nDsOSQw==", + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", "dev": true, "optional": true }, @@ -741,14 +748,6 @@ "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" - }, - "dependencies": { - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } } }, "flat": { @@ -803,7 +802,7 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", "dev": true }, "get-intrinsic": { @@ -995,7 +994,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, "is-fullwidth-code-point": { @@ -1005,9 +1004,9 @@ "dev": true }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -1034,6 +1033,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -1375,6 +1380,15 @@ "resolved": "https://registry.npmjs.org/lotto-draw/-/lotto-draw-1.0.2.tgz", "integrity": "sha512-1ih414A35BWpApfNlWAHBKOBLSxTj45crAJ+CMWF/kVY5nx6N22DA1OVF/FWW5WM5CGJbIMRh1O+xe8ukyoQ8Q==" }, + "loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "requires": { + "get-func-name": "^2.0.0" + } + }, "memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -1401,9 +1415,9 @@ } }, "mocha": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", - "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", "dev": true, "requires": { "ansi-colors": "4.1.1", @@ -1467,12 +1481,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true } } }, @@ -1620,6 +1628,12 @@ "p-limit": "^3.0.2" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -2097,9 +2111,9 @@ } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true }, "yargs-unparser": { @@ -2112,20 +2126,6 @@ "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - } } }, "yocto-queue": { diff --git a/package.json b/package.json index ae27a81..0b47c4a 100644 --- a/package.json +++ b/package.json @@ -8,10 +8,10 @@ "dist/*" ], "devDependencies": { - "chai": "^4.3.4", - "esbuild": "^0.15.13", + "chai": "^4.3.7", + "esbuild": "^0.15.18", "expect": "^25.5.0", - "mocha": "^10.1.0", + "mocha": "^10.2.0", "npm-run-all": "^4.1.5", "prettier": "2.7.1", "should": "^1.3.0",