diff --git a/Chess Game/assets/blacks/Black-Bishop.png b/Chess Game/assets/blacks/Black-Bishop.png
new file mode 100644
index 00000000..453cb323
Binary files /dev/null and b/Chess Game/assets/blacks/Black-Bishop.png differ
diff --git a/Chess Game/assets/blacks/Black-King.png b/Chess Game/assets/blacks/Black-King.png
new file mode 100644
index 00000000..225f869e
Binary files /dev/null and b/Chess Game/assets/blacks/Black-King.png differ
diff --git a/Chess Game/assets/blacks/Black-Knight.png b/Chess Game/assets/blacks/Black-Knight.png
new file mode 100644
index 00000000..8e3d04e6
Binary files /dev/null and b/Chess Game/assets/blacks/Black-Knight.png differ
diff --git a/Chess Game/assets/blacks/Black-Pawn.png b/Chess Game/assets/blacks/Black-Pawn.png
new file mode 100644
index 00000000..c432d38a
Binary files /dev/null and b/Chess Game/assets/blacks/Black-Pawn.png differ
diff --git a/Chess Game/assets/blacks/Black-Queen.png b/Chess Game/assets/blacks/Black-Queen.png
new file mode 100644
index 00000000..0d94a1c2
Binary files /dev/null and b/Chess Game/assets/blacks/Black-Queen.png differ
diff --git a/Chess Game/assets/blacks/Black-Rook.png b/Chess Game/assets/blacks/Black-Rook.png
new file mode 100644
index 00000000..b9748e87
Binary files /dev/null and b/Chess Game/assets/blacks/Black-Rook.png differ
diff --git a/Chess Game/assets/whites/White-Bishop.png b/Chess Game/assets/whites/White-Bishop.png
new file mode 100644
index 00000000..26dae01c
Binary files /dev/null and b/Chess Game/assets/whites/White-Bishop.png differ
diff --git a/Chess Game/assets/whites/White-King.png b/Chess Game/assets/whites/White-King.png
new file mode 100644
index 00000000..d7341649
Binary files /dev/null and b/Chess Game/assets/whites/White-King.png differ
diff --git a/Chess Game/assets/whites/White-Knight.png b/Chess Game/assets/whites/White-Knight.png
new file mode 100644
index 00000000..2d716b15
Binary files /dev/null and b/Chess Game/assets/whites/White-Knight.png differ
diff --git a/Chess Game/assets/whites/White-Pawn.png b/Chess Game/assets/whites/White-Pawn.png
new file mode 100644
index 00000000..e98fae2b
Binary files /dev/null and b/Chess Game/assets/whites/White-Pawn.png differ
diff --git a/Chess Game/assets/whites/White-Queen.png b/Chess Game/assets/whites/White-Queen.png
new file mode 100644
index 00000000..a4fe68c8
Binary files /dev/null and b/Chess Game/assets/whites/White-Queen.png differ
diff --git a/Chess Game/assets/whites/White-Rook.png b/Chess Game/assets/whites/White-Rook.png
new file mode 100644
index 00000000..a805de49
Binary files /dev/null and b/Chess Game/assets/whites/White-Rook.png differ
diff --git a/Chess Game/game-28-128.png b/Chess Game/game-28-128.png
new file mode 100644
index 00000000..7838ce20
Binary files /dev/null and b/Chess Game/game-28-128.png differ
diff --git a/Chess Game/game-28-48.png b/Chess Game/game-28-48.png
new file mode 100644
index 00000000..47af7e1b
Binary files /dev/null and b/Chess Game/game-28-48.png differ
diff --git a/Chess Game/index.html b/Chess Game/index.html
new file mode 100644
index 00000000..b61cc08e
--- /dev/null
+++ b/Chess Game/index.html
@@ -0,0 +1,301 @@
+
+
+
+
+ Chess Board
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
7
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2
+
+
+
+
+
+
+
+
+
a
+
+
+
+
+
+
+
b
+
+
+
+
+
+
+
c
+
+
+
+
+
+
+
d
+
+
+
+
+
+
+
e
+
+
+
+
+
+
+
f
+
+
+
+
+
+
g
+
+
+
+
+
+
+
1
+
h
+
+
+
+
+
+ Draw
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Chess Game/manifest.json b/Chess Game/manifest.json
new file mode 100644
index 00000000..063d91d8
--- /dev/null
+++ b/Chess Game/manifest.json
@@ -0,0 +1,30 @@
+{
+ "manifest_version": 3,
+ "name": "Chess Game Extension JS",
+ "version": "1.0",
+ "description": "Chess game extension built in pure HTML CSS JS...",
+ "author": "sambitmondal2005@gmail.com",
+ "icons": {
+ "48": "game-28-48.png",
+ "128": "game-28-128.png"
+ },
+ "permissions": [
+ "storage"
+ ],
+ "optional-permissions": [
+ "tabs"
+ ],
+ "action": {
+ "default_popup": "index.html"
+ },
+ "web_accessible_resources": [
+ {
+ "resources": [
+ "index.html"
+ ],
+ "matches": [
+ ""
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Chess Game/scripts/script.js b/Chess Game/scripts/script.js
new file mode 100644
index 00000000..e5c84a81
--- /dev/null
+++ b/Chess Game/scripts/script.js
@@ -0,0 +1,1569 @@
+let boardSquaresArray = [];
+let positionArray = [];
+let moves = [];
+const castlingSquares = ["g1", "g8", "c1", "c8"];
+let isWhiteTurn = true;
+let enPassantSquare = "blank";
+let allowMovement = true;
+let isEngineWhite = false;
+let selectedLevel = 1;
+const boardSquares = document.getElementsByClassName("square");
+const pieces = document.getElementsByClassName("piece");
+const piecesImages = document.getElementsByTagName("img");
+const chessBoard = document.querySelector(".chessBoard");
+setupBoardSquares();
+setupPieces();
+fillBoardSquaresArray();
+
+const startingPosition = chessBoard.innerHTML;
+newGame.addEventListener("click", function () {
+ if (isEngineWhite)
+ flipBoard();
+ enPassantSquare = "blank";
+ allowMovement = true;
+ isEngineWhite = false;
+ isWhiteTurn = true;
+ moves = [];
+ positionArray = [];
+ boardSquaresArray = [];
+ chessBoard.innerHTML = startingPosition;
+ setupBoardSquares();
+ setupPieces();
+ fillBoardSquaresArray();
+ switchSides.disabled = false;
+ level.disabled = false;
+});
+
+switchSides.addEventListener("click", flipBoard);
+function flipBoard() {
+ Array.from(document.getElementsByClassName("piece")).forEach(div => {
+ div.style.transform = div.style.transform === "rotate(180deg)" ? "rotate(0deg)" : "rotate(180deg)";
+ });
+ Array.from(document.getElementsByClassName("coordinate")).forEach(div => {
+ div.style.transform = div.style.transform === "rotate(180deg)" ? "rotate(0deg)" : "rotate(180deg)";
+ if (div.classList.contains("rank"))
+ div.style.height = "20%";
+ });
+ chessBoard.style.transform = chessBoard.style.transform === "rotate(180deg)" ? "rotate(0deg)" : "rotate(180deg)";
+ isEngineWhite = !isEngineWhite;
+ let currentPosition = generateFEN(boardSquaresArray);
+ if (isEngineWhite)
+ getBestMove(currentPosition, playBestMove);
+}
+
+level.addEventListener("change", function () {
+ selectedLevel = this.value;
+});
+
+function fillBoardSquaresArray() {
+ const boardSquares = document.getElementsByClassName("square");
+ for (let i = 0; i < boardSquares.length; i++) {
+ let row = 8 - Math.floor(i / 8);
+ let column = String.fromCharCode(97 + (i % 8));
+ let square = boardSquares[i];
+ square.id = column + row;
+ let color = "";
+ let pieceType = "";
+ let pieceId = "";
+ if (square.querySelector(".piece")) {
+ color = square.querySelector(".piece").getAttribute("color");
+ pieceType = square.querySelector(".piece").classList[1];
+ pieceId = square.querySelector(".piece").id;
+ } else {
+ color = "blank";
+ pieceType = "blank";
+ pieceId = "blank";
+ }
+ let arrayElement = {
+ squareId: square.id,
+ pieceColor: color,
+ pieceType: pieceType,
+ pieceId: pieceId,
+ };
+ boardSquaresArray.push(arrayElement);
+ }
+}
+function updateBoardSquaresArray(
+ currentSquareId,
+ destinationSquareId,
+ boardSquaresArray,
+ promotionOption = "blank"
+) {
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let destinationSquareElement = boardSquaresArray.find(
+ (element) => element.squareId === destinationSquareId
+ );
+ let pieceColor = currentSquare.pieceColor;
+ let pieceType =
+ promotionOption == "blank" ? currentSquare.pieceType : promotionOption;
+ let pieceId =
+ promotionOption == "blank"
+ ? currentSquare.pieceId
+ : promotionOption + currentSquare.pieceId;
+ destinationSquareElement.pieceColor = pieceColor;
+ destinationSquareElement.pieceType = pieceType;
+ destinationSquareElement.pieceId = pieceId;
+ currentSquare.pieceColor = "blank";
+ currentSquare.pieceType = "blank";
+ currentSquare.pieceId = "blank";
+}
+
+function makeMove(
+ startingSquareId,
+ destinationSquareId,
+ pieceType,
+ pieceColor,
+ captured,
+ promotedTo = "blank"
+) {
+ moves.push({
+ from: startingSquareId,
+ to: destinationSquareId,
+ pieceType: pieceType,
+ pieceColor: pieceColor,
+ captured: captured,
+ promotedTo: promotedTo,
+ });
+}
+
+function generateFEN(boardSquares) {
+ let fen = "";
+ let rank = 8;
+ while (rank >= 1) {
+ for (let file = "a"; file <= "h"; file = String.fromCharCode(file.charCodeAt(0) + 1)) {
+ const square = boardSquares.find((element) => element.squareId === `${file}${rank}`);
+ if (square && square.pieceType) {
+ let pieceNotation = "";
+ switch (square.pieceType) {
+ case "pawn":
+ pieceNotation = "p";
+ break;
+ case "bishop":
+ pieceNotation = "b";
+ break;
+ case "knight":
+ pieceNotation = "n";
+ break;
+ case "rook":
+ pieceNotation = "r";
+ break;
+ case "queen":
+ pieceNotation = "q";
+ break;
+ case "king":
+ pieceNotation = "k";
+ break;
+ case "blank":
+ pieceNotation = "blank";
+ break;
+ }
+ fen += square.pieceColor === "white" ? pieceNotation.toUpperCase() : pieceNotation;
+ }
+ }
+ if (rank > 1) {
+ fen += "/";
+ }
+ rank--;
+ }
+ fen = fen.replace(new RegExp("blankblankblankblankblankblankblankblank", "g"), "8");
+ fen = fen.replace(new RegExp("blankblankblankblankblankblankblank", "g"), "7");
+ fen = fen.replace(new RegExp("blankblankblankblankblankblank", "g"), "6");
+ fen = fen.replace(new RegExp("blankblankblankblankblank", "g"), "5");
+ fen = fen.replace(new RegExp("blankblankblankblank", "g"), "4");
+ fen = fen.replace(new RegExp("blankblankblank", "g"), "3");
+ fen = fen.replace(new RegExp("blankblank", "g"), "2");
+ fen = fen.replace(new RegExp("blank", "g"), "1");
+
+ fen += isWhiteTurn ? " w " : " b ";
+
+ let castlingString = "";
+
+ let shortCastlePossibleForWhite = !kingHasMoved("white") && !rookHasMoved("white", "h1");
+ let longCastlePossibleForWhite = !kingHasMoved("white") && !rookHasMoved("white", "a1");
+ let shortCastlePossibleForBlack = !kingHasMoved("black") && !rookHasMoved("black", "h8");
+ let longCastlePossibleForBlack = !kingHasMoved("black") && !rookHasMoved("black", "a8");
+
+ if (shortCastlePossibleForWhite) castlingString += "K";
+ if (longCastlePossibleForWhite) castlingString += "Q";
+ if (shortCastlePossibleForBlack) castlingString += "k";
+ if (longCastlePossibleForBlack) castlingString += "q";
+ if (castlingString == "") castlingString += "-";
+ castlingString += " ";
+ fen += castlingString;
+
+ fen += enPassantSquare == "blank" ? "-" : enPassantSquare;
+
+ let fiftyMovesRuleCount = getFiftyMovesRuleCount();
+ fen += " " + fiftyMovesRuleCount;
+ let moveCount = Math.floor(moves.length / 2) + 1;
+ fen += " " + moveCount;
+ console.log(fen);
+ return fen;
+
+
+}
+
+function performCastling(
+ piece,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId,
+ boardSquaresArray
+) {
+ let rookId, rookDestinationSquareId, checkSquareId;
+ if (destinationSquareId == "g1") {
+ rookId = "rookh1";
+ rookDestinationSquareId = "f1";
+ checkSquareId = "f1";
+ } else if (destinationSquareId == "c1") {
+ rookId = "rooka1";
+ rookDestinationSquareId = "d1";
+ checkSquareId = "d1";
+ } else if (destinationSquareId == "g8") {
+ rookId = "rookh8";
+ rookDestinationSquareId = "f8";
+ checkSquareId = "f8";
+ } else if (destinationSquareId == "c8") {
+ rookId = "rooka8";
+ rookDestinationSquareId = "d8";
+ checkSquareId = "d8";
+ }
+ if (isKingInCheck(checkSquareId, pieceColor, boardSquaresArray)) return;
+ let rook = document.getElementById(rookId);
+ let rookDestinationSquare = document.getElementById(rookDestinationSquareId);
+ rookDestinationSquare.appendChild(rook);
+ updateBoardSquaresArray(
+ rook.id.slice(-2),
+ rookDestinationSquare.id,
+ boardSquaresArray
+ );
+
+ const destinationSquare = document.getElementById(destinationSquareId);
+ destinationSquare.appendChild(piece);
+ isWhiteTurn = !isWhiteTurn;
+ updateBoardSquaresArray(
+ startingSquareId,
+ destinationSquareId,
+ boardSquaresArray
+ );
+ let captured = false;
+ makeMove(startingSquareId, destinationSquareId, "king", pieceColor, captured);
+ checkForEndGame();
+ return;
+}
+function performEnPassant(
+ piece,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId
+) {
+ let file = destinationSquareId[0];
+ let rank = parseInt(destinationSquareId[1]);
+ rank += pieceColor === "white" ? -1 : 1;
+ let squareBehindId = file + rank;
+
+ const squareBehindElement = document.getElementById(squareBehindId);
+ while (squareBehindElement.firstChild) {
+ squareBehindElement.removeChild(squareBehindElement.firstChild);
+ }
+
+ let squareBehind = boardSquaresArray.find(
+ (element) => element.squareId === squareBehindId
+ );
+ squareBehind.pieceColor = "blank";
+ squareBehind.pieceType = "blank";
+ squareBehind.pieceId = "blank";
+
+ const destinationSquare = document.getElementById(destinationSquareId);
+ destinationSquare.appendChild(piece);
+ isWhiteTurn = !isWhiteTurn;
+ updateBoardSquaresArray(
+ startingSquareId,
+ destinationSquareId,
+ boardSquaresArray
+ );
+ let captured = true;
+ makeMove(startingSquareId, destinationSquareId, "pawn", pieceColor, captured);
+ enPassantSquare = "blank";
+ checkForEndGame();
+ return;
+}
+function displayPromotionChoices(
+ pieceId,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId,
+ captured,
+ promotedTo = "blank"
+) {
+ if (promotedTo != "blank") {
+ performPromotion(pieceId, promotedTo, pieceColor, startingSquareId, destinationSquareId, captured);
+ return;
+ }
+
+ let file = destinationSquareId[0];
+ let rank = parseInt(destinationSquareId[1]);
+ let rank1 = pieceColor === "white" ? rank - 1 : rank + 1;
+ let rank2 = pieceColor === "white" ? rank - 2 : rank + 2;
+ let rank3 = pieceColor === "white" ? rank - 3 : rank + 3;
+
+ let squareBehindId1 = file + rank1;
+ let squareBehindId2 = file + rank2;
+ let squareBehindId3 = file + rank3;
+
+ const destinationSquare = document.getElementById(destinationSquareId);
+ const squareBehind1 = document.getElementById(squareBehindId1);
+ const squareBehind2 = document.getElementById(squareBehindId2);
+ const squareBehind3 = document.getElementById(squareBehindId3);
+
+ let piece1 = createChessPiece("queen", pieceColor, "promotionOption");
+ let piece2 = createChessPiece("knight", pieceColor, "promotionOption");
+ let piece3 = createChessPiece("rook", pieceColor, "promotionOption");
+ let piece4 = createChessPiece("bishop", pieceColor, "promotionOption");
+
+ destinationSquare.appendChild(piece1);
+ squareBehind1.appendChild(piece2);
+ squareBehind2.appendChild(piece3);
+ squareBehind3.appendChild(piece4);
+
+ let promotionOptions = document.getElementsByClassName("promotionOption");
+ for (let i = 0; i < promotionOptions.length; i++) {
+ let pieceType = promotionOptions[i].classList[1];
+ promotionOptions[i].addEventListener("click", function () {
+ performPromotion(
+ pieceId,
+ pieceType,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId,
+ captured
+ );
+ });
+ }
+}
+
+function createChessPiece(pieceType, color, pieceClass) {
+ let pieceName =
+ color.charAt(0).toUpperCase() +
+ color.slice(1) +
+ "-" +
+ pieceType.charAt(0).toUpperCase() +
+ pieceType.slice(1) +
+ ".png";
+ let pieceDiv = document.createElement("div");
+ pieceDiv.className = `${pieceClass} ${pieceType}`;
+ pieceDiv.setAttribute("color", color);
+ let img = document.createElement("img");
+ img.src = pieceName;
+ img.alt = pieceType;
+ pieceDiv.appendChild(img);
+ return pieceDiv;
+}
+
+chessBoard.addEventListener("click", clearPromotionOptions);
+
+function clearPromotionOptions() {
+ for (let i = 0; i < boardSquares.length; i++) {
+ let style = getComputedStyle(boardSquares[i]);
+ let backgroundColor = style.backgroundColor;
+ let rgbaColor = backgroundColor.replace("0.5)", "1)");
+ boardSquares[i].style.backgroundColor = rgbaColor;
+ boardSquares[i].style.opacity = 1;
+
+ if (boardSquares[i].querySelector(".piece"))
+ boardSquares[i].querySelector(".piece").style.opacity = 1;
+ }
+ let elementsToRemove = chessBoard.querySelectorAll(".promotionOption");
+ elementsToRemove.forEach(function (element) {
+ element.parentElement.removeChild(element);
+ });
+ allowMovement = true;
+}
+
+function updateBoardSquaresOpacity(startingSquareId) {
+ for (let i = 0; i < boardSquares.length; i++) {
+
+ if (boardSquares[i].id == startingSquareId)
+ boardSquares[i].querySelector(".piece").style.opacity = 0;
+
+ if (!boardSquares[i].querySelector(".promotionOption")) {
+ boardSquares[i].style.opacity = 0.5;
+ } else {
+ let style = getComputedStyle(boardSquares[i]);
+ let backgroundColor = style.backgroundColor;
+ let rgbaColor = backgroundColor
+ .replace("rgb", "rgba")
+ .replace(")", ",0.5)");
+ boardSquares[i].style.backgroundColor = rgbaColor;
+
+ if (boardSquares[i].querySelector(".piece"))
+ boardSquares[i].querySelector(".piece").style.opacity = 0;
+ }
+ }
+}
+
+function performPromotion(
+ pieceId,
+ pieceType,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId,
+ captured
+) {
+ clearPromotionOptions();
+ promotionPiece = pieceType;
+ piece = createChessPiece(pieceType, pieceColor, "piece");
+
+ piece.addEventListener("dragstart", drag);
+ piece.setAttribute("draggable", true);
+ piece.firstChild.setAttribute("draggable", false);
+ piece.id = pieceType + pieceId;
+
+ const startingSquare = document.getElementById(startingSquareId);
+ while (startingSquare.firstChild) {
+ startingSquare.removeChild(startingSquare.firstChild);
+ }
+ const destinationSquare = document.getElementById(destinationSquareId);
+
+ if (captured) {
+ let children = destinationSquare.children;
+ for (let i = 0; i < children.length; i++) {
+ if (!children[i].classList.contains("coordinate")) {
+ destinationSquare.removeChild(children[i]);
+ }
+ }
+ }
+ // while(destinationSquare.firstChild){
+ // destinationSquare.removeChild(destinationSquare.firstChild);
+ // }
+ destinationSquare.appendChild(piece);
+ isWhiteTurn = !isWhiteTurn;
+ updateBoardSquaresArray(
+ startingSquareId,
+ destinationSquareId,
+ boardSquaresArray,
+ pieceType
+ );
+ makeMove(
+ startingSquareId,
+ destinationSquareId,
+ pieceType,
+ pieceColor,
+ captured,
+ pieceType
+ );
+ checkForEndGame();
+ return;
+}
+function deepCopyArray(array) {
+ let arrayCopy = array.map((element) => {
+ return { ...element };
+ });
+ return arrayCopy;
+}
+function setupBoardSquares() {
+ for (let i = 0; i < boardSquares.length; i++) {
+ boardSquares[i].addEventListener("dragover", allowDrop);
+ boardSquares[i].addEventListener("drop", drop);
+ let row = 8 - Math.floor(i / 8);
+ let column = String.fromCharCode(97 + (i % 8));
+ let square = boardSquares[i];
+ square.id = column + row;
+ }
+}
+function setupPieces() {
+ for (let i = 0; i < pieces.length; i++) {
+ pieces[i].addEventListener("dragstart", drag);
+ pieces[i].setAttribute("draggable", true);
+ pieces[i].id =
+ pieces[i].className.split(" ")[1] + pieces[i].parentElement.id;
+ }
+ for (let i = 0; i < piecesImages.length; i++) {
+ piecesImages[i].setAttribute("draggable", false);
+ }
+}
+function allowDrop(ev) {
+ ev.preventDefault();
+}
+function drag(ev) {
+ if (!allowMovement) return;
+
+ const piece = ev.target;
+ const pieceColor = piece.getAttribute("color");
+ const pieceType = piece.classList[1];
+ const pieceId = piece.id;
+ if (
+ (isWhiteTurn && pieceColor == "white") ||
+ (!isWhiteTurn && pieceColor == "black")
+ ) {
+ const startingSquareId = piece.parentNode.id;
+ ev.dataTransfer.setData("text", piece.id + "|" + startingSquareId);
+ const pieceObject = {
+ pieceColor: pieceColor,
+ pieceType: pieceType,
+ pieceId: pieceId,
+ };
+ let legalSquares = getPossibleMoves(
+ startingSquareId,
+ pieceObject,
+ boardSquaresArray
+ );
+ let legalSquaresJson = JSON.stringify(legalSquares);
+ ev.dataTransfer.setData("application/json", legalSquaresJson);
+ }
+}
+function drop(ev) {
+ let isEngineTurn = (isEngineWhite && isWhiteTurn) || (!isEngineWhite && !isWhiteTurn);
+ if (isEngineTurn) return;
+ ev.preventDefault();
+ const destinationSquare = ev.currentTarget;
+ let destinationSquareId = destinationSquare.id;
+ let data = ev.dataTransfer.getData("text");
+ let [pieceId, startingSquareId] = data.split("|");
+ displayMove(startingSquareId, destinationSquareId);
+}
+
+function displayMove(startingSquareId, destinationSquareId, promotedTo = "blank") {
+
+ const pieceObject = getPieceAtSquare(startingSquareId, boardSquaresArray);
+ const piece = document.getElementById(pieceObject.pieceId);
+ const pieceId = pieceObject.pieceId;
+ const pieceColor = pieceObject.pieceColor;
+ const pieceType = pieceObject.pieceType;
+ let destinationSquare = document.getElementById(destinationSquareId);
+ let legalSquares = getPossibleMoves(startingSquareId, pieceObject, boardSquaresArray);
+
+ legalSquares = isMoveValidAgainstCheck(
+ legalSquares,
+ startingSquareId,
+ pieceColor,
+ pieceType
+ );
+ if (pieceType == "king") {
+ let isCheck = isKingInCheck(
+ destinationSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ if (isCheck) return;
+ }
+ let squareContent = getPieceAtSquare(destinationSquareId, boardSquaresArray);
+ if (
+ squareContent.pieceColor == "blank" &&
+ legalSquares.includes(destinationSquareId)
+ ) {
+ let isCheck = false;
+ if (pieceType == "king")
+ isCheck = isKingInCheck(startingSquareId, pieceColor, boardSquaresArray);
+ if (
+ pieceType == "king" &&
+ !kingHasMoved(pieceColor) &&
+ castlingSquares.includes(destinationSquareId) &&
+ !isCheck
+ ) {
+ performCastling(
+ piece,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId,
+ boardSquaresArray
+ );
+ return;
+
+ }
+ if (
+ pieceType == "king" &&
+ !kingHasMoved(pieceColor) &&
+ castlingSquares.includes(destinationSquareId) &&
+ isCheck
+ )
+ return;
+
+
+ if (pieceType == "pawn" && enPassantSquare == destinationSquareId) {
+ performEnPassant(
+ piece,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId
+ );
+ return;
+ }
+ enPassantSquare = "blank";
+ if (
+ pieceType == "pawn" &&
+ (destinationSquareId.charAt(1) == 8 || destinationSquareId.charAt(1) == 1)
+ ) {
+ allowMovement = false;
+ displayPromotionChoices(
+ pieceId,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId,
+ false,
+ promotedTo
+ );
+ if (promotedTo == "blank")
+ updateBoardSquaresOpacity(startingSquareId);
+ return;
+ }
+ destinationSquare.appendChild(piece);
+ isWhiteTurn = !isWhiteTurn;
+ updateBoardSquaresArray(
+ startingSquareId,
+ destinationSquareId,
+ boardSquaresArray
+ );
+ let captured = false;
+ makeMove(
+ startingSquareId,
+ destinationSquareId,
+ pieceType,
+ pieceColor,
+ captured
+ );
+ if (moves.length == 1) {
+ level.disabled = true;
+ switchSides.disabled = true;
+ }
+ checkForEndGame();
+ return;
+ }
+ if (
+ squareContent.pieceColor != "blank" &&
+ legalSquares.includes(destinationSquareId)
+ ) {
+ if (
+ pieceType == "pawn" &&
+ (destinationSquareId.charAt(1) == 8 || destinationSquareId.charAt(1) == 1)
+ ) {
+ allowMovement = false;
+ displayPromotionChoices(
+ pieceId,
+ pieceColor,
+ startingSquareId,
+ destinationSquareId,
+ true,
+ promotedTo
+ );
+ if (promotedTo == "blank")
+ updateBoardSquaresOpacity(startingSquareId);
+ return;
+ }
+ let children = destinationSquare.children;
+ for (let i = 0; i < children.length; i++) {
+ if (!children[i].classList.contains("coordinate")) {
+ destinationSquare.removeChild(children[i]);
+ }
+ }
+ // while (destinationSquare.firstChild) {
+ // if(!destinationSquare.firstChild.classList.contains("coordinate"))
+ // destinationSquare.removeChild(destinationSquare.firstChild);
+ // }
+ destinationSquare.appendChild(piece);
+ isWhiteTurn = !isWhiteTurn;
+ updateBoardSquaresArray(
+ startingSquareId,
+ destinationSquareId,
+ boardSquaresArray
+ );
+ let captured = true;
+
+ makeMove(
+ startingSquareId,
+ destinationSquareId,
+ pieceType,
+ pieceColor,
+ captured
+ );
+ checkForEndGame();
+ return;
+ }
+}
+
+function getBestMove(fen, callback) {
+ let engine = new Worker("./node_modules/stockfish/src/stockfish-nnue-16.js");
+ engine.onmessage = function (event) {
+ let message = event.data;
+ if (message.startsWith("bestmove")) {
+ let bestMove = event.data.split(" ")[1];
+ callback(bestMove);
+ engine.terminate();
+ }
+ };
+ engine.postMessage("position fen " + fen);
+ engine.postMessage(`go depth ${selectedLevel}`);
+}
+
+function playBestMove(bestMove) {
+ let startingSquareId = bestMove.substring(0, 2);
+ let destinationSquareId = bestMove.substring(2, 4);
+ let promotedTo = "";
+ if (bestMove.length === 5) {
+ promotedTo = bestMove.substring(4, 5);
+ let pieceMap = {
+ "q": "queen",
+ "r": "rook",
+ "n": "knight",
+ "b": "bishop"
+ };
+ promotedTo = pieceMap[promotedTo];
+ }
+ displayMove(startingSquareId, destinationSquareId, promotedTo);
+}
+
+
+function getPossibleMoves(startingSquareId, piece, boardSquaresArray) {
+ const pieceColor = piece.pieceColor;
+ const pieceType = piece.pieceType;
+ let legalSquares = [];
+ if (pieceType == "rook") {
+ legalSquares = getRookMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ return legalSquares;
+ }
+ if (pieceType == "bishop") {
+ legalSquares = getBishopMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ return legalSquares;
+ }
+ if (pieceType == "queen") {
+ legalSquares = getQueenMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ return legalSquares;
+ }
+ if (pieceType == "knight") {
+ legalSquares = getKnightMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ return legalSquares;
+ }
+
+ if (pieceType == "pawn") {
+ legalSquares = getPawnMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ return legalSquares;
+ }
+ if (pieceType == "king") {
+ legalSquares = getKingMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ return legalSquares;
+ }
+}
+
+function getPawnMoves(startingSquareId, pieceColor, boardSquaresArray) {
+ let diogonalSquares = checkPawnDiagonalCaptures(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let forwardSquares = checkPawnForwardMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let legalSquares = [...diogonalSquares, ...forwardSquares];
+ return legalSquares;
+}
+
+function checkPawnDiagonalCaptures(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+) {
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let legalSquares = [];
+ let currentFile = file;
+ let currentRank = rankNumber;
+ let currentSquareId = currentFile + currentRank;
+ const direction = pieceColor == "white" ? 1 : -1;
+ currentRank += direction;
+ for (let i = -1; i <= 1; i += 2) {
+ currentFile = String.fromCharCode(file.charCodeAt(0) + i);
+ if (currentFile >= "a" && currentFile <= "h" && currentRank <= 8 && currentRank >= 1) {
+ currentSquareId = currentFile + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent != pieceColor)
+ legalSquares.push(currentSquareId);
+
+ if (squareContent == "blank") {
+ currentSquareId = currentFile + rank;
+ let pawnStartingSquareRank = rankNumber + direction * 2;
+ let pawnStartingSquareId = currentFile + pawnStartingSquareRank;
+
+ if (
+ enPassantPossible(currentSquareId, pawnStartingSquareId, direction)
+ ) {
+ let pawnStartingSquareRank = rankNumber + direction;
+ let enPassantSquare = currentFile + pawnStartingSquareRank;
+ legalSquares.push(enPassantSquare);
+ }
+ }
+ }
+ }
+ return legalSquares;
+}
+function enPassantPossible(currentSquareId, pawnStartingSquareId, direction) {
+ if (moves.length == 0) return false;
+ let lastMove = moves[moves.length - 1];
+ if (
+ !(lastMove.to === currentSquareId && lastMove.from === pawnStartingSquareId)
+ )
+ return false;
+
+ let file = currentSquareId[0];
+ let rank = parseInt(currentSquareId[1]);
+ rank += direction;
+ let squareBehindId = file + rank;
+ enPassantSquare = squareBehindId;
+ return true;
+}
+function checkPawnForwardMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+) {
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let legalSquares = [];
+ let currentFile = file;
+ let currentRank = rankNumber;
+ let currentSquareId = currentFile + currentRank;
+ const direction = pieceColor == "white" ? 1 : -1;
+ currentRank += direction;
+ currentSquareId = currentFile + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank") return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (
+ !(
+ (rankNumber == 2 && pieceColor == "white") ||
+ (rankNumber == 7 && pieceColor == "black")
+ )
+ )
+ return legalSquares;
+ currentRank += direction;
+ currentSquareId = currentFile + currentRank;
+ currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank")
+ if (squareContent != "blank") return legalSquares;
+ legalSquares.push(currentSquareId);
+ return legalSquares;
+}
+function getKnightMoves(startingSquareId, pieceColor, boardSquaresArray) {
+ const file = startingSquareId.charCodeAt(0) - 97;
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let currentFile = file;
+ let currentRank = rankNumber;
+ let legalSquares = [];
+
+ const moves = [
+ [-2, 1],
+ [-1, 2],
+ [1, 2],
+ [2, 1],
+ [2, -1],
+ [1, -2],
+ [-1, -2],
+ [-2, -1],
+ ];
+ moves.forEach((move) => {
+ currentFile = file + move[0];
+ currentRank = rankNumber + move[1];
+ if (
+ currentFile >= 0 &&
+ currentFile <= 7 &&
+ currentRank > 0 &&
+ currentRank <= 8
+ ) {
+ let currentSquareId = String.fromCharCode(currentFile + 97) + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(String.fromCharCode(currentFile + 97) + currentRank);
+ }
+ });
+ return legalSquares;
+}
+function getRookMoves(startingSquareId, pieceColor, boardSquaresArray) {
+ let moveToEighthRankSquares = moveToEighthRank(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let moveToFirstRankSquares = moveToFirstRank(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let moveToAFileSquares = moveToAFile(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let moveToHFileSquares = moveToHFile(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let legalSquares = [
+ ...moveToEighthRankSquares,
+ ...moveToFirstRankSquares,
+ ...moveToAFileSquares,
+ ...moveToHFileSquares,
+ ];
+ return legalSquares;
+}
+function getBishopMoves(startingSquareId, pieceColor, boardSquaresArray) {
+ let moveToEighthRankHFileSquares = moveToEighthRankHFile(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let moveToEighthRankAFileSquares = moveToEighthRankAFile(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let moveToFirstRankHFileSquares = moveToFirstRankHFile(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let moveToFirstRankAFileSquares = moveToFirstRankAFile(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let legalSquares = [
+ ...moveToEighthRankHFileSquares,
+ ...moveToEighthRankAFileSquares,
+ ...moveToFirstRankHFileSquares,
+ ...moveToFirstRankAFileSquares,
+ ];
+ return legalSquares;
+}
+function getQueenMoves(startingSquareId, pieceColor, boardSquaresArray) {
+ let bishopMoves = getBishopMoves(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ let rookMoves = getRookMoves(startingSquareId, pieceColor, boardSquaresArray);
+ let legalSquares = [...bishopMoves, ...rookMoves];
+ return legalSquares;
+}
+function getKingMoves(startingSquareId, pieceColor, boardSquaresArray) {
+ const file = startingSquareId.charCodeAt(0) - 97; // get the second character of the string
+ const rank = startingSquareId.charAt(1); // get the second character of the string
+ const rankNumber = parseInt(rank); // convert the second character to a number
+ let currentFile = file;
+ let currentRank = rankNumber;
+ let legalSquares = [];
+ const moves = [
+ [0, 1],
+ [0, -1],
+ [1, 1],
+ [1, -1],
+ [-1, 0],
+ [-1, 1],
+ [-1, -1],
+ [1, 0],
+ ];
+
+ moves.forEach((move) => {
+ let currentFile = file + move[0];
+ let currentRank = rankNumber + move[1];
+
+ if (
+ currentFile >= 0 &&
+ currentFile <= 7 &&
+ currentRank > 0 &&
+ currentRank <= 8
+ ) {
+ let currentSquareId = String.fromCharCode(currentFile + 97) + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor) {
+ return legalSquares;
+ }
+ legalSquares.push(String.fromCharCode(currentFile + 97) + currentRank);
+ }
+ });
+ let shortCastleSquare = isShortCastlePossible(pieceColor, boardSquaresArray);
+ let longCastleSquare = isLongCastlePossible(pieceColor, boardSquaresArray);
+ if (shortCastleSquare != "blank") legalSquares.push(shortCastleSquare);
+ if (longCastleSquare != "blank") legalSquares.push(longCastleSquare);
+
+ return legalSquares;
+}
+function isShortCastlePossible(pieceColor, boardSquaresArray) {
+ let rank = pieceColor === "white" ? "1" : "8";
+ let fSquare = boardSquaresArray.find(
+ (element) => element.squareId === `f${rank}`
+ );
+ let gSquare = boardSquaresArray.find(
+ (element) => element.squareId === `g${rank}`
+ );
+ if (
+ fSquare.pieceColor !== "blank" ||
+ gSquare.pieceColor !== "blank" ||
+ kingHasMoved(pieceColor) ||
+ rookHasMoved(pieceColor, `h${rank}`)
+ ) {
+ return "blank";
+ }
+
+ return `g${rank}`;
+}
+function isLongCastlePossible(pieceColor, boardSquaresArray) {
+ let rank = pieceColor === "white" ? "1" : "8";
+ let dSquare = boardSquaresArray.find(
+ (element) => element.squareId === `d${rank}`
+ );
+ let cSquare = boardSquaresArray.find(
+ (element) => element.squareId === `c${rank}`
+ );
+ let bSquare = boardSquaresArray.find(
+ (element) => element.squareId === `b${rank}`
+ );
+ if (
+ dSquare.pieceColor !== "blank" ||
+ cSquare.pieceColor !== "blank" ||
+ bSquare.pieceColor !== "blank" ||
+ kingHasMoved(pieceColor) ||
+ rookHasMoved(pieceColor, `a${rank}`)
+ ) {
+ return "blank";
+ }
+
+ return `c${rank}`;
+}
+function kingHasMoved(pieceColor) {
+ let result = moves.find(
+ (element) =>
+ element.pieceColor === pieceColor && element.pieceType === "king"
+ );
+ if (result != undefined) return true;
+ return false;
+}
+function rookHasMoved(pieceColor, startingSquareId) {
+ let result = moves.find(
+ (element) =>
+ element.pieceColor === pieceColor &&
+ element.pieceType === "rook" &&
+ element.from === startingSquareId
+ );
+ if (result != undefined) return true;
+ return false;
+}
+
+function moveToEighthRank(startingSquareId, pieceColor, boardSquaresArray) {
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let currentRank = rankNumber;
+ let legalSquares = [];
+ while (currentRank != 8) {
+ currentRank++;
+ let currentSquareId = file + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (squareContent != "blank" && squareContent != pieceColor)
+ return legalSquares;
+ }
+ return legalSquares;
+}
+function moveToFirstRank(startingSquareId, pieceColor, boardSquaresArray) {
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let currentRank = rankNumber;
+ let legalSquares = [];
+ while (currentRank != 1) {
+ currentRank--;
+ let currentSquareId = file + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (squareContent != "blank" && squareContent != pieceColor)
+ return legalSquares;
+ }
+ return legalSquares;
+}
+function moveToAFile(startingSquareId, pieceColor, boardSquaresArray) {
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ let currentFile = file;
+ let legalSquares = [];
+
+ while (currentFile != "a") {
+ currentFile = String.fromCharCode(
+ currentFile.charCodeAt(currentFile.length - 1) - 1
+ );
+ let currentSquareId = currentFile + rank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (squareContent != "blank" && squareContent != pieceColor)
+ return legalSquares;
+ }
+ return legalSquares;
+}
+function moveToHFile(startingSquareId, pieceColor, boardSquaresArray) {
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ let currentFile = file;
+ let legalSquares = [];
+ while (currentFile != "h") {
+ currentFile = String.fromCharCode(
+ currentFile.charCodeAt(currentFile.length - 1) + 1
+ );
+ let currentSquareId = currentFile + rank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (squareContent != "blank" && squareContent != pieceColor)
+ return legalSquares;
+ }
+ return legalSquares;
+}
+function moveToEighthRankAFile(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+)
+
+{
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let currentFile = file;
+ let currentRank = rankNumber;
+ let legalSquares = [];
+ while (!(currentFile == "a" || currentRank == 8)) {
+ currentFile = String.fromCharCode(
+ currentFile.charCodeAt(currentFile.length - 1) - 1
+ );
+ currentRank++;
+ let currentSquareId = currentFile + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (squareContent != "blank" && squareContent != pieceColor)
+ return legalSquares;
+ }
+ return legalSquares;
+}
+
+function moveToEighthRankHFile(
+ startingSquareId,
+ pieceColor,
+ boardSquaresArray
+)
+
+{
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let currentFile = file;
+ let currentRank = rankNumber;
+ let legalSquares = [];
+ while (!(currentFile == "h" || currentRank == 8)) {
+ currentFile = String.fromCharCode(
+ currentFile.charCodeAt(currentFile.length - 1) + 1
+ );
+ currentRank++;
+ let currentSquareId = currentFile + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (squareContent != "blank" && squareContent != pieceColor)
+ return legalSquares;
+ }
+ return legalSquares;
+}
+
+function moveToFirstRankAFile(startingSquareId, pieceColor, boardSquaresArray) {
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let currentFile = file;
+ let currentRank = rankNumber;
+ let legalSquares = [];
+ while (!(currentFile == "a" || currentRank == 1)) {
+ currentFile = String.fromCharCode(
+ currentFile.charCodeAt(currentFile.length - 1) - 1
+ );
+ currentRank--;
+ let currentSquareId = currentFile + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (squareContent != "blank" && squareContent != pieceColor)
+ return legalSquares;
+ }
+ return legalSquares;
+}
+
+function moveToFirstRankHFile(startingSquareId, pieceColor, boardSquaresArray) {
+ const file = startingSquareId.charAt(0);
+ const rank = startingSquareId.charAt(1);
+ const rankNumber = parseInt(rank);
+ let currentFile = file;
+ let currentRank = rankNumber;
+ let legalSquares = [];
+ while (!(currentFile == "h" || currentRank == 1)) {
+ currentFile = String.fromCharCode(
+ currentFile.charCodeAt(currentFile.length - 1) + 1
+ );
+ currentRank--;
+ let currentSquareId = currentFile + currentRank;
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === currentSquareId
+ );
+ let squareContent = currentSquare.pieceColor;
+ if (squareContent != "blank" && squareContent == pieceColor)
+ return legalSquares;
+ legalSquares.push(currentSquareId);
+ if (squareContent != "blank" && squareContent != pieceColor)
+ return legalSquares;
+ }
+ return legalSquares;
+}
+
+function getPieceAtSquare(squareId, boardSquaresArray) {
+ let currentSquare = boardSquaresArray.find(
+ (element) => element.squareId === squareId
+ );
+ const color = currentSquare.pieceColor;
+ const pieceType = currentSquare.pieceType;
+ const pieceId = currentSquare.pieceId;
+ return { pieceColor: color, pieceType: pieceType, pieceId: pieceId };
+}
+
+function isKingInCheck(squareId, pieceColor, boardSquaresArray) {
+ let legalSquares = getRookMoves(squareId, pieceColor, boardSquaresArray);
+ for (let squareId of legalSquares) {
+ let pieceProperties = getPieceAtSquare(squareId, boardSquaresArray);
+ if (
+ (pieceProperties.pieceType == "rook" ||
+ pieceProperties.pieceType == "queen") &&
+ pieceColor != pieceProperties.pieceColor
+ )
+ return true;
+ }
+ legalSquares = getBishopMoves(squareId, pieceColor, boardSquaresArray);
+ for (let squareId of legalSquares) {
+ let pieceProperties = getPieceAtSquare(squareId, boardSquaresArray);
+ if (
+ (pieceProperties.pieceType == "bishop" ||
+ pieceProperties.pieceType == "queen") &&
+ pieceColor != pieceProperties.pieceColor
+ )
+ return true;
+ }
+ legalSquares = getKnightMoves(squareId, pieceColor, boardSquaresArray);
+ for (let squareId of legalSquares) {
+ let pieceProperties = getPieceAtSquare(squareId, boardSquaresArray);
+ if (
+ pieceProperties.pieceType == "knight" &&
+ pieceColor != pieceProperties.pieceColor
+ )
+ return true;
+ }
+ legalSquares = checkPawnDiagonalCaptures(
+ squareId,
+ pieceColor,
+ boardSquaresArray
+ );
+ for (let squareId of legalSquares) {
+ let pieceProperties = getPieceAtSquare(squareId, boardSquaresArray);
+ if (
+ pieceProperties.pieceType == "pawn" &&
+ pieceColor != pieceProperties.color
+ )
+ return true;
+ }
+ legalSquares = getKingMoves(squareId, pieceColor, boardSquaresArray);
+ for (let squareId of legalSquares) {
+ let pieceProperties = getPieceAtSquare(squareId, boardSquaresArray);
+ if (
+ pieceProperties.pieceType == "king" &&
+ pieceColor != pieceProperties.color
+ )
+ return true;
+ }
+ return false;
+}
+
+function getkingLastMove(color) {
+ let kingLastMove = moves.findLast(
+ (element) => element.pieceType === "king" && element.pieceColor === color
+ );
+ if (kingLastMove == undefined) return isWhiteTurn ? "e1" : "e8";
+ return kingLastMove.to;
+}
+
+function isMoveValidAgainstCheck(
+ legalSquares,
+ startingSquareId,
+ pieceColor,
+ pieceType
+)
+
+{
+ let kingSquare = isWhiteTurn
+ ? getkingLastMove("white")
+ : getkingLastMove("black");
+ let boardSquaresArrayCopy = deepCopyArray(boardSquaresArray);
+ let legalSquaresCopy = legalSquares.slice();
+ legalSquaresCopy.forEach((element) => {
+ let destinationId = element;
+ boardSquaresArrayCopy = deepCopyArray(boardSquaresArray);
+ updateBoardSquaresArray(
+ startingSquareId,
+ destinationId,
+ boardSquaresArrayCopy
+ );
+ if (
+ pieceType != "king" &&
+ isKingInCheck(kingSquare, pieceColor, boardSquaresArrayCopy)
+ ) {
+ legalSquares = legalSquares.filter((item) => item != destinationId);
+ }
+ if (
+ pieceType == "king" &&
+ isKingInCheck(destinationId, pieceColor, boardSquaresArrayCopy)
+ ) {
+ legalSquares = legalSquares.filter((item) => item != destinationId);
+ }
+ });
+ return legalSquares;
+}
+
+function checkForEndGame() {
+ checkForCheckMateAndStaleMate();
+ let currentPosition = generateFEN(boardSquaresArray);
+ if ((isEngineWhite && isWhiteTurn) || (!isEngineWhite && !isWhiteTurn))
+ getBestMove(currentPosition, playBestMove);
+ positionArray.push(currentPosition);
+ let threeFoldRepetition = isThreefoldRepetition();
+ let insufficientMaterial = hasInsufficientMaterial(currentPosition);
+ let fiftyMovesRuleCount = currentPosition.split(" ")[4];
+ let fiftyMovesRule = fiftyMovesRuleCount != 100 ? false : true;
+ let isDraw = threeFoldRepetition || insufficientMaterial || fiftyMovesRule;
+ if (isDraw) {
+ allowMovement = false;
+ showAlert("Draw");
+
+ document.addEventListener('dragstart', function (event) {
+ event.preventDefault();
+ });
+ document.addEventListener('drop', function (event) {
+ event.preventDefault();
+ });
+
+ }
+}
+
+function checkForCheckMateAndStaleMate() {
+ let kingSquare = isWhiteTurn
+ ? getkingLastMove("white")
+ : getkingLastMove("black");
+ let pieceColor = isWhiteTurn ? "white" : "black";
+ let boardSquaresArrayCopy = deepCopyArray(boardSquaresArray);
+ let kingIsCheck = isKingInCheck(
+ kingSquare,
+ pieceColor,
+ boardSquaresArrayCopy
+ );
+ let possibleMoves = getAllPossibleMoves(boardSquaresArrayCopy, pieceColor);
+ if (possibleMoves.length > 0) return;
+ let message = "";
+ if (kingIsCheck)
+ isWhiteTurn ? (message = "Black Wins!") : (message = "White Wins!");
+ else
+ message = "Draw";
+ showAlert(message);
+}
+
+function getFiftyMovesRuleCount() {
+ let count = 0;
+ for (let i = 0; i < moves.length; i++) {
+ count++;
+ if (moves[i].captured || moves[i].pieceType === "pawn" || moves[i].promotedTo != "blank")
+ count = 0;
+ }
+ return count;
+}
+
+function isThreefoldRepetition() {
+ return positionArray.some((string) => {
+ const fen = string.split(" ").slice(0, 4).join(" ");
+ return positionArray.filter(
+ (element) => element.split(" ").slice(0, 4).join(" ") === fen
+ ).length >= 3
+ });
+}
+
+function hasInsufficientMaterial(fen) {
+ const piecePlacement = fen.split(" ")[0];
+
+ const whiteBishops = piecePlacement.split("").filter(char => char === "B").length;
+ const blackBishops = piecePlacement.split("").filter(char => char === "b").length;
+ const whiteKnights = piecePlacement.split("").filter(char => char === "N").length;
+ const blackKnights = piecePlacement.split("").filter(char => char === "n").length;
+ const whiteQueens = piecePlacement.split("").filter(char => char === "Q").length;
+ const blackQueens = piecePlacement.split("").filter(char => char === "q").length;
+ const whiteRooks = piecePlacement.split("").filter(char => char === "R").length;
+ const blackRooks = piecePlacement.split("").filter(char => char === "r").length;
+ const whitePawns = piecePlacement.split("").filter(char => char === "P").length;
+ const blackPawns = piecePlacement.split("").filter(char => char === "p").length;
+
+ if (whiteQueens + blackQueens + whiteRooks + blackRooks + whitePawns + blackPawns > 0) {
+ return false;
+ }
+
+ if (whiteKnights + blackKnights > 1) {
+ return false;
+ }
+ if (whiteKnights + blackKnights > 1) {
+ return false;
+ }
+
+ if ((whiteBishops > 0 || blackBishops > 0) && (whiteKnights + blackKnights > 0))
+ return false;
+
+ if (whiteBishops > 1 || blackBishops > 1)
+ return false;
+
+ if (whiteBishops === 1 && blackBishops === 1) {
+ let whiteBishopSquareColor, blackBishopSquareColor;
+
+ let whiteBishopSquare = boardSquaresArray.find(element => (element.pieceType === "bishop" && element.pieceColor === "white"));
+ let blackBishopSquare = boardSquaresArray.find(element => (element.pieceType === "bishop" && element.pieceColor === "black"));
+
+ whiteBishopSquareColor = getSqaureColor(whiteBishopSquare.squareId);
+ blackBishopSquareColor = getSqaureColor(blackBishopSquare.squareId);
+
+ if (whiteBishopSquareColor !== blackBishopSquareColor) {
+ return false;
+ }
+ }
+ return true;
+}
+
+function getSqaureColor(squareId) {
+ let squareElement = document.getElementById(squareId);
+ let squareColor = squareElement.classList.contains("white") ? "white" : "black";
+ return squareColor;
+}
+
+function getAllPossibleMoves(squaresArray, color) {
+ return squaresArray
+ .filter((square) => square.pieceColor === color)
+ .flatMap((square) => {
+ const { pieceColor, pieceType, pieceId } = getPieceAtSquare(
+ square.squareId,
+ squaresArray
+ );
+ if (pieceId === "blank") return [];
+ let squaresArrayCopy = deepCopyArray(squaresArray);
+ const pieceObject = {
+ pieceColor: pieceColor,
+ pieceType: pieceType,
+ pieceId: pieceId,
+ };
+ let legalSquares = getPossibleMoves(
+ square.squareId,
+ pieceObject,
+ squaresArrayCopy
+ );
+ legalSquares = isMoveValidAgainstCheck(
+ legalSquares,
+ square.squareId,
+ pieceColor,
+ pieceType
+ );
+ return legalSquares;
+ });
+}
+
+function showAlert(message) {
+ const alert = document.getElementById("alert");
+ alert.innerHTML = message;
+ alert.style.display = "flex";
+ if (isEngineWhite)
+ alert.style.transform = alert.style.transform = 'rotate(180deg)';
+
+ setTimeout(function () {
+ alert.style.display = "none";
+ }, 3000);
+}
\ No newline at end of file
diff --git a/Chess Game/src/style.css b/Chess Game/src/style.css
new file mode 100644
index 00000000..8e0398ca
--- /dev/null
+++ b/Chess Game/src/style.css
@@ -0,0 +1,188 @@
+body {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 100vh;
+ overflow: hidden;
+ background: #0084ff76;
+}
+
+.chessBoard {
+ width: 500px;
+ height: 500px;
+ margin: 0 auto;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ align-items: center;
+}
+
+.square {
+ width: 12.5%;
+ height: 12.5%;
+ float: left;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: relative;
+}
+
+.white {
+ background-color: #f0d9b5;
+}
+
+.black {
+ background-color: #b58863;
+}
+
+.coordinate {
+ height: auto;
+ display: flex;
+ bottom: 4%;
+ left: 4%;
+ position: absolute;
+ font-size: 12px;
+ font-weight: bold;
+ font-family: Verdana, Geneva, Tahoma, sans-serif;
+}
+
+.rank {
+ top: 4%;
+ right: 4%;
+ left: auto;
+}
+
+.whiteText {
+ color: #f0d9b5;
+}
+
+.blackText {
+ color: #b58863;
+}
+
+.piece {
+ width: 100%;
+ z-index: 1;
+ cursor: pointer;
+}
+
+.piece img {
+ max-width: 100%;
+ width: 100%;
+ height: auto;
+}
+
+#alert {
+ position: absolute;
+ color: whitesmoke;
+ width: 50vw;
+ height: 12%;
+ text-align: center;
+ align-content: center;
+ justify-content: center;
+ font-size: 35px;
+ font-weight: bold;
+ z-index: 1000;
+ display: none;
+ background: #008080bf;
+ border-radius: 5px;
+ align-items: center;
+}
+
+.promotionOption {
+ border-radius: 50%;
+ background-color: darkgray;
+ transition: transform 0.2s;
+ position: absolute;
+ z-index: 1000;
+}
+
+.promotionOption:hover {
+ cursor: pointer;
+ border-radius: 0%;
+ background-color: #539B0C;
+ width: 100%;
+}
+
+.promotionOption img {
+ max-width: 100%;
+ width: 100%;
+ height: auto;
+}
+
+.container {
+ display: flex;
+ flex-wrap: wrap-reverse;
+ align-items: center;
+ width: 90%;
+}
+
+.buttonContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 10vw;
+ margin: 20px 0px 0px 20px;
+}
+
+.buttonContainer button {
+ width: 120px;
+ height: 40px;
+ border: none;
+ cursor: pointer;
+ border-radius: 5px;
+ background-color: rgb(87, 64, 64);
+ color: white;
+ font-weight: bold;
+ margin: 10px;
+}
+
+.buttonContainer select {
+ width: 120px;
+ height: 40px;
+ background-color: whitesmoke;
+}
+
+div:has(>#levelLabel) {
+ margin-bottom: 5px;
+}
+
+@media (min-width:600px) {
+ .chessBoard {
+ width: 500px;
+ height: 500px;
+ }
+
+ #alert {
+ width: 450px;
+ height: 80px;
+ }
+}
+
+@media (max-width:600px) {
+ .coordinate {
+ font-size: 8px;
+ }
+
+ #alert {
+ font-size: 20px;
+ }
+
+ button {
+ font-size: 10px;
+ }
+
+ .buttonContainer {
+ flex-direction: row;
+ align-items: last baseline;
+ justify-content: center;
+ width: 80vw;
+ }
+
+ .buttonContainer button,
+ .buttonContainer select {
+ width: 20vw;
+ margin-right: 5px;
+ }
+}
\ No newline at end of file