Skip to content

scripting

Gguidini edited this page May 13, 2021 · 3 revisions

The Script or Control system provides tooling to automate behaviors of entities in the simulation. It is particularly indicated to create NPC-like entities (that have pre-defined behaviors during the simulation).

This is a somewhat complex and VERY extensible system. It is a reactive DES system. It needs only the Script component for an entity to be controled. The Script processor is a reactive DES processor.

The script component

The script component holds the instructions that an entity is supposed to execute. Much like the PathProcessor's only job is to take an entity through its path, the "only" job of the Scripting system is to execute the entity's script.

Scripts are created with the following properties:

  • instructions: List[str] - the list of instructions to execute. They will be executed in order
  • error_handlers: Dict[str, ErrorHandler] - A list of actions to be executed when a certain error is found. The error is identified by a string, with a corresponding ErrorHandler function to be executed.
  • default_error_tag: str - The tag for the ErrorHandler that should be executed when an error is found that doesn't have an ErrorHandler assigned to it. Default value is '__default'.

ErrorHandler is any function with type Callable[[NamedTuple, SystemArgs], None]. Here the parameters are respectively the Error event that triggered the error and the SystemArgs that all systems receive. Return must be None.

During execution the Script component also holds some important informations:

  • curr_instruction - The number of the current instruction being executed, 0-indexed.
  • state - The current state of the script. States are READY (ready to execute next instruction), BLOCKED (waiting some asynchronous condition to complete the current instruction), and DONE (all instructions executed)
  • expecting - A list of event tags that the script is expecting to occur. Details below.
  • logs - A list of log messages of the script execution.

Initializing the Script System

When initializing the Script system 2 informations must be given:

  1. extra_instructions: List[ExtraInstruction] - A list of extra instructions that the system can use. ExtraInstructions can be exported by any system. Details below.
  2. watch_list: List[str] - A list of event tags that the system must react to. Usually used to unblock entities waiting for asynchronous operations to complete.

Creating extra instructions

Any system can export extra instructions to be used with the Script system. ExtraInstruction is defined as (str, Callable[[int, List[str], scriptComponent.Script, FilterStore], scriptComponent.States]), where str is the tag of the instruction (i.e. what must be written in the script instruction that identifies this instruction), and Callable is a function that effectively implements the new instruction. Instructions are usually high level commands.

The parameters for these functions are respectively entityId, list of arguments, the entity's script component, the EVENT_STORE. The return of the function is the state in which the Script component should be, usually READY or BLOCKED. THe GotoProcessor exports a goInstruction, as an example. Instructions are also responsible for adding the list of event tags to the expecting list on the entity's script, if necessary.

If an instruction may fail, the system exporting that instruction should also export an ErrorHandler for the error event that the function may produce.

Asynchronous operations

When an instruction represents an asynchronous operation, the script execution must be blocked while the instruction is being carried out. Let's see how that is done:

  1. Before using an instruction, the Scripting component must be initialized with the extra instruction and with the event tags that mark the end of the instruction.
  2. An asynchronous function is executed. The instruction that implements it MUST add to the expecting list in the Script component all the event tags that mark the end of the instruction, AND return the state BLOCKED. For example, the "Go" instruction adds the "EndOfPath" tag to the expecting list, because is that event that marks the end of the instruction.
  3. After some time, the event that marks the end of the instruction is received by the Script system in the EVENT_STORE. It should contain at least the entity id. The script system will then remove from that entity's script component expecting list the tag for that event. IF the expecting list becomes empty, the script system will then change the entity's state from BLOCKED to READY.

⚠️
If you forget to add the event tags to the Script system watch list the entity will be blocked forever