User prompt
make the chess bot smarter
User prompt
add coordinates of the squares
User prompt
add a button at the right bottom to restart the game
User prompt
Please fix the bug: 'self.getPieceSymbol is not a function' in or related to this line: 'self.symbol = new Text2(self.getPieceSymbol(), {' Line Number: 109
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'easyBtn.style.fill = "#ffff00";' Line Number: 1276
Code edit (1 edits merged)
Please save this source code
User prompt
Classic Chess Challenge
Initial prompt
chess game
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
aiDifficulty: 1,
gameHistory: []
});
/****
* Classes
****/
var Board = Container.expand(function () {
var self = Container.call(this);
self.tiles = [];
self.tileSize = 256;
self.boardSize = 8 * self.tileSize;
self.highlightLayer = new Container();
self.piecesLayer = new Container();
self.createBoard = function () {
// Create tiles
for (var row = 0; row < 8; row++) {
self.tiles[row] = [];
for (var col = 0; col < 8; col++) {
var isWhite = (row + col) % 2 === 0;
var tile = self.attachAsset(isWhite ? 'whiteTile' : 'blackTile', {
x: col * self.tileSize,
y: row * self.tileSize,
anchorX: 0,
anchorY: 0
});
self.tiles[row][col] = tile;
tile.boardRow = row;
tile.boardCol = col;
}
}
self.addChild(self.highlightLayer);
self.addChild(self.piecesLayer);
};
self.highlightTile = function (row, col, type) {
var highlight = LK.getAsset(type, {
x: col * self.tileSize,
y: row * self.tileSize,
anchorX: 0,
anchorY: 0,
alpha: 0.5
});
self.highlightLayer.addChild(highlight);
return highlight;
};
self.clearHighlights = function () {
while (self.highlightLayer.children.length > 0) {
self.highlightLayer.removeChildAt(0);
}
};
self.getTileAt = function (x, y) {
var col = Math.floor(x / self.tileSize);
var row = Math.floor(y / self.tileSize);
if (row >= 0 && row < 8 && col >= 0 && col < 8) {
return {
row: row,
col: col
};
}
return null;
};
return self;
});
var Piece = Container.expand(function (type, color, row, col) {
var self = Container.call(this);
self.type = type;
self.color = color;
self.row = row;
self.col = col;
self.hasMoved = false;
// Get asset id based on color and type
var assetId = color + type.charAt(0).toUpperCase() + type.slice(1);
self.sprite = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// Add chess piece symbol
self.symbol = new Text2(self.getPieceSymbol(), {
size: 150,
fill: color === 'white' ? "#333333" : "#ffffff"
});
self.symbol.anchor.set(0.5, 0.5);
self.addChild(self.symbol);
self.getPieceSymbol = function () {
switch (self.type) {
case 'king':
return '♚';
case 'queen':
return '♛';
case 'rook':
return '♜';
case 'bishop':
return '♝';
case 'knight':
return '♞';
case 'pawn':
return '♟';
default:
return '';
}
};
self.moveTo = function (row, col, duration) {
self.row = row;
self.col = col;
var newX = col * chessBoard.tileSize + chessBoard.tileSize / 2;
var newY = row * chessBoard.tileSize + chessBoard.tileSize / 2;
if (duration) {
tween(self, {
x: newX,
y: newY
}, {
duration: duration,
easing: tween.easeOutQuad
});
} else {
self.x = newX;
self.y = newY;
}
self.hasMoved = true;
};
self.update = function () {
// For any per-frame updates
};
self.down = function (x, y, obj) {
if (gameState.currentTurn === self.color && !gameState.isAnimating) {
gameState.selectedPiece = self;
chessBoard.clearHighlights();
// Highlight the current piece's tile
self.currentHighlight = chessBoard.highlightTile(self.row, self.col, 'highlightTile');
// Highlight valid moves
var validMoves = getValidMoves(self);
gameState.validMoves = validMoves;
for (var i = 0; i < validMoves.length; i++) {
var move = validMoves[i];
chessBoard.highlightTile(move.row, move.col, 'validMoveTile');
}
}
};
// Place piece at its position
self.x = col * 256 + 128;
self.y = row * 256 + 128;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
// Game state
var gameState = {
currentTurn: 'white',
selectedPiece: null,
validMoves: [],
board: Array(8).fill().map(function () {
return Array(8).fill(null);
}),
isAnimating: false,
lastMove: null,
aiDifficulty: storage.aiDifficulty || 1,
gameMode: 'ai',
// 'ai' or 'twoPlayer'
status: 'playing',
// 'playing', 'check', 'checkmate', 'stalemate'
aiPlayer: 'black'
};
// Create UI
var titleText = new Text2('Chess Challenge', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
LK.gui.top.addChild(titleText);
var turnText = new Text2('White to move', {
size: 50,
fill: 0xFFFFFF
});
turnText.anchor.set(0.5, 0);
turnText.y = 100;
LK.gui.top.addChild(turnText);
var statusText = new Text2('', {
size: 50,
fill: 0xFFFF00
});
statusText.anchor.set(0.5, 0);
statusText.y = 160;
LK.gui.top.addChild(statusText);
// Create and position the chess board
var chessBoard = new Board();
game.addChild(chessBoard);
chessBoard.createBoard();
// Center the board
chessBoard.x = (2048 - chessBoard.boardSize) / 2;
chessBoard.y = (2732 - chessBoard.boardSize) / 2;
// Initialize pieces
function initializeChessBoard() {
// Clear existing pieces
while (chessBoard.piecesLayer.children.length > 0) {
chessBoard.piecesLayer.removeChildAt(0);
}
// Reset game state
gameState.board = Array(8).fill().map(function () {
return Array(8).fill(null);
});
gameState.currentTurn = 'white';
gameState.selectedPiece = null;
gameState.validMoves = [];
gameState.isAnimating = false;
gameState.lastMove = null;
gameState.status = 'playing';
// Update UI
updateTurnText();
// Create pieces
var pieces = [{
type: 'rook',
color: 'black',
row: 0,
col: 0
}, {
type: 'knight',
color: 'black',
row: 0,
col: 1
}, {
type: 'bishop',
color: 'black',
row: 0,
col: 2
}, {
type: 'queen',
color: 'black',
row: 0,
col: 3
}, {
type: 'king',
color: 'black',
row: 0,
col: 4
}, {
type: 'bishop',
color: 'black',
row: 0,
col: 5
}, {
type: 'knight',
color: 'black',
row: 0,
col: 6
}, {
type: 'rook',
color: 'black',
row: 0,
col: 7
}, {
type: 'rook',
color: 'white',
row: 7,
col: 0
}, {
type: 'knight',
color: 'white',
row: 7,
col: 1
}, {
type: 'bishop',
color: 'white',
row: 7,
col: 2
}, {
type: 'queen',
color: 'white',
row: 7,
col: 3
}, {
type: 'king',
color: 'white',
row: 7,
col: 4
}, {
type: 'bishop',
color: 'white',
row: 7,
col: 5
}, {
type: 'knight',
color: 'white',
row: 7,
col: 6
}, {
type: 'rook',
color: 'white',
row: 7,
col: 7
}];
// Add pawns
for (var i = 0; i < 8; i++) {
pieces.push({
type: 'pawn',
color: 'black',
row: 1,
col: i
});
pieces.push({
type: 'pawn',
color: 'white',
row: 6,
col: i
});
}
// Create and position pieces
for (var i = 0; i < pieces.length; i++) {
var p = pieces[i];
var piece = new Piece(p.type, p.color, p.row, p.col);
chessBoard.piecesLayer.addChild(piece);
gameState.board[p.row][p.col] = piece;
}
// Clear highlights
chessBoard.clearHighlights();
}
// Chess move validation
function getValidMoves(piece) {
var moves = [];
if (!piece) return moves;
function addMove(row, col) {
moves.push({
row: row,
col: col
});
}
function isOnBoard(row, col) {
return row >= 0 && row < 8 && col >= 0 && col < 8;
}
function isOccupied(row, col) {
return gameState.board[row][col] !== null;
}
function isEnemyPiece(row, col) {
return isOccupied(row, col) && gameState.board[row][col].color !== piece.color;
}
function isFriendlyPiece(row, col) {
return isOccupied(row, col) && gameState.board[row][col].color === piece.color;
}
var row = piece.row;
var col = piece.col;
switch (piece.type) {
case 'pawn':
var direction = piece.color === 'white' ? -1 : 1;
// Move forward one square
if (isOnBoard(row + direction, col) && !isOccupied(row + direction, col)) {
addMove(row + direction, col);
// Move forward two squares on first move
if (!piece.hasMoved && isOnBoard(row + 2 * direction, col) && !isOccupied(row + 2 * direction, col)) {
addMove(row + 2 * direction, col);
}
}
// Capture diagonally
if (isOnBoard(row + direction, col - 1) && isEnemyPiece(row + direction, col - 1)) {
addMove(row + direction, col - 1);
}
if (isOnBoard(row + direction, col + 1) && isEnemyPiece(row + direction, col + 1)) {
addMove(row + direction, col + 1);
}
// En passant (simplified)
if (gameState.lastMove && gameState.lastMove.piece.type === 'pawn' && gameState.lastMove.fromRow === (piece.color === 'white' ? 1 : 6) && gameState.lastMove.toRow === (piece.color === 'white' ? 3 : 4) && Math.abs(gameState.lastMove.toCol - col) === 1 && row === gameState.lastMove.toRow) {
addMove(row + direction, gameState.lastMove.toCol);
}
break;
case 'rook':
// Horizontal and vertical directions
var directions = [{
dr: -1,
dc: 0
},
// up
{
dr: 1,
dc: 0
},
// down
{
dr: 0,
dc: -1
},
// left
{
dr: 0,
dc: 1
} // right
];
directions.forEach(function (dir) {
var r = row + dir.dr;
var c = col + dir.dc;
while (isOnBoard(r, c)) {
if (isOccupied(r, c)) {
if (isEnemyPiece(r, c)) {
addMove(r, c);
}
break;
}
addMove(r, c);
r += dir.dr;
c += dir.dc;
}
});
break;
case 'knight':
// Knight moves
var knightMoves = [{
dr: -2,
dc: -1
}, {
dr: -2,
dc: 1
}, {
dr: -1,
dc: -2
}, {
dr: -1,
dc: 2
}, {
dr: 1,
dc: -2
}, {
dr: 1,
dc: 2
}, {
dr: 2,
dc: -1
}, {
dr: 2,
dc: 1
}];
knightMoves.forEach(function (move) {
var r = row + move.dr;
var c = col + move.dc;
if (isOnBoard(r, c) && !isFriendlyPiece(r, c)) {
addMove(r, c);
}
});
break;
case 'bishop':
// Diagonal directions
var directions = [{
dr: -1,
dc: -1
},
// up-left
{
dr: -1,
dc: 1
},
// up-right
{
dr: 1,
dc: -1
},
// down-left
{
dr: 1,
dc: 1
} // down-right
];
directions.forEach(function (dir) {
var r = row + dir.dr;
var c = col + dir.dc;
while (isOnBoard(r, c)) {
if (isOccupied(r, c)) {
if (isEnemyPiece(r, c)) {
addMove(r, c);
}
break;
}
addMove(r, c);
r += dir.dr;
c += dir.dc;
}
});
break;
case 'queen':
// Combine rook and bishop moves
var directions = [{
dr: -1,
dc: 0
}, {
dr: 1,
dc: 0
},
// vertical
{
dr: 0,
dc: -1
}, {
dr: 0,
dc: 1
},
// horizontal
{
dr: -1,
dc: -1
}, {
dr: -1,
dc: 1
},
// diagonal
{
dr: 1,
dc: -1
}, {
dr: 1,
dc: 1
} // diagonal
];
directions.forEach(function (dir) {
var r = row + dir.dr;
var c = col + dir.dc;
while (isOnBoard(r, c)) {
if (isOccupied(r, c)) {
if (isEnemyPiece(r, c)) {
addMove(r, c);
}
break;
}
addMove(r, c);
r += dir.dr;
c += dir.dc;
}
});
break;
case 'king':
// King moves (one square in any direction)
var directions = [{
dr: -1,
dc: -1
}, {
dr: -1,
dc: 0
}, {
dr: -1,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 0,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: 1,
dc: 1
}];
directions.forEach(function (dir) {
var r = row + dir.dr;
var c = col + dir.dc;
if (isOnBoard(r, c) && !isFriendlyPiece(r, c)) {
addMove(r, c);
}
});
// Castling
if (!piece.hasMoved) {
// Kingside castling
if (!isOccupied(row, col + 1) && !isOccupied(row, col + 2) && isOccupied(row, col + 3) && !gameState.board[row][col + 3].hasMoved && gameState.board[row][col + 3].type === 'rook') {
addMove(row, col + 2);
}
// Queenside castling
if (!isOccupied(row, col - 1) && !isOccupied(row, col - 2) && !isOccupied(row, col - 3) && isOccupied(row, col - 4) && !gameState.board[row][col - 4].hasMoved && gameState.board[row][col - 4].type === 'rook') {
addMove(row, col - 2);
}
}
break;
}
// Filter out moves that would put the king in check
var validMoves = [];
for (var i = 0; i < moves.length; i++) {
var move = moves[i];
// Make a temporary move
var tempPiece = gameState.board[move.row][move.col];
gameState.board[move.row][move.col] = piece;
gameState.board[row][col] = null;
// Check if the move puts/leaves the king in check
var inCheck = isKingInCheck(piece.color);
// Undo the move
gameState.board[row][col] = piece;
gameState.board[move.row][move.col] = tempPiece;
if (!inCheck) {
validMoves.push(move);
}
}
return validMoves;
}
function isKingInCheck(color) {
// Find the king
var kingRow = -1;
var kingCol = -1;
for (var r = 0; r < 8; r++) {
for (var c = 0; c < 8; c++) {
var piece = gameState.board[r][c];
if (piece && piece.type === 'king' && piece.color === color) {
kingRow = r;
kingCol = c;
break;
}
}
if (kingRow !== -1) break;
}
// Check if any enemy piece can capture the king
for (var r = 0; r < 8; r++) {
for (var c = 0; c < 8; c++) {
var piece = gameState.board[r][c];
if (piece && piece.color !== color) {
// Get the enemy's valid moves (ignoring check)
var moves = getBasicMoves(piece);
// See if any of the moves can capture the king
for (var i = 0; i < moves.length; i++) {
if (moves[i].row === kingRow && moves[i].col === kingCol) {
return true;
}
}
}
}
}
return false;
}
function getBasicMoves(piece) {
var moves = [];
if (!piece) return moves;
function addMove(row, col) {
moves.push({
row: row,
col: col
});
}
function isOnBoard(row, col) {
return row >= 0 && row < 8 && col >= 0 && col < 8;
}
function isOccupied(row, col) {
return gameState.board[row][col] !== null;
}
function isEnemyPiece(row, col) {
return isOccupied(row, col) && gameState.board[row][col].color !== piece.color;
}
function isFriendlyPiece(row, col) {
return isOccupied(row, col) && gameState.board[row][col].color === piece.color;
}
var row = piece.row;
var col = piece.col;
switch (piece.type) {
case 'pawn':
var direction = piece.color === 'white' ? -1 : 1;
// Move forward one square
if (isOnBoard(row + direction, col) && !isOccupied(row + direction, col)) {
addMove(row + direction, col);
// Move forward two squares on first move
if (!piece.hasMoved && isOnBoard(row + 2 * direction, col) && !isOccupied(row + 2 * direction, col)) {
addMove(row + 2 * direction, col);
}
}
// Capture diagonally
if (isOnBoard(row + direction, col - 1) && isEnemyPiece(row + direction, col - 1)) {
addMove(row + direction, col - 1);
}
if (isOnBoard(row + direction, col + 1) && isEnemyPiece(row + direction, col + 1)) {
addMove(row + direction, col + 1);
}
break;
case 'rook':
// Horizontal and vertical directions
var directions = [{
dr: -1,
dc: 0
},
// up
{
dr: 1,
dc: 0
},
// down
{
dr: 0,
dc: -1
},
// left
{
dr: 0,
dc: 1
} // right
];
directions.forEach(function (dir) {
var r = row + dir.dr;
var c = col + dir.dc;
while (isOnBoard(r, c)) {
if (isOccupied(r, c)) {
if (isEnemyPiece(r, c)) {
addMove(r, c);
}
break;
}
addMove(r, c);
r += dir.dr;
c += dir.dc;
}
});
break;
case 'knight':
// Knight moves
var knightMoves = [{
dr: -2,
dc: -1
}, {
dr: -2,
dc: 1
}, {
dr: -1,
dc: -2
}, {
dr: -1,
dc: 2
}, {
dr: 1,
dc: -2
}, {
dr: 1,
dc: 2
}, {
dr: 2,
dc: -1
}, {
dr: 2,
dc: 1
}];
knightMoves.forEach(function (move) {
var r = row + move.dr;
var c = col + move.dc;
if (isOnBoard(r, c) && !isFriendlyPiece(r, c)) {
addMove(r, c);
}
});
break;
case 'bishop':
// Diagonal directions
var directions = [{
dr: -1,
dc: -1
},
// up-left
{
dr: -1,
dc: 1
},
// up-right
{
dr: 1,
dc: -1
},
// down-left
{
dr: 1,
dc: 1
} // down-right
];
directions.forEach(function (dir) {
var r = row + dir.dr;
var c = col + dir.dc;
while (isOnBoard(r, c)) {
if (isOccupied(r, c)) {
if (isEnemyPiece(r, c)) {
addMove(r, c);
}
break;
}
addMove(r, c);
r += dir.dr;
c += dir.dc;
}
});
break;
case 'queen':
// Combine rook and bishop moves
var directions = [{
dr: -1,
dc: 0
}, {
dr: 1,
dc: 0
},
// vertical
{
dr: 0,
dc: -1
}, {
dr: 0,
dc: 1
},
// horizontal
{
dr: -1,
dc: -1
}, {
dr: -1,
dc: 1
},
// diagonal
{
dr: 1,
dc: -1
}, {
dr: 1,
dc: 1
} // diagonal
];
directions.forEach(function (dir) {
var r = row + dir.dr;
var c = col + dir.dc;
while (isOnBoard(r, c)) {
if (isOccupied(r, c)) {
if (isEnemyPiece(r, c)) {
addMove(r, c);
}
break;
}
addMove(r, c);
r += dir.dr;
c += dir.dc;
}
});
break;
case 'king':
// King moves (one square in any direction)
var directions = [{
dr: -1,
dc: -1
}, {
dr: -1,
dc: 0
}, {
dr: -1,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 0,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: 1,
dc: 1
}];
directions.forEach(function (dir) {
var r = row + dir.dr;
var c = col + dir.dc;
if (isOnBoard(r, c) && !isFriendlyPiece(r, c)) {
addMove(r, c);
}
});
break;
}
return moves;
}
function isCheckmate(color) {
if (!isKingInCheck(color)) return false;
// Check if any piece can make a valid move
for (var r = 0; r < 8; r++) {
for (var c = 0; c < 8; c++) {
var piece = gameState.board[r][c];
if (piece && piece.color === color) {
var validMoves = getValidMoves(piece);
if (validMoves.length > 0) {
return false;
}
}
}
}
return true;
}
function isStalemate(color) {
if (isKingInCheck(color)) return false;
// Check if any piece can make a valid move
for (var r = 0; r < 8; r++) {
for (var c = 0; c < 8; c++) {
var piece = gameState.board[r][c];
if (piece && piece.color === color) {
var validMoves = getValidMoves(piece);
if (validMoves.length > 0) {
return false;
}
}
}
}
return true;
}
function updateGameStatus() {
if (isCheckmate(gameState.currentTurn)) {
gameState.status = 'checkmate';
var winner = gameState.currentTurn === 'white' ? 'Black' : 'White';
statusText.setText(winner + ' wins by checkmate!');
LK.getSound('gameEnd').play();
// Update score if AI was played against
if (gameState.gameMode === 'ai') {
if (winner === 'White' && gameState.aiPlayer === 'black' || winner === 'Black' && gameState.aiPlayer === 'white') {
LK.setScore(LK.getScore() + 1);
}
}
return true;
} else if (isStalemate(gameState.currentTurn)) {
gameState.status = 'stalemate';
statusText.setText('Game drawn by stalemate!');
LK.getSound('gameEnd').play();
return true;
} else if (isKingInCheck(gameState.currentTurn)) {
gameState.status = 'check';
statusText.setText(gameState.currentTurn.charAt(0).toUpperCase() + gameState.currentTurn.slice(1) + ' is in check!');
LK.getSound('check').play();
} else {
gameState.status = 'playing';
statusText.setText('');
}
return false;
}
function updateTurnText() {
var turnName = gameState.currentTurn.charAt(0).toUpperCase() + gameState.currentTurn.slice(1);
turnText.setText(turnName + ' to move');
}
function movePiece(piece, targetRow, targetCol) {
var isCapture = gameState.board[targetRow][targetCol] !== null;
var capturedPiece = gameState.board[targetRow][targetCol];
var fromRow = piece.row;
var fromCol = piece.col;
// Handle castling
if (piece.type === 'king' && Math.abs(targetCol - fromCol) === 2) {
// Kingside castling
if (targetCol > fromCol) {
var rook = gameState.board[fromRow][7];
gameState.board[fromRow][5] = rook;
gameState.board[fromRow][7] = null;
rook.moveTo(fromRow, 5, 300);
}
// Queenside castling
else {
var rook = gameState.board[fromRow][0];
gameState.board[fromRow][3] = rook;
gameState.board[fromRow][0] = null;
rook.moveTo(fromRow, 3, 300);
}
}
// Handle en passant capture
if (piece.type === 'pawn' && Math.abs(targetCol - fromCol) === 1 && !isCapture) {
var enPassantRow = piece.color === 'white' ? targetRow + 1 : targetRow - 1;
capturedPiece = gameState.board[enPassantRow][targetCol];
gameState.board[enPassantRow][targetCol] = null;
if (capturedPiece) {
capturedPiece.parent.removeChild(capturedPiece);
}
isCapture = true;
}
// Update board array
gameState.board[fromRow][fromCol] = null;
if (capturedPiece) {
capturedPiece.parent.removeChild(capturedPiece);
}
gameState.board[targetRow][targetCol] = piece;
// Move the piece with animation
gameState.isAnimating = true;
piece.moveTo(targetRow, targetCol, 300);
// Play sound
if (isCapture) {
LK.getSound('capture').play();
} else {
LK.getSound('move').play();
}
// Handle pawn promotion (always to queen for simplicity)
if (piece.type === 'pawn' && (targetRow === 0 || targetRow === 7)) {
// Wait for the piece to finish moving
var promotionTimeout = LK.setTimeout(function () {
// Remove the pawn
piece.parent.removeChild(piece);
gameState.board[targetRow][targetCol] = null;
// Create a new queen
var queen = new Piece('queen', piece.color, targetRow, targetCol);
chessBoard.piecesLayer.addChild(queen);
gameState.board[targetRow][targetCol] = queen;
LK.clearTimeout(promotionTimeout);
}, 350);
}
// Update last move
gameState.lastMove = {
piece: piece,
fromRow: fromRow,
fromCol: fromCol,
toRow: targetRow,
toCol: targetCol
};
// Highlight the last move
var moveTimeout = LK.setTimeout(function () {
chessBoard.clearHighlights();
chessBoard.highlightTile(fromRow, fromCol, 'lastMoveTile');
chessBoard.highlightTile(targetRow, targetCol, 'lastMoveTile');
// Switch turns
gameState.currentTurn = gameState.currentTurn === 'white' ? 'black' : 'white';
updateTurnText();
// Check for check, checkmate, stalemate
var gameEnded = updateGameStatus();
gameState.isAnimating = false;
gameState.selectedPiece = null;
// If AI is playing and it's AI's turn
if (!gameEnded && gameState.gameMode === 'ai' && gameState.currentTurn === gameState.aiPlayer) {
makeAIMove();
}
LK.clearTimeout(moveTimeout);
}, 350);
}
function makeAIMove() {
var aiTimeout = LK.setTimeout(function () {
var allPossibleMoves = [];
// Collect all possible moves for AI pieces
for (var r = 0; r < 8; r++) {
for (var c = 0; c < 8; c++) {
var piece = gameState.board[r][c];
if (piece && piece.color === gameState.aiPlayer) {
var validMoves = getValidMoves(piece);
for (var i = 0; i < validMoves.length; i++) {
allPossibleMoves.push({
piece: piece,
move: validMoves[i]
});
}
}
}
}
if (allPossibleMoves.length > 0) {
var selectedMove;
// Basic AI difficulty levels
if (gameState.aiDifficulty === 1) {
// Easy: Random move
selectedMove = allPossibleMoves[Math.floor(Math.random() * allPossibleMoves.length)];
} else if (gameState.aiDifficulty === 2) {
// Medium: Prefer captures and checks
var captureMoves = allPossibleMoves.filter(function (moveObj) {
return gameState.board[moveObj.move.row][moveObj.move.col] !== null;
});
if (captureMoves.length > 0) {
selectedMove = captureMoves[Math.floor(Math.random() * captureMoves.length)];
} else {
selectedMove = allPossibleMoves[Math.floor(Math.random() * allPossibleMoves.length)];
}
} else {
// Hard: Prioritize captures by piece value
var bestValue = -1;
var bestMoves = [];
for (var i = 0; i < allPossibleMoves.length; i++) {
var moveObj = allPossibleMoves[i];
var targetPiece = gameState.board[moveObj.move.row][moveObj.move.col];
var moveValue = 0;
if (targetPiece) {
// Assign values to pieces
switch (targetPiece.type) {
case 'pawn':
moveValue = 1;
break;
case 'knight':
case 'bishop':
moveValue = 3;
break;
case 'rook':
moveValue = 5;
break;
case 'queen':
moveValue = 9;
break;
case 'king':
moveValue = 100;
break;
}
}
// Prioritize center control for pawns and knights
if (moveObj.piece.type === 'pawn' || moveObj.piece.type === 'knight') {
var centerDistance = Math.abs(moveObj.move.row - 3.5) + Math.abs(moveObj.move.col - 3.5);
moveValue += (4 - centerDistance) * 0.1;
}
if (moveValue > bestValue) {
bestValue = moveValue;
bestMoves = [moveObj];
} else if (moveValue === bestValue) {
bestMoves.push(moveObj);
}
}
if (bestMoves.length > 0) {
selectedMove = bestMoves[Math.floor(Math.random() * bestMoves.length)];
} else {
selectedMove = allPossibleMoves[Math.floor(Math.random() * allPossibleMoves.length)];
}
}
// Make the selected move
movePiece(selectedMove.piece, selectedMove.move.row, selectedMove.move.col);
}
LK.clearTimeout(aiTimeout);
}, 500);
}
// Game event handlers
game.down = function (x, y, obj) {
if (gameState.isAnimating) return;
// Convert screen coordinates to board coordinates
var boardX = x - chessBoard.x;
var boardY = y - chessBoard.y;
var tile = chessBoard.getTileAt(boardX, boardY);
if (tile && gameState.selectedPiece) {
// Check if the clicked tile is a valid move
var isValidMove = false;
for (var i = 0; i < gameState.validMoves.length; i++) {
var move = gameState.validMoves[i];
if (move.row === tile.row && move.col === tile.col) {
isValidMove = true;
break;
}
}
if (isValidMove) {
// Move the piece
movePiece(gameState.selectedPiece, tile.row, tile.col);
return;
}
}
// Clear selection if clicking elsewhere
if (gameState.selectedPiece) {
chessBoard.clearHighlights();
gameState.selectedPiece = null;
}
};
// Game Mode Buttons
var twoPlayerBtn = new Text2('Two Player', {
size: 50,
fill: 0xFFFFFF
});
twoPlayerBtn.anchor.set(0.5, 0);
twoPlayerBtn.y = 2732 - 200;
twoPlayerBtn.x = 2048 / 2 - 300;
LK.gui.addChild(twoPlayerBtn);
twoPlayerBtn.interactive = true;
twoPlayerBtn.buttonMode = true;
twoPlayerBtn.on('pointerdown', function () {
gameState.gameMode = 'twoPlayer';
gameState.aiPlayer = null;
LK.setScore(0);
initializeChessBoard();
updateTurnText();
chessBoard.clearHighlights();
});
var aiBtn = new Text2('Play vs AI', {
size: 50,
fill: 0xFFFFFF
});
aiBtn.anchor.set(0.5, 0);
aiBtn.y = 2732 - 200;
aiBtn.x = 2048 / 2 + 300;
LK.gui.addChild(aiBtn);
aiBtn.interactive = true;
aiBtn.buttonMode = true;
aiBtn.on('pointerdown', function () {
gameState.gameMode = 'ai';
gameState.aiPlayer = 'black';
LK.setScore(0);
initializeChessBoard();
updateTurnText();
chessBoard.clearHighlights();
});
// AI Difficulty Buttons
var easyBtn = new Text2('Easy', {
size: 40,
fill: gameState.aiDifficulty === 1 ? "#ffff00" : "#aaaaaa"
});
easyBtn.style = {
fill: gameState.aiDifficulty === 1 ? "#ffff00" : "#aaaaaa"
};
easyBtn.anchor.set(0.5, 0);
easyBtn.y = 2732 - 120;
easyBtn.x = 2048 / 2 - 300;
LK.gui.addChild(easyBtn);
easyBtn.interactive = true;
easyBtn.buttonMode = true;
easyBtn.on('pointerdown', function () {
gameState.aiDifficulty = 1;
storage.aiDifficulty = 1;
easyBtn.style.fill = "#ffff00";
mediumBtn.style.fill = "#aaaaaa";
hardBtn.style.fill = "#aaaaaa";
});
var mediumBtn = new Text2('Medium', {
size: 40,
fill: gameState.aiDifficulty === 2 ? "#ffff00" : "#aaaaaa"
});
mediumBtn.style = {
fill: gameState.aiDifficulty === 2 ? "#ffff00" : "#aaaaaa"
};
mediumBtn.anchor.set(0.5, 0);
mediumBtn.y = 2732 - 120;
mediumBtn.x = 2048 / 2;
LK.gui.addChild(mediumBtn);
mediumBtn.interactive = true;
mediumBtn.buttonMode = true;
mediumBtn.on('pointerdown', function () {
gameState.aiDifficulty = 2;
storage.aiDifficulty = 2;
easyBtn.style.fill = "#aaaaaa";
mediumBtn.style.fill = "#ffff00";
hardBtn.style.fill = "#aaaaaa";
});
var hardBtn = new Text2('Hard', {
size: 40,
fill: gameState.aiDifficulty === 3 ? "#ffff00" : "#aaaaaa"
});
hardBtn.style = {
fill: gameState.aiDifficulty === 3 ? "#ffff00" : "#aaaaaa"
};
hardBtn.anchor.set(0.5, 0);
hardBtn.y = 2732 - 120;
hardBtn.x = 2048 / 2 + 300;
LK.gui.addChild(hardBtn);
hardBtn.interactive = true;
hardBtn.buttonMode = true;
hardBtn.on('pointerdown', function () {
gameState.aiDifficulty = 3;
storage.aiDifficulty = 3;
easyBtn.style.fill = "#aaaaaa";
mediumBtn.style.fill = "#aaaaaa";
hardBtn.style.fill = "#ffff00";
});
// Update difficulty button colors based on current setting
switch (gameState.aiDifficulty) {
case 1:
easyBtn.style.fill = "#ffff00";
mediumBtn.style.fill = "#aaaaaa";
hardBtn.style.fill = "#aaaaaa";
break;
case 2:
easyBtn.style.fill = "#aaaaaa";
mediumBtn.style.fill = "#ffff00";
hardBtn.style.fill = "#aaaaaa";
break;
case 3:
easyBtn.style.fill = "#aaaaaa";
mediumBtn.style.fill = "#aaaaaa";
hardBtn.style.fill = "#ffff00";
break;
}
// New Game button
var newGameBtn = new Text2('New Game', {
size: 50,
fill: 0xFFFFFF
});
newGameBtn.anchor.set(0.5, 0);
newGameBtn.y = 2732 - 280;
newGameBtn.x = 2048 / 2;
LK.gui.addChild(newGameBtn);
newGameBtn.interactive = true;
newGameBtn.buttonMode = true;
newGameBtn.on('pointerdown', function () {
initializeChessBoard();
updateTurnText();
});
// Initialize the game
initializeChessBoard();
// Main game loop
game.update = function () {
// Game update logic happens in event handlers and callbacks
};
// Play background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
}); ===================================================================
--- original.js
+++ change.js
@@ -1184,8 +1184,11 @@
var easyBtn = new Text2('Easy', {
size: 40,
fill: gameState.aiDifficulty === 1 ? "#ffff00" : "#aaaaaa"
});
+easyBtn.style = {
+ fill: gameState.aiDifficulty === 1 ? "#ffff00" : "#aaaaaa"
+};
easyBtn.anchor.set(0.5, 0);
easyBtn.y = 2732 - 120;
easyBtn.x = 2048 / 2 - 300;
LK.gui.addChild(easyBtn);
@@ -1201,8 +1204,11 @@
var mediumBtn = new Text2('Medium', {
size: 40,
fill: gameState.aiDifficulty === 2 ? "#ffff00" : "#aaaaaa"
});
+mediumBtn.style = {
+ fill: gameState.aiDifficulty === 2 ? "#ffff00" : "#aaaaaa"
+};
mediumBtn.anchor.set(0.5, 0);
mediumBtn.y = 2732 - 120;
mediumBtn.x = 2048 / 2;
LK.gui.addChild(mediumBtn);
@@ -1218,8 +1224,11 @@
var hardBtn = new Text2('Hard', {
size: 40,
fill: gameState.aiDifficulty === 3 ? "#ffff00" : "#aaaaaa"
});
+hardBtn.style = {
+ fill: gameState.aiDifficulty === 3 ? "#ffff00" : "#aaaaaa"
+};
hardBtn.anchor.set(0.5, 0);
hardBtn.y = 2732 - 120;
hardBtn.x = 2048 / 2 + 300;
LK.gui.addChild(hardBtn);