A terminal position with no legal moves and no check was always shown as stalemate, so atomic explosions, antichess, king of the hill, racing kings and horde wins got the stalemate glyph. Use the chessops outcome of the position instead, and don't treat a crazyhouse check that can be blocked by a drop as mate.
112 lines
3.3 KiB
TypeScript
112 lines
3.3 KiB
TypeScript
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'),
|
|
{},
|
|
));
|
|
});
|