Run-time

This chapter describes the observable behavior of a running script: how return, break, continue, and the handler guards propagate; how a script can span game ticks; the limits that bound an execution; and the determinism a script can rely on.

Control-flow propagation

return, break, and continue do not merely end the current block — they propagate outward through the constructs that invoked it until a construct catches them. Ordinary fall-through off the end of a block, or a return value once it reaches its catch site, simply yields that value to the caller.

Statement Passes through Caught by
return [value] if, each, select, every, some, randomly the [block …] or bareword call site that invoked the block, or the handler invocation — yielding value there
break / continue if, randomly the nearest enclosing each/select/every/some
a failed require / satisfied unless (top-level handler statements) handler processing, which advances to the next matching handler (Program initialization and execution)

Within a loop, continue skips to the next element and break ends the iteration; a return in the body unwinds out of the loop to its caller. select produces its filtered elements on demand, so a break in the predicate ends the filtered sequence and a continue drops the current candidate.

break/continue do not cross into an outer loop: an inner each/select catches them, so an inner break ends only the inner iteration. To escape several levels at once, set a flag and test it. A break or continue with no enclosing loop to catch it propagates out and terminates the script.

Suspension and cross-tick execution

A script runs to completion within a single game tick unless it suspends itself with pause n, which suspends the running script for n ticks and then resumes where it left off, with its locals intact.

after enter {
  do "bow $actor"
  pause 3
  do "emote points to a sign."
}

Execution limits

Every execution is bounded so that no single script can stall the game:

These bounds are the only limit on iteration and recursion — there are no unbounded loops. A script may invoke other scripts re-entrantly (for example, a do that triggers another entity's handler); each such execution is bounded by the same limits (Error conditions).

Determinism

A script runs to a stopping point — its normal end, an error, a pause, or the execution budget — without being preempted. The randomized builtins (random, randrange, choose, randomly) are the only source of non-determinism; apart from those, an execution's behavior is determined entirely by the world state at the moment it begins. The one subtlety is that an after handler observes a later world state than the before/handle handlers of the same event, because it runs after the event's effects are applied.