- runtime: HEADLESS_FRAME_PATH, STICK_DEADZONE / STICK_LEFT_X/Y, key and byte codes as char literals throughout (`k == 'w'`, `fill(rt_map, ' ', …)`) - ludic.gameplay/stats: drop the duplicate `stat_field` (it answered "atk" for every build stat); Stats.base uses stats_field_name - ludic.shooter: compare aim modes and fire patterns with AimMode.* and WeaponPattern.* instead of raw ints; STICK_RIGHT_X/Y - ludic.npcai: DecisionMade / brain_set_state use AiState.* - examples/games/menu.ludic uses Font.load / Ui.* with FONT_PATH and BACKDROP named; strings.ludic header says what it prints - whole tree: `x = x + 1` → `x += 1` (single-term right-hand sides only), `0 - x` → `-x`, ASCII codes → char literals; every .ludic and every ```ludic fence reformatted with the fixed formatter (whitespace only) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
28 lines
997 B
Text
28 lines
997 B
Text
# errors.ludic — error handling (issue #8): assert(cond, msg) guards an invariant
|
|
# and aborts with a located message when it is broken; panic(msg) aborts outright.
|
|
# This is the SUCCESS path — every assertion here holds, so nothing aborts and the
|
|
# program runs to the end, printing:
|
|
# 5 10 0 7 1
|
|
# The failure path (a panic exits non-zero with `file:line: panic: …` on stderr)
|
|
# is exercised separately in the test runner.
|
|
program Errors {
|
|
function checked_div(a: int, b: int) -> int {
|
|
assert(b != 0, "division by zero")
|
|
return a / b
|
|
}
|
|
|
|
function clampi(v: int, lo: int, hi: int) -> int {
|
|
assert(lo <= hi, "lo must not exceed hi")
|
|
if v < lo { return lo }
|
|
if v > hi { return hi }
|
|
return v
|
|
}
|
|
|
|
entry {
|
|
print(checked_div(10, 2)) # 5
|
|
print(clampi(15, 0, 10)) # 10 (above hi)
|
|
print(clampi(-3, 0, 10)) # 0 (below lo)
|
|
print(clampi(7, 0, 10)) # 7 (in range)
|
|
print(1) # reached: every assertion held
|
|
}
|
|
}
|