Expressions

Expression Language

The Cade Console includes an expression evaluator for testing scoring logic interactively. Expressions are used with the eval command and in watched expressions.

Variable References

Variables are referenced using ${variable.name} syntax. Nested paths and array access are supported.

cade:debug> eval ${score}
Result: 1000

cade:debug> eval ${player.bonus.multiplier}
Result: 3

cade:debug> eval ${targets[0].value}
Result: 500

Variables resolve against the current player’s game state. Use the player command to switch context between players before evaluating.

Operators

Arithmetic

OperatorDescriptionExample
+Addition${score} + 100
-Subtraction${score} - 50
*Multiplication${score} * 2
/Division${score} / 10
%Modulus${score} % 1000
^Power2 ^ 10

Comparison

OperatorDescriptionExample
>Greater than${score} > 1000
<Less than${score} < 500
>=Greater than or equal${combo} >= 3
<=Less than or equal${balls.locked} <= 2
==Equal${multiball.active} == true
!=Not equal${bonus.level} != 0

Logical

OperatorDescriptionExample
&&Logical AND${multiball.active} && ${jackpot.lit}
||Logical OR${bonus.active} || ${combo} > 5
!Logical NOT!${game.over}

Ternary

The ternary operator selects between two values based on a condition:

cade:debug> eval ${combo} >= 3 ? ${score} * 2 : ${score}
Result: 2000

Built-in Functions

Math

FunctionDescriptionExample
min(a, b)Returns the smaller valuemin(${score}, 10000)
max(a, b)Returns the larger valuemax(${bonus}, 0)
abs(x)Returns the absolute valueabs(${delta})
round(x)Rounds to the nearest integerround(${score} / 3)
floor(x)Rounds down to the nearest integerfloor(${multiplier} * 1.5)
ceil(x)Rounds up to the nearest integerceil(${score} / 7)

String

String functions operate on string values and are accessed via the string.* namespace.

FunctionDescriptionExample
string.length(s)Returns the number of charactersstring.length(${player.name})
string.concat(s1, s2, ...)Concatenates two or more stringsstring.concat(${first}, " ", ${last})
string.contains(s, sub)Returns true if s contains substring.contains(${mode.name}, "ball")
string.substring(s, start, len)Extracts len characters starting at start (0-based)string.substring(${code}, 0, 3)
string.to_upper(s)Converts all characters to uppercasestring.to_upper(${label})
string.to_lower(s)Converts all characters to lowercasestring.to_lower(${label})
string.trim(s)Removes leading and trailing whitespacestring.trim(${input})
string.replace(s, old, new)Replaces all occurrences of old with newstring.replace(${path}, "/", ".")
string.matches(s, pattern)Returns true if s matches the regex patternstring.matches(${device}, "^left_")
string.split(s, delim)Splits s on delim and returns a list of stringsstring.split(${tags}, ",")
string.join(list, delim)Joins a list of strings with delim and returns a stringstring.join(${parts}, "-")
string.to_int(s)Parses s as an integerstring.to_int(${count_str})
string.to_bool(s)Parses s as a boolean ("true"/"false")string.to_bool(${flag_str})
string.from_int(i)Converts an integer to its string representationstring.from_int(${score})
string.from_bool(b)Converts a boolean to "true" or "false"string.from_bool(${active})
cade:debug> eval string.length("hello")
Result: 5

cade:debug> eval string.contains(${player.name}, "Guest")
Result: false

cade:debug> eval string.to_upper("multiball")
Result: "MULTIBALL"

cade:debug> eval string.replace("left_inlane", "_", "-")
Result: "left-inlane"

cade:debug> eval string.split("a,b,c", ",")
Result: ["a", "b", "c"]

cade:debug> eval string.join(${tag_list}, " | ")
Result: "jackpot | multiball | bonus"

List

List functions operate on list values and are accessed via the list.* namespace. Lists are ordered, zero-indexed collections. Functions that return a modified list always return a new list — existing lists are never mutated.

Inspection

FunctionDescriptionExample
list.length(list)Returns the number of elementslist.length(${targets})
list.empty(list)Returns true if the list has no elementslist.empty(${queue})
list.contains(list, elem)Returns true if elem is in the listlist.contains(${active_modes}, "multiball")
list.index_of(list, elem)Returns the index of the first occurrence of elem, or -1list.index_of(${players}, ${current})

Access

