fix endgame glyphs for variant wins - closes #21810

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.
This commit is contained in:
dualfroz committed 2026-09-26 10:47:45 +02:00
1 parent 3f6c487976
commit 8e8500f7ac
2 files changed
+122 -17

No files matched your search

+11 -17
View File
@@ -1,9 +1,10 @@
import type { DrawShape } from '@lichess-org/chessground/draw';
import type { Outcome } from 'chessops';
import type { Outcome, Position } from 'chessops';
import { parseFen } from 'chessops/fen';
import { makeSquare, opposite } from 'chessops/util';
import { fenColor } from './chess';
import type { PositionResult } from '@/tree/types';
import { endgameGlyphs } from './glyphs';
import type { StatusName } from './status';
@@ -14,31 +15,24 @@ export interface EndgameResult {
type EndgameNode = {
fen: FEN;
pos: () => PositionResult;
outcome: () => Outcome | undefined;
check: () => boolean;
dests: () => Dests;
};
const terminalStatus = (pos: Position, outcome: Outcome): StatusName =>
outcome.winner ? (pos.isCheckmate() ? 'mate' : 'variantEnd') : pos.isStalemate() ? 'stalemate' : 'draw';
const endgameResult = (
node: EndgameNode,
isLast: boolean,
gameWinner: Color | undefined,
gameStatus: StatusName,
): EndgameResult => {
const isTerminal = node.dests().size === 0,
isMate = node.check() && isTerminal,
isStalemate = !node.check() && isTerminal,
isGameEnd = isLast || isTerminal;
if (!isGameEnd) return {};
return {
winner: isMate
? opposite(fenColor(node.fen))
: isStalemate
? undefined
: (node.outcome()?.winner ?? gameWinner),
status: isMate ? 'mate' : isStalemate ? 'stalemate' : gameStatus,
};
const outcome = node.dests().size === 0 ? node.outcome() : undefined;
if (outcome) return { winner: outcome.winner, status: terminalStatus(node.pos().unwrap(), outcome) };
if (!isLast) return {};
return { winner: node.outcome()?.winner ?? gameWinner, status: gameStatus };
};
export function endgameShapesForNode(