import assert from 'node:assert/strict'; import { describe, test } from 'node:test'; import { endgameShapesForNode } from '../src/game/endgame'; import { endgameGlyphs } from '../src/game/glyphs'; import type { StatusName } from '../src/game/status'; import { completeNode } from '../src/tree/node'; const glyphName = (html: string | undefined) => Object.entries(endgameGlyphs).find(([, glyph]) => glyph(0) === html)?.[0]; type GameEnd = { isLast?: boolean; winner?: Color; status?: StatusName }; const kingGlyphs = ( variant: VariantKey, fen: FEN, { isLast = false, winner, status = 'started' }: GameEnd = {}, ) => { const node = completeNode(variant)({ ply: 1, fen }); return Object.fromEntries( endgameShapesForNode(node, isLast, winner, status).map(shape => [ shape.orig, glyphName(shape.customSvg?.html), ]), ); }; describe('endgame glyphs on terminal positions', () => { test('standard checkmate', () => assert.deepEqual(kingGlyphs('standard', 'R5k1/5ppp/8/8/8/8/8/6K1 b - - 1 1'), { g1: 'win', g8: 'mate', })); test('standard stalemate', () => assert.deepEqual(kingGlyphs('standard', '7k/5Q2/6K1/8/8/8/8/8 b - - 0 1'), { g6: 'stalemate', h8: 'stalemate', })); test('atomic king explosion', () => assert.deepEqual(kingGlyphs('atomic', 'rn2k2r/ppp3pp/8/3ppp2/3P2P1/5P1B/PP5P/RNB4R w kq - 0 12'), { e8: 'win', })); test('atomic checkmate', () => assert.deepEqual(kingGlyphs('atomic', 'R5k1/5ppp/8/8/8/8/8/6K1 b - - 1 1'), { g1: 'win', g8: 'mate', })); test('antichess win by losing all pieces', () => assert.deepEqual(kingGlyphs('antichess', '8/8/8/8/8/8/8/k7 w - - 0 1'), { a1: 'unknown', })); test('antichess win by being stalemated', () => assert.deepEqual(kingGlyphs('antichess', '8/8/8/p7/P7/8/8/7k w - - 0 1'), { h1: 'unknown', })); test('king of the hill', () => assert.deepEqual(kingGlyphs('kingOfTheHill', '8/8/8/8/4K3/8/8/k7 b - - 0 1'), { e4: 'win', a1: 'unknown', })); test('racing kings win', () => assert.deepEqual(kingGlyphs('racingKings', 'K7/8/8/8/8/8/k7/8 b - - 0 1'), { a8: 'win', a2: 'unknown', })); test('racing kings draw', () => assert.deepEqual(kingGlyphs('racingKings', 'K6k/8/8/8/8/8/8/8 w - - 0 1'), { a8: 'draw', h8: 'draw', })); test('three-check', () => assert.deepEqual( kingGlyphs('threeCheck', 'rnb1kbnr/pppp1ppp/8/4p3/4P2q/5P2/PPPP2PP/RNBQKBNR w KQkq - 3+0 0 1'), { e8: 'win', e1: 'unknown' }, )); test('horde', () => assert.deepEqual(kingGlyphs('horde', 'k7/8/8/8/8/8/8/8 w - - 0 1'), { a8: 'win', })); }); describe('endgame glyphs on non-terminal positions', () => { test('crazyhouse check that can be blocked by a drop', () => assert.deepEqual(kingGlyphs('crazyhouse', 'R5k1/5ppp/8/8/8/8/8/6K1[n] b - - 1 1'), {})); test('last move of a resigned game', () => assert.deepEqual( kingGlyphs('standard', 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1', { isLast: true, winner: 'black', status: 'resign', }), { e8: 'win', e1: 'resign' }, )); test('mid-game position', () => assert.deepEqual( kingGlyphs('standard', 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1'), {}, )); });