Fix Chess960 FEN parsing for chess.js compatibility
All checks were successful
Build and Push / build-all (push) Successful in 2m11s
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:
parent
e52f3b7cc7
commit
24d9a945b3
1 changed files with 45 additions and 10 deletions
|
|
@ -13,6 +13,39 @@
|
||||||
let legalMoves = [];
|
let legalMoves = [];
|
||||||
let moveHistory = [];
|
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
|
// Match state from overlay store
|
||||||
let myColor = null;
|
let myColor = null;
|
||||||
|
|
||||||
|
|
@ -73,8 +106,8 @@
|
||||||
try {
|
try {
|
||||||
const chessModule = await import('chess.js');
|
const chessModule = await import('chess.js');
|
||||||
Chess = chessModule.Chess;
|
Chess = chessModule.Chess;
|
||||||
// Don't initialize with default position - we'll load Chess960 FEN later
|
// Don't initialize game yet - we'll create with Chess960 FEN when received
|
||||||
game = new Chess();
|
game = null;
|
||||||
|
|
||||||
// Set up match event handler
|
// Set up match event handler
|
||||||
console.log('[ChessOverlay] Registering match event handler...');
|
console.log('[ChessOverlay] Registering match event handler...');
|
||||||
|
|
@ -126,9 +159,9 @@
|
||||||
if (payload.status === 'waiting') {
|
if (payload.status === 'waiting') {
|
||||||
myColor = payload.yourColor;
|
myColor = payload.yourColor;
|
||||||
|
|
||||||
// Load the Chess960 starting position
|
// Create Chess960 game with the starting position
|
||||||
if (game && payload.fen) {
|
if (Chess && payload.fen) {
|
||||||
game.load(payload.fen, { chess960: true });
|
game = new Chess(convertChess960Fen(payload.fen));
|
||||||
updateBoardDisplay();
|
updateBoardDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,8 +176,9 @@
|
||||||
const session = nakama.getSession();
|
const session = nakama.getSession();
|
||||||
myColor = payload.whiteId === session?.user_id ? 'w' : 'b';
|
myColor = payload.whiteId === session?.user_id ? 'w' : 'b';
|
||||||
|
|
||||||
if (game) {
|
// Create Chess960 game with current position
|
||||||
game.load(payload.fen, { chess960: true });
|
if (Chess && payload.fen) {
|
||||||
|
game = new Chess(convertChess960Fen(payload.fen));
|
||||||
}
|
}
|
||||||
|
|
||||||
gamesOverlay.setMode('playing');
|
gamesOverlay.setMode('playing');
|
||||||
|
|
@ -163,8 +197,9 @@
|
||||||
} else if (payload.status === 'spectating') {
|
} else if (payload.status === 'spectating') {
|
||||||
myColor = null; // Spectator has no color
|
myColor = null; // Spectator has no color
|
||||||
|
|
||||||
if (game) {
|
// Create Chess960 game with current position
|
||||||
game.load(payload.fen, { chess960: true });
|
if (Chess && payload.fen) {
|
||||||
|
game = new Chess(convertChess960Fen(payload.fen));
|
||||||
}
|
}
|
||||||
|
|
||||||
gamesOverlay.setMode('spectating');
|
gamesOverlay.setMode('spectating');
|
||||||
|
|
@ -184,7 +219,7 @@
|
||||||
|
|
||||||
function handleOpponentMove(payload) {
|
function handleOpponentMove(payload) {
|
||||||
if (game) {
|
if (game) {
|
||||||
game.load(payload.fen, { chess960: true });
|
game.load(convertChess960Fen(payload.fen));
|
||||||
}
|
}
|
||||||
moveHistory = [...moveHistory, payload.move];
|
moveHistory = [...moveHistory, payload.move];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue