Implement castling

This commit is contained in:
Juhani Krekelä 2021-01-10 21:12:46 +02:00
parent f8f0c794cd
commit 54e4621548
1 changed files with 123 additions and 0 deletions

View File

@ -306,6 +306,10 @@
case 'h':
piece = 'P';
break;
case 'O':
case '0':
// Castling, handled in its own function
return doCastle(move);
default:
return {error: 'Not a valid piece: ' + piece};
}
@ -435,6 +439,125 @@
return {}
}
function doCastle(move) {
let ballChar = move[0];
// Figure out distance between king and rook
let emptySquares = 1;
let index = 1;
while (index < move.length) {
if (move.slice(index, index + 2) === '-' + ballChar) {
emptySquares += 1;
index += 2;
} else {
break;
}
}
// Check(mate)
if (!['', '+', '++', '#'].includes(move.slice(index))) {
// TODO: Implement handling
return {error: 'Unexpected contents at the end of the move: ' + move.slice(index)};
}
// Find the king(s)
let whiteMove = document.getElementById('tomove').childNodes[0].data === 'White';
let renderedKing = whiteMove ? '♔' : '♚';
let renderedRook = whiteMove ? '♖' : '♜';
let kings = [];
for (let kingLetter of 'abcdefgh') {
for (let kingNumber of '12345678') {
let square = document.getElementById(kingLetter + kingNumber);
if (square.childNodes.length !== 0 && square.childNodes[0].data === renderedKing) {
kings.push([kingLetter, kingNumber]);
}
}
}
// Find the rook(s)
function squareDiff(squareLetter, squareNumber, dLetter, dNumber) {
let x = 'abcdefgh'.indexOf(squareLetter) + dLetter;
let y = '12345678'.indexOf(squareNumber) + dNumber;
if (x < 0 || x > 7 || y < 0 || y > 7) {
// Would be outside of the board
return null;
}
return ['abcdefgh'[x], '12345678'[y]]
}
let distance = emptySquares + 1;
let possiblePairs = [];
for (let [kingLetter, kingNumber] of kings) {
for (let [dLetter, dNumber] of [[-distance, 0], [distance, 0], [0, -distance], [0, distance]]) {
let rookCoords = squareDiff(kingLetter, kingNumber, dLetter, dNumber);
if (rookCoords === null) {
continue;
}
let [rookLetter, rookNumber] = rookCoords;
let square = document.getElementById(rookLetter + rookNumber);
if (square.childNodes.length !== 0 && square.childNodes[0].data === renderedRook) {
possiblePairs.push([kingLetter, kingNumber, rookLetter, rookNumber, dLetter, dNumber]);
}
}
}
if (possiblePairs.length === 0) {
return {error: 'Could not find king and rook matching castling criteria'};
} else if (possiblePairs.length > 1) {
return {error: 'Found ' + String(possiblePairs.length) + ' possible pairs of king and rook to castle'};
}
let [kingLetter, kingNumber, rookLetter, rookNumber, dLetter, dNumber] = possiblePairs[0];
let kingStartSquare = document.getElementById(kingLetter + kingNumber);
let rookStartSquare = document.getElementById(rookLetter + rookNumber);
// Make sure there there are no pieces between the king and the rook
let signLetter = Math.sign(dLetter);
let signNumber = Math.sign(dNumber);
let [squareLetter, squareNumber] = squareDiff(kingLetter, kingNumber, signLetter, signNumber);
while (squareLetter !== rookLetter || squareNumber !== rookNumber) {
if (document.getElementById(squareLetter + squareNumber).childNodes.length !== 0) {
return {error: squareLetter + squareNumber + ' is occupied'};
}
[squareLetter, squareNumber] = squareDiff(squareLetter, squareNumber, signLetter, signNumber);
}
// King moves two squares towards rook
let [kingEndLetter, kingEndNumber] = squareDiff(kingLetter, kingNumber, 2 * signLetter, 2 * signNumber);
let kingEndSquare = document.getElementById(kingEndLetter + kingEndNumber);
// Rook moves to the square king crossed
let [rookEndLetter, rookEndNumber] = squareDiff(kingLetter, kingNumber, signLetter, signNumber);
let rookEndSquare = document.getElementById(rookEndLetter + rookEndNumber);
// Move pieces
kingStartSquare.removeChild(kingStartSquare.childNodes[0]);
rookStartSquare.removeChild(rookStartSquare.childNodes[0]);
kingEndSquare.appendChild(document.createTextNode(renderedKing));
rookEndSquare.appendChild(document.createTextNode(renderedRook));
// Flip whose turn it is
document.getElementById('tomove').childNodes[0].data = whiteMove ? 'Black' : 'White';
// Record our alterations to the table
let removedPieces = {};
let placedPieces = {};
removedPieces[kingLetter + kingNumber] = renderedKing;
removedPieces[rookLetter + rookNumber] = renderedRook;
placedPieces[kingEndLetter + kingEndNumber] = renderedKing;
placedPieces[rookEndLetter + rookEndNumber] = renderedRook;
let moveRecord = {
removedPieces: removedPieces,
placedPieces: placedPieces,
moveText: move
};
moveHistory.push(moveRecord);
return {}
}
function undoMove() {
if (moveHistory.length === 0) {
alert('No moves to undo');