FunctionDescriptionExample
list.first(list)Returns the first elementlist.first(${scores})
list.last(list)Returns the last elementlist.last(${scores})
list.get(list, index)Returns the element at index (0-based)list.get(${targets}, 2)
list.slice(list, start, end)Returns a sublist from start to end (exclusive)list.slice(${events}, 0, 5)
list.random(list)Returns a random elementlist.random(${bonuses})

Modification

FunctionDescriptionExample
list.append(list, elem)Returns a new list with elem added at the endlist.append(${hits}, "target_a")
list.prepend(list, elem)Returns a new list with elem added at the beginninglist.prepend(${queue}, "jackpot")
list.insert(list, index, elem)Returns a new list with elem inserted at indexlist.insert(${steps}, 1, "bonus")
list.remove(list, elem)Returns a new list with the first occurrence of elem removedlist.remove(${modes}, "attract")
list.remove_at(list, index)Returns a new list with the element at index removedlist.remove_at(${items}, 0)
list.reverse(list)Returns a new list in reverse orderlist.reverse(${history})
list.sort(list)Returns a new list with elements in ascending orderlist.sort(${scores})
list.shuffle(list)Returns a new list with elements in random orderlist.shuffle(${deck})
list.unique(list)Returns a new list with duplicate elements removed (first occurrence kept)list.unique(${events})

Construction

FunctionDescriptionExample
list.from_element(elem)Creates a single-element listlist.from_element(${score})
list.concat(list1, list2)Returns a new list combining both listslist.concat(${left}, ${right})
list.join(list, delim)Joins a list of strings with delim and returns a stringlist.join(${tags}, ", ")

Set Operations

FunctionDescriptionExample
list.difference(list1, list2)Returns elements in list1 not present in list2list.difference(${all}, ${seen})
list.intersection(list1, list2)Returns elements present in both listslist.intersection(${required}, ${collected})
cade:debug> eval list.length(${targets})
Result: 5

cade:debug> eval list.contains(${active_modes}, "multiball")
Result: true

cade:debug> eval list.first(${scores})
Result: 4200

cade:debug> eval list.append(${hits}, "spinner")
Result: ["ramp", "orbit", "spinner"]

cade:debug> eval list.sort(${scores})
Result: [500, 1000, 4200, 8750]

cade:debug> eval list.intersection(${required_targets}, ${hit_targets})
Result: ["left_ramp", "right_orbit"]

Module Namespace

The expression evaluator supports querying module state through the module namespace. This enables expressions that check whether a module is active, how many instances are running, or read module-scoped variables.

ExpressionReturnsDescription
module.<name>.activeBooleanWhether the module’s mode is currently active
module.<name>.instance_countIntegerNumber of active instances (for stackable modules)
module.<name>.<variable>ValueA module-scoped variable value

Module variables are registered under both their qualified name (module.<moduleName>.<varName>) and a short name (<varName>). If two modules define a variable with the same short name, a collision warning is logged and only the qualified name is available.

cade:debug> eval module.multiball.active
Result: true

cade:debug> eval module.multiball.instance_count
Result: 2

cade:debug> eval module.multiball.active && module.bonus.active
Result: false

cade:debug> eval module.multiball.jackpot_value
Result: 50000

Tab Completion in Expressions

The expression completion provider offers context-aware suggestions while typing expressions. After the eval keyword, pressing Tab completes:

The completion system parses partial expressions with error recovery, so completions remain available even when the expression is incomplete.

Examples

Scoring Calculations

cade:debug> eval (${baseScore} + ${bonus}) * ${multiplier}
Result: 7500

cade:debug> eval ${targets.completed} * 500 * ${bonus.multiplier}
Result: 5000

Conditional Logic

cade:debug> eval ${combo} >= 3 ? ${score} * 2 : ${score}
Result: 2000

cade:debug> eval ${balls.locked} >= 3 ? "start_multiball" : "lock_more"
Result: "lock_more"

Boolean Checks

cade:debug> eval ${multiball.active} && ${jackpot.lit}
Result: false

cade:debug> eval ${score} > 1000 || ${bonus.level} > 2
Result: true

Combining Functions

cade:debug> eval max(${score}, ${highScore})
Result: 15000

cade:debug> eval min(${bonus.multiplier}, 5) * ${basePoints}
Result: 2500

Expression Watching

Expressions can be watched to continuously evaluate and display updated results. The watch panel shows watched expression values alongside watched variables, updating in real time as game state changes.