import { describe, it, expect } from 'vitest'; import { readFileSync } from 'node:fs'; import { applyEndAdjustment, winner, type EndReason } from './engine'; import { RULESETS } from './ruleset'; import type { Variant } from '../model'; // The offline engine must settle unplayed racks and decide the winner exactly as the Go engine // does, so a local game finishes with the same scores. Golden from the in-package emitter // (backend/internal/engine/endfixture_test.go). interface EndCase { name: string; variant: Variant; reason: EndReason; hands: number[][]; scores: number[]; resigned: boolean[]; toMove: number; scoresAfter: number[]; winner: number; } const fx = JSON.parse( readFileSync(new URL('./testdata/endgame.json', import.meta.url), 'utf8'), ) as { cases: EndCase[] }; describe('offline engine end-game parity vs Go', () => { for (const c of fx.cases) { it(c.name, () => { const values = RULESETS[c.variant].values; const after = applyEndAdjustment(c.reason, c.hands, c.scores, c.toMove, values); expect(after).toEqual(c.scoresAfter); expect(winner(true, c.reason, after, c.resigned)).toBe(c.winner); }); } });