User prompt
add gamestart, castling, cappture, check, game over(stalemate), game over(checkmate) sounds
User prompt
Let each move make a solid sound, like the move sound in classical chess games.
User prompt
var titleText = new Text2('Chess Game', { size: 120, fill: 0xFFFFFF }); chess game change FakeChess
User prompt
// Back button backButton.y = 600; change 700 and showHowToPlay Background color change orange
User prompt
Add a new button to the main menu. Let the name of the button be "How to play?" When you click on the button, a container will open and on that page, it will explain the function of the pieces one by one, that is, how they can make moves.
User prompt
In ai mode, when the opponent's pawn reaches the 1st square of the white team, the pawn turns into a queen. Up to this point, everything is normal, but when it turns, no one can move in the game. Let the game continue.
User prompt
In AI mode, the opponent's pawn enters my area and becomes a queen normally, but when it becomes a queen, the game stops and no one can move. The game must continue, fix it.
User prompt
When you become king, the game is bugged, no one can move in AI mode, fix that
User prompt
In AI mode, when the opponent reaches my first square, he automatically becomes the queen, but the game is bugged and no one moves. Fix that.
User prompt
In online mode, if black wins, it says black won, if white wins, it says white won.
User prompt
Place the white period slightly lower (a b c d e f g h ) so that it does not overlap with the letters
User prompt
put the times at the top right and bottom right of the chessboard
User prompt
In online mode, set a 10-minute timer for both my opponent and me. Whoever's turn is it, their time will decrease. Whoever's time runs out, loses.
User prompt
In AI mode, when the opponent's pawn, namely AI's pawn, reaches my first square, it does not make me choose the piece it will choose randomly, it chooses its own queen automatically.
User prompt
If I am in check or have made a check, if the team that has been put in check has no moves to make, checkmate occurs and the opponent, that is, the one who has made a check, wins.
User prompt
Ai does not eat any of my pieces. If he can eat my pieces, he should eat them. Ai should be a smarter chess player.
User prompt
When I start white, Ai makes a move after the move, but when Ai starts white, he doesn't make a move. Fix this bug.
User prompt
Set the ai delay back to 800ms.
User prompt
AI thinks a lot in computer mode, let the AI play faster
User prompt
There will be a main menu when you enter the game. The options will be Computer, Online. When you click on Computer, it will randomly give black or white to the player and he will play the game against the computer, that is, against the artificial intelligence.
User prompt
okey prepare this game for online mode but for example when playing online black stones came to me and white stones came to my opponent black stones will be at the bottom and white stones will be at the top and 1 2 3 4 5 6 7 8 and a b c d e f g h will be sorted according to white again
User prompt
from the leftmost of the white stones to the top left of the squares from bottom to top write (1 2 3 4 5 6 7 8). again from the bottom of the white stones from left to right write (a b c d e f g h)
User prompt
You couldn't fix it, it became a king and there are many alternative pieces that can capture the king piece, but the alternative pieces can't move.
User prompt
In the game, the man who is the king, for example: can capture the piece that checkmates with a knight. Under normal circumstances, he would capture the piece and avoid checkmate, but when he becomes the king in the game, only the king can move. The knight cannot capture it. There is such a bug, fix it.
User prompt
If the opponent checks, a warning is given. If the king is in the game, if the king has no chance to make any move to save his king, he is checkmated and the opponent wins the game.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var ChessPiece = Container.expand(function (type, color, row, col) {
var self = Container.call(this);
self.pieceType = type;
self.color = color;
self.row = row;
self.col = col;
self.hasMoved = false;
var assetName = color + type.charAt(0).toUpperCase() + type.slice(1);
self.graphic = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.setPosition = function (row, col) {
self.row = row;
self.col = col;
if (playerPerspective === 'black') {
// Flip the board for black player perspective
self.x = boardOffsetX + (7 - col) * 200 + 100;
self.y = boardOffsetY + (7 - row) * 200 + 100;
} else {
self.x = boardOffsetX + col * 200 + 100;
self.y = boardOffsetY + row * 200 + 100;
}
};
self.getValidMoves = function () {
var moves = [];
if (self.pieceType === 'pawn') {
// Pawns move diagonally forward, capture straight forward
var direction = self.color === 'white' ? -1 : 1;
var newRow = self.row + direction;
// Diagonal movement (normal pawn movement)
if (newRow >= 0 && newRow < 8) {
if (self.col > 0 && !board[newRow][self.col - 1]) {
moves.push({
row: newRow,
col: self.col - 1
});
}
if (self.col < 7 && !board[newRow][self.col + 1]) {
moves.push({
row: newRow,
col: self.col + 1
});
}
}
// Capture straight forward
if (newRow >= 0 && newRow < 8) {
var piece = board[newRow][self.col];
if (piece && piece.color !== self.color) {
moves.push({
row: newRow,
col: self.col
});
}
}
// Initial two-square diagonal move
if (!self.hasMoved) {
newRow = self.row + direction * 2;
if (newRow >= 0 && newRow < 8) {
if (self.col > 1 && !board[newRow][self.col - 2]) {
moves.push({
row: newRow,
col: self.col - 2
});
}
if (self.col < 6 && !board[newRow][self.col + 2]) {
moves.push({
row: newRow,
col: self.col + 2
});
}
}
}
} else if (self.pieceType === 'rook') {
// Rooks move diagonally (like bishops)
var directions = [[-1, -1], [-1, 1], [1, -1], [1, 1]];
for (var d = 0; d < directions.length; d++) {
var dir = directions[d];
for (var i = 1; i < 8; i++) {
var newRow = self.row + dir[0] * i;
var newCol = self.col + dir[1] * i;
if (newRow < 0 || newRow >= 8 || newCol < 0 || newCol >= 8) break;
var piece = board[newRow][newCol];
if (!piece) {
moves.push({
row: newRow,
col: newCol
});
} else {
if (piece.color !== self.color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
}
}
} else if (self.pieceType === 'bishop') {
// Bishops move like knights (L-shaped)
var knightMoves = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]];
for (var k = 0; k < knightMoves.length; k++) {
var move = knightMoves[k];
var newRow = self.row + move[0];
var newCol = self.col + move[1];
if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8) {
var piece = board[newRow][newCol];
if (!piece || piece.color !== self.color) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
} else if (self.pieceType === 'knight') {
// Knights move straight (like rooks)
var directions = [[0, 1], [0, -1], [1, 0], [-1, 0]];
for (var d = 0; d < directions.length; d++) {
var dir = directions[d];
for (var i = 1; i < 8; i++) {
var newRow = self.row + dir[0] * i;
var newCol = self.col + dir[1] * i;
if (newRow < 0 || newRow >= 8 || newCol < 0 || newCol >= 8) break;
var piece = board[newRow][newCol];
if (!piece) {
moves.push({
row: newRow,
col: newCol
});
} else {
if (piece.color !== self.color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
}
}
} else if (self.pieceType === 'queen') {
// Queen moves both diagonally and straight
var directions = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
for (var d = 0; d < directions.length; d++) {
var dir = directions[d];
for (var i = 1; i < 8; i++) {
var newRow = self.row + dir[0] * i;
var newCol = self.col + dir[1] * i;
if (newRow < 0 || newRow >= 8 || newCol < 0 || newCol >= 8) break;
var piece = board[newRow][newCol];
if (!piece) {
moves.push({
row: newRow,
col: newCol
});
} else {
if (piece.color !== self.color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
}
}
} else if (self.pieceType === 'king') {
// King moves one square in any direction
var directions = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]];
for (var d = 0; d < directions.length; d++) {
var dir = directions[d];
var newRow = self.row + dir[0];
var newCol = self.col + dir[1];
if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8) {
var piece = board[newRow][newCol];
if (!piece || piece.color !== self.color) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
}
return moves;
};
return self;
});
var ChessSquare = Container.expand(function (row, col) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.isLight = (row + col) % 2 === 0;
self.background = self.attachAsset(self.isLight ? 'lightSquare' : 'darkSquare', {
anchorX: 0.5,
anchorY: 0.5
});
self.highlight = self.attachAsset('highlight', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.validMoveIndicator = self.attachAsset('validMove', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.selectedIndicator = self.attachAsset('selectedPiece', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.setHighlight = function (show) {
self.highlight.alpha = show ? 0.3 : 0;
};
self.setValidMove = function (show) {
self.validMoveIndicator.alpha = show ? 0.5 : 0;
};
self.setSelected = function (show) {
self.selectedIndicator.alpha = show ? 0.4 : 0;
};
self.down = function (x, y, obj) {
handleSquareClick(self.row, self.col);
};
return self;
});
var PromotionDialog = Container.expand(function (color, onSelect) {
var self = Container.call(this);
self.color = color;
self.onSelect = onSelect;
// Background
self.background = self.attachAsset('promotionDialog', {
anchorX: 0.5,
anchorY: 0.5
});
// Title text
self.titleText = new Text2('Choose promotion piece:', {
size: 60,
fill: 0xFFFFFF
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 0;
self.titleText.y = -120;
self.addChild(self.titleText);
// Promotion pieces
var pieceTypes = ['queen', 'rook', 'bishop', 'knight'];
var buttons = [];
for (var i = 0; i < pieceTypes.length; i++) {
var pieceType = pieceTypes[i];
var button = new Container();
// Button background
var buttonBg = button.attachAsset('promotionButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Piece image
var assetName = color + pieceType.charAt(0).toUpperCase() + pieceType.slice(1);
var pieceImage = button.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
button.x = (i - 1.5) * 180;
button.y = 0;
button.pieceType = pieceType;
// Create closure to capture the correct pieceType for each button
button.down = function (capturedPieceType) {
return function (x, y, obj) {
self.onSelect(capturedPieceType);
};
}(pieceType);
buttons.push(button);
self.addChild(button);
}
// Position dialog at center of screen
self.x = 1024;
self.y = 1366;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8B4513
});
/****
* Game Code
****/
// White pieces
// Black pieces
var boardOffsetX = 224;
var boardOffsetY = 566;
var board = [];
var squares = [];
var pieces = [];
var selectedPiece = null;
var validMoves = [];
var currentPlayer = 'white';
var gameOver = false;
var promotionDialog = null;
var pendingPromotion = null;
var playerPerspective = 'white'; // 'white' or 'black' - determines board orientation
var gameMode = 'menu'; // 'menu', 'computer', 'online'
var isPlayerTurn = true;
var aiColor = 'black';
var mainMenu = null;
var whiteTimeRemaining = 600; // 10 minutes in seconds
var blackTimeRemaining = 600; // 10 minutes in seconds
var gameTimer = null;
var whiteTimerText = null;
var blackTimerText = null;
var lastTimerUpdate = 0;
function createMainMenu() {
mainMenu = new Container();
game.addChild(mainMenu);
// Title
var titleText = new Text2('Chess Game', {
size: 120,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
mainMenu.addChild(titleText);
// Computer button
var computerButton = new Container();
var computerBg = computerButton.attachAsset('promotionDialog', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.4
});
var computerText = new Text2('Computer', {
size: 80,
fill: 0xFFFFFF
});
computerText.anchor.set(0.5, 0.5);
computerButton.addChild(computerText);
computerButton.x = 1024;
computerButton.y = 900;
computerButton.down = function (x, y, obj) {
startComputerGame();
};
mainMenu.addChild(computerButton);
// Online button
var onlineButton = new Container();
var onlineBg = onlineButton.attachAsset('promotionDialog', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.4
});
var onlineText = new Text2('Online', {
size: 80,
fill: 0xFFFFFF
});
onlineText.anchor.set(0.5, 0.5);
onlineButton.addChild(onlineText);
onlineButton.x = 1024;
onlineButton.y = 1200;
onlineButton.down = function (x, y, obj) {
startOnlineGame();
};
mainMenu.addChild(onlineButton);
}
function startComputerGame() {
gameMode = 'computer';
// Randomly assign player color
var playerColor = Math.random() < 0.5 ? 'white' : 'black';
playerPerspective = playerColor;
aiColor = playerColor === 'white' ? 'black' : 'white';
isPlayerTurn = currentPlayer === playerColor;
// Hide menu and initialize game
mainMenu.destroy();
mainMenu = null;
initializeBoard();
initializePieces();
addCoordinateLabels();
createTurnIndicator();
// If AI should start (AI is white), make first move
if (aiColor === 'white') {
LK.setTimeout(function () {
makeAIMove();
}, 800);
}
}
function startOnlineGame() {
gameMode = 'online';
// Reset timers
whiteTimeRemaining = 600;
blackTimeRemaining = 600;
playerPerspective = 'white';
mainMenu.destroy();
mainMenu = null;
initializeBoard();
initializePieces();
addCoordinateLabels();
createTurnIndicator();
createTimerDisplay();
startGameTimer();
}
function initializeBoard() {
// Initialize board
for (var row = 0; row < 8; row++) {
board[row] = [];
squares[row] = [];
for (var col = 0; col < 8; col++) {
board[row][col] = null;
var square = new ChessSquare(row, col);
if (playerPerspective === 'black') {
// Flip the board for black player perspective
square.x = boardOffsetX + (7 - col) * 200 + 100;
square.y = boardOffsetY + (7 - row) * 200 + 100;
} else {
square.x = boardOffsetX + col * 200 + 100;
square.y = boardOffsetY + row * 200 + 100;
}
squares[row][col] = square;
game.addChild(square);
}
}
}
// Show main menu on startup
createMainMenu();
// Initialize pieces
function initializePieces() {
// White pieces
var whitePieces = [{
type: 'rook',
positions: [[7, 0], [7, 7]]
}, {
type: 'knight',
positions: [[7, 1], [7, 6]]
}, {
type: 'bishop',
positions: [[7, 2], [7, 5]]
}, {
type: 'queen',
positions: [[7, 3]]
}, {
type: 'king',
positions: [[7, 4]]
}, {
type: 'pawn',
positions: [[6, 0], [6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [6, 6], [6, 7]]
}];
// Black pieces
var blackPieces = [{
type: 'rook',
positions: [[0, 0], [0, 7]]
}, {
type: 'knight',
positions: [[0, 1], [0, 6]]
}, {
type: 'bishop',
positions: [[0, 2], [0, 5]]
}, {
type: 'queen',
positions: [[0, 3]]
}, {
type: 'king',
positions: [[0, 4]]
}, {
type: 'pawn',
positions: [[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7]]
}];
// Create white pieces
for (var i = 0; i < whitePieces.length; i++) {
var pieceData = whitePieces[i];
for (var j = 0; j < pieceData.positions.length; j++) {
var pos = pieceData.positions[j];
var piece = new ChessPiece(pieceData.type, 'white', pos[0], pos[1]);
piece.setPosition(pos[0], pos[1]);
board[pos[0]][pos[1]] = piece;
pieces.push(piece);
game.addChild(piece);
}
}
// Create black pieces
for (var i = 0; i < blackPieces.length; i++) {
var pieceData = blackPieces[i];
for (var j = 0; j < pieceData.positions.length; j++) {
var pos = pieceData.positions[j];
var piece = new ChessPiece(pieceData.type, 'black', pos[0], pos[1]);
piece.setPosition(pos[0], pos[1]);
board[pos[0]][pos[1]] = piece;
pieces.push(piece);
game.addChild(piece);
}
}
}
function clearHighlights() {
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
squares[row][col].setHighlight(false);
squares[row][col].setValidMove(false);
squares[row][col].setSelected(false);
}
}
}
function showValidMoves(piece) {
var allMoves = piece.getValidMoves();
validMoves = [];
// Filter out moves that would leave the king in check
for (var i = 0; i < allMoves.length; i++) {
var move = allMoves[i];
if (isValidMove(piece, move.row, move.col)) {
validMoves.push(move);
squares[move.row][move.col].setValidMove(true);
}
}
}
function handleSquareClick(row, col) {
if (gameOver) return;
if (gameMode === 'computer' && !isPlayerTurn) return; // Don't allow moves during AI turn
if (gameMode === 'menu') return; // Don't allow moves in menu
var clickedPiece = board[row][col];
if (selectedPiece) {
// Check if clicked square is a valid move
var validMove = false;
for (var i = 0; i < validMoves.length; i++) {
if (validMoves[i].row === row && validMoves[i].col === col) {
validMove = true;
break;
}
}
if (validMove) {
// Make the move
movePiece(selectedPiece, row, col);
selectedPiece = null;
clearHighlights();
validMoves = [];
// Only switch players and check game over if not promoting
if (!pendingPromotion) {
// Switch players
currentPlayer = currentPlayer === 'white' ? 'black' : 'white';
if (gameMode === 'computer') {
isPlayerTurn = currentPlayer !== aiColor;
}
// Update timer display for online mode
if (gameMode === 'online') {
updateTimerDisplay();
lastTimerUpdate = Date.now();
}
// Check for game over conditions
checkGameOver();
if (gameMode === 'computer' && !isPlayerTurn) {
// AI turn - make move after short delay
LK.setTimeout(function () {
makeAIMove();
}, 800);
}
}
} else if (clickedPiece && clickedPiece.color === currentPlayer) {
// Select new piece
clearHighlights();
selectedPiece = clickedPiece;
squares[row][col].setSelected(true);
showValidMoves(selectedPiece);
} else {
// Deselect
selectedPiece = null;
clearHighlights();
validMoves = [];
}
} else if (clickedPiece && clickedPiece.color === currentPlayer) {
// Select piece
selectedPiece = clickedPiece;
squares[row][col].setSelected(true);
showValidMoves(selectedPiece);
}
}
function movePiece(piece, toRow, toCol) {
var capturedPiece = board[toRow][toCol];
// Remove piece from old position
board[piece.row][piece.col] = null;
// Place piece in new position
board[toRow][toCol] = piece;
piece.setPosition(toRow, toCol);
piece.hasMoved = true;
// Handle captured piece
if (capturedPiece) {
capturedPiece.destroy();
for (var i = pieces.length - 1; i >= 0; i--) {
if (pieces[i] === capturedPiece) {
pieces.splice(i, 1);
break;
}
}
LK.getSound('capture').play();
} else {
LK.getSound('move').play();
}
// Animate piece movement
tween(piece, {
x: piece.x,
y: piece.y
}, {
duration: 300
});
// Check for pawn promotion
if (piece.pieceType === 'pawn') {
var promotionRow = piece.color === 'white' ? 0 : 7;
if (toRow === promotionRow) {
// Check if it's AI's turn in computer mode
if (gameMode === 'computer' && piece.color === aiColor) {
// AI automatically promotes to queen
handleAIPromotion(piece, toRow, toCol, 'queen');
return; // Don't switch players yet
} else {
// Store promotion details for player
pendingPromotion = {
piece: piece,
row: toRow,
col: toCol
};
// Show promotion dialog
showPromotionDialog(piece.color);
return; // Don't switch players yet
}
}
}
}
function isKingInCheck(kingColor) {
// Find the king
var king = null;
for (var i = 0; i < pieces.length; i++) {
var piece = pieces[i];
if (piece.pieceType === 'king' && piece.color === kingColor) {
king = piece;
break;
}
}
if (!king) return false;
// Check if any enemy piece can attack the king
for (var i = 0; i < pieces.length; i++) {
var piece = pieces[i];
if (piece.color !== kingColor) {
var moves = piece.getValidMoves();
for (var j = 0; j < moves.length; j++) {
if (moves[j].row === king.row && moves[j].col === king.col) {
return true;
}
}
}
}
return false;
}
function isValidMove(piece, toRow, toCol) {
// Save current state
var originalRow = piece.row;
var originalCol = piece.col;
var capturedPiece = board[toRow][toCol];
// Temporarily remove captured piece from pieces array for accurate check detection
var capturedPieceIndex = -1;
if (capturedPiece) {
for (var i = 0; i < pieces.length; i++) {
if (pieces[i] === capturedPiece) {
capturedPieceIndex = i;
pieces.splice(i, 1);
break;
}
}
}
// Simulate the move
board[originalRow][originalCol] = null;
board[toRow][toCol] = piece;
piece.row = toRow;
piece.col = toCol;
// Check if this move leaves the king in check
var kingInCheck = isKingInCheck(piece.color);
// Restore original state
board[originalRow][originalCol] = piece;
board[toRow][toCol] = capturedPiece;
piece.row = originalRow;
piece.col = originalCol;
// Restore captured piece to pieces array
if (capturedPiece && capturedPieceIndex !== -1) {
pieces.splice(capturedPieceIndex, 0, capturedPiece);
}
// Debug: Log when moves are being blocked
if (kingInCheck && capturedPiece) {
console.log("Move blocked: " + piece.pieceType + " cannot capture " + capturedPiece.pieceType + " - king still in check");
}
return !kingInCheck;
}
function getValidMovesForPlayer(playerColor) {
var allMoves = [];
for (var i = 0; i < pieces.length; i++) {
var piece = pieces[i];
if (piece.color === playerColor) {
var moves = piece.getValidMoves();
for (var j = 0; j < moves.length; j++) {
if (isValidMove(piece, moves[j].row, moves[j].col)) {
allMoves.push({
piece: piece,
row: moves[j].row,
col: moves[j].col
});
}
}
}
}
return allMoves;
}
function makeAIMove() {
if (gameMode !== 'computer' || currentPlayer !== aiColor || gameOver) return;
var validMoves = getValidMovesForPlayer(aiColor);
if (validMoves.length === 0) return;
// Evaluate and score all possible moves
var bestMoves = [];
var bestScore = -1000;
for (var i = 0; i < validMoves.length; i++) {
var move = validMoves[i];
var score = evaluateMove(move);
if (score > bestScore) {
bestScore = score;
bestMoves = [move];
} else if (score === bestScore) {
bestMoves.push(move);
}
}
// Pick randomly from the best moves
var selectedMove = bestMoves[Math.floor(Math.random() * bestMoves.length)];
movePiece(selectedMove.piece, selectedMove.row, selectedMove.col);
// Clear selection and highlights
selectedPiece = null;
clearHighlights();
// Switch players if not promoting
if (!pendingPromotion) {
currentPlayer = currentPlayer === 'white' ? 'black' : 'white';
isPlayerTurn = currentPlayer !== aiColor;
checkGameOver();
}
}
function evaluateMove(move) {
var score = 0;
var targetPiece = board[move.row][move.col];
var movingPiece = move.piece;
// Prioritize captures - assign values to different pieces
if (targetPiece) {
var pieceValues = {
'pawn': 10,
'knight': 30,
'bishop': 30,
'rook': 50,
'queen': 90,
'king': 1000
};
score += pieceValues[targetPiece.pieceType] || 0;
}
// Bonus for moving towards center
var centerDistance = Math.abs(move.row - 3.5) + Math.abs(move.col - 3.5);
score += (7 - centerDistance) * 2;
// Bonus for advancing pawns
if (movingPiece.pieceType === 'pawn') {
if (aiColor === 'white') {
score += (7 - move.row) * 3; // White pawns advance by decreasing row
} else {
score += move.row * 3; // Black pawns advance by increasing row
}
}
// Bonus for developing pieces early
if (!movingPiece.hasMoved) {
if (movingPiece.pieceType === 'knight' || movingPiece.pieceType === 'bishop') {
score += 15;
}
}
// Small penalty for moving the same piece multiple times early
if (movingPiece.hasMoved && movingPiece.pieceType !== 'pawn') {
score -= 2;
}
// Bonus for protecting valuable pieces
var protectedPieces = 0;
var attackingMoves = movingPiece.getValidMoves();
for (var i = 0; i < attackingMoves.length; i++) {
var attackMove = attackingMoves[i];
var protectedPiece = board[attackMove.row][attackMove.col];
if (protectedPiece && protectedPiece.color === aiColor) {
protectedPieces++;
}
}
score += protectedPieces * 5;
return score;
}
function checkGameOver() {
// Find kings
var whiteKing = null;
var blackKing = null;
for (var i = 0; i < pieces.length; i++) {
var piece = pieces[i];
if (piece.pieceType === 'king') {
if (piece.color === 'white') {
whiteKing = piece;
} else {
blackKing = piece;
}
}
}
// Check if either king is captured (shouldn't happen in proper chess)
if (!whiteKing) {
gameOver = true;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
} else if (!blackKing) {
gameOver = true;
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
return;
}
// Check for check and checkmate
var currentPlayerInCheck = isKingInCheck(currentPlayer);
var validMoves = getValidMovesForPlayer(currentPlayer);
if (currentPlayerInCheck) {
if (validMoves.length === 0) {
// Checkmate - the current player is in check and has no valid moves
gameOver = true;
// In computer mode, determine win/loss based on player perspective
if (gameMode === 'computer') {
if (currentPlayer === playerPerspective) {
// Player is checkmated - AI wins
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
} else {
// AI is checkmated - Player wins
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
} else {
// Online mode - show result based on color
if (currentPlayer === 'white') {
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
} else {
LK.setTimeout(function () {
LK.showYouWin();
}, 1000);
}
}
} else {
// Check warning - player is in check but has moves
LK.effects.flashScreen(0xff0000, 500);
}
} else if (validMoves.length === 0) {
// Stalemate - no check but no valid moves
gameOver = true;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
function showPromotionDialog(color) {
if (promotionDialog) {
promotionDialog.destroy();
}
promotionDialog = new PromotionDialog(color, function (selectedPiece) {
handlePromotion(selectedPiece);
});
game.addChild(promotionDialog);
}
function handlePromotion(newPieceType) {
if (!pendingPromotion) return;
var oldPiece = pendingPromotion.piece;
var row = pendingPromotion.row;
var col = pendingPromotion.col;
// Remove old pawn
oldPiece.destroy();
for (var i = pieces.length - 1; i >= 0; i--) {
if (pieces[i] === oldPiece) {
pieces.splice(i, 1);
break;
}
}
board[row][col] = null;
// Create new piece
var newPiece = new ChessPiece(newPieceType, oldPiece.color, row, col);
newPiece.setPosition(row, col);
newPiece.hasMoved = true;
board[row][col] = newPiece;
pieces.push(newPiece);
game.addChild(newPiece);
// Clean up
promotionDialog.destroy();
promotionDialog = null;
pendingPromotion = null;
// Switch players
currentPlayer = currentPlayer === 'white' ? 'black' : 'white';
// Update timer display for online mode
if (gameMode === 'online') {
updateTimerDisplay();
lastTimerUpdate = Date.now();
}
// Check for game over conditions
checkGameOver();
}
function handleAIPromotion(oldPiece, row, col, newPieceType) {
// Remove old pawn
oldPiece.destroy();
for (var i = pieces.length - 1; i >= 0; i--) {
if (pieces[i] === oldPiece) {
pieces.splice(i, 1);
break;
}
}
board[row][col] = null;
// Create new piece
var newPiece = new ChessPiece(newPieceType, oldPiece.color, row, col);
newPiece.setPosition(row, col);
newPiece.hasMoved = true;
board[row][col] = newPiece;
pieces.push(newPiece);
game.addChild(newPiece);
// Switch players
currentPlayer = currentPlayer === 'white' ? 'black' : 'white';
if (gameMode === 'computer') {
isPlayerTurn = currentPlayer !== aiColor;
}
// Check for game over conditions
checkGameOver();
}
function setPlayerPerspective(perspective) {
playerPerspective = perspective;
// Clear existing board and pieces
for (var i = pieces.length - 1; i >= 0; i--) {
pieces[i].destroy();
}
pieces = [];
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
board[row][col] = null;
squares[row][col].destroy();
}
}
// Clear coordinate labels
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child instanceof Text2 && child !== turnText) {
child.destroy();
}
}
// Reinitialize board
for (var row = 0; row < 8; row++) {
board[row] = [];
squares[row] = [];
for (var col = 0; col < 8; col++) {
board[row][col] = null;
var square = new ChessSquare(row, col);
if (playerPerspective === 'black') {
square.x = boardOffsetX + (7 - col) * 200 + 100;
square.y = boardOffsetY + (7 - row) * 200 + 100;
} else {
square.x = boardOffsetX + col * 200 + 100;
square.y = boardOffsetY + row * 200 + 100;
}
squares[row][col] = square;
game.addChild(square);
}
}
// Reinitialize pieces and coordinates
initializePieces();
addCoordinateLabels();
}
function addCoordinateLabels() {
// Add numbers 1-8 on the left side (always from white's perspective)
for (var i = 0; i < 8; i++) {
var rankNumber, rankY;
if (playerPerspective === 'black') {
rankNumber = i + 1;
rankY = boardOffsetY + i * 200 + 100;
} else {
rankNumber = 8 - i;
rankY = boardOffsetY + i * 200 + 100;
}
var rankText = new Text2(rankNumber.toString(), {
size: 40,
fill: 0xFFFFFF
});
rankText.anchor.set(0.5, 0.5);
rankText.x = boardOffsetX - 60;
rankText.y = rankY;
game.addChild(rankText);
}
// Add letters a-h (always from white's perspective)
var files = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
for (var i = 0; i < 8; i++) {
var fileLabel, fileX;
if (playerPerspective === 'black') {
fileLabel = files[7 - i];
fileX = boardOffsetX + i * 200 + 100;
} else {
fileLabel = files[i];
fileX = boardOffsetX + i * 200 + 100;
}
var fileText = new Text2(fileLabel, {
size: 40,
fill: 0xFFFFFF
});
fileText.anchor.set(0.5, 0.5);
fileText.x = fileX;
fileText.y = boardOffsetY + 8 * 200 + 60;
game.addChild(fileText);
}
}
function createTurnIndicator() {
// Add turn indicator
turnText = new Text2('White to move', {
size: 80,
fill: 0xFFFFFF
});
turnText.anchor.set(0.5, 0);
turnText.x = 1024;
turnText.y = 200;
game.addChild(turnText);
}
function createTimerDisplay() {
if (gameMode !== 'online') return;
// White timer
whiteTimerText = new Text2(formatTime(whiteTimeRemaining), {
size: 60,
fill: 0xFFFFFF
});
whiteTimerText.anchor.set(0.5, 0.5);
whiteTimerText.x = boardOffsetX + 1600 - 80;
whiteTimerText.y = boardOffsetY + 1600 + 60;
game.addChild(whiteTimerText);
// Black timer
blackTimerText = new Text2(formatTime(blackTimeRemaining), {
size: 60,
fill: 0xFFFFFF
});
blackTimerText.anchor.set(0.5, 0.5);
blackTimerText.x = boardOffsetX + 1600 - 80;
blackTimerText.y = boardOffsetY - 60;
game.addChild(blackTimerText);
}
function formatTime(seconds) {
var minutes = Math.floor(seconds / 60);
var remainingSeconds = seconds % 60;
return minutes + ':' + (remainingSeconds < 10 ? '0' : '') + remainingSeconds;
}
function startGameTimer() {
if (gameMode !== 'online') return;
lastTimerUpdate = Date.now();
gameTimer = LK.setInterval(function () {
var currentTime = Date.now();
var deltaTime = Math.floor((currentTime - lastTimerUpdate) / 1000);
if (deltaTime >= 1) {
if (currentPlayer === 'white') {
whiteTimeRemaining -= deltaTime;
if (whiteTimeRemaining <= 0) {
whiteTimeRemaining = 0;
handleTimeOut('white');
return;
}
} else {
blackTimeRemaining -= deltaTime;
if (blackTimeRemaining <= 0) {
blackTimeRemaining = 0;
handleTimeOut('black');
return;
}
}
updateTimerDisplay();
lastTimerUpdate = currentTime;
}
}, 100);
}
function updateTimerDisplay() {
if (gameMode !== 'online') return;
if (whiteTimerText) {
whiteTimerText.setText(formatTime(whiteTimeRemaining));
// Highlight current player's timer
if (currentPlayer === 'white') {
whiteTimerText.tint = 0x00ff00;
blackTimerText.tint = 0xffffff;
} else {
whiteTimerText.tint = 0xffffff;
blackTimerText.tint = 0x00ff00;
}
}
if (blackTimerText) {
blackTimerText.setText(formatTime(blackTimeRemaining));
}
}
function handleTimeOut(timedOutPlayer) {
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
gameOver = true;
LK.setTimeout(function () {
if (timedOutPlayer === 'white') {
LK.showGameOver();
} else {
LK.showYouWin();
}
}, 1000);
}
function stopGameTimer() {
if (gameTimer) {
LK.clearInterval(gameTimer);
gameTimer = null;
}
}
// Game starts with main menu - no immediate initialization
game.update = function () {
// Only update turn indicator if not in menu and turnText exists
if (gameMode !== 'menu' && turnText && !gameOver) {
var checkText = '';
var currentPlayerInCheck = isKingInCheck(currentPlayer);
var validMoves = getValidMovesForPlayer(currentPlayer);
if (currentPlayerInCheck) {
if (validMoves.length === 0) {
checkText = ' - CHECKMATE!';
} else {
checkText = ' - CHECK!';
}
}
var turnDisplay = '';
if (gameMode === 'computer') {
if (currentPlayer === playerPerspective) {
turnDisplay = 'Your turn';
} else {
turnDisplay = 'AI thinking...';
}
} else if (gameMode === 'online') {
turnDisplay = currentPlayer === 'white' ? 'White to move' : 'Black to move';
// Add time pressure warning
if (currentPlayer === 'white' && whiteTimeRemaining <= 60) {
turnDisplay += ' (LOW TIME!)';
} else if (currentPlayer === 'black' && blackTimeRemaining <= 60) {
turnDisplay += ' (LOW TIME!)';
}
} else {
turnDisplay = currentPlayer === 'white' ? 'White to move' : 'Black to move';
}
turnText.setText(turnDisplay + checkText);
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1037,19 +1037,19 @@
size: 60,
fill: 0xFFFFFF
});
whiteTimerText.anchor.set(0.5, 0.5);
- whiteTimerText.x = 1024;
- whiteTimerText.y = 1600;
+ whiteTimerText.x = boardOffsetX + 1600 - 80;
+ whiteTimerText.y = boardOffsetY + 1600 + 60;
game.addChild(whiteTimerText);
// Black timer
blackTimerText = new Text2(formatTime(blackTimeRemaining), {
size: 60,
fill: 0xFFFFFF
});
blackTimerText.anchor.set(0.5, 0.5);
- blackTimerText.x = 1024;
- blackTimerText.y = 400;
+ blackTimerText.x = boardOffsetX + 1600 - 80;
+ blackTimerText.y = boardOffsetY - 60;
game.addChild(blackTimerText);
}
function formatTime(seconds) {
var minutes = Math.floor(seconds / 60);