Chapter 3: Variables and control flow
Scripts can declare local variables, do arithmetic, and branch based on
conditions. This chapter covers let, set, if, and each.
Local variables with let and set
let creates a new variable. set changes one that already exists.
after command (say) {
require [keyword $args count]
let n [count [people [room $self]]]
do "say There are $n people in this room."
}
Breaking it down:
[room $self]— the room the mob is in.[people [room $self]]— the creatures in that room.[count ...]— how many elements are in the iterable.let n [count ...]— store the result in a variable calledn."...$n..."— interpolate the variable into a string.
Note that let and set write the variable name without the $
sigil. The $ is only used when reading a variable.
let x 10 # create x with value 10
set x [+ $x 1] # change x to x + 1 (now 11)
Arithmetic
Math uses prefix notation inside [...]:
[+ 3 4] # 7
[- 10 3] # 7
[* 2 5] # 10
[/ 20 4] # 5
[% 17 5] # 2 (remainder)
Combine them by nesting:
let damage [+ [* 2 $strength] $weapon_bonus]
Comparisons
Comparisons also use prefix notation and return booleans:
[eq $x $y] # equal (works for any type)
[ne $x $y] # not equal
[gt $x $y] # greater than (integers only)
[lt $x $y] # less than
[ge $x $y] # greater or equal
[le $x $y] # less or equal
Conditional execution with if
after command (say) {
require [keyword $args time]
let h [hour]
if [lt $h 6] {
do "say It is still night."
} elif [lt $h 12] {
do "say Good morning."
} elif [lt $h 18] {
do "say Good afternoon."
} else {
do "say Good evening."
}
}
if [condition] { body }— runs the body if the condition is true.elif [condition] { body }— checked if the previous conditions were false.else { body }— runs if nothing else matched.
The condition must be a boolean (true or false). Integers and
strings are not automatically treated as booleans — you need a
comparison like [gt $x 0], not just $x.
Looping with each
each iterates over a collection:
after command (say) {
require [keyword $args roll-call]
each [people [room $self]] { <person>
do "say I see [name $person]."
}
}
[people [room $self]]produces the creatures in the room.{ <person> ... }is a block with a parameter. Each creature is bound to$personin turn.- The block runs once per element.
You can iterate over words in a string:
after command (say) {
each [words $arg] { <word>
do "say Word: $word"
}
}
If the player types say one two three, the mob says each word
separately.
Combining conditions
Use and, or, and not:
if [and [gt $level 10] [lt $level 20]] {
do "say You are mid-level."
}
if [or [eq $class 'Warrior'] [eq $class 'Knight']] {
do "say A fighting type!"
}
if [not [isplayer $actor]] {
do "say You are not a player."
}
All operands must be booleans. [and] and [or] take two or more
arguments.
Example: a level-checking guard
after command (say) {
require [keyword $args pass enter]
let lvl [level $actor]
if [lt $lvl 10] {
do "say You are too inexperienced, [name $actor]. Come back when you are stronger."
} else {
do "say You may pass, [name $actor]."
do "emote steps aside."
}
}
Example: counting objects
after command (say) {
require [keyword $args inventory]
let n [count [objects $actor]]
do "say You carry $n items, [name $actor]."
}
Key points
let name valuecreates a variable (no$on the name).set name valuechanges an existing variable.- Arithmetic and comparisons use prefix:
[+ 1 2],[gt $x 5]. if/elif/elsefor branching. Conditions must bebool.each iter { <item> body }for looping over collections.and,or,notfor combining booleans.