Fix Chess960 FEN parsing for chess.js compatibility
All checks were successful
Build and Push / build-all (push) Successful in 2m11s

- Add convertChess960Fen() function to convert Chess960 file-based
  castling notation (e.g., "HAha") to standard notation ("KQkq")
- chess.js doesn't support Chess960 FEN natively, so we convert before
  loading
- Apply conversion in all places where FEN is loaded: waiting state,
  playing state, and opponent move handler

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
doomtube 2026-01-08 17:07:53 -05:00
parent e52f3b7cc7
commit 24d9a945b3

View file

@ -13,6 +13,39 @@
let legalMoves = [];
let moveHistory = [];
// Convert Chess960 FEN to standard FEN for chess.js compatibility
// Chess960 uses file-based castling (e.g., "HAha") instead of "KQkq"
function convertChess960Fen(fen) {
if (!fen) return fen;
const parts = fen.split(' ');
if (parts.length < 3) return fen;
// Check if castling field contains Chess960 notation (letters other than KQkq-)
const castling = parts[2];
if (/^[KQkq-]+$/.test(castling)) {
return fen; // Already standard notation
}
// Convert Chess960 castling to standard: any uppercase = KQ rights, any lowercase = kq rights
let newCastling = '';
if (/[A-H]/.test(castling)) {
// Has white castling rights - simplified to KQ
const whiteFiles = castling.match(/[A-H]/g) || [];
if (whiteFiles.length >= 2) newCastling += 'KQ';
else if (whiteFiles.length === 1) newCastling += 'K';
}
if (/[a-h]/.test(castling)) {
// Has black castling rights - simplified to kq
const blackFiles = castling.match(/[a-h]/g) || [];
if (blackFiles.length >= 2) newCastling += 'kq';
else if (blackFiles.length === 1) newCastling += 'k';
}
if (!newCastling) newCastling = '-';
parts[2] = newCastling;
return parts.join(' ');
}
// Match state from overlay store
let myColor = null;
@ -73,8 +106,8 @@
try {
const chessModule = await import('chess.js');
Chess = chessModule.Chess;
// Don't initialize with default position - we'll load Chess960 FEN later
game = new Chess();
// Don't initialize game yet - we'll create with Chess960 FEN when received
game = null;
// Set up match event handler
console.log('[ChessOverlay] Registering match event handler...');
@ -126,9 +159,9 @@
if (payload.status === 'waiting') {
myColor = payload.yourColor;
// Load the Chess960 starting position
if (game && payload.fen) {
game.load(payload.fen, { chess960: true });
// Create Chess960 game with the starting position
if (Chess && payload.fen) {
game = new Chess(convertChess960Fen(payload.fen));
updateBoardDisplay();
}
@ -143,8 +176,9 @@
const session = nakama.getSession();
myColor = payload.whiteId === session?.user_id ? 'w' : 'b';
if (game) {
game.load(payload.fen, { chess960: true });
// Create Chess960 game with current position
if (Chess && payload.fen) {
game = new Chess(convertChess960Fen(payload.fen));
}
gamesOverlay.setMode('playing');
@ -163,8 +197,9 @@
} else if (payload.status === 'spectating') {
myColor = null; // Spectator has no color
if (game) {
game.load(payload.fen, { chess960: true });
// Create Chess960 game with current position
if (Chess && payload.fen) {
game = new Chess(convertChess960Fen(payload.fen));
}
gamesOverlay.setMode('spectating');
@ -184,7 +219,7 @@
function handleOpponentMove(payload) {
if (game) {
game.load(payload.fen, { chess960: true });
game.load(convertChess960Fen(payload.fen));
}
moveHistory = [...moveHistory, payload.move];