Files
functional-programming-snake/scripts/fixtures/m10-session-and-golden.mjs
T
Lucas WintherandClaude Fable 5.2 5062838604 chore: keep the fixture generator scripts and the replay-sample bot
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>
2026-11-11 12:13:03 +01:00

57 lines
3.6 KiB
JavaScript

import { writeFileSync, readFileSync } 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 R = SOL
const F = FIX
const { sessionUpdate, sessionView, play, main } = await import(R + 'app.js')
const { Action } = await import(R + 'model.js')
const { update } = await import(R + 'game.js')
const g = (o) => ({ width: 4, height: 3, snake: [{ x: 1, y: 1 }, { x: 0, y: 1 }], dir: 'Right', nextDir: 'Right',
apple: { x: 3, y: 0 }, seed: 5, score: 0, status: 'Playing', frame: 0, queued: null, ...o })
const eating = (score) => g({ score, apple: { x: 2, y: 1 } })
const S = (game, best, improved = false) => ({ game, best, improved })
const su = (name, s, a) => ({ name, args: [s, a], expected: sessionUpdate(s, a) })
const suCases = [
su('a-step-without-eating-keeps-the-best', S(g({ score: 2 }), 5), Action.Tick),
su('the-first-apple-with-no-record-is-an-improvement', S(eating(0), 0), Action.Tick),
su('eating-past-the-record-raises-the-best', S(eating(5), 5), Action.Tick),
su('eating-below-the-record-keeps-the-best', S(eating(1), 5), Action.Tick),
su('equalling-the-record-is-not-an-improvement', S(eating(4), 5), Action.Tick),
su('the-next-action-clears-improved', S(g({ score: 6 }), 6, true), Action.Turn('Up')),
su('a-frame-that-steps-and-eats-raises-the-best', S({ ...eating(3), frame: 6 }, 3), Action.Frame),
su('a-frame-that-only-counts-keeps-the-best-and-clears-improved', S(g({ score: 3, frame: 1 }), 3, true), Action.Frame),
su('game-over-keeps-the-best', S(g({ snake: [{ x: 3, y: 1 }, { x: 2, y: 1 }], score: 4 }), 4), Action.Tick),
su('restart-keeps-the-best', S(g({ status: 'GameOver', score: 6 }), 6), Action.Restart),
su('pausing-keeps-the-best', S(g({ score: 2 }), 9, true), Action.TogglePause),
]
const fx = (fn, cases) => JSON.stringify({ function: fn, cases }, null, 2) + '\n'
writeFileSync(F + 'm10-session-update.json', fx('sessionUpdate', suCases))
const v = (o) => ({ width: 3, height: 2, snake: [{ x: 1, y: 0 }, { x: 0, y: 0 }], dir: 'Right', nextDir: 'Right',
apple: { x: 2, y: 1 }, seed: 0, score: 5, status: 'Playing', frame: 0, queued: null, ...o })
const sv = (name, s) => ({ name, args: [s], expected: sessionView(s) })
writeFileSync(F + 'm10-session-view.json', fx('sessionView', [
sv('playing-adds-the-best-at-the-top-right', S(v({}), 12)),
sv('a-best-of-zero-is-shown-too', S(v({ score: 0 }), 0)),
sv('game-over-shows-the-banner-and-then-the-best', S(v({ status: 'GameOver' }), 7, true)),
]))
// golden: play the final main and keep the last drawing's scene
const golden = (name, file, seed, best) => {
const events = JSON.parse(readFileSync(HERE + 'golden-events/' + file, 'utf8'))
const drawings = play(main, seed, events, best)
const scene = drawings.at(-1).filter((o) => o.tag === 'Draw').map((o) => o.shape)
const saves = drawings.flat().filter((o) => o.tag === 'SaveBest')
console.error(name, 'drawings', drawings.length, 'saves', JSON.stringify(saves))
return { name, args: [seed, events, best], expected: scene }
}
writeFileSync(F + 'm10-golden.json', fx('play', [
golden('seed-42-eats-three-apples-with-no-stored-best', 'ev-42-0-3-stop.json', 42, 0),
golden('seed-7-beats-a-stored-best-of-2-and-hits-the-wall', 'ev-7-2-4-wall.json', 7, 2),
golden('seed-42-restart-after-game-over-keeps-the-best', 'ev-42-0-2-restart.json', 42, 0),
]))