Control flow
How a script chooses what to run and how it stops. Control flow is not
special syntax — if, return, break, continue, and the rest are
ordinary command calls that take block arguments or direct
execution.
if / elif / else
if [cond] { body }
if [cond] { body } elif [cond] { body } else { body }
Conditions are tested top to bottom; the first one that is true runs its
branch, and the rest are skipped. elif may appear any number of times;
else, at most once and last. The condition must be a bool — a
non-bool raises a type error, because there is no truthiness (see
Values).
after command (say) {
if [ge [level $actor] 10] {
do "say welcome, veteran"
} else {
do "say you have much to learn"
}
}
For an inverted test, use if [not [cond]] { … }.
if is also an expression: it yields the value of the branch that
runs (with no match and no else, it yields null). The branch's
value is its last statement's value, so that statement must be a
value-producing call:
let label [if [ge [level $actor] 10] { [upper "veteran"] } else { [upper "novice"] }]
do "say you are a $label"
Against a level-26 actor $label is VETERAN. Note the branch bodies
use [upper "veteran"], a command call — a bare "veteran" in
statement position would be read as a command and fail.
return
return value exits the enclosing block, def,
or handler, yielding value. Bare return yields null. A return
inside a loop unwinds out of the loop.
def classify { <c>
if [ge [level $c] 20] { return [upper "elite"] }
return [upper "common"]
}
break and continue
Inside a loop body (each, select,
every, some):
continueskips to the next element.breakends the loop.
after command (say) {
each [words "1 2 3 4 5"] { <n>
if [streqi $n '3'] { continue }
if [streqi $n '5'] { break }
do "say n is $n"
}
}
It reports n is 1, n is 2, n is 4, then stops. (Compare the
words as strings — '3' — since words yields strings,
not ints.)
break and continue affect only the nearest enclosing loop; they do
not jump out of an outer loop. To escape several levels, set a flag with
set and test it. A break/continue with no enclosing
loop propagates out and stops the script.
halt
halt stops the current execution immediately. Nothing after
it in the handler runs.
after command (say) {
do "say first"
halt
do "say never reached" # not executed
}
Only "first" is said.
pause
pause n suspends the script for n ticks, then resumes right where
it left off with its locals intact — the one way a script spans game
ticks.
after enter {
do "bow $actor"
pause 3
do "emote points to a sign."
}
nuke
nuke cancels every other script currently running on the same owner
— the running script that calls nuke keeps going, but any sibling
scripts on the same creature/object/room are terminated, including ones
suspended on a pause or queued to run later. Use it when a
script needs to take sole control of its owner and stop competing
handlers (e.g. an aggressive sequence that should override a paused
idle routine).
handle command {
require [streqi $arg "stop"]
nuke
do "say everything else is cancelled."
}