Skip to content

11. Reactions

EBNF
reaction = reaction_header ":" reaction_body .
reaction_header = "queue" reaction_target .
reaction_target = reaction_target_type identifier .
reaction_target_type = "action" | "action-selector" | "plan" | "plan-selector" .

A reaction declaration, or just reaction, specifies a construct that may be queued for future execution in response to an action being performed. Reactions appear in the reactions field of an action definition or as plan instructions.

EBNF
reaction_header = "queue" reaction_target .
reaction_target = reaction_target_type identifier .
reaction_target_type = "action" | "action-selector" | "plan" | "plan-selector" .

The reaction header is introduced by the queue keyword, followed by a reaction target. The target comprises a target type and an identifier naming the construct to queue.

The four reaction-target types are:

KeywordTargets
actionAn action definition
action-selectorAn action selector
planA plan definition
plan-selectorA plan selector
queue action retaliate:
...
queue action-selector choose-response:
...
queue plan revenge-arc:
...
EBNF
reaction_body = (* unordered; bindings required, others optional *)
bindings
[ reaction_urgency ]
[ reaction_priority ]
[ reaction_location ]
[ reaction_time ]
[ reaction_abandonment_conditions ]
[ reaction_repeat_logic ] .

The reaction body contains zero or more fields, each introduced by a keyword. The fields are: bindings (with), urgency (urgent), priority (priority), location (location), time (time), abandonment conditions (abandon), and repeat logic (repeat). All fields except bindings are optional, and they may appear in any order.

The bindings for a reaction precast one or more roles of the targeted construct. Bindings are required; use with none; to explicitly declare that no roles are precast. For full details on bindings syntax, see the Bindings chapter.

queue action retaliate:
with:
@attacker: @insulter
@defender: @target
EBNF
reaction_urgency = "urgent" ":" expression .

The urgency field is introduced by the urgent keyword, and specifies an expression that determines whether this reaction should be processed urgently—that is, before the next simulation tick rather than in the normal queue order. The expression SHOULD evaluate to a boolean value:

queue action flee:
with none;
urgent: @victim.fear > 80
EBNF
reaction_priority = "priority" ":" expression .

The priority field is introduced by the priority keyword, and specifies an expression that yields a numeric value used to order this reaction relative to others in the queue. Higher values indicate higher priority:

queue action retaliate:
with none;
priority: @target.aggression
EBNF
reaction_location = "location" ":" set_predicate+ .

The location field is introduced by the location keyword, and constrains where the reaction may be executed using one or more set predicates. The reaction will only proceed if the location conditions are met at the time of execution:

queue action confront:
with none;
location:
any: @scene_of_crime

For full details on set predicates (none, any, all, exactly), see the Queries chapter.

EBNF
reaction_time = "time" ":" temporal_constraint+ .

The time field is introduced by the time keyword, and constrains when the reaction may be executed using one or more temporal constraints. The reaction will only proceed within the specified time frame:

queue action retaliate:
with none;
time:
after: 1 hour from action
before: 1 week from action

For full details on temporal constraints, see the Temporal constraints chapter.

EBNF
reaction_abandonment_conditions = "abandon" ":" statements .

The abandonment-conditions field is introduced by the abandon keyword, and specifies a block of statements that, if all evaluate to truthy values, cause the queued reaction to be abandoned (removed from the queue) rather than executed:

queue action retaliate:
with none;
abandon:
@target.mood > 80
@insulter.dead
EBNF
reaction_repeat_logic = "repeat" ":" reaction_repeat_logic_if reaction_repeat_logic_max
| "repeat" ":" reaction_repeat_logic_max reaction_repeat_logic_if .
reaction_repeat_logic_if = "if" ":" statements .
reaction_repeat_logic_max = "max" ":" integer .

The repeat-logic field is introduced by the repeat keyword, and specifies conditions under which a reaction will be re-queued after execution. It has two subfields, which may appear in either order:

  • if: A block of statements. If all evaluate to truthy values after the reaction executes, the reaction is re-queued.

  • max: An integer specifying the maximum number of times the reaction may be repeated.

queue action pester:
with none;
repeat:
if:
@target.patience > 0
max: 5