Conditions¶
For: advanced users branching command lines.
<if> branches and <switch> dispatch: the two ways a command line decides. The one-line forms live in the cheatsheet.
| Tag | Meaning |
|---|---|
<if:"cond","y","n"> |
y when the condition holds, else n (else omittable; only the chosen branch runs). |
<switch:value,case,result,...> |
First matching result, or the trailing default; other arms never run. |
Comparisons: ==, !=, lt, le, gt, ge; joiners and / or (and binds tighter); leading not flips one comparison. Angle brackets (<, >, <=, >=) warn and yield nothing.
<if> compares with ==, !=, lt, le, gt, ge and joins
parts with and / or (and binds tighter, case does not matter).
Parentheses group conditions, including nested groups:
pending == true and (nearby ge 1 or elapsed ge 300).
Groups may nest up to 64 levels; unmatched or excessive parentheses warn
and yield nothing. Parentheses around math operands still work normally.
Leading not words flip one comparison and bind tightest of all,
so not a == b and c == d reads as (not (a == b)) and (c == d),
and not not x cancels out:
- 'say <if:"1 == 1 and 2 lt 3 or 4 == 5","y","n">'
- 'say <if:"not <pstat:<p>,health> le 6","healthy","heal!">'
Like and / or, not matches case-blindly and needs whitespace
after it, which keeps words like notable plain text. A not with
no comparison behind it warns and yields nothing.
Only the condition and the chosen branch evaluate: tags in the dead branch never run. Use the word operators for ordering comparisons, and backslash escapes for literal brackets (see Escaping Special Characters): quotes group condition text but never hid tags from the scanner. Empty branch results, including side-effect branches (which yield empty), are fine and warn-free on both paths.
Dead branches never run
Side effects in the unchosen branch (messages, sounds, flag
writes, <run>) do NOT fire. Flatten nested <if>s into one
condition with and / or whenever both elses agree:
Tags on a command line resolve left-to-right: flag writes earlier
on the line are visible to <if>s and loops later on it, so setup
can share the line with the logic that reads it. Each ordinary tag
finishes evaluating its nested arguments and writing its value before
the next tag reads it, including within each loop iteration.
<if> conditions short-circuit: a false and operand skips the remaining
operands in that group, and a true or operand skips the remaining
alternatives. Tags inside skipped comparisons never run. This lets
kind == item and <pcountitem:<p>,<lf:material>> ge 1 query inventory
only for item tasks, without warnings for other task keys.
Ordering compares decimals as well as whole numbers (7.5 gt 7
holds, 7.5 le 7.5 holds). Each side compares as a number when it
parses as math, otherwise as text. Word operators need a
non-letter-or-digit boundary on each side (spaces work, so does the
edge of the condition), which keeps them distinct from tag brackets:
An <if> without an else branch yields nothing when the condition
fails, so a bare guard line aborts the list only on a hit. This
first line skips the rest when the runner already holds a gapple:
Angle brackets are never comparisons: <, >, <=, and >= in a
condition warn and yield nothing, naming the word operators to use
instead. Quote the condition when it holds commas or nested tags.
<switch:value,case,result,...[,default]> dispatches on exact text:
the value evaluates once, labels compare left to right as strings
(case-sensitive, one quote layer stripped), and only the first
matching result evaluates. A trailing odd part is the default, used
when nothing matches; with no match and no default the tag yields
nothing. Results holding commas must be quoted, as anywhere:
Arms are lazy: messages, sounds, flag writes, loops, and nested
<if>s in unselected arms never run, which makes <switch> cheaper
than the equivalent chain of <if>s (one value evaluation instead
of one condition per branch). One nesting rule mirrors <if>: a
<switch> nested inside an arm resolves innermost-first, before the
outer switch picks, so keep nested switches out of dead arms. (This
is unrelated to <pswitch>, which moves a player between roles.)
# bingo completion check (one arm shown; the real line holds eleven):
# kind dispatches once per slot, the guard stays inside the arm
- '<for:<range:0,<gflag:bingo:slots:<lf:who>>>,<switch:<gflag:bingo:kind:<lf:who>:<i>>,sneak,"<if:"<gflag:bingo:done:<lf:who>:<i>> != true and <gflag:bingo:prog:<lf:who>:sneak> ge <gflag:bingo:need:<lf:who>:<i>>","<runblock:announce-slot,<lf:who>,<i>>">",...>>'
Each pass resolves defs, loops, filters, switches, ifs, then list
mutators, resolving the plain window before each span plus one final
left-to-right sweep, repeating until nothing changes. The trap this
order sets: an
<if> holding a nested <if> (or a <switch> holding a nested
<switch>) resolves the inner span first, before the outer
selection, while plain tags in the outer branches fire in the plain
sweep meanwhile. Effects in a dead outer branch still run. Flatten
with and / or (or dispatch once through <switch>) instead of
nesting same-kind spans.