Variables
A variable is a named box holding one value. You read a variable with the
$ sigil — $actor, $count — and you create or change one with let,
set, or const.
A variable can hold a value of any type, and a single variable
may hold different types at different times. Variables are not the same
as persistent entity state: state that must survive between handler runs
lives in slots reached through store/recall,
not in variables.
Reading a variable — $name
$name (or the braced form ${name}) evaluates to the value of the
nearest enclosing binding of that name (see Scope for what
"nearest enclosing" means).
$actor # the creature that triggered the handler
$self # the script's owner
${count} # braced form, same meaning as $count
The braced form is handy inside a string when text follows
the name: "${count}coins" reads count, while "$countcoins" would
look for a variable named countcoins.
A $name that has no binding anywhere is caught when the script is
compiled — it never loads. (A handler-injected name the event does not
provide, like $actor in a tick handler, is a run-time error instead.)
Introducing a local variable — let
let name value creates a fresh, mutable local variable in the
current scope. The name is written without $ — the sigil appears
only when reading.
let counter 0
let target $actor
let shadows any outer binding of the same name. Declaring a name that is
already bound in the same scope is a compile-time error.
Changing a local variable — set
set name value rewrites an existing binding, searching outward through
the enclosing scopes. It never creates a binding.
let counter 0
set counter [+ $counter 1] # mutates the let above
set of a name that is not bound, or of an immutable const, is a
compile-time error. Because set searches outward, a block
can change a variable owned by an enclosing scope — the basis of the
counter idiom in Scope.
An immutable local — const
const name value introduces an immutable local: it can be read but never
set. Use it for fixed values you want to name.
const GREETING 'gossip'
do "say $GREETING"
(const is also a top-level declaration form; see Scope.)
Local variables are fresh every time
A handler's local variables start fresh on each invocation and are
gone when it ends. They do not carry over from one event to the
next. To keep state between invocations, write it to persistent entity
state with store/recall.
Examples
after command (say) {
let counter 0
set counter [+ $counter 1]
do "say counter is $counter"
}
Introduces counter, mutates it, then reports its value ("counter is
1").
const GREETING 'gossip'
after command (say) {
store $self 'state' $GREETING
do "say my state is [recall $self 'state']"
}
Names a constant, then uses it as a persistent value the script can read back later. The mob would report "my state is gossip."
See also
- Scope — where a name is visible and how lookup walks outward.
- Persistent state —
store/recall, for state that outlives a single run. - Types · Values · Blocks