El engine-kit (opcional)
Esta página es opcional. Todo aquí es una forma conveniente de producir un run conforme; puedes ignorar el kit por completo y publicar un run pelado que escribiste a mano. Echa mano de @caputchin/engine-kit cuando prefieras escribir lógica de juego ordinaria y que el determinismo, el bucle de repetición, y la codificación de trazas se gestionen por ti.
El kit re-exporta toda la superficie del contrato de repetición, así que los usuarios del kit tienen un único sitio de import.
npm install @caputchin/engine-kitLa idea: escribe un reducer, obtén un run
El movimiento central del kit es dejarte expresar tu juego como un reducer puro: una función que toma el estado actual y la entrada de un tick y devuelve el siguiente estado. A partir de ese reducer más primitivas deterministas, el adaptador toRun del kit produce un run(seed, config, trace) que se conforma al contrato por construcción.
import { defineEngine, toRun, cap } from "@caputchin/engine-kit";
const engine = defineEngine({
setup(seed) {
const rng = cap.rng(seed); // deterministic, seeded RNG
return { score: 0, targets: spawn(rng), rng };
},
tick(state, input) {
// pure: same (state, input) always yields the same next state
return applyInput(state, input);
},
result(state) {
return { passed: state.score >= 3, score: state.score, durationMs: state.elapsed };
},
});
export const run = toRun(engine); // a conforming RunFnPrimitivas deterministas
El kit te da las dos cosas que más a menudo rompen el determinismo entre runtimes, ambas sembradas y reproducibles:
cap.rng(seed)(ycap.rngFromState) - un PRNG sembrable. Úsalo para cada elección aleatoria en vez deMath.random().cap.math- transcendentales deterministas (sin,cos, ...) que concuerdan entre runtimes, en vez de las delMathde la plataforma que pueden no hacerlo.
Shims opcionales
applyShim()- neutraliza los globales no deterministas (el reloj de pared,Math.random) para que una llamada accidental falle ruidosamente en desarrollo en vez de divergir en silencio en la repetición.applyDomShim()- un DOM headless mínimo para el camino de framework, para que un reducer que toca una pequeña superficie de DOM aún se repita en el isolate sin DOM.
Córrelo en local antes de publicar
El harness replay del kit corre una traza a través de tu engine de la misma forma que lo hará el servidor, y selfCheck corre una batería de casos y reporta cualquier no-determinismo antes de que publiques:
import { selfCheck } from "@caputchin/engine-kit";
const report = selfCheck(engine, { cases: myCases });
if (!report.ok) console.error(report.violations);Un selfCheck local limpio es el mejor predictor de que la autocomprobación de publicación del marketplace pasará (es el mismo estándar de determinismo). El kit también incluye una CLI para correr esto desde scripts de package.json o CI.
Codificación de trazas
encodeTrace / decodeTrace te dan un formato de traza compacto y versionado para que el flujo de entrada que tu juego en vivo emite sea exactamente lo que tu run decodifica en la repetición. Usarlos en ambos lados mantiene los dos al unísono.
Cuándo saltarse el kit
Sáltatelo cuando ya tengas lógica determinista (una simulación de coma fija, un módulo WASM compilado para floats de la spec) o cuando tu juego sea lo bastante simple como para que escribir run a mano sea trivial. La plataforma nunca sabe ni le importa si el kit produjo tu run; solo carga y repite el contrato.
Véase también
- El contrato de repetición: el
run/ seed / verdict que este kit produce. - Construye un juego del marketplace: el juego cuya lógica este kit puede respaldar.
- El manifiesto caputchin.json: publicar el
runproducido como el artefacto.