The two ideas the input revamp leads with, built in Ludic over the single-key poll every target already provides: - Action maps: gameplay reads named actions, not physical keys, so keys are rebindable and a scheme is data. Input.bind(action, key), Input.down/pressed(action), Input.rebind(action, from, to). - Deterministic record/replay: Input.poll() is the one per-frame input read; Input.record() captures the key each frame and Input.replay() feeds the tape back, so a run reproduces exactly — the seed of lockstep netcode. "Read input" and "read a recorded snapshot" are the same call. runtime/native/input.ludic (spliced when the new Input.* methods are used; pulls in core.ludic for rt_poll). emit_ns_call routes the methods to the @fn_input_* runtime; parse.ludic gates the splice. Seven docs/language pages; worked example + regression examples/library/input_actions.ludic (1 0 1 1 0 1 0). Full suite 75 passed, self-host fixpoint intact, no golden drift. The device layer (multi-key held, gamepads, touch, analog) needs a platform key-state backend and is tracked separately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
37 lines
1.6 KiB
Text
37 lines
1.6 KiB
Text
# input_actions.ludic — action maps, runtime rebinding, and deterministic input
|
|
# record/replay (#7). Gameplay reads named actions, not physical keys, so a key
|
|
# is rebindable; and because the sim is deterministic in its input stream, a
|
|
# recorded run replays exactly. Driven headless off stdin (one key per poll):
|
|
#
|
|
# printf ' xwa' | bin/ludic examples/library/input_actions.ludic -> 1 0 1 1 0 1 0
|
|
program InputActions {
|
|
function bi(b: bool) -> int { if b { return 1 }; return 0 }
|
|
|
|
entry {
|
|
Input.bind("jump", ' ') # space triggers "jump"
|
|
Input.bind("up", 'w') # w triggers "up"
|
|
|
|
# --- action map + runtime rebinding (live) ---
|
|
Input.poll() # stdin: ' '
|
|
print(bi(Input.down("jump"))) # 1 — space is bound to jump
|
|
|
|
Input.rebind("jump", ' ', 'x') # remap jump from space to x at runtime
|
|
Input.poll() # stdin: ' '
|
|
print(bi(Input.down("jump"))) # 0 — space no longer fires jump
|
|
Input.poll() # stdin: 'x'
|
|
print(bi(Input.down("jump"))) # 1 — x now fires jump
|
|
|
|
# --- deterministic record / replay ---
|
|
Input.record() # capture the polled keys from here
|
|
Input.poll() # stdin: 'w'
|
|
print(bi(Input.down("up"))) # 1
|
|
Input.poll() # stdin: 'a'
|
|
print(bi(Input.down("up"))) # 0
|
|
|
|
Input.replay() # rewind; poll now reads the tape, not stdin
|
|
Input.poll()
|
|
print(bi(Input.down("up"))) # 1 — reproduces the recorded frame exactly
|
|
Input.poll()
|
|
print(bi(Input.down("up"))) # 0
|
|
}
|
|
}
|