User prompt
Where is the red hight light add it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When you check or checkmate any player(ai or player) there is a red highlight to checked* king ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make captured pieces bigger and the text bigger and a bit up ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add an sound asset for checkmate
User prompt
If the check mate text plays the check text wont play ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
If there is a check mate there comes a text says Check Mate! And game ends 1 sec after the text ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the game_music asset loop and play all the game
User prompt
Less the capture effect %50 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move the check text a bit up and add a sound asset for check (when there is a check it should play)
User prompt
When we check or enemy check A text comes up says (Check!) Let it slowly disappear, let it be rainbow colored ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make captured pieces text a bit bigger and a bit up
User prompt
Captured pieces text Collides with captured pieces fix it
User prompt
Bro less efect pls but a bit less like if the efect 100 make it 80 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
So make it a bit less (very very little less) ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make exploison efect better and more efective ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Move the Capt. pieces section a little to the right because it is not visible from the stop button.
User prompt
Please enhance the chess game with these features: 1. Add a visual explosion or particle effect whenever a piece is captured, to make the capture feel dramatic. 2. When a piece is captured, move its sprite or icon to a designated “captured pieces area” above the board, grouped by color, so players can see which pieces were taken. 3. Animate the captured piece moving smoothly from its square to the captured area before it disappears from the board. 4. Make sure the explosion or particle effect only happens on a successful capture, not on normal moves. 5. Keep all piece dragging and movement functionality working as before, with no interruption. 6. Test the game after adding these enhancements to confirm that captures show both the effect and the captured-pieces list correctly. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the drag-and-drop bug where if a chess piece is dragged but then returned to its original square, it becomes unselectable or frozen. - When a piece is dragged and dropped back to its starting square, it must remain fully selectable and movable. - Reset any dragging flags or lock states so the piece is still active. - Ensure that after canceling a drag, the piece can be picked up and moved again with no problem. - Test this by dragging a piece, returning it to the same square, then dragging it again, to confirm the bug is fixed.
User prompt
Taşları sürükleyip bırakınca taşlar daha hareket edilemez oluyor bunu düzelt
User prompt
Kendi taşlarım birbirinin üzerine binemez bunu düzelt
User prompt
Please correct the pawn movement rules: - Pawns can only move straight forward to an empty square, by 1 square, or by 2 squares on their first move if the path is clear. - Pawns can only move diagonally when they are capturing an opponent piece. - Pawns cannot move diagonally if there is no opponent piece on the target square. - Please rewrite the getRawMoves logic to strictly follow these pawn rules, so that pawns do not move diagonally freely unless capturing. Test a pawn with and without a target piece diagonally and confirm correct behavior after applying this fix.
User prompt
There is a syntax bug in my code that causes a ReferenceError on this line: var piece board [row][col].piece; Please correct this syntax: - It must use an assignment with "=" instead of missing equals. - The correct line should be: var piece = board[row][col].piece; Please automatically fix this line in the code and replace the faulty statement with the correct syntax. Then verify that getRawMoves(piece, row, col) will work correctly because 'piece' will no longer be undefined. Test the code after applying this fix to confirm no more ReferenceError occurs.
User prompt
Please fix the bug: 'ReferenceError: getRawMoves is not defined' in or related to this line: 'var moves = getRawMoves(piece, row, col);' Line Number: 803
User prompt
Define getraw moves
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var ChessPiece = Container.expand(function (type, color, row, col) { var self = Container.call(this); self.pieceType = type; self.pieceColor = color; self.boardRow = row; self.boardCol = col; self.hasMoved = false; var assetId = color + type.charAt(0).toUpperCase() + type.slice(1); var pieceGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.updateBoardPosition = function (newRow, newCol) { self.boardRow = newRow; self.boardCol = newCol; self.hasMoved = true; }; return self; }); var ChessSquare = Container.expand(function (row, col) { var self = Container.call(this); self.row = row; self.col = col; self.piece = null; self.isHighlighted = false; var isLight = (row + col) % 2 === 0; var squareGraphics = self.attachAsset(isLight ? 'lightSquare' : 'darkSquare', { anchorX: 0.5, anchorY: 0.5 }); self.highlight = function () { if (!self.isHighlighted) { var highlight = LK.getAsset('highlightSquare', { anchorX: 0.5, anchorY: 0.5, alpha: 0, scaleX: 0.5, scaleY: 0.5 }); self.addChild(highlight); self.isHighlighted = true; self.highlightGraphics = highlight; // Animate highlight appearance tween(highlight, { alpha: 0.5, scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut }); } }; self.removeHighlight = function () { if (self.isHighlighted && self.highlightGraphics) { var highlightToRemove = self.highlightGraphics; self.isHighlighted = false; self.highlightGraphics = null; // Animate highlight disappearance tween(highlightToRemove, { alpha: 0, scaleX: 0.5, scaleY: 0.5 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { self.removeChild(highlightToRemove); } }); } }; self.setPiece = function (piece) { if (self.piece) { self.removeChild(self.piece); } self.piece = piece; if (piece) { self.addChild(piece); piece.x = 0; piece.y = 0; } }; return self; }); var DifficultyButton = Container.expand(function (text, difficulty) { var self = Container.call(this); self.difficulty = difficulty; var buttonBg = self.attachAsset('difficultyButton', { anchorX: 0.5, anchorY: 0.5 }); var buttonText = new Text2(text, { size: 60, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.down = function (x, y, obj) { selectedDifficulty = self.difficulty; startGame(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x8b4513 }); /**** * Game Code ****/ // Game state variables // Chess pieces - white pieces // Chess pieces - black pieces // Board squares // UI elements // Sound effects var gameState = 'difficulty'; // 'difficulty', 'playing', 'gameOver' var selectedDifficulty = 'medium'; var currentPlayer = 'white'; var board = []; var selectedSquare = null; var possibleMoves = []; var difficultyButtons = []; var draggedPiece = null; var dragOffset = { x: 0, y: 0 }; var aiHasMoved = false; // Board constants var BOARD_SIZE = 8; var SQUARE_SIZE = 230; var BOARD_START_X = 2048 / 2 - BOARD_SIZE * SQUARE_SIZE / 2; var BOARD_START_Y = 2732 / 2 - BOARD_SIZE * SQUARE_SIZE / 2; // Initialize difficulty selection function initializeDifficultySelection() { var easyButton = new DifficultyButton('EASY', 'easy'); easyButton.x = 2048 / 2; easyButton.y = 2732 / 2 - 200; game.addChild(easyButton); difficultyButtons.push(easyButton); var mediumButton = new DifficultyButton('MEDIUM', 'medium'); mediumButton.x = 2048 / 2; mediumButton.y = 2732 / 2; game.addChild(mediumButton); difficultyButtons.push(mediumButton); var hardButton = new DifficultyButton('HARD', 'hard'); hardButton.x = 2048 / 2; hardButton.y = 2732 / 2 + 200; game.addChild(hardButton); difficultyButtons.push(hardButton); var titleText = new Text2('Select Difficulty', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 2732 / 2 - 400; game.addChild(titleText); } // Start the game after difficulty selection function startGame() { // Remove difficulty buttons for (var i = 0; i < difficultyButtons.length; i++) { game.removeChild(difficultyButtons[i]); } difficultyButtons = []; // Remove title for (var j = game.children.length - 1; j >= 0; j--) { var child = game.children[j]; if (child instanceof Text2) { game.removeChild(child); } } gameState = 'playing'; initializeBoard(); setupInitialPieces(); } // Initialize the chess board function initializeBoard() { board = []; for (var row = 0; row < BOARD_SIZE; row++) { board[row] = []; for (var col = 0; col < BOARD_SIZE; col++) { var square = new ChessSquare(row, col); square.x = BOARD_START_X + col * SQUARE_SIZE + SQUARE_SIZE / 2; square.y = BOARD_START_Y + row * SQUARE_SIZE + SQUARE_SIZE / 2; game.addChild(square); board[row][col] = square; } } } // Setup initial piece positions function setupInitialPieces() { var pieceOrder = ['rook', 'knight', 'bishop', 'queen', 'king', 'bishop', 'knight', 'rook']; // Black pieces (top of board) for (var col = 0; col < 8; col++) { var blackPiece = new ChessPiece(pieceOrder[col], 'black', 0, col); board[0][col].setPiece(blackPiece); var blackPawn = new ChessPiece('pawn', 'black', 1, col); board[1][col].setPiece(blackPawn); } // White pieces (bottom of board) for (var col = 0; col < 8; col++) { var whitePawn = new ChessPiece('pawn', 'white', 6, col); board[6][col].setPiece(whitePawn); var whitePiece = new ChessPiece(pieceOrder[col], 'white', 7, col); board[7][col].setPiece(whitePiece); } } // Get legal moves for a piece function getLegalMoves(piece, fromRow, fromCol) { var moves = getRawMoves(piece, fromRow, fromCol); var type = piece.pieceType; var color = piece.pieceColor; if (type === 'pawn') { var direction = color === 'white' ? -1 : 1; var startRow = color === 'white' ? 6 : 1; // Forward move if (isValidPosition(fromRow + direction, fromCol) && !board[fromRow + direction][fromCol].piece) { moves.push({ row: fromRow + direction, col: fromCol }); // Two squares forward from starting position if (fromRow === startRow && !board[fromRow + 2 * direction][fromCol].piece) { moves.push({ row: fromRow + 2 * direction, col: fromCol }); } } // Diagonal captures for (var dc = -1; dc <= 1; dc += 2) { if (isValidPosition(fromRow + direction, fromCol + dc)) { var targetPiece = board[fromRow + direction][fromCol + dc].piece; if (targetPiece && targetPiece.pieceColor !== color) { moves.push({ row: fromRow + direction, col: fromCol + dc }); } } } } else if (type === 'rook') { var directions = [[0, 1], [0, -1], [1, 0], [-1, 0]]; for (var d = 0; d < directions.length; d++) { var dr = directions[d][0]; var dc = directions[d][1]; for (var i = 1; i < 8; i++) { var newRow = fromRow + dr * i; var newCol = fromCol + dc * i; if (!isValidPosition(newRow, newCol)) break; var targetPiece = board[newRow][newCol].piece; if (targetPiece) { if (targetPiece.pieceColor !== color) { moves.push({ row: newRow, col: newCol }); } break; } else { moves.push({ row: newRow, col: newCol }); } } } } else if (type === 'bishop') { var directions = [[1, 1], [1, -1], [-1, 1], [-1, -1]]; for (var d = 0; d < directions.length; d++) { var dr = directions[d][0]; var dc = directions[d][1]; for (var i = 1; i < 8; i++) { var newRow = fromRow + dr * i; var newCol = fromCol + dc * i; if (!isValidPosition(newRow, newCol)) break; var targetPiece = board[newRow][newCol].piece; if (targetPiece) { if (targetPiece.pieceColor !== color) { moves.push({ row: newRow, col: newCol }); } break; } else { moves.push({ row: newRow, col: newCol }); } } } } else if (type === 'queen') { var directions = [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]]; for (var d = 0; d < directions.length; d++) { var dr = directions[d][0]; var dc = directions[d][1]; for (var i = 1; i < 8; i++) { var newRow = fromRow + dr * i; var newCol = fromCol + dc * i; if (!isValidPosition(newRow, newCol)) break; var targetPiece = board[newRow][newCol].piece; if (targetPiece) { if (targetPiece.pieceColor !== color) { moves.push({ row: newRow, col: newCol }); } break; } else { moves.push({ row: newRow, col: newCol }); } } } } else if (type === 'king') { var directions = [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]]; for (var d = 0; d < directions.length; d++) { var newRow = fromRow + directions[d][0]; var newCol = fromCol + directions[d][1]; if (isValidPosition(newRow, newCol)) { var targetPiece = board[newRow][newCol].piece; if (!targetPiece || targetPiece.pieceColor !== color) { moves.push({ row: newRow, col: newCol }); } } } } else if (type === 'knight') { var knightMoves = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]]; for (var m = 0; m < knightMoves.length; m++) { var newRow = fromRow + knightMoves[m][0]; var newCol = fromCol + knightMoves[m][1]; if (isValidPosition(newRow, newCol)) { var targetPiece = board[newRow][newCol].piece; if (!targetPiece || targetPiece.pieceColor !== color) { moves.push({ row: newRow, col: newCol }); } } } } // Get all pseudo-legal moves for a piece (ignores pins and king safety) function getRawMoves(piece, fromRow, fromCol) { var moves = []; var type = piece.pieceType; var color = piece.pieceColor; if (type === 'pawn') { var direction = color === 'white' ? -1 : 1; // Move forward 1 square if (isValidPosition(fromRow + direction, fromCol)) { moves.push({ row: fromRow + direction, col: fromCol }); // Move forward 2 squares from starting position var startRow = color === 'white' ? 6 : 1; if (fromRow === startRow && isValidPosition(fromRow + 2 * direction, fromCol)) { moves.push({ row: fromRow + 2 * direction, col: fromCol }); } } // Pawn captures diagonally for (var dc = -1; dc <= 1; dc += 2) { if (isValidPosition(fromRow + direction, fromCol + dc)) { moves.push({ row: fromRow + direction, col: fromCol + dc }); } } } else if (type === 'rook') { var directions = [[0, 1], [0, -1], [1, 0], [-1, 0]]; for (var d = 0; d < directions.length; d++) { var dr = directions[d][0]; var dc = directions[d][1]; for (var i = 1; i < 8; i++) { var newRow = fromRow + dr * i; var newCol = fromCol + dc * i; if (!isValidPosition(newRow, newCol)) break; moves.push({ row: newRow, col: newCol }); var targetPiece = board[newRow][newCol].piece; if (targetPiece) { break; } } } } else if (type === 'bishop') { var directions = [[1, 1], [1, -1], [-1, 1], [-1, -1]]; for (var d = 0; d < directions.length; d++) { var dr = directions[d][0]; var dc = directions[d][1]; for (var i = 1; i < 8; i++) { var newRow = fromRow + dr * i; var newCol = fromCol + dc * i; if (!isValidPosition(newRow, newCol)) break; moves.push({ row: newRow, col: newCol }); var targetPiece = board[newRow][newCol].piece; if (targetPiece) { break; } } } } else if (type === 'queen') { var directions = [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]]; for (var d = 0; d < directions.length; d++) { var dr = directions[d][0]; var dc = directions[d][1]; for (var i = 1; i < 8; i++) { var newRow = fromRow + dr * i; var newCol = fromCol + dc * i; if (!isValidPosition(newRow, newCol)) break; moves.push({ row: newRow, col: newCol }); var targetPiece = board[newRow][newCol].piece; if (targetPiece) { break; } } } } else if (type === 'king') { var directions = [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]]; for (var d = 0; d < directions.length; d++) { var newRow = fromRow + directions[d][0]; var newCol = fromCol + directions[d][1]; if (isValidPosition(newRow, newCol)) { moves.push({ row: newRow, col: newCol }); } } } else if (type === 'knight') { var knightMoves = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]]; for (var m = 0; m < knightMoves.length; m++) { var newRow = fromRow + knightMoves[m][0]; var newCol = fromCol + knightMoves[m][1]; if (isValidPosition(newRow, newCol)) { moves.push({ row: newRow, col: newCol }); } } } return moves; } // Filter out moves that would leave own king in check (pin rule) var legalMoves = []; var _loop = function _loop() { move = moves[i]; // Simulate the move fromPiece = board[fromRow][fromCol].piece; toPiece = board[move.row][move.col].piece; // Temporarily move the piece board[fromRow][fromCol].setPiece(null); board[move.row][move.col].setPiece(fromPiece); kingSafe = true; // Find own king position after move kingRow = -1, kingCol = -1; for (r = 0; r < BOARD_SIZE; r++) { for (c = 0; c < BOARD_SIZE; c++) { p = board[r][c].piece; if (p && p.pieceType === 'king' && p.pieceColor === color) { kingRow = r; kingCol = c; } } } // If this piece is the king, update kingRow/kingCol to new position if (type === 'king') { kingRow = move.row; kingCol = move.col; } // Check if any enemy piece can attack the king after this move for (r = 0; r < BOARD_SIZE; r++) { for (c = 0; c < BOARD_SIZE; c++) { enemy = board[r][c].piece; if (enemy && enemy.pieceColor !== color) { enemyMoves = getRawMoves(enemy, r, c); for (j = 0; j < enemyMoves.length; j++) { if (enemyMoves[j].row === kingRow && enemyMoves[j].col === kingCol) { kingSafe = false; break; } } } if (!kingSafe) break; } if (!kingSafe) break; } // Undo the move board[move.row][move.col].setPiece(toPiece); board[fromRow][fromCol].setPiece(fromPiece); if (kingSafe) { legalMoves.push(move); } }, move, fromPiece, toPiece, kingSafe, kingRow, kingCol, r, c, p, r, c, enemy, enemyMoves, j; for (var i = 0; i < moves.length; i++) { _loop(); } return legalMoves; } // Check if position is valid on board function isValidPosition(row, col) { return row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE; } // Highlight possible moves function highlightMoves(moves) { for (var i = 0; i < moves.length; i++) { board[moves[i].row][moves[i].col].highlight(); } } // Clear all highlights function clearHighlights() { for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { board[row][col].removeHighlight(); } } } // Make a move function makeMove(fromRow, fromCol, toRow, toCol) { var piece = board[fromRow][fromCol].piece; var capturedPiece = board[toRow][toCol].piece; // Prevent capturing the king if (capturedPiece && capturedPiece.pieceType === 'king') { // Invalid move: cannot capture king, revert and return // Return piece to original position if dragged if (draggedPiece) { game.removeChild(draggedPiece); board[fromRow][fromCol].setPiece(draggedPiece); } clearHighlights(); draggedPiece = null; selectedSquare = null; possibleMoves = []; return; } // Calculate target position var targetX = BOARD_START_X + toCol * SQUARE_SIZE + SQUARE_SIZE / 2; var targetY = BOARD_START_Y + toRow * SQUARE_SIZE + SQUARE_SIZE / 2; // Check if this is an AI move (piece is black and not being dragged) var isAIMove = piece.pieceColor === 'black' && !draggedPiece; if (isAIMove) { // For AI moves, animate the piece movement // First, bring piece to game level for animation var currentSquare = board[fromRow][fromCol]; var currentGlobalPos = currentSquare.toGlobal(piece.position); currentSquare.removeChild(piece); game.addChild(piece); piece.x = currentGlobalPos.x; piece.y = currentGlobalPos.y; // Remove piece from old position on board board[fromRow][fromCol].setPiece(null); // Handle captured piece animation if there's a capture if (capturedPiece) { // Remove captured piece from board immediately board[toRow][toCol].setPiece(null); // Animate captured piece disappearing tween(capturedPiece, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { // Destroy the captured piece capturedPiece.destroy(); } }); } // Set piece in new position but don't add to square yet board[toRow][toCol].piece = piece; piece.updateBoardPosition(toRow, toCol); // Animate piece to target position tween(piece, { x: targetX, y: targetY }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { // Move piece from game to target square game.removeChild(piece); board[toRow][toCol].setPiece(piece); // Play sound after animation if (capturedPiece) { LK.getSound('captureSound').play(); } else { LK.getSound('moveSound').play(); } // Check for pawn promotion if (piece.pieceType === 'pawn') { if (piece.pieceColor === 'white' && toRow === 0 || piece.pieceColor === 'black' && toRow === 7) { // Promote to queen board[toRow][toCol].setPiece(null); var promotedQueen = new ChessPiece('queen', piece.pieceColor, toRow, toCol); board[toRow][toCol].setPiece(promotedQueen); } } // Switch turns currentPlayer = currentPlayer === 'white' ? 'black' : 'white'; // Reset AI move flag when switching turns if (currentPlayer === 'black') { aiHasMoved = false; } // Check for game end conditions if (isCheckmate(currentPlayer)) { if (currentPlayer === 'white') { LK.showGameOver(); } else { LK.showYouWin(); } gameState = 'gameOver'; } else if (isStalemate(currentPlayer)) { LK.showGameOver(); // Show as draw gameState = 'gameOver'; } } }); } else { // For player moves, animate the piece smoothly to target position // Remove piece from old position board[fromRow][fromCol].setPiece(null); // Set piece in new position but don't add to square yet board[toRow][toCol].piece = piece; piece.updateBoardPosition(toRow, toCol); // Add capture animation if there's a captured piece if (capturedPiece) { // Scale down the captured piece before removing tween(capturedPiece, { scaleX: 0, scaleY: 0, alpha: 0 }, { duration: 200, easing: tween.easeIn, onFinish: function onFinish() { // Captured piece animation complete } }); } // Animate piece to target position tween(piece, { x: targetX, y: targetY }, { duration: 250, easing: tween.easeOut, onFinish: function onFinish() { // Move piece from game to target square game.removeChild(piece); board[toRow][toCol].setPiece(piece); // Play sound after animation if (capturedPiece) { LK.getSound('captureSound').play(); } else { LK.getSound('moveSound').play(); } // Check for pawn promotion if (piece.pieceType === 'pawn') { if (piece.pieceColor === 'white' && toRow === 0 || piece.pieceColor === 'black' && toRow === 7) { // Promote to queen board[toRow][toCol].setPiece(null); var promotedQueen = new ChessPiece('queen', piece.pieceColor, toRow, toCol); board[toRow][toCol].setPiece(promotedQueen); } } // Switch turns currentPlayer = currentPlayer === 'white' ? 'black' : 'white'; // Reset AI move flag when switching turns if (currentPlayer === 'black') { aiHasMoved = false; } // Check for game end conditions if (isCheckmate(currentPlayer)) { if (currentPlayer === 'white') { LK.showGameOver(); } else { LK.showYouWin(); } gameState = 'gameOver'; } else if (isStalemate(currentPlayer)) { LK.showGameOver(); // Show as draw gameState = 'gameOver'; } } }); } } // Check if a king is in check function isInCheck(color) { // Find king position var kingPos = null; for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var piece = board[row][col].piece; if (piece && piece.pieceType === 'king' && piece.pieceColor === color) { kingPos = { row: row, col: col }; break; } } if (kingPos) break; } if (!kingPos) return false; // No king found // Check if any enemy piece can attack the king for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var piece = board[row][col].piece; if (piece && piece.pieceColor !== color) { var moves = getRawMoves(piece, row, col); for (var i = 0; i < moves.length; i++) { if (moves[i].row === kingPos.row && moves[i].col === kingPos.col) { return true; // King is under attack } } } } } return false; // King is safe } // Simple checkmate detection - king must be in check AND have no legal moves function isCheckmate(color) { // First check if king is in check if (!isInCheck(color)) { return false; // Not checkmate if king is not in check } // Find king var kingPos = null; for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var piece = board[row][col].piece; if (piece && piece.pieceType === 'king' && piece.pieceColor === color) { kingPos = { row: row, col: col }; break; } } if (kingPos) break; } if (!kingPos) return true; // No king found // Check if any piece can make a legal move for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var piece = board[row][col].piece; if (piece && piece.pieceColor === color) { var moves = getLegalMoves(piece, row, col); if (moves.length > 0) { return false; // Found a legal move } } } } return true; // No legal moves found and king is in check } // Simple stalemate detection - king is NOT in check but has no legal moves function isStalemate(color) { // First check if king is in check if (isInCheck(color)) { return false; // Not stalemate if king is in check } // Check if any piece can make a legal move for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var piece = board[row][col].piece; if (piece && piece.pieceColor === color) { var moves = getLegalMoves(piece, row, col); if (moves.length > 0) { return false; // Found a legal move } } } } return true; // No legal moves found but king is not in check } // AI move selection based on difficulty function getAIMove() { var allMoves = []; // Get all possible moves for AI (black pieces) for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var piece = board[row][col].piece; if (piece && piece.pieceColor === 'black') { var moves = getLegalMoves(piece, row, col); for (var m = 0; m < moves.length; m++) { // Prevent AI from selecting a move that would capture the king var target = board[moves[m].row][moves[m].col].piece; if (target && target.pieceType === 'king') { continue; } allMoves.push({ fromRow: row, fromCol: col, toRow: moves[m].row, toCol: moves[m].col, piece: piece }); } } } } if (allMoves.length === 0) return null; if (selectedDifficulty === 'easy') { // Random move return allMoves[Math.floor(Math.random() * allMoves.length)]; } else if (selectedDifficulty === 'medium') { // Prefer captures var captures = []; for (var i = 0; i < allMoves.length; i++) { var move = allMoves[i]; if (board[move.toRow][move.toCol].piece) { captures.push(move); } } if (captures.length > 0) { return captures[Math.floor(Math.random() * captures.length)]; } return allMoves[Math.floor(Math.random() * allMoves.length)]; } else { // Hard: prefer captures, then center moves var captures = []; var centerMoves = []; for (var i = 0; i < allMoves.length; i++) { var move = allMoves[i]; if (board[move.toRow][move.toCol].piece) { captures.push(move); } else if (move.toRow >= 3 && move.toRow <= 4 && move.toCol >= 3 && move.toCol <= 4) { centerMoves.push(move); } } if (captures.length > 0) { return captures[Math.floor(Math.random() * captures.length)]; } if (centerMoves.length > 0) { return centerMoves[Math.floor(Math.random() * centerMoves.length)]; } return allMoves[Math.floor(Math.random() * allMoves.length)]; } } // Get board position from screen coordinates function getBoardPosition(x, y) { var col = Math.floor((x - BOARD_START_X) / SQUARE_SIZE); var row = Math.floor((y - BOARD_START_Y) / SQUARE_SIZE); if (row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE) { return { row: row, col: col }; } return null; } // Handle mouse/touch down game.down = function (x, y, obj) { if (gameState !== 'playing' || currentPlayer !== 'white') return; var pos = getBoardPosition(x, y); if (!pos) return; var square = board[pos.row][pos.col]; var piece = square.piece; if (piece && piece.pieceColor === 'white') { // Start dragging draggedPiece = piece; // Set drag offset to zero so piece stays at click position dragOffset.x = 0; dragOffset.y = 0; // Clear previous highlights clearHighlights(); // Highlight possible moves possibleMoves = getLegalMoves(piece, pos.row, pos.col); highlightMoves(possibleMoves); selectedSquare = { row: pos.row, col: pos.col }; // Bring piece to front but keep it at current position var tempParent = piece.parent; var currentGlobalPos = tempParent.toGlobal(piece.position); tempParent.removeChild(piece); game.addChild(piece); piece.x = currentGlobalPos.x; piece.y = currentGlobalPos.y; // Add selection animation tween(piece, { scaleX: 1.1, scaleY: 1.1 }, { duration: 150, easing: tween.easeOut }); } }; // Handle mouse/touch move game.move = function (x, y, obj) { if (draggedPiece) { draggedPiece.x = x; draggedPiece.y = y; } }; // Handle mouse/touch up game.up = function (x, y, obj) { if (!draggedPiece || gameState !== 'playing') return; var pos = getBoardPosition(x, y); var validMove = false; if (pos && selectedSquare) { // Check if this is a valid move for (var i = 0; i < possibleMoves.length; i++) { if (possibleMoves[i].row === pos.row && possibleMoves[i].col === pos.col) { validMove = true; break; } } if (validMove) { // Prevent player from capturing the king var targetPiece = board[pos.row][pos.col].piece; if (targetPiece && targetPiece.pieceType === 'king') { // Invalid move: cannot capture king, revert and return game.removeChild(draggedPiece); board[selectedSquare.row][selectedSquare.col].setPiece(draggedPiece); clearHighlights(); draggedPiece = null; selectedSquare = null; possibleMoves = []; return; } // Make the move makeMove(selectedSquare.row, selectedSquare.col, pos.row, pos.col); } } if (!validMove && selectedSquare) { // Return piece to original position with animation var originalSquare = board[selectedSquare.row][selectedSquare.col]; var originalX = BOARD_START_X + selectedSquare.col * SQUARE_SIZE + SQUARE_SIZE / 2; var originalY = BOARD_START_Y + selectedSquare.row * SQUARE_SIZE + SQUARE_SIZE / 2; // Reset scale and animate back to original position tween(draggedPiece, { x: originalX, y: originalY, scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { game.removeChild(draggedPiece); originalSquare.setPiece(draggedPiece); } }); } else { // Reset scale for valid moves if (draggedPiece) { tween(draggedPiece, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.easeOut }); } } // Clean up clearHighlights(); draggedPiece = null; selectedSquare = null; possibleMoves = []; }; // Game update loop game.update = function () { if (gameState === 'playing' && currentPlayer === 'black' && !draggedPiece && !aiHasMoved) { // AI turn - only if player is not currently dragging a piece and AI hasn't moved yet if (LK.ticks % 60 === 0) { // Wait 1 second before AI move aiHasMoved = true; // Set flag immediately to prevent multiple moves LK.setTimeout(function () { var aiMove = getAIMove(); if (aiMove) { makeMove(aiMove.fromRow, aiMove.fromCol, aiMove.toRow, aiMove.toCol); } }, 1000); } } }; // Initialize the game if (gameState === 'difficulty') { initializeDifficultySelection(); }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ChessPiece = Container.expand(function (type, color, row, col) {
var self = Container.call(this);
self.pieceType = type;
self.pieceColor = color;
self.boardRow = row;
self.boardCol = col;
self.hasMoved = false;
var assetId = color + type.charAt(0).toUpperCase() + type.slice(1);
var pieceGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.updateBoardPosition = function (newRow, newCol) {
self.boardRow = newRow;
self.boardCol = newCol;
self.hasMoved = true;
};
return self;
});
var ChessSquare = Container.expand(function (row, col) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.piece = null;
self.isHighlighted = false;
var isLight = (row + col) % 2 === 0;
var squareGraphics = self.attachAsset(isLight ? 'lightSquare' : 'darkSquare', {
anchorX: 0.5,
anchorY: 0.5
});
self.highlight = function () {
if (!self.isHighlighted) {
var highlight = LK.getAsset('highlightSquare', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
});
self.addChild(highlight);
self.isHighlighted = true;
self.highlightGraphics = highlight;
// Animate highlight appearance
tween(highlight, {
alpha: 0.5,
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut
});
}
};
self.removeHighlight = function () {
if (self.isHighlighted && self.highlightGraphics) {
var highlightToRemove = self.highlightGraphics;
self.isHighlighted = false;
self.highlightGraphics = null;
// Animate highlight disappearance
tween(highlightToRemove, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 150,
easing: tween.easeIn,
onFinish: function onFinish() {
self.removeChild(highlightToRemove);
}
});
}
};
self.setPiece = function (piece) {
if (self.piece) {
self.removeChild(self.piece);
}
self.piece = piece;
if (piece) {
self.addChild(piece);
piece.x = 0;
piece.y = 0;
}
};
return self;
});
var DifficultyButton = Container.expand(function (text, difficulty) {
var self = Container.call(this);
self.difficulty = difficulty;
var buttonBg = self.attachAsset('difficultyButton', {
anchorX: 0.5,
anchorY: 0.5
});
var buttonText = new Text2(text, {
size: 60,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
self.addChild(buttonText);
self.down = function (x, y, obj) {
selectedDifficulty = self.difficulty;
startGame();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8b4513
});
/****
* Game Code
****/
// Game state variables
// Chess pieces - white pieces
// Chess pieces - black pieces
// Board squares
// UI elements
// Sound effects
var gameState = 'difficulty'; // 'difficulty', 'playing', 'gameOver'
var selectedDifficulty = 'medium';
var currentPlayer = 'white';
var board = [];
var selectedSquare = null;
var possibleMoves = [];
var difficultyButtons = [];
var draggedPiece = null;
var dragOffset = {
x: 0,
y: 0
};
var aiHasMoved = false;
// Board constants
var BOARD_SIZE = 8;
var SQUARE_SIZE = 230;
var BOARD_START_X = 2048 / 2 - BOARD_SIZE * SQUARE_SIZE / 2;
var BOARD_START_Y = 2732 / 2 - BOARD_SIZE * SQUARE_SIZE / 2;
// Initialize difficulty selection
function initializeDifficultySelection() {
var easyButton = new DifficultyButton('EASY', 'easy');
easyButton.x = 2048 / 2;
easyButton.y = 2732 / 2 - 200;
game.addChild(easyButton);
difficultyButtons.push(easyButton);
var mediumButton = new DifficultyButton('MEDIUM', 'medium');
mediumButton.x = 2048 / 2;
mediumButton.y = 2732 / 2;
game.addChild(mediumButton);
difficultyButtons.push(mediumButton);
var hardButton = new DifficultyButton('HARD', 'hard');
hardButton.x = 2048 / 2;
hardButton.y = 2732 / 2 + 200;
game.addChild(hardButton);
difficultyButtons.push(hardButton);
var titleText = new Text2('Select Difficulty', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 2048 / 2;
titleText.y = 2732 / 2 - 400;
game.addChild(titleText);
}
// Start the game after difficulty selection
function startGame() {
// Remove difficulty buttons
for (var i = 0; i < difficultyButtons.length; i++) {
game.removeChild(difficultyButtons[i]);
}
difficultyButtons = [];
// Remove title
for (var j = game.children.length - 1; j >= 0; j--) {
var child = game.children[j];
if (child instanceof Text2) {
game.removeChild(child);
}
}
gameState = 'playing';
initializeBoard();
setupInitialPieces();
}
// Initialize the chess board
function initializeBoard() {
board = [];
for (var row = 0; row < BOARD_SIZE; row++) {
board[row] = [];
for (var col = 0; col < BOARD_SIZE; col++) {
var square = new ChessSquare(row, col);
square.x = BOARD_START_X + col * SQUARE_SIZE + SQUARE_SIZE / 2;
square.y = BOARD_START_Y + row * SQUARE_SIZE + SQUARE_SIZE / 2;
game.addChild(square);
board[row][col] = square;
}
}
}
// Setup initial piece positions
function setupInitialPieces() {
var pieceOrder = ['rook', 'knight', 'bishop', 'queen', 'king', 'bishop', 'knight', 'rook'];
// Black pieces (top of board)
for (var col = 0; col < 8; col++) {
var blackPiece = new ChessPiece(pieceOrder[col], 'black', 0, col);
board[0][col].setPiece(blackPiece);
var blackPawn = new ChessPiece('pawn', 'black', 1, col);
board[1][col].setPiece(blackPawn);
}
// White pieces (bottom of board)
for (var col = 0; col < 8; col++) {
var whitePawn = new ChessPiece('pawn', 'white', 6, col);
board[6][col].setPiece(whitePawn);
var whitePiece = new ChessPiece(pieceOrder[col], 'white', 7, col);
board[7][col].setPiece(whitePiece);
}
}
// Get legal moves for a piece
function getLegalMoves(piece, fromRow, fromCol) {
var moves = getRawMoves(piece, fromRow, fromCol);
var type = piece.pieceType;
var color = piece.pieceColor;
if (type === 'pawn') {
var direction = color === 'white' ? -1 : 1;
var startRow = color === 'white' ? 6 : 1;
// Forward move
if (isValidPosition(fromRow + direction, fromCol) && !board[fromRow + direction][fromCol].piece) {
moves.push({
row: fromRow + direction,
col: fromCol
});
// Two squares forward from starting position
if (fromRow === startRow && !board[fromRow + 2 * direction][fromCol].piece) {
moves.push({
row: fromRow + 2 * direction,
col: fromCol
});
}
}
// Diagonal captures
for (var dc = -1; dc <= 1; dc += 2) {
if (isValidPosition(fromRow + direction, fromCol + dc)) {
var targetPiece = board[fromRow + direction][fromCol + dc].piece;
if (targetPiece && targetPiece.pieceColor !== color) {
moves.push({
row: fromRow + direction,
col: fromCol + dc
});
}
}
}
} else if (type === 'rook') {
var directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];
for (var d = 0; d < directions.length; d++) {
var dr = directions[d][0];
var dc = directions[d][1];
for (var i = 1; i < 8; i++) {
var newRow = fromRow + dr * i;
var newCol = fromCol + dc * i;
if (!isValidPosition(newRow, newCol)) break;
var targetPiece = board[newRow][newCol].piece;
if (targetPiece) {
if (targetPiece.pieceColor !== color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
} else {
moves.push({
row: newRow,
col: newCol
});
}
}
}
} else if (type === 'bishop') {
var directions = [[1, 1], [1, -1], [-1, 1], [-1, -1]];
for (var d = 0; d < directions.length; d++) {
var dr = directions[d][0];
var dc = directions[d][1];
for (var i = 1; i < 8; i++) {
var newRow = fromRow + dr * i;
var newCol = fromCol + dc * i;
if (!isValidPosition(newRow, newCol)) break;
var targetPiece = board[newRow][newCol].piece;
if (targetPiece) {
if (targetPiece.pieceColor !== color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
} else {
moves.push({
row: newRow,
col: newCol
});
}
}
}
} else if (type === 'queen') {
var directions = [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]];
for (var d = 0; d < directions.length; d++) {
var dr = directions[d][0];
var dc = directions[d][1];
for (var i = 1; i < 8; i++) {
var newRow = fromRow + dr * i;
var newCol = fromCol + dc * i;
if (!isValidPosition(newRow, newCol)) break;
var targetPiece = board[newRow][newCol].piece;
if (targetPiece) {
if (targetPiece.pieceColor !== color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
} else {
moves.push({
row: newRow,
col: newCol
});
}
}
}
} else if (type === 'king') {
var directions = [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]];
for (var d = 0; d < directions.length; d++) {
var newRow = fromRow + directions[d][0];
var newCol = fromCol + directions[d][1];
if (isValidPosition(newRow, newCol)) {
var targetPiece = board[newRow][newCol].piece;
if (!targetPiece || targetPiece.pieceColor !== color) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
} else if (type === 'knight') {
var knightMoves = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]];
for (var m = 0; m < knightMoves.length; m++) {
var newRow = fromRow + knightMoves[m][0];
var newCol = fromCol + knightMoves[m][1];
if (isValidPosition(newRow, newCol)) {
var targetPiece = board[newRow][newCol].piece;
if (!targetPiece || targetPiece.pieceColor !== color) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
}
// Get all pseudo-legal moves for a piece (ignores pins and king safety)
function getRawMoves(piece, fromRow, fromCol) {
var moves = [];
var type = piece.pieceType;
var color = piece.pieceColor;
if (type === 'pawn') {
var direction = color === 'white' ? -1 : 1;
// Move forward 1 square
if (isValidPosition(fromRow + direction, fromCol)) {
moves.push({
row: fromRow + direction,
col: fromCol
});
// Move forward 2 squares from starting position
var startRow = color === 'white' ? 6 : 1;
if (fromRow === startRow && isValidPosition(fromRow + 2 * direction, fromCol)) {
moves.push({
row: fromRow + 2 * direction,
col: fromCol
});
}
}
// Pawn captures diagonally
for (var dc = -1; dc <= 1; dc += 2) {
if (isValidPosition(fromRow + direction, fromCol + dc)) {
moves.push({
row: fromRow + direction,
col: fromCol + dc
});
}
}
} else if (type === 'rook') {
var directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];
for (var d = 0; d < directions.length; d++) {
var dr = directions[d][0];
var dc = directions[d][1];
for (var i = 1; i < 8; i++) {
var newRow = fromRow + dr * i;
var newCol = fromCol + dc * i;
if (!isValidPosition(newRow, newCol)) break;
moves.push({
row: newRow,
col: newCol
});
var targetPiece = board[newRow][newCol].piece;
if (targetPiece) {
break;
}
}
}
} else if (type === 'bishop') {
var directions = [[1, 1], [1, -1], [-1, 1], [-1, -1]];
for (var d = 0; d < directions.length; d++) {
var dr = directions[d][0];
var dc = directions[d][1];
for (var i = 1; i < 8; i++) {
var newRow = fromRow + dr * i;
var newCol = fromCol + dc * i;
if (!isValidPosition(newRow, newCol)) break;
moves.push({
row: newRow,
col: newCol
});
var targetPiece = board[newRow][newCol].piece;
if (targetPiece) {
break;
}
}
}
} else if (type === 'queen') {
var directions = [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]];
for (var d = 0; d < directions.length; d++) {
var dr = directions[d][0];
var dc = directions[d][1];
for (var i = 1; i < 8; i++) {
var newRow = fromRow + dr * i;
var newCol = fromCol + dc * i;
if (!isValidPosition(newRow, newCol)) break;
moves.push({
row: newRow,
col: newCol
});
var targetPiece = board[newRow][newCol].piece;
if (targetPiece) {
break;
}
}
}
} else if (type === 'king') {
var directions = [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]];
for (var d = 0; d < directions.length; d++) {
var newRow = fromRow + directions[d][0];
var newCol = fromCol + directions[d][1];
if (isValidPosition(newRow, newCol)) {
moves.push({
row: newRow,
col: newCol
});
}
}
} else if (type === 'knight') {
var knightMoves = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]];
for (var m = 0; m < knightMoves.length; m++) {
var newRow = fromRow + knightMoves[m][0];
var newCol = fromCol + knightMoves[m][1];
if (isValidPosition(newRow, newCol)) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
return moves;
}
// Filter out moves that would leave own king in check (pin rule)
var legalMoves = [];
var _loop = function _loop() {
move = moves[i]; // Simulate the move
fromPiece = board[fromRow][fromCol].piece;
toPiece = board[move.row][move.col].piece; // Temporarily move the piece
board[fromRow][fromCol].setPiece(null);
board[move.row][move.col].setPiece(fromPiece);
kingSafe = true; // Find own king position after move
kingRow = -1, kingCol = -1;
for (r = 0; r < BOARD_SIZE; r++) {
for (c = 0; c < BOARD_SIZE; c++) {
p = board[r][c].piece;
if (p && p.pieceType === 'king' && p.pieceColor === color) {
kingRow = r;
kingCol = c;
}
}
}
// If this piece is the king, update kingRow/kingCol to new position
if (type === 'king') {
kingRow = move.row;
kingCol = move.col;
}
// Check if any enemy piece can attack the king after this move
for (r = 0; r < BOARD_SIZE; r++) {
for (c = 0; c < BOARD_SIZE; c++) {
enemy = board[r][c].piece;
if (enemy && enemy.pieceColor !== color) {
enemyMoves = getRawMoves(enemy, r, c);
for (j = 0; j < enemyMoves.length; j++) {
if (enemyMoves[j].row === kingRow && enemyMoves[j].col === kingCol) {
kingSafe = false;
break;
}
}
}
if (!kingSafe) break;
}
if (!kingSafe) break;
}
// Undo the move
board[move.row][move.col].setPiece(toPiece);
board[fromRow][fromCol].setPiece(fromPiece);
if (kingSafe) {
legalMoves.push(move);
}
},
move,
fromPiece,
toPiece,
kingSafe,
kingRow,
kingCol,
r,
c,
p,
r,
c,
enemy,
enemyMoves,
j;
for (var i = 0; i < moves.length; i++) {
_loop();
}
return legalMoves;
}
// Check if position is valid on board
function isValidPosition(row, col) {
return row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE;
}
// Highlight possible moves
function highlightMoves(moves) {
for (var i = 0; i < moves.length; i++) {
board[moves[i].row][moves[i].col].highlight();
}
}
// Clear all highlights
function clearHighlights() {
for (var row = 0; row < BOARD_SIZE; row++) {
for (var col = 0; col < BOARD_SIZE; col++) {
board[row][col].removeHighlight();
}
}
}
// Make a move
function makeMove(fromRow, fromCol, toRow, toCol) {
var piece = board[fromRow][fromCol].piece;
var capturedPiece = board[toRow][toCol].piece;
// Prevent capturing the king
if (capturedPiece && capturedPiece.pieceType === 'king') {
// Invalid move: cannot capture king, revert and return
// Return piece to original position if dragged
if (draggedPiece) {
game.removeChild(draggedPiece);
board[fromRow][fromCol].setPiece(draggedPiece);
}
clearHighlights();
draggedPiece = null;
selectedSquare = null;
possibleMoves = [];
return;
}
// Calculate target position
var targetX = BOARD_START_X + toCol * SQUARE_SIZE + SQUARE_SIZE / 2;
var targetY = BOARD_START_Y + toRow * SQUARE_SIZE + SQUARE_SIZE / 2;
// Check if this is an AI move (piece is black and not being dragged)
var isAIMove = piece.pieceColor === 'black' && !draggedPiece;
if (isAIMove) {
// For AI moves, animate the piece movement
// First, bring piece to game level for animation
var currentSquare = board[fromRow][fromCol];
var currentGlobalPos = currentSquare.toGlobal(piece.position);
currentSquare.removeChild(piece);
game.addChild(piece);
piece.x = currentGlobalPos.x;
piece.y = currentGlobalPos.y;
// Remove piece from old position on board
board[fromRow][fromCol].setPiece(null);
// Handle captured piece animation if there's a capture
if (capturedPiece) {
// Remove captured piece from board immediately
board[toRow][toCol].setPiece(null);
// Animate captured piece disappearing
tween(capturedPiece, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
// Destroy the captured piece
capturedPiece.destroy();
}
});
}
// Set piece in new position but don't add to square yet
board[toRow][toCol].piece = piece;
piece.updateBoardPosition(toRow, toCol);
// Animate piece to target position
tween(piece, {
x: targetX,
y: targetY
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Move piece from game to target square
game.removeChild(piece);
board[toRow][toCol].setPiece(piece);
// Play sound after animation
if (capturedPiece) {
LK.getSound('captureSound').play();
} else {
LK.getSound('moveSound').play();
}
// Check for pawn promotion
if (piece.pieceType === 'pawn') {
if (piece.pieceColor === 'white' && toRow === 0 || piece.pieceColor === 'black' && toRow === 7) {
// Promote to queen
board[toRow][toCol].setPiece(null);
var promotedQueen = new ChessPiece('queen', piece.pieceColor, toRow, toCol);
board[toRow][toCol].setPiece(promotedQueen);
}
}
// Switch turns
currentPlayer = currentPlayer === 'white' ? 'black' : 'white';
// Reset AI move flag when switching turns
if (currentPlayer === 'black') {
aiHasMoved = false;
}
// Check for game end conditions
if (isCheckmate(currentPlayer)) {
if (currentPlayer === 'white') {
LK.showGameOver();
} else {
LK.showYouWin();
}
gameState = 'gameOver';
} else if (isStalemate(currentPlayer)) {
LK.showGameOver(); // Show as draw
gameState = 'gameOver';
}
}
});
} else {
// For player moves, animate the piece smoothly to target position
// Remove piece from old position
board[fromRow][fromCol].setPiece(null);
// Set piece in new position but don't add to square yet
board[toRow][toCol].piece = piece;
piece.updateBoardPosition(toRow, toCol);
// Add capture animation if there's a captured piece
if (capturedPiece) {
// Scale down the captured piece before removing
tween(capturedPiece, {
scaleX: 0,
scaleY: 0,
alpha: 0
}, {
duration: 200,
easing: tween.easeIn,
onFinish: function onFinish() {
// Captured piece animation complete
}
});
}
// Animate piece to target position
tween(piece, {
x: targetX,
y: targetY
}, {
duration: 250,
easing: tween.easeOut,
onFinish: function onFinish() {
// Move piece from game to target square
game.removeChild(piece);
board[toRow][toCol].setPiece(piece);
// Play sound after animation
if (capturedPiece) {
LK.getSound('captureSound').play();
} else {
LK.getSound('moveSound').play();
}
// Check for pawn promotion
if (piece.pieceType === 'pawn') {
if (piece.pieceColor === 'white' && toRow === 0 || piece.pieceColor === 'black' && toRow === 7) {
// Promote to queen
board[toRow][toCol].setPiece(null);
var promotedQueen = new ChessPiece('queen', piece.pieceColor, toRow, toCol);
board[toRow][toCol].setPiece(promotedQueen);
}
}
// Switch turns
currentPlayer = currentPlayer === 'white' ? 'black' : 'white';
// Reset AI move flag when switching turns
if (currentPlayer === 'black') {
aiHasMoved = false;
}
// Check for game end conditions
if (isCheckmate(currentPlayer)) {
if (currentPlayer === 'white') {
LK.showGameOver();
} else {
LK.showYouWin();
}
gameState = 'gameOver';
} else if (isStalemate(currentPlayer)) {
LK.showGameOver(); // Show as draw
gameState = 'gameOver';
}
}
});
}
}
// Check if a king is in check
function isInCheck(color) {
// Find king position
var kingPos = null;
for (var row = 0; row < BOARD_SIZE; row++) {
for (var col = 0; col < BOARD_SIZE; col++) {
var piece = board[row][col].piece;
if (piece && piece.pieceType === 'king' && piece.pieceColor === color) {
kingPos = {
row: row,
col: col
};
break;
}
}
if (kingPos) break;
}
if (!kingPos) return false; // No king found
// Check if any enemy piece can attack the king
for (var row = 0; row < BOARD_SIZE; row++) {
for (var col = 0; col < BOARD_SIZE; col++) {
var piece = board[row][col].piece;
if (piece && piece.pieceColor !== color) {
var moves = getRawMoves(piece, row, col);
for (var i = 0; i < moves.length; i++) {
if (moves[i].row === kingPos.row && moves[i].col === kingPos.col) {
return true; // King is under attack
}
}
}
}
}
return false; // King is safe
}
// Simple checkmate detection - king must be in check AND have no legal moves
function isCheckmate(color) {
// First check if king is in check
if (!isInCheck(color)) {
return false; // Not checkmate if king is not in check
}
// Find king
var kingPos = null;
for (var row = 0; row < BOARD_SIZE; row++) {
for (var col = 0; col < BOARD_SIZE; col++) {
var piece = board[row][col].piece;
if (piece && piece.pieceType === 'king' && piece.pieceColor === color) {
kingPos = {
row: row,
col: col
};
break;
}
}
if (kingPos) break;
}
if (!kingPos) return true; // No king found
// Check if any piece can make a legal move
for (var row = 0; row < BOARD_SIZE; row++) {
for (var col = 0; col < BOARD_SIZE; col++) {
var piece = board[row][col].piece;
if (piece && piece.pieceColor === color) {
var moves = getLegalMoves(piece, row, col);
if (moves.length > 0) {
return false; // Found a legal move
}
}
}
}
return true; // No legal moves found and king is in check
}
// Simple stalemate detection - king is NOT in check but has no legal moves
function isStalemate(color) {
// First check if king is in check
if (isInCheck(color)) {
return false; // Not stalemate if king is in check
}
// Check if any piece can make a legal move
for (var row = 0; row < BOARD_SIZE; row++) {
for (var col = 0; col < BOARD_SIZE; col++) {
var piece = board[row][col].piece;
if (piece && piece.pieceColor === color) {
var moves = getLegalMoves(piece, row, col);
if (moves.length > 0) {
return false; // Found a legal move
}
}
}
}
return true; // No legal moves found but king is not in check
}
// AI move selection based on difficulty
function getAIMove() {
var allMoves = [];
// Get all possible moves for AI (black pieces)
for (var row = 0; row < BOARD_SIZE; row++) {
for (var col = 0; col < BOARD_SIZE; col++) {
var piece = board[row][col].piece;
if (piece && piece.pieceColor === 'black') {
var moves = getLegalMoves(piece, row, col);
for (var m = 0; m < moves.length; m++) {
// Prevent AI from selecting a move that would capture the king
var target = board[moves[m].row][moves[m].col].piece;
if (target && target.pieceType === 'king') {
continue;
}
allMoves.push({
fromRow: row,
fromCol: col,
toRow: moves[m].row,
toCol: moves[m].col,
piece: piece
});
}
}
}
}
if (allMoves.length === 0) return null;
if (selectedDifficulty === 'easy') {
// Random move
return allMoves[Math.floor(Math.random() * allMoves.length)];
} else if (selectedDifficulty === 'medium') {
// Prefer captures
var captures = [];
for (var i = 0; i < allMoves.length; i++) {
var move = allMoves[i];
if (board[move.toRow][move.toCol].piece) {
captures.push(move);
}
}
if (captures.length > 0) {
return captures[Math.floor(Math.random() * captures.length)];
}
return allMoves[Math.floor(Math.random() * allMoves.length)];
} else {
// Hard: prefer captures, then center moves
var captures = [];
var centerMoves = [];
for (var i = 0; i < allMoves.length; i++) {
var move = allMoves[i];
if (board[move.toRow][move.toCol].piece) {
captures.push(move);
} else if (move.toRow >= 3 && move.toRow <= 4 && move.toCol >= 3 && move.toCol <= 4) {
centerMoves.push(move);
}
}
if (captures.length > 0) {
return captures[Math.floor(Math.random() * captures.length)];
}
if (centerMoves.length > 0) {
return centerMoves[Math.floor(Math.random() * centerMoves.length)];
}
return allMoves[Math.floor(Math.random() * allMoves.length)];
}
}
// Get board position from screen coordinates
function getBoardPosition(x, y) {
var col = Math.floor((x - BOARD_START_X) / SQUARE_SIZE);
var row = Math.floor((y - BOARD_START_Y) / SQUARE_SIZE);
if (row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE) {
return {
row: row,
col: col
};
}
return null;
}
// Handle mouse/touch down
game.down = function (x, y, obj) {
if (gameState !== 'playing' || currentPlayer !== 'white') return;
var pos = getBoardPosition(x, y);
if (!pos) return;
var square = board[pos.row][pos.col];
var piece = square.piece;
if (piece && piece.pieceColor === 'white') {
// Start dragging
draggedPiece = piece;
// Set drag offset to zero so piece stays at click position
dragOffset.x = 0;
dragOffset.y = 0;
// Clear previous highlights
clearHighlights();
// Highlight possible moves
possibleMoves = getLegalMoves(piece, pos.row, pos.col);
highlightMoves(possibleMoves);
selectedSquare = {
row: pos.row,
col: pos.col
};
// Bring piece to front but keep it at current position
var tempParent = piece.parent;
var currentGlobalPos = tempParent.toGlobal(piece.position);
tempParent.removeChild(piece);
game.addChild(piece);
piece.x = currentGlobalPos.x;
piece.y = currentGlobalPos.y;
// Add selection animation
tween(piece, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 150,
easing: tween.easeOut
});
}
};
// Handle mouse/touch move
game.move = function (x, y, obj) {
if (draggedPiece) {
draggedPiece.x = x;
draggedPiece.y = y;
}
};
// Handle mouse/touch up
game.up = function (x, y, obj) {
if (!draggedPiece || gameState !== 'playing') return;
var pos = getBoardPosition(x, y);
var validMove = false;
if (pos && selectedSquare) {
// Check if this is a valid move
for (var i = 0; i < possibleMoves.length; i++) {
if (possibleMoves[i].row === pos.row && possibleMoves[i].col === pos.col) {
validMove = true;
break;
}
}
if (validMove) {
// Prevent player from capturing the king
var targetPiece = board[pos.row][pos.col].piece;
if (targetPiece && targetPiece.pieceType === 'king') {
// Invalid move: cannot capture king, revert and return
game.removeChild(draggedPiece);
board[selectedSquare.row][selectedSquare.col].setPiece(draggedPiece);
clearHighlights();
draggedPiece = null;
selectedSquare = null;
possibleMoves = [];
return;
}
// Make the move
makeMove(selectedSquare.row, selectedSquare.col, pos.row, pos.col);
}
}
if (!validMove && selectedSquare) {
// Return piece to original position with animation
var originalSquare = board[selectedSquare.row][selectedSquare.col];
var originalX = BOARD_START_X + selectedSquare.col * SQUARE_SIZE + SQUARE_SIZE / 2;
var originalY = BOARD_START_Y + selectedSquare.row * SQUARE_SIZE + SQUARE_SIZE / 2;
// Reset scale and animate back to original position
tween(draggedPiece, {
x: originalX,
y: originalY,
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
game.removeChild(draggedPiece);
originalSquare.setPiece(draggedPiece);
}
});
} else {
// Reset scale for valid moves
if (draggedPiece) {
tween(draggedPiece, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
easing: tween.easeOut
});
}
}
// Clean up
clearHighlights();
draggedPiece = null;
selectedSquare = null;
possibleMoves = [];
};
// Game update loop
game.update = function () {
if (gameState === 'playing' && currentPlayer === 'black' && !draggedPiece && !aiHasMoved) {
// AI turn - only if player is not currently dragging a piece and AI hasn't moved yet
if (LK.ticks % 60 === 0) {
// Wait 1 second before AI move
aiHasMoved = true; // Set flag immediately to prevent multiple moves
LK.setTimeout(function () {
var aiMove = getAIMove();
if (aiMove) {
makeMove(aiMove.fromRow, aiMove.fromCol, aiMove.toRow, aiMove.toCol);
}
}, 1000);
}
}
};
// Initialize the game
if (gameState === 'difficulty') {
initializeDifficultySelection();
}
Chess pawn View from above. In-Game asset. 2d. High contrast. No shadows
Chess king view from above. In-Game asset. 2d. High contrast. No shadows
Chess White king view from top. In-Game asset. 2d. High contrast. No shadows
Chess queen white View from above. In-Game asset. 2d. High contrast. No shadows
Chess black bishop. In-Game asset. 2d. High contrast. No shadows
Chess black queen. In-Game asset. 2d. High contrast. No shadows
Chess black knight. In-Game asset. 2d. High contrast. No shadows
Chess rook view from above. In-Game asset. 2d. High contrast. No shadows
Chess bishop white view frome above. In-Game asset. 2d. High contrast. No shadows
Şimdi içini beyaz renkle doldur