@caputchin/engine-kit
v0.5.0
Published
Optional authoring kit: the reducer-to-run adapter (fixed-step replay loop + default trace codec) for Caputchin server-validated game replay
Downloads
343
Maintainers
Readme
@caputchin/engine-kit
The reducer-to-run authoring lane for Caputchin server-validated game replay.
Write your game as a pure reducer and this kit turns it into the one conforming
run(seed, config, trace) the platform replays. It is optional: you can ignore
it and ship a bare run you wrote by hand against
@caputchin/replay-contract.
This kit exports only its own surface and re-exports nothing. Install the pieces it builds on directly, from their owners:
- the mandatory contract from
@caputchin/replay-contract, - the deterministic primitives (
rng,capMath, the ambient ban shim) from@caputchin/determinism, - the determinism self-check from
@caputchin/replay-selfcheck(also shipped here as thecaputchin-selfcheckCLI).
What it provides
defineEngine(spec)- declare your reducer (init/step/tick/isOver/result, plus an optional renderview). A typed identity helper; it wraps nothing.toRun(engine, { maxTicks })- the adapter: turns the reducer into the conformingrun(seed, config, trace). This is the kit's reason to exist.replay- the fixed-step loop that drives both live play and the server replay, so live score equals replay score by construction.encodeTrace/decodeTrace- the batteries-included JSON trace codec (opaque to the platform; bring your own if you prefer).FIXED_TIMESTEP_MS,CODEC_Vand the reducer types (EngineDef,TickInput,Result, ...).caputchin-selfcheck(CLI bin) - probe a builtrunartifact for determinism before publish:caputchin-selfcheck dist/run.js.
Usage
import { defineEngine, toRun } from '@caputchin/engine-kit';
import { rng, capMath } from '@caputchin/determinism';
const engine = defineEngine<State, Action, Config>({
init: ({ seed }) => ({ rngState: rng(seed).state, score: 0 /* ... */ }),
step: (s, action) => ({ /* apply one input */ }),
tick: (s) => ({ /* advance one fixed step */ }),
isOver: (s) => s.score >= s.goal,
result: (s) => ({ score: s.score, passed: s.score >= s.goal }),
});
// The one mandatory export the artifact ships:
export const run = toRun(engine, { maxTicks: 2000 });Then, before publishing, prove it is deterministic:
caputchin-selfcheck dist/run.jsDeterminism is the author's burden
The kit gives you the loop and the adapter; cross-environment float determinism
is yours. Use rng / capMath from @caputchin/determinism for randomness and
transcendentals, keep wall-clock and Math.random out of the sim, and the live
run and the server replay agree bit-for-bit.
