scripts/fixtures/ holds the scripts that produced the 2026-11-11 fixtures, with a README on running them safely into a copy. Run in order they reproduce the content of every fixture they touch. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
63 lines
3.9 KiB
JavaScript
63 lines
3.9 KiB
JavaScript
import { readFileSync, writeFileSync } from 'node:fs'
|
|
// Fixture regeneration aid (see scripts/fixtures/README.md). Written during the 2026-11-11 build, kept for reference.
|
|
// Writes into fixtures/ unless FIXTURES_OUT names another directory (with a trailing slash).
|
|
const FIX = process.env.FIXTURES_OUT ?? new URL('../../fixtures/', import.meta.url).pathname
|
|
const SOL = new URL('../../js/solutions/', import.meta.url).href
|
|
const HERE = new URL('./', import.meta.url).pathname
|
|
const { update } = await import(SOL + 'game.js')
|
|
const { tick } = await import(SOL + 'spawn.js')
|
|
const { pongUpdate } = await import(SOL + 'pong/rules.js')
|
|
const load = (n) => JSON.parse(readFileSync(`${FIX}${n}.json`, 'utf8'))
|
|
const save = (n, fx) => writeFileSync(`${FIX}${n}.json`, JSON.stringify(fx, null, 2) + '\n')
|
|
const clone = (x) => JSON.parse(JSON.stringify(x))
|
|
|
|
// ---- m10-update
|
|
{
|
|
const fx = load('m10-update')
|
|
const base = fx.cases.find((c) => c.name === 'frame-below-threshold-only-counts-the-frame').args[0]
|
|
const mk = (name, patch) => { const s = { ...clone(base), ...patch }; return { name, args: [s, { tag: 'Frame' }], expected: update(s, { tag: 'Frame' }) } }
|
|
const frames = [
|
|
mk('frame-below-threshold-only-counts-the-frame', { frame: 0 }),
|
|
mk('frame-just-before-threshold-only-counts-the-frame', { frame: 6 }),
|
|
mk('frame-at-threshold-ticks-the-game-and-restarts-the-count', { frame: 7 }),
|
|
mk('frame-after-a-move-counts-from-zero-again', { snake: [{ x: 1, y: 0 }], frame: 0 }),
|
|
mk('frame-tick-that-eats-restarts-the-count', { frame: 7, score: 2, apple: { x: 1, y: 0 } }),
|
|
mk('frame-just-before-the-shrunk-threshold-only-counts-the-frame', { frame: 5, score: 3 }),
|
|
mk('frame-threshold-shrinks-as-score-grows', { frame: 6, score: 3 }),
|
|
mk('frame-at-top-speed-first-frame-does-not-tick', { frame: 0, score: 18 }),
|
|
mk('frame-at-top-speed-ticks-every-second-frame', { frame: 1, score: 18 }),
|
|
mk('frame-count-past-the-threshold-still-ticks', { frame: 9 }),
|
|
mk('frame-tick-can-end-the-game', { snake: [{ x: 2, y: 0 }], frame: 7 }),
|
|
]
|
|
const keep = fx.cases.filter((c) => !c.name.startsWith('frame-') || c.name.startsWith('frame-when-'))
|
|
const i = keep.findIndex((c) => c.name.startsWith('frame-when-'))
|
|
fx.cases = [...keep.slice(0, i), ...frames, ...keep.slice(i)]
|
|
save('m10-update', fx)
|
|
}
|
|
// ---- m04-tick
|
|
{
|
|
const fx = load('m04-tick')
|
|
const s = { width: 2, height: 2, snake: [{ x: 0, y: 0 }, { x: 0, y: 1 }, { x: 1, y: 1 }], dir: 'Up', nextDir: 'Right',
|
|
apple: { x: 1, y: 0 }, seed: 7, score: 2, status: 'Playing', frame: 0 }
|
|
fx.cases = [...fx.cases.filter((c) => c.name !== 'eating-the-last-free-cell-wins'),
|
|
{ name: 'eating-the-last-free-cell-wins', args: [s], expected: tick(s) }]
|
|
save('m04-tick', fx)
|
|
}
|
|
// ---- m11-pong-update
|
|
{
|
|
const fx = load('m11-pong-update')
|
|
const base = fx.cases.find((c) => c.name === 'ball-bounces-off-the-player-paddle').args[0]
|
|
const mk = (name, patch, action = { tag: 'Frame' }) => { const s = { ...clone(base), ...patch }; return { name, args: [s, action], expected: pongUpdate(s, action) } }
|
|
fx.cases.forEach((c) => { if (c.name.startsWith('restart-')) c.expected = pongUpdate(c.args[0], c.args[1]) })
|
|
const extra = [
|
|
mk('player-paddle-catches-the-ball-at-its-first-row', { ball: { x: 3, y: 19 } }),
|
|
mk('ball-may-enter-the-top-row', { ball: { x: 40, y: 1 }, vel: { dx: 1, dy: -1 } }),
|
|
mk('ball-may-enter-the-bottom-row', { ball: { x: 40, y: 48 }, vel: { dx: 1, dy: 1 } }),
|
|
mk('ball-in-column-zero-is-still-in-play', { ball: { x: 1, y: 40 }, vel: { dx: -1, dy: 1 } }),
|
|
mk('ball-in-the-last-column-is-still-in-play', { ball: { x: 78, y: 40 }, vel: { dx: 1, dy: 1 } }),
|
|
mk('restart-keeps-the-held-keys', { held: { up: true, down: false }, score: { player: 1, cpu: 4 }, frame: 250, player: 3 }, { tag: 'Restart' }),
|
|
]
|
|
fx.cases = [...fx.cases.filter((c) => !extra.some((e) => e.name === c.name)), ...extra]
|
|
save('m11-pong-update', fx)
|
|
}
|