Scoring Safety Mode and Fallback Points
Scoring Safety Mode and Fallback Points
Cade is designed to never halt a game in progress. If a scoring rule panics, times out, or produces bad state, the engine catches the fault, awards a fallback point value, and keeps running. After too many consecutive faults on the same event, the engine switches into safety mode — it keeps scoring at a reduced level until normal rules start succeeding again.
This behavior is automatic. You do not need to enable it. The only thing you configure directly is the fallback point value per event.
Fallback Points
When a scoring rule fails, the engine looks up a fallback point value rather than awarding zero. The lookup has three tiers, in order:
- Event-specific fallback — a
fallback_pointsvalue on the score event itself. - Category default — looked up from the first segment of the event name.
- Global minimum — a final floor of
10points.
Event-Specific fallback_points
score "event" "bumper_hit" {
trigger = switch.bumper.hit
points = "${var.bumper_value} * ${var.multiplier}"
fallback_points = 100
}
score "event" "jackpot" {
trigger = jackpot.collected
points = "${var.base_jackpot} * ${var.jackpot_multiplier}"
fallback_points = 10000
}
fallback_points is used whenever the rule’s points expression cannot be evaluated (panic, timeout, or invalid state) and whenever the engine is in safety mode.
Category Defaults
If no fallback_points is set, the engine extracts a category from the dot-delimited event name and uses a built-in default:
| Category | Fallback points |
|---|---|
switch | 10 |
target | 100 |
bumper | 100 |
ramp | 1,000 |
loop | 1,000 |
mode | 5,000 |
jackpot | 10,000 |
wizard | 50,000 |
For example, switch.bumper.hit matches bumper and falls back to 100 points.
Global Minimum
If neither an event-specific fallback nor a category match exists, the engine awards the global minimum (10 points). Zero is never awarded on a recovered error.
Safety Mode Activation
When any single event’s rule fails several times in a row, the engine enters safety mode. In safety mode it:
- Skips conditions, complex point expressions, and variable updates.
- Skips accumulator processing.
- Awards only fallback points per event.
The engine exits safety mode after a longer run of successful scores. The thresholds default to:
| Threshold | Default | What it controls |
|---|---|---|
| Activation | 5 consecutive failures on any single event | When the engine enters safety mode |
| Recovery | 20 consecutive successes | When the engine returns to full operation |
Observability
When safety mode activates or deactivates, and whenever an individual scoring error is recovered, the engine emits system events so external observers can react:
| System event | Emitted when |
|---|---|
system.scoring.safety_mode.activated | Engine enters safety mode |
system.scoring.safety_mode.deactivated | Engine exits safety mode |
system.scoring.error | A scoring error was recovered and fallback points were awarded |
The deactivation event also includes how long the engine spent in safety mode.
Three performance counters track the cumulative impact of error recovery across a game:
| Counter | Incremented when |
|---|---|
safe_mode_activations | Engine enters safety mode |
total_scoring_errors | Any recovered scoring error |
fallback_points_awarded | Fallback points are awarded |
Watch these via the console to spot systematic problems before they affect players.
Best Practices
- Assign
fallback_pointsto high-value events. Jackpots and wizard mode scoring especially benefit from explicit fallback values — category defaults are intentionally modest. - Favor conservative fallback values. It is better to under-award than to over-award when a rule misbehaves.
- Monitor counters. Rising
total_scoring_errorswithout a matching rise insafe_mode_activationsusually indicates a buggy rule that is within tolerance but still failing regularly.