Expressions
Expressions
There are two expression evaluators in play when you debug a table, and it saves confusion to keep them apart:
| Where it runs | What it does | |
|---|---|---|
| Console evaluator | The eval command and watched expressions | A compact calculator over the variables in your debug session |
| Scoring evaluator | Expression fields in your .cade files | The full language your table actually scores with |
The first half of this page covers what you can type at the prompt. The second half is the complete function reference for scoring expressions.
Part 1 — The eval Command
Variable References
Reference a variable by the name you gave it, written bare — no ${...} wrapper:
cade:debug> set var.score 1000
Set var.score = 1000 for player 1
cade:debug> eval var.score * 2
Expression: "var.score * 2"
Variables:
var.score = 1000
(use var.<name> to reference variables in expressions)
Result: 2000The name in eval must match the name you used in set. Dotted names work as expected:
cade:debug> set var.bonus.multiplier 3
cade:debug> eval var.bonus.multiplier * 500
Result: 1500Prefer the
var.prefix. It is what the console itself suggests, and it matches how variables are written in.cadefiles, so you keep one habit.
Migrating from
${...}: older debug scripts wrapped references as${var.score}. The console still accepts that form, but bare is canonical — and in.cadefiles${...}is a hard parse error.
Variables resolve against the current debug session. Use player to switch player context before evaluating.
Values
| Kind | Examples |
|---|---|
| Numbers | 100, -5, 2.5 |
| Booleans | true, false |
| Strings | "multiball" (double quotes required) |
Operators
Arithmetic — +, -, *, /, %. Unary + and - are supported.
Comparison — ==, !=, <, <=, >, >=.
Logical — &&, ||, !.
Parentheses group subexpressions: eval (var.base + var.bonus) * var.multiplier.
Functions
The console evaluator provides three numeric functions:
| Function | Description | Example |
|---|---|---|
min(a, b, ...) | Smallest of two or more values | min(var.score, 10000) |
max(a, b, ...) | Largest of two or more values | max(var.bonus, 0) |
abs(x) | Absolute value | abs(var.delta) |
min and max take two or more arguments; abs takes exactly one. All require numeric arguments.
Not Available at the Prompt
These are valid in .cade scoring expressions but not in eval:
- Ternary (
cond ? a : b) - Exponentiation — use
powin scoring expressions - The math functions beyond
min/max/abs—round,floor,ceil,clamp,sqrt,pow - String and list functions (
string.to_upper,list.length, …) - Module state (
module.<name>.active)
To exercise those, put them in a .cade scoring expression and trigger the event that runs it, then read the computed value off the cascade viewer.
Examples
cade:debug> eval 100 + 50
Result: 150
cade:debug> eval (var.base_score + var.bonus) * var.multiplier
Result: 7500
cade:debug> eval var.score > 1000 && var.multiball.active
Result: false
cade:debug> eval max(var.score, var.high_score)
Result: 15000Watched Expressions
watch accepts an expression, not just a plain variable name, and re-evaluates it as game state changes:
cade:debug> watch var.score
Now watching variable: var.score
cade:debug> watch var.score > 1000
Now watching expression: var.score > 1000
cade:debug> unwatch var.score
Stopped watching variable: var.scoreThe operator and function rules above apply. An expression that cannot be evaluated — usually because a variable is not set yet — reports its error instead of a value, and starts working as soon as the variable exists.
Watched variables and expressions survive a config hot reload. See Configuration.
Part 2 — Scoring Expression Functions
These functions are available in expression fields in your .cade files, evaluated by the scoring engine. For syntax, quoting rules, and worked examples, see Writing Expressions.
Math
| Function | Description |
|---|---|
min(a, b) | Smaller of two values |
max(a, b) | Larger of two values |
abs(x) | Absolute value |
round(x) | Round to the nearest integer |
floor(x) | Round down |
ceil(x) | Round up |
clamp(x, lo, hi) | Constrain x to the range lo–hi |
sqrt(x) | Square root |
pow(x, y) | x raised to the power y |
For deterministic randomness — noise, random_range, weighted_choice and friends — see the Noise Generator.
String
| Function | Description |
|---|---|
string.length(s) | Number of characters |
string.concat(s1, s2, ...) | Concatenate two or more strings |
string.contains(s, sub) | true if s contains sub |
string.substring(s, start, len) | len characters starting at start (0-based) |
string.to_upper(s) | Convert to uppercase |
string.to_lower(s) | Convert to lowercase |
string.trim(s) | Remove leading and trailing whitespace |
string.replace(s, old, new) | Replace all occurrences of old with new |
string.matches(s, pattern) | true if s matches the regular expression pattern |
string.split(s, delim) | Split s on delim, returning a list |
string.join(list, delim) | Join a list of strings with delim |
string.to_int(s) | Parse s as an integer |
string.to_bool(s) | Parse s as a boolean |
string.from_int(i) | Convert an integer to a string |
string.from_bool(b) | Convert a boolean to "true" or "false" |
List
Lists are ordered and zero-indexed. Functions that return a modified list always return a new one — existing lists are never mutated.
Inspection
| Function | Description |
|---|---|
list.length(list) | Number of elements |
list.empty(list) | true if the list has no elements |
list.contains(list, elem) | true if elem is present |
list.index_of(list, elem) | Index of the first occurrence, or -1 |
Access
| Function | Description |
|---|---|
list.first(list) | First element |
list.last(list) | Last element |
list.get(list, index) | Element at index |
list.slice(list, start, end) | Sublist from start to end (exclusive) |
list.random(list) | A random element |
Modification
| Function | Description |
|---|---|
list.append(list, elem) | New list with elem added at the end |
list.prepend(list, elem) | New list with elem added at the beginning |
list.insert(list, index, elem) | New list with elem inserted at index |
list.remove(list, elem) | New list with the first occurrence of elem removed |
list.remove_at(list, index) | New list with the element at index removed |
list.reverse(list) | New list in reverse order |
list.sort(list) | New list in ascending order |
list.shuffle(list) | New list in random order |
list.unique(list) | New list with duplicates removed (first occurrence kept) |
Construction and Set Operations
| Function | Description |
|---|---|
list.from_element(elem) | Single-element list |
list.concat(list1, list2) | New list combining both |
list.join(list, delim) | Join a list of strings with delim |
list.difference(list1, list2) | Elements in list1 not present in list2 |
list.intersection(list1, list2) | Elements present in both lists |
Module Namespace
Scoring expressions can query module state through the module namespace:
| Expression | Returns | Description |
|---|---|---|
module.<name>.active | Boolean | Whether the module’s mode is currently active |
module.<name>.instance_count | Integer | Number of active instances (for stackable modules) |
module.<name>.<variable> | Value | A module-scoped variable |
Module variables are registered under both their qualified name (module.<moduleName>.<varName>) and a short name (<varName>). If two modules define the same short name, a collision warning is logged and only the qualified name resolves.