diff --git a/takhta.html b/takhta.html index d08b720..2e494ec 100644 --- a/takhta.html +++ b/takhta.html @@ -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');