const board = document.getElementById("chessboard");
const turnDisplay = document.getElementById("turn");
const undoButton = document.getElementById("undo");
const pieces = {
r: "♜", n: "♞", b: "♝", q: "♛", k: "♚", p: "♟",
R: "♖", N: "♘", B: "♗", Q: "♕", K: "♔", P: "♙"
};
const initialBoard = [
["r", "n", "b", "q", "k", "b", "n", "r"],
["p", "p", "p", "p", "p", "p", "p", "p"],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["", "", "", "", "", "", "", ""],
["P", "P", "P", "P", "P", "P", "P", "P"],
["R", "N", "B", "Q", "K", "B", "N", "R"]
];
let boardState = JSON.parse(JSON.stringify(initialBoard)); // Deep Copy
let selectedPiece = null;
let turn = "white"; // White moves first
let lastMove = null;
function renderBoard() {
board.innerHTML = "";
boardState.forEach((row, rowIndex) => {
row.forEach((cell, colIndex) => {
const square = document.createElement("div");
square.classList.add("cell", (rowIndex + colIndex) % 2 === 0 ? "white" : "black");
square.dataset.row = rowIndex;
square.dataset.col = colIndex;
if (cell) {
square.innerText = pieces[cell] || "";
square.dataset.piece = cell;
}
square.addEventListener("click", handlePieceClick);
board.appendChild(square);
});
});
}
function handlePieceClick(event) {
const clickedSquare = event.target;
const row = parseInt(clickedSquare.dataset.row);
const col = parseInt(clickedSquare.dataset.col);
const piece = clickedSquare.dataset.piece;
if (selectedPiece) {
movePiece(row, col);
} else if (piece) {
if ((turn === "white" && piece === piece.toUpperCase()) || (turn === "black" && piece === piece.toLowerCase())) {
selectedPiece = { row, col, piece };
clickedSquare.classList.add("selected");
}
}
}
function isValidMove(fromRow, fromCol, toRow, toCol, piece) {
let rowDiff = Math.abs(toRow - fromRow);
let colDiff = Math.abs(toCol - fromCol);
let targetPiece = boardState[toRow][toCol];
// Ensure piece is not capturing its own team
if (targetPiece && ((turn === "white" && targetPiece === targetPiece.toUpperCase()) ||
(turn === "black" && targetPiece === targetPiece.toLowerCase()))) {
return false;
}
switch (piece.toLowerCase()) {
case 'p': // Pawn
let direction = piece === 'P' ? -1 : 1; // White moves up (-1), Black moves down (+1)
let startRow = piece === 'P' ? 6 : 1; // White starts at row 6, Black at row 1
if (fromCol === toCol) { // Normal forward move
if (toRow === fromRow + direction && !targetPiece) return true;
if (fromRow === startRow && toRow === fromRow + 2 * direction && !targetPiece && !boardState[fromRow + direction][fromCol]) return true;
} else if (colDiff === 1 && toRow === fromRow + direction && targetPiece) { // Diagonal Capture
return true;
}
return false;
case 'r': // Rook
if (fromRow !== toRow && fromCol !== toCol) return false; // Move only straight
// Check if path is clear
if (fromRow === toRow) { // Moving horizontally
let step = fromCol < toCol ? 1 : -1;
for (let c = fromCol + step; c !== toCol; c += step) {
if (boardState[fromRow][c]) return false;
}
} else { // Moving vertically
let step = fromRow < toRow ? 1 : -1;
for (let r = fromRow + step; r !== toRow; r += step) {
if (boardState[r][fromCol]) return false;
}
}
return true;
case 'b': // Bishop
if (rowDiff !== colDiff) return false; // Must move diagonally
let rowStep = fromRow < toRow ? 1 : -1;
let colStep = fromCol < toCol ? 1 : -1;
for (let i = 1; i < rowDiff; i++) {
if (boardState[fromRow + i * rowStep][fromCol + i * colStep]) return false;
}
return true;
case 'q': // Queen (Rook + Bishop)
return isValidMove(fromRow, fromCol, toRow, toCol, 'r') || isValidMove(fromRow, fromCol, toRow, toCol, 'b');
case 'k': // King (One step any direction)
return rowDiff <= 1 && colDiff <= 1;
case 'n': // Knight (L-shape)
return (rowDiff === 2 && colDiff === 1) || (rowDiff === 1 && colDiff === 2);
default:
return false;
}
}
function movePiece(row, col) {
if (!selectedPiece) return;
const { row: fromRow, col: fromCol, piece } = selectedPiece;
if (!isValidMove(fromRow, fromCol, row, col, piece)) {
selectedPiece = null;
renderBoard();
return;
}
let targetPiece = boardState[row][col];
// Check if the captured piece is the Queen
if (targetPiece.toLowerCase() === 'k') {
let winner = (turn === "white") ? "White Wins!" : "Black Wins!";
setTimeout(() => {
alert(winner);
location.reload(); // Restart game after alert
}, 100);
return;
}
boardState[row][col] = piece;
boardState[fromRow][fromCol] = "";
// **Pawn Promotion Logic**
if (piece === 'P' && row === 0) {
boardState[row][col] = 'Q'; // Promote White Pawn to Queen
}
if (piece === 'p' && row === 7) {
boardState[row][col] = 'q'; // Promote Black Pawn to Queen
}
turn = (turn === "white") ? "black" : "white";
turnDisplay.innerText = `${turn.charAt(0).toUpperCase() + turn.slice(1)}'s Turn`;
selectedPiece = null;
renderBoard();
}
renderBoard();
```javascript
// pawn->queen logic
if (piece == "p" && row == 7) {
boardState[row][col] = "q";
}
if (piece == "P" && row == 0) {
boardState[row][col] = "Q";
}
```