/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
gameHistory: [],
stats: {
wins: 0,
losses: 0,
draws: 0
}
});
/****
* Classes
****/
var Button = Container.expand(function () {
var self = Container.call(this);
self.init = function (text, width, height, color) {
self.background = self.attachAsset('whiteSquare', {
anchorX: 0,
anchorY: 0,
width: width,
height: height,
tint: color || 0x4488FF
});
self.label = new Text2(text, {
size: 50,
//{e} // Increased text size
fill: 0xFFFFFF
});
self.label.anchor.set(0.5, 0.5);
self.label.x = width / 2;
self.label.y = height / 2;
self.addChild(self.label);
return self;
};
self.setEnabled = function (enabled) {
self.enabled = enabled;
self.background.alpha = enabled ? 1 : 0.5;
};
self.down = function (x, y, obj) {
if (self.enabled !== false) {
LK.getSound('movePiece').play();
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
}
};
self.up = function (x, y, obj) {
if (self.enabled !== false) {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
onFinish: function onFinish() {
if (self.onClick) {
self.onClick();
}
}
});
}
};
return self;
});
var ChessGame = Container.expand(function () {
var self = Container.call(this);
// Game state
self.board = [];
self.selectedSquare = null;
self.possibleMoves = [];
self.currentPlayer = 'white';
self.gameOver = false;
self.moveHistory = [];
self.lastMovedPiece = null;
self.lastMoveFrom = null;
self.lastMoveTo = null;
self.inCheck = {
white: false,
black: false
};
self.init = function () {
self.initializeBoard();
self.setupPieces();
self.createControls();
return self;
};
self.initializeBoard = function () {
for (var row = 0; row < 8; row++) {
self.board[row] = [];
for (var col = 0; col < 8; col++) {
var color = (row + col) % 2 === 0 ? 'white' : 'black';
var square = new ChessSquare().init(row, col, color);
square.x = col * SQUARE_SIZE;
square.y = row * SQUARE_SIZE;
self.addChild(square);
self.board[row][col] = square;
}
}
};
self.setupPieces = function () {
// Place pawns
for (var col = 0; col < 8; col++) {
self.placePiece('pawn', 'white', 6, col);
self.placePiece('pawn', 'black', 1, col);
}
// Place rooks
self.placePiece('rook', 'white', 7, 0);
self.placePiece('rook', 'white', 7, 7);
self.placePiece('rook', 'black', 0, 0);
self.placePiece('rook', 'black', 0, 7);
// Place knights
self.placePiece('knight', 'white', 7, 1);
self.placePiece('knight', 'white', 7, 6);
self.placePiece('knight', 'black', 0, 1);
self.placePiece('knight', 'black', 0, 6);
// Place bishops
self.placePiece('bishop', 'white', 7, 2);
self.placePiece('bishop', 'white', 7, 5);
self.placePiece('bishop', 'black', 0, 2);
self.placePiece('bishop', 'black', 0, 5);
// Place queens
self.placePiece('queen', 'white', 7, 3);
self.placePiece('queen', 'black', 0, 3);
// Place kings
self.placePiece('king', 'white', 7, 4);
self.placePiece('king', 'black', 0, 4);
};
self.createControls = function () {
// Undo button
self.undoButton = new Button().init("UNDO", 250, 100); // Increased button size
self.undoButton.x = BOARD_SIZE / 2 - 270; // Positioned to left of center
self.undoButton.y = BOARD_SIZE + 200; // Below indicators
self.addChild(self.undoButton);
self.undoButton.onClick = function () {
self.undoLastMove();
};
self.undoButton.setEnabled(false);
// Reset button
self.resetButton = new Button().init("RESET", 250, 100); // Increased button size
self.resetButton.x = BOARD_SIZE / 2 + 20; // Positioned to right of center
self.resetButton.y = BOARD_SIZE + 200; // Below indicators
self.addChild(self.resetButton);
self.resetButton.onClick = function () {
self.resetGame();
};
// Turn indicator
self.turnIndicator = new Text2("White's Turn", {
size: 60,
//{13} // Increased text size
fill: 0xFFFFFF
});
self.turnIndicator.x = BOARD_SIZE / 2; // Center horizontally on board
self.turnIndicator.y = BOARD_SIZE + 50; // Below board
self.turnIndicator.anchor.set(0.5, 0);
self.addChild(self.turnIndicator);
// Check indicator
self.checkIndicator = new Text2("", {
size: 60,
//{16} // Increased text size
fill: 0xFF0000
});
self.checkIndicator.x = BOARD_SIZE / 2; // Center horizontally on board
self.checkIndicator.y = BOARD_SIZE + 120; // Below turn indicator
self.checkIndicator.anchor.set(0.5, 0);
self.addChild(self.checkIndicator);
};
self.placePiece = function (type, color, row, col) {
var piece = new ChessPiece().init(type, color);
self.board[row][col].setPiece(piece);
};
self.squareClicked = function (square) {
if (self.gameOver || self.currentPlayer === 'black' && AI_ENABLED) return;
if (self.selectedSquare) {
// If selected square is clicked again, deselect it
if (self.selectedSquare === square) {
self.clearSelection();
return;
}
// Check if clicked square is a possible move
if (self.isPossibleMove(square)) {
self.movePiece(self.selectedSquare, square);
return;
}
}
// Check if square has a piece of current player's color
if (square.piece && square.piece.color === self.currentPlayer) {
self.selectSquare(square);
}
};
self.selectSquare = function (square) {
self.clearSelection();
self.selectedSquare = square;
square.setSelected(true);
self.possibleMoves = self.calculatePossibleMoves(square);
// Highlight possible moves
for (var i = 0; i < self.possibleMoves.length; i++) {
var move = self.possibleMoves[i];
self.board[move.row][move.col].setHighlight(true);
}
};
self.clearSelection = function () {
if (self.selectedSquare) {
self.selectedSquare.setSelected(false);
self.selectedSquare = null;
}
// Clear highlights
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
self.board[row][col].setHighlight(false);
}
}
self.possibleMoves = [];
};
self.isPossibleMove = function (square) {
for (var i = 0; i < self.possibleMoves.length; i++) {
var move = self.possibleMoves[i];
if (move.row === square.row && move.col === square.col) {
return true;
}
}
return false;
};
self.movePiece = function (fromSquare, toSquare) {
var piece = fromSquare.piece;
var capturedPiece = toSquare.piece;
var moveRecord = {
piece: piece,
from: {
row: fromSquare.row,
col: fromSquare.col
},
to: {
row: toSquare.row,
col: toSquare.col
},
captured: capturedPiece,
firstMove: !piece.hasMoved,
isCheck: false
};
// Clear any previous 'last move' highlights
if (self.lastMoveFrom) {
self.lastMoveFrom.setLastMove(false);
}
if (self.lastMoveTo) {
self.lastMoveTo.setLastMove(false);
}
// Handle castling
var isCastling = piece.type === 'king' && Math.abs(fromSquare.col - toSquare.col) === 2;
if (isCastling) {
var rookCol = toSquare.col === 6 ? 7 : 0;
var newRookCol = toSquare.col === 6 ? 5 : 3;
var rookSquare = self.board[fromSquare.row][rookCol];
var rook = rookSquare.piece;
moveRecord.castling = {
rook: rook,
from: {
row: fromSquare.row,
col: rookCol
},
to: {
row: fromSquare.row,
col: newRookCol
}
};
// Move the rook
rookSquare.setPiece(null);
self.board[fromSquare.row][newRookCol].setPiece(rook);
rook.hasMoved = true;
LK.getSound('castle').play();
} else if (capturedPiece) {
LK.getSound('capture').play();
} else {
LK.getSound('movePiece').play();
}
// Handle pawn promotion
if (piece.type === 'pawn' && (toSquare.row === 0 || toSquare.row === 7)) {
// Clear the source square first
fromSquare.setPiece(null);
// Create new queen
var newQueen = new ChessPiece().init('queen', piece.color);
// Place the queen on the destination square
toSquare.setPiece(newQueen);
moveRecord.promotion = {
from: 'pawn',
to: 'queen'
};
piece = newQueen;
} else {
// Move the piece
fromSquare.setPiece(null);
toSquare.setPiece(piece);
}
// Mark the piece as moved
piece.hasMoved = true;
// Record the last move for highlighting
self.lastMoveFrom = fromSquare;
self.lastMoveTo = toSquare;
fromSquare.setLastMove(true);
toSquare.setLastMove(true);
// Add move to history
self.moveHistory.push(moveRecord);
// Clear selection
self.clearSelection();
// Switch player
self.currentPlayer = self.currentPlayer === 'white' ? 'black' : 'white';
self.turnIndicator.setText("MissPiece's Turn");
// Check for check or checkmate
self.checkForCheckAndMate();
// Update undo button state
self.undoButton.setEnabled(self.moveHistory.length > 0);
// If AI is enabled and it's black's turn, make AI move
if (AI_ENABLED && self.currentPlayer === 'black' && !self.gameOver) {
LK.setTimeout(function () {
self.makeAIMove();
}, 500);
}
};
self.checkForCheckAndMate = function () {
// Check if current player is in check
var isInCheck = self.isPlayerInCheck(self.currentPlayer);
self.inCheck[self.currentPlayer] = isInCheck;
if (isInCheck) {
// Check if it's checkmate
var hasLegalMoves = self.playerHasLegalMoves(self.currentPlayer);
if (!hasLegalMoves) {
// Checkmate
self.gameOver = true;
self.checkIndicator.setText("Checkmate! " + (self.currentPlayer === 'white' ? "Black" : "White") + " wins!");
// Update stats
var stats = storage.stats || {
wins: 0,
losses: 0,
draws: 0
};
if (self.currentPlayer === 'white') {
stats.losses++;
} else {
stats.wins++;
}
storage.stats = stats;
} else {
// Just check
self.checkIndicator.setText(self.currentPlayer.charAt(0).toUpperCase() + self.currentPlayer.slice(1) + " is in check!");
LK.getSound('check').play();
}
} else {
// Check for stalemate
var hasLegalMoves = self.playerHasLegalMoves(self.currentPlayer);
if (!hasLegalMoves) {
// Stalemate
self.gameOver = true;
self.checkIndicator.setText("Stalemate! Draw game.");
// Update stats
var stats = storage.stats || {
wins: 0,
losses: 0,
draws: 0
};
stats.draws++;
storage.stats = stats;
} else {
self.checkIndicator.setText("");
}
}
};
self.isPlayerInCheck = function (player) {
// Find player's king
var kingPosition;
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
var piece = self.board[row][col].piece;
if (piece && piece.type === 'king' && piece.color === player) {
kingPosition = {
row: row,
col: col
};
break;
}
}
if (kingPosition) break;
}
// Check if any opponent piece can capture the king
var opponent = player === 'white' ? 'black' : 'white';
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
var piece = self.board[row][col].piece;
if (piece && piece.color === opponent) {
var moves = self.getRawPieceMoves(self.board[row][col]);
for (var i = 0; i < moves.length; i++) {
if (moves[i].row === kingPosition.row && moves[i].col === kingPosition.col) {
return true;
}
}
}
}
}
return false;
};
self.playerHasLegalMoves = function (player) {
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
var square = self.board[row][col];
var piece = square.piece;
if (piece && piece.color === player) {
var moves = self.calculatePossibleMoves(square);
if (moves.length > 0) {
return true;
}
}
}
}
return false;
};
self.undoLastMove = function () {
if (self.moveHistory.length === 0) return;
// Get the last move
var lastMove = self.moveHistory.pop();
// If AI is enabled and we're undoing our move and AI's move
if (AI_ENABLED && self.currentPlayer === 'white' && self.moveHistory.length > 0) {
var aiMove = lastMove;
lastMove = self.moveHistory.pop();
self.undoSingleMove(aiMove);
}
self.undoSingleMove(lastMove);
// Update undo button state
self.undoButton.setEnabled(self.moveHistory.length > 0);
// Clear any check status
self.inCheck = {
white: false,
black: false
};
self.checkIndicator.setText("");
// Ensure game over flag is reset
self.gameOver = false;
};
self.undoSingleMove = function (move) {
// Undo the move
var fromSquare = self.board[move.from.row][move.from.col];
var toSquare = self.board[move.to.row][move.to.col];
var piece = toSquare.piece;
// Handle pawn promotion
if (move.promotion) {
piece = new ChessPiece().init('pawn', piece.color);
}
// Move piece back
toSquare.setPiece(null);
fromSquare.setPiece(piece);
// Restore captured piece
if (move.captured) {
toSquare.setPiece(move.captured);
}
// Undo castling
if (move.castling) {
var rookTo = self.board[move.castling.to.row][move.castling.to.col];
var rookFrom = self.board[move.castling.from.row][move.castling.from.col];
var rook = rookTo.piece;
rookTo.setPiece(null);
rookFrom.setPiece(rook);
if (move.firstMove) {
rook.hasMoved = false;
}
}
// Restore first move status
if (move.firstMove) {
piece.hasMoved = false;
}
// Clear last move highlights
if (self.lastMoveFrom) {
self.lastMoveFrom.setLastMove(false);
}
if (self.lastMoveTo) {
self.lastMoveTo.setLastMove(false);
}
// Find the previous move for highlighting
if (self.moveHistory.length > 0) {
var prevMove = self.moveHistory[self.moveHistory.length - 1];
self.lastMoveFrom = self.board[prevMove.from.row][prevMove.from.col];
self.lastMoveTo = self.board[prevMove.to.row][prevMove.to.col];
self.lastMoveFrom.setLastMove(true);
self.lastMoveTo.setLastMove(true);
} else {
self.lastMoveFrom = null;
self.lastMoveTo = null;
}
// Switch player back
self.currentPlayer = self.currentPlayer === 'white' ? 'black' : 'white';
self.turnIndicator.setText(self.currentPlayer.charAt(0).toUpperCase() + self.currentPlayer.slice(1) + "'s Turn");
};
self.resetGame = function () {
// Clear the entire board
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
if (self.board[row][col].piece) {
self.board[row][col].setPiece(null);
}
// Clear highlights
self.board[row][col].setHighlight(false);
self.board[row][col].setSelected(false);
self.board[row][col].setLastMove(false);
}
}
// Clear game state
self.selectedSquare = null;
self.possibleMoves = [];
self.currentPlayer = 'white';
self.gameOver = false;
self.moveHistory = [];
self.lastMovedPiece = null;
self.lastMoveFrom = null;
self.lastMoveTo = null;
self.inCheck = {
white: false,
black: false
};
// Reset UI
self.turnIndicator.setText("White's Turn");
self.checkIndicator.setText("");
self.undoButton.setEnabled(false);
// Re-populate pieces
self.setupPieces();
// Play move sound
LK.getSound('movePiece').play();
};
self.makeAIMove = function () {
// Simple AI - find all possible moves and choose a random one
// For a smarter AI, you'd implement minimax with alpha-beta pruning
var allMoves = [];
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
var square = self.board[row][col];
if (square.piece && square.piece.color === 'black') {
var moves = self.calculatePossibleMoves(square);
for (var i = 0; i < moves.length; i++) {
allMoves.push({
from: square,
to: self.board[moves[i].row][moves[i].col]
});
}
}
}
}
if (allMoves.length > 0) {
// Prioritize captures and checks
var goodMoves = allMoves.filter(function (move) {
// Is this a capture?
if (move.to.piece) return true;
// Would this move put the opponent in check?
// Simulate the move
var fromPiece = move.from.piece;
var toPiece = move.to.piece;
move.from.piece = null;
move.to.piece = fromPiece;
var wouldCauseCheck = self.isPlayerInCheck('white');
// Undo the simulation
move.from.piece = fromPiece;
move.to.piece = toPiece;
return wouldCauseCheck;
});
// If we have any "good" moves, pick from those
var finalMoves = goodMoves.length > 0 ? goodMoves : allMoves;
// Choose a random move
var randomIndex = Math.floor(Math.random() * finalMoves.length);
var aiMove = finalMoves[randomIndex];
// Make the move
self.movePiece(aiMove.from, aiMove.to);
}
};
self.calculatePossibleMoves = function (square) {
var piece = square.piece;
if (!piece) return [];
var rawMoves = self.getRawPieceMoves(square);
var legalMoves = [];
// Filter out moves that would put or leave the king in check
for (var i = 0; i < rawMoves.length; i++) {
var move = rawMoves[i];
var targetSquare = self.board[move.row][move.col];
// Simulate the move
var capturedPiece = targetSquare.piece;
square.piece = null;
targetSquare.piece = piece;
// Check if the move leaves the king in check
var inCheck = self.isPlayerInCheck(piece.color);
// Undo the simulation
square.piece = piece;
targetSquare.piece = capturedPiece;
if (!inCheck) {
legalMoves.push(move);
}
}
return legalMoves;
};
self.getRawPieceMoves = function (square) {
var piece = square.piece;
if (!piece) return [];
var moves = [];
var row = square.row;
var col = square.col;
switch (piece.type) {
case 'pawn':
self.getPawnMoves(piece, row, col, moves);
break;
case 'rook':
self.getRookMoves(piece, row, col, moves);
break;
case 'knight':
self.getKnightMoves(piece, row, col, moves);
break;
case 'bishop':
self.getBishopMoves(piece, row, col, moves);
break;
case 'queen':
self.getQueenMoves(piece, row, col, moves);
break;
case 'king':
self.getKingMoves(piece, row, col, moves);
break;
}
return moves;
};
self.getPawnMoves = function (piece, row, col, moves) {
var direction = piece.color === 'white' ? -1 : 1;
var startRow = piece.color === 'white' ? 6 : 1;
// Forward move
if (self.isInBounds(row + direction, col) && !self.board[row + direction][col].piece) {
moves.push({
row: row + direction,
col: col
});
// Double move from starting position
if (row === startRow && !self.board[row + 2 * direction][col].piece) {
moves.push({
row: row + 2 * direction,
col: col
});
}
}
// Captures
for (var dcol = -1; dcol <= 1; dcol += 2) {
if (self.isInBounds(row + direction, col + dcol)) {
var targetSquare = self.board[row + direction][col + dcol];
if (targetSquare.piece && targetSquare.piece.color !== piece.color) {
moves.push({
row: row + direction,
col: col + dcol
});
}
}
}
};
self.getRookMoves = function (piece, row, col, moves) {
// Horizontal and vertical moves
var directions = [{
dr: 0,
dc: 1
},
// right
{
dr: 0,
dc: -1
},
// left
{
dr: 1,
dc: 0
},
// down
{
dr: -1,
dc: 0
} // up
];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
for (var dist = 1; dist < 8; dist++) {
var newRow = row + dir.dr * dist;
var newCol = col + dir.dc * dist;
if (!self.isInBounds(newRow, newCol)) break;
var targetSquare = self.board[newRow][newCol];
if (!targetSquare.piece) {
moves.push({
row: newRow,
col: newCol
});
} else {
if (targetSquare.piece.color !== piece.color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
}
}
};
self.getKnightMoves = function (piece, row, col, 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
}];
for (var i = 0; i < knightMoves.length; i++) {
var move = knightMoves[i];
var newRow = row + move.dr;
var newCol = col + move.dc;
if (self.isInBounds(newRow, newCol)) {
var targetSquare = self.board[newRow][newCol];
if (!targetSquare.piece || targetSquare.piece.color !== piece.color) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
};
self.getBishopMoves = function (piece, row, col, moves) {
// Diagonal moves
var directions = [{
dr: 1,
dc: 1
},
// down-right
{
dr: 1,
dc: -1
},
// down-left
{
dr: -1,
dc: 1
},
// up-right
{
dr: -1,
dc: -1
} // up-left
];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
for (var dist = 1; dist < 8; dist++) {
var newRow = row + dir.dr * dist;
var newCol = col + dir.dc * dist;
if (!self.isInBounds(newRow, newCol)) break;
var targetSquare = self.board[newRow][newCol];
if (!targetSquare.piece) {
moves.push({
row: newRow,
col: newCol
});
} else {
if (targetSquare.piece.color !== piece.color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
}
}
};
self.getQueenMoves = function (piece, row, col, moves) {
// Queen = Rook + Bishop
self.getRookMoves(piece, row, col, moves);
self.getBishopMoves(piece, row, col, moves);
};
self.getKingMoves = function (piece, row, col, moves) {
// All 8 directions
for (var dr = -1; dr <= 1; dr++) {
for (var dc = -1; dc <= 1; dc++) {
if (dr === 0 && dc === 0) continue;
var newRow = row + dr;
var newCol = col + dc;
if (self.isInBounds(newRow, newCol)) {
var targetSquare = self.board[newRow][newCol];
if (!targetSquare.piece || targetSquare.piece.color !== piece.color) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
}
// Castling
if (!piece.hasMoved && !self.inCheck[piece.color]) {
// Kingside castling
if (self.canCastle(row, col, 0, 3)) {
moves.push({
row: row,
col: col + 2
});
}
// Queenside castling
if (self.canCastle(row, col, 0, -4)) {
moves.push({
row: row,
col: col - 2
});
}
}
};
self.canCastle = function (row, col, rowOffset, colOffset) {
var direction = colOffset > 0 ? 1 : -1;
var distance = Math.abs(colOffset);
// Check if the rook is there and hasn't moved
var rookCol = direction > 0 ? 7 : 0;
var rookSquare = self.board[row][rookCol];
if (!rookSquare.piece || rookSquare.piece.type !== 'rook' || rookSquare.piece.color !== self.currentPlayer || rookSquare.piece.hasMoved) {
return false;
}
// Check if the squares between king and rook are empty
for (var i = 1; i < distance; i++) {
var checkCol = col + i * direction;
if (self.board[row][checkCol].piece) {
return false;
}
}
// Check if the king passes through or ends up in check
for (var i = 0; i <= 2; i++) {
var checkCol = col + i * direction;
// Simulate the king at this position
var originalSquare = self.board[row][col];
var checkSquare = self.board[row][checkCol];
var kingPiece = originalSquare.piece;
var tempPiece = checkSquare.piece;
originalSquare.piece = null;
checkSquare.piece = kingPiece;
var inCheck = self.isPlayerInCheck(self.currentPlayer);
// Restore board
originalSquare.piece = kingPiece;
checkSquare.piece = tempPiece;
if (inCheck) {
return false;
}
}
return true;
};
self.isInBounds = function (row, col) {
return row >= 0 && row < 8 && col >= 0 && col < 8;
};
return self;
});
var ChessPiece = Container.expand(function () {
var self = Container.call(this);
self.init = function (type, color) {
self.type = type;
self.color = color;
self.hasMoved = false;
var assetId = color + type.charAt(0).toUpperCase() + type.slice(1);
var pieceAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// No letters on pieces
return self;
};
return self;
});
var ChessSquare = Container.expand(function () {
var self = Container.call(this);
self.init = function (row, col, color) {
self.row = row;
self.col = col;
self.color = color;
self.piece = null;
var squareAsset = self.attachAsset(color === 'white' ? 'whiteSquare' : 'blackSquare', {
anchorX: 0,
anchorY: 0,
width: SQUARE_SIZE,
height: SQUARE_SIZE
});
self.highlight = self.attachAsset('highlight', {
anchorX: 0,
anchorY: 0,
width: SQUARE_SIZE,
height: SQUARE_SIZE,
alpha: 0
});
self.selected = self.attachAsset('selected', {
anchorX: 0,
anchorY: 0,
width: SQUARE_SIZE,
height: SQUARE_SIZE,
alpha: 0
});
self.lastMove = self.attachAsset('lastMove', {
anchorX: 0,
anchorY: 0,
width: SQUARE_SIZE,
height: SQUARE_SIZE,
alpha: 0
});
return self;
};
self.setHighlight = function (value) {
self.highlight.alpha = value ? 0.5 : 0;
};
self.setSelected = function (value) {
self.selected.alpha = value ? 0.5 : 0;
};
self.setLastMove = function (value) {
self.lastMove.alpha = value ? 0.3 : 0;
};
self.setPiece = function (piece) {
if (self.piece) {
self.removeChild(self.piece);
}
self.piece = piece;
if (piece) {
self.addChild(piece);
piece.x = SQUARE_SIZE / 2;
piece.y = SQUARE_SIZE / 2;
}
};
self.down = function (x, y, obj) {
chessGame.squareClicked(self);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x333333
});
/****
* Game Code
****/
// Constants
var SQUARE_SIZE = 200; // Increased square size
var BOARD_SIZE = SQUARE_SIZE * 8;
var AI_ENABLED = true;
// Center the board horizontally and vertically
var boardOffsetX = (2048 - BOARD_SIZE) / 2;
var boardOffsetY = (2732 - BOARD_SIZE) / 2 - 100; // Center vertically with offset for title
// Create chess game
var chessGame = new ChessGame().init();
chessGame.x = boardOffsetX;
chessGame.y = boardOffsetY;
game.addChild(chessGame);
// Add title
var title = new Text2("Play against MissPiece", {
size: 120,
// Increased text size
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0);
title.x = 2048 / 2;
title.y = 50; // Adjusted position
game.addChild(title);
// No instructions text needed
// Play background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
}); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
gameHistory: [],
stats: {
wins: 0,
losses: 0,
draws: 0
}
});
/****
* Classes
****/
var Button = Container.expand(function () {
var self = Container.call(this);
self.init = function (text, width, height, color) {
self.background = self.attachAsset('whiteSquare', {
anchorX: 0,
anchorY: 0,
width: width,
height: height,
tint: color || 0x4488FF
});
self.label = new Text2(text, {
size: 50,
//{e} // Increased text size
fill: 0xFFFFFF
});
self.label.anchor.set(0.5, 0.5);
self.label.x = width / 2;
self.label.y = height / 2;
self.addChild(self.label);
return self;
};
self.setEnabled = function (enabled) {
self.enabled = enabled;
self.background.alpha = enabled ? 1 : 0.5;
};
self.down = function (x, y, obj) {
if (self.enabled !== false) {
LK.getSound('movePiece').play();
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
}
};
self.up = function (x, y, obj) {
if (self.enabled !== false) {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100,
onFinish: function onFinish() {
if (self.onClick) {
self.onClick();
}
}
});
}
};
return self;
});
var ChessGame = Container.expand(function () {
var self = Container.call(this);
// Game state
self.board = [];
self.selectedSquare = null;
self.possibleMoves = [];
self.currentPlayer = 'white';
self.gameOver = false;
self.moveHistory = [];
self.lastMovedPiece = null;
self.lastMoveFrom = null;
self.lastMoveTo = null;
self.inCheck = {
white: false,
black: false
};
self.init = function () {
self.initializeBoard();
self.setupPieces();
self.createControls();
return self;
};
self.initializeBoard = function () {
for (var row = 0; row < 8; row++) {
self.board[row] = [];
for (var col = 0; col < 8; col++) {
var color = (row + col) % 2 === 0 ? 'white' : 'black';
var square = new ChessSquare().init(row, col, color);
square.x = col * SQUARE_SIZE;
square.y = row * SQUARE_SIZE;
self.addChild(square);
self.board[row][col] = square;
}
}
};
self.setupPieces = function () {
// Place pawns
for (var col = 0; col < 8; col++) {
self.placePiece('pawn', 'white', 6, col);
self.placePiece('pawn', 'black', 1, col);
}
// Place rooks
self.placePiece('rook', 'white', 7, 0);
self.placePiece('rook', 'white', 7, 7);
self.placePiece('rook', 'black', 0, 0);
self.placePiece('rook', 'black', 0, 7);
// Place knights
self.placePiece('knight', 'white', 7, 1);
self.placePiece('knight', 'white', 7, 6);
self.placePiece('knight', 'black', 0, 1);
self.placePiece('knight', 'black', 0, 6);
// Place bishops
self.placePiece('bishop', 'white', 7, 2);
self.placePiece('bishop', 'white', 7, 5);
self.placePiece('bishop', 'black', 0, 2);
self.placePiece('bishop', 'black', 0, 5);
// Place queens
self.placePiece('queen', 'white', 7, 3);
self.placePiece('queen', 'black', 0, 3);
// Place kings
self.placePiece('king', 'white', 7, 4);
self.placePiece('king', 'black', 0, 4);
};
self.createControls = function () {
// Undo button
self.undoButton = new Button().init("UNDO", 250, 100); // Increased button size
self.undoButton.x = BOARD_SIZE / 2 - 270; // Positioned to left of center
self.undoButton.y = BOARD_SIZE + 200; // Below indicators
self.addChild(self.undoButton);
self.undoButton.onClick = function () {
self.undoLastMove();
};
self.undoButton.setEnabled(false);
// Reset button
self.resetButton = new Button().init("RESET", 250, 100); // Increased button size
self.resetButton.x = BOARD_SIZE / 2 + 20; // Positioned to right of center
self.resetButton.y = BOARD_SIZE + 200; // Below indicators
self.addChild(self.resetButton);
self.resetButton.onClick = function () {
self.resetGame();
};
// Turn indicator
self.turnIndicator = new Text2("White's Turn", {
size: 60,
//{13} // Increased text size
fill: 0xFFFFFF
});
self.turnIndicator.x = BOARD_SIZE / 2; // Center horizontally on board
self.turnIndicator.y = BOARD_SIZE + 50; // Below board
self.turnIndicator.anchor.set(0.5, 0);
self.addChild(self.turnIndicator);
// Check indicator
self.checkIndicator = new Text2("", {
size: 60,
//{16} // Increased text size
fill: 0xFF0000
});
self.checkIndicator.x = BOARD_SIZE / 2; // Center horizontally on board
self.checkIndicator.y = BOARD_SIZE + 120; // Below turn indicator
self.checkIndicator.anchor.set(0.5, 0);
self.addChild(self.checkIndicator);
};
self.placePiece = function (type, color, row, col) {
var piece = new ChessPiece().init(type, color);
self.board[row][col].setPiece(piece);
};
self.squareClicked = function (square) {
if (self.gameOver || self.currentPlayer === 'black' && AI_ENABLED) return;
if (self.selectedSquare) {
// If selected square is clicked again, deselect it
if (self.selectedSquare === square) {
self.clearSelection();
return;
}
// Check if clicked square is a possible move
if (self.isPossibleMove(square)) {
self.movePiece(self.selectedSquare, square);
return;
}
}
// Check if square has a piece of current player's color
if (square.piece && square.piece.color === self.currentPlayer) {
self.selectSquare(square);
}
};
self.selectSquare = function (square) {
self.clearSelection();
self.selectedSquare = square;
square.setSelected(true);
self.possibleMoves = self.calculatePossibleMoves(square);
// Highlight possible moves
for (var i = 0; i < self.possibleMoves.length; i++) {
var move = self.possibleMoves[i];
self.board[move.row][move.col].setHighlight(true);
}
};
self.clearSelection = function () {
if (self.selectedSquare) {
self.selectedSquare.setSelected(false);
self.selectedSquare = null;
}
// Clear highlights
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
self.board[row][col].setHighlight(false);
}
}
self.possibleMoves = [];
};
self.isPossibleMove = function (square) {
for (var i = 0; i < self.possibleMoves.length; i++) {
var move = self.possibleMoves[i];
if (move.row === square.row && move.col === square.col) {
return true;
}
}
return false;
};
self.movePiece = function (fromSquare, toSquare) {
var piece = fromSquare.piece;
var capturedPiece = toSquare.piece;
var moveRecord = {
piece: piece,
from: {
row: fromSquare.row,
col: fromSquare.col
},
to: {
row: toSquare.row,
col: toSquare.col
},
captured: capturedPiece,
firstMove: !piece.hasMoved,
isCheck: false
};
// Clear any previous 'last move' highlights
if (self.lastMoveFrom) {
self.lastMoveFrom.setLastMove(false);
}
if (self.lastMoveTo) {
self.lastMoveTo.setLastMove(false);
}
// Handle castling
var isCastling = piece.type === 'king' && Math.abs(fromSquare.col - toSquare.col) === 2;
if (isCastling) {
var rookCol = toSquare.col === 6 ? 7 : 0;
var newRookCol = toSquare.col === 6 ? 5 : 3;
var rookSquare = self.board[fromSquare.row][rookCol];
var rook = rookSquare.piece;
moveRecord.castling = {
rook: rook,
from: {
row: fromSquare.row,
col: rookCol
},
to: {
row: fromSquare.row,
col: newRookCol
}
};
// Move the rook
rookSquare.setPiece(null);
self.board[fromSquare.row][newRookCol].setPiece(rook);
rook.hasMoved = true;
LK.getSound('castle').play();
} else if (capturedPiece) {
LK.getSound('capture').play();
} else {
LK.getSound('movePiece').play();
}
// Handle pawn promotion
if (piece.type === 'pawn' && (toSquare.row === 0 || toSquare.row === 7)) {
// Clear the source square first
fromSquare.setPiece(null);
// Create new queen
var newQueen = new ChessPiece().init('queen', piece.color);
// Place the queen on the destination square
toSquare.setPiece(newQueen);
moveRecord.promotion = {
from: 'pawn',
to: 'queen'
};
piece = newQueen;
} else {
// Move the piece
fromSquare.setPiece(null);
toSquare.setPiece(piece);
}
// Mark the piece as moved
piece.hasMoved = true;
// Record the last move for highlighting
self.lastMoveFrom = fromSquare;
self.lastMoveTo = toSquare;
fromSquare.setLastMove(true);
toSquare.setLastMove(true);
// Add move to history
self.moveHistory.push(moveRecord);
// Clear selection
self.clearSelection();
// Switch player
self.currentPlayer = self.currentPlayer === 'white' ? 'black' : 'white';
self.turnIndicator.setText("MissPiece's Turn");
// Check for check or checkmate
self.checkForCheckAndMate();
// Update undo button state
self.undoButton.setEnabled(self.moveHistory.length > 0);
// If AI is enabled and it's black's turn, make AI move
if (AI_ENABLED && self.currentPlayer === 'black' && !self.gameOver) {
LK.setTimeout(function () {
self.makeAIMove();
}, 500);
}
};
self.checkForCheckAndMate = function () {
// Check if current player is in check
var isInCheck = self.isPlayerInCheck(self.currentPlayer);
self.inCheck[self.currentPlayer] = isInCheck;
if (isInCheck) {
// Check if it's checkmate
var hasLegalMoves = self.playerHasLegalMoves(self.currentPlayer);
if (!hasLegalMoves) {
// Checkmate
self.gameOver = true;
self.checkIndicator.setText("Checkmate! " + (self.currentPlayer === 'white' ? "Black" : "White") + " wins!");
// Update stats
var stats = storage.stats || {
wins: 0,
losses: 0,
draws: 0
};
if (self.currentPlayer === 'white') {
stats.losses++;
} else {
stats.wins++;
}
storage.stats = stats;
} else {
// Just check
self.checkIndicator.setText(self.currentPlayer.charAt(0).toUpperCase() + self.currentPlayer.slice(1) + " is in check!");
LK.getSound('check').play();
}
} else {
// Check for stalemate
var hasLegalMoves = self.playerHasLegalMoves(self.currentPlayer);
if (!hasLegalMoves) {
// Stalemate
self.gameOver = true;
self.checkIndicator.setText("Stalemate! Draw game.");
// Update stats
var stats = storage.stats || {
wins: 0,
losses: 0,
draws: 0
};
stats.draws++;
storage.stats = stats;
} else {
self.checkIndicator.setText("");
}
}
};
self.isPlayerInCheck = function (player) {
// Find player's king
var kingPosition;
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
var piece = self.board[row][col].piece;
if (piece && piece.type === 'king' && piece.color === player) {
kingPosition = {
row: row,
col: col
};
break;
}
}
if (kingPosition) break;
}
// Check if any opponent piece can capture the king
var opponent = player === 'white' ? 'black' : 'white';
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
var piece = self.board[row][col].piece;
if (piece && piece.color === opponent) {
var moves = self.getRawPieceMoves(self.board[row][col]);
for (var i = 0; i < moves.length; i++) {
if (moves[i].row === kingPosition.row && moves[i].col === kingPosition.col) {
return true;
}
}
}
}
}
return false;
};
self.playerHasLegalMoves = function (player) {
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
var square = self.board[row][col];
var piece = square.piece;
if (piece && piece.color === player) {
var moves = self.calculatePossibleMoves(square);
if (moves.length > 0) {
return true;
}
}
}
}
return false;
};
self.undoLastMove = function () {
if (self.moveHistory.length === 0) return;
// Get the last move
var lastMove = self.moveHistory.pop();
// If AI is enabled and we're undoing our move and AI's move
if (AI_ENABLED && self.currentPlayer === 'white' && self.moveHistory.length > 0) {
var aiMove = lastMove;
lastMove = self.moveHistory.pop();
self.undoSingleMove(aiMove);
}
self.undoSingleMove(lastMove);
// Update undo button state
self.undoButton.setEnabled(self.moveHistory.length > 0);
// Clear any check status
self.inCheck = {
white: false,
black: false
};
self.checkIndicator.setText("");
// Ensure game over flag is reset
self.gameOver = false;
};
self.undoSingleMove = function (move) {
// Undo the move
var fromSquare = self.board[move.from.row][move.from.col];
var toSquare = self.board[move.to.row][move.to.col];
var piece = toSquare.piece;
// Handle pawn promotion
if (move.promotion) {
piece = new ChessPiece().init('pawn', piece.color);
}
// Move piece back
toSquare.setPiece(null);
fromSquare.setPiece(piece);
// Restore captured piece
if (move.captured) {
toSquare.setPiece(move.captured);
}
// Undo castling
if (move.castling) {
var rookTo = self.board[move.castling.to.row][move.castling.to.col];
var rookFrom = self.board[move.castling.from.row][move.castling.from.col];
var rook = rookTo.piece;
rookTo.setPiece(null);
rookFrom.setPiece(rook);
if (move.firstMove) {
rook.hasMoved = false;
}
}
// Restore first move status
if (move.firstMove) {
piece.hasMoved = false;
}
// Clear last move highlights
if (self.lastMoveFrom) {
self.lastMoveFrom.setLastMove(false);
}
if (self.lastMoveTo) {
self.lastMoveTo.setLastMove(false);
}
// Find the previous move for highlighting
if (self.moveHistory.length > 0) {
var prevMove = self.moveHistory[self.moveHistory.length - 1];
self.lastMoveFrom = self.board[prevMove.from.row][prevMove.from.col];
self.lastMoveTo = self.board[prevMove.to.row][prevMove.to.col];
self.lastMoveFrom.setLastMove(true);
self.lastMoveTo.setLastMove(true);
} else {
self.lastMoveFrom = null;
self.lastMoveTo = null;
}
// Switch player back
self.currentPlayer = self.currentPlayer === 'white' ? 'black' : 'white';
self.turnIndicator.setText(self.currentPlayer.charAt(0).toUpperCase() + self.currentPlayer.slice(1) + "'s Turn");
};
self.resetGame = function () {
// Clear the entire board
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
if (self.board[row][col].piece) {
self.board[row][col].setPiece(null);
}
// Clear highlights
self.board[row][col].setHighlight(false);
self.board[row][col].setSelected(false);
self.board[row][col].setLastMove(false);
}
}
// Clear game state
self.selectedSquare = null;
self.possibleMoves = [];
self.currentPlayer = 'white';
self.gameOver = false;
self.moveHistory = [];
self.lastMovedPiece = null;
self.lastMoveFrom = null;
self.lastMoveTo = null;
self.inCheck = {
white: false,
black: false
};
// Reset UI
self.turnIndicator.setText("White's Turn");
self.checkIndicator.setText("");
self.undoButton.setEnabled(false);
// Re-populate pieces
self.setupPieces();
// Play move sound
LK.getSound('movePiece').play();
};
self.makeAIMove = function () {
// Simple AI - find all possible moves and choose a random one
// For a smarter AI, you'd implement minimax with alpha-beta pruning
var allMoves = [];
for (var row = 0; row < 8; row++) {
for (var col = 0; col < 8; col++) {
var square = self.board[row][col];
if (square.piece && square.piece.color === 'black') {
var moves = self.calculatePossibleMoves(square);
for (var i = 0; i < moves.length; i++) {
allMoves.push({
from: square,
to: self.board[moves[i].row][moves[i].col]
});
}
}
}
}
if (allMoves.length > 0) {
// Prioritize captures and checks
var goodMoves = allMoves.filter(function (move) {
// Is this a capture?
if (move.to.piece) return true;
// Would this move put the opponent in check?
// Simulate the move
var fromPiece = move.from.piece;
var toPiece = move.to.piece;
move.from.piece = null;
move.to.piece = fromPiece;
var wouldCauseCheck = self.isPlayerInCheck('white');
// Undo the simulation
move.from.piece = fromPiece;
move.to.piece = toPiece;
return wouldCauseCheck;
});
// If we have any "good" moves, pick from those
var finalMoves = goodMoves.length > 0 ? goodMoves : allMoves;
// Choose a random move
var randomIndex = Math.floor(Math.random() * finalMoves.length);
var aiMove = finalMoves[randomIndex];
// Make the move
self.movePiece(aiMove.from, aiMove.to);
}
};
self.calculatePossibleMoves = function (square) {
var piece = square.piece;
if (!piece) return [];
var rawMoves = self.getRawPieceMoves(square);
var legalMoves = [];
// Filter out moves that would put or leave the king in check
for (var i = 0; i < rawMoves.length; i++) {
var move = rawMoves[i];
var targetSquare = self.board[move.row][move.col];
// Simulate the move
var capturedPiece = targetSquare.piece;
square.piece = null;
targetSquare.piece = piece;
// Check if the move leaves the king in check
var inCheck = self.isPlayerInCheck(piece.color);
// Undo the simulation
square.piece = piece;
targetSquare.piece = capturedPiece;
if (!inCheck) {
legalMoves.push(move);
}
}
return legalMoves;
};
self.getRawPieceMoves = function (square) {
var piece = square.piece;
if (!piece) return [];
var moves = [];
var row = square.row;
var col = square.col;
switch (piece.type) {
case 'pawn':
self.getPawnMoves(piece, row, col, moves);
break;
case 'rook':
self.getRookMoves(piece, row, col, moves);
break;
case 'knight':
self.getKnightMoves(piece, row, col, moves);
break;
case 'bishop':
self.getBishopMoves(piece, row, col, moves);
break;
case 'queen':
self.getQueenMoves(piece, row, col, moves);
break;
case 'king':
self.getKingMoves(piece, row, col, moves);
break;
}
return moves;
};
self.getPawnMoves = function (piece, row, col, moves) {
var direction = piece.color === 'white' ? -1 : 1;
var startRow = piece.color === 'white' ? 6 : 1;
// Forward move
if (self.isInBounds(row + direction, col) && !self.board[row + direction][col].piece) {
moves.push({
row: row + direction,
col: col
});
// Double move from starting position
if (row === startRow && !self.board[row + 2 * direction][col].piece) {
moves.push({
row: row + 2 * direction,
col: col
});
}
}
// Captures
for (var dcol = -1; dcol <= 1; dcol += 2) {
if (self.isInBounds(row + direction, col + dcol)) {
var targetSquare = self.board[row + direction][col + dcol];
if (targetSquare.piece && targetSquare.piece.color !== piece.color) {
moves.push({
row: row + direction,
col: col + dcol
});
}
}
}
};
self.getRookMoves = function (piece, row, col, moves) {
// Horizontal and vertical moves
var directions = [{
dr: 0,
dc: 1
},
// right
{
dr: 0,
dc: -1
},
// left
{
dr: 1,
dc: 0
},
// down
{
dr: -1,
dc: 0
} // up
];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
for (var dist = 1; dist < 8; dist++) {
var newRow = row + dir.dr * dist;
var newCol = col + dir.dc * dist;
if (!self.isInBounds(newRow, newCol)) break;
var targetSquare = self.board[newRow][newCol];
if (!targetSquare.piece) {
moves.push({
row: newRow,
col: newCol
});
} else {
if (targetSquare.piece.color !== piece.color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
}
}
};
self.getKnightMoves = function (piece, row, col, 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
}];
for (var i = 0; i < knightMoves.length; i++) {
var move = knightMoves[i];
var newRow = row + move.dr;
var newCol = col + move.dc;
if (self.isInBounds(newRow, newCol)) {
var targetSquare = self.board[newRow][newCol];
if (!targetSquare.piece || targetSquare.piece.color !== piece.color) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
};
self.getBishopMoves = function (piece, row, col, moves) {
// Diagonal moves
var directions = [{
dr: 1,
dc: 1
},
// down-right
{
dr: 1,
dc: -1
},
// down-left
{
dr: -1,
dc: 1
},
// up-right
{
dr: -1,
dc: -1
} // up-left
];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
for (var dist = 1; dist < 8; dist++) {
var newRow = row + dir.dr * dist;
var newCol = col + dir.dc * dist;
if (!self.isInBounds(newRow, newCol)) break;
var targetSquare = self.board[newRow][newCol];
if (!targetSquare.piece) {
moves.push({
row: newRow,
col: newCol
});
} else {
if (targetSquare.piece.color !== piece.color) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
}
}
};
self.getQueenMoves = function (piece, row, col, moves) {
// Queen = Rook + Bishop
self.getRookMoves(piece, row, col, moves);
self.getBishopMoves(piece, row, col, moves);
};
self.getKingMoves = function (piece, row, col, moves) {
// All 8 directions
for (var dr = -1; dr <= 1; dr++) {
for (var dc = -1; dc <= 1; dc++) {
if (dr === 0 && dc === 0) continue;
var newRow = row + dr;
var newCol = col + dc;
if (self.isInBounds(newRow, newCol)) {
var targetSquare = self.board[newRow][newCol];
if (!targetSquare.piece || targetSquare.piece.color !== piece.color) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
}
// Castling
if (!piece.hasMoved && !self.inCheck[piece.color]) {
// Kingside castling
if (self.canCastle(row, col, 0, 3)) {
moves.push({
row: row,
col: col + 2
});
}
// Queenside castling
if (self.canCastle(row, col, 0, -4)) {
moves.push({
row: row,
col: col - 2
});
}
}
};
self.canCastle = function (row, col, rowOffset, colOffset) {
var direction = colOffset > 0 ? 1 : -1;
var distance = Math.abs(colOffset);
// Check if the rook is there and hasn't moved
var rookCol = direction > 0 ? 7 : 0;
var rookSquare = self.board[row][rookCol];
if (!rookSquare.piece || rookSquare.piece.type !== 'rook' || rookSquare.piece.color !== self.currentPlayer || rookSquare.piece.hasMoved) {
return false;
}
// Check if the squares between king and rook are empty
for (var i = 1; i < distance; i++) {
var checkCol = col + i * direction;
if (self.board[row][checkCol].piece) {
return false;
}
}
// Check if the king passes through or ends up in check
for (var i = 0; i <= 2; i++) {
var checkCol = col + i * direction;
// Simulate the king at this position
var originalSquare = self.board[row][col];
var checkSquare = self.board[row][checkCol];
var kingPiece = originalSquare.piece;
var tempPiece = checkSquare.piece;
originalSquare.piece = null;
checkSquare.piece = kingPiece;
var inCheck = self.isPlayerInCheck(self.currentPlayer);
// Restore board
originalSquare.piece = kingPiece;
checkSquare.piece = tempPiece;
if (inCheck) {
return false;
}
}
return true;
};
self.isInBounds = function (row, col) {
return row >= 0 && row < 8 && col >= 0 && col < 8;
};
return self;
});
var ChessPiece = Container.expand(function () {
var self = Container.call(this);
self.init = function (type, color) {
self.type = type;
self.color = color;
self.hasMoved = false;
var assetId = color + type.charAt(0).toUpperCase() + type.slice(1);
var pieceAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
// No letters on pieces
return self;
};
return self;
});
var ChessSquare = Container.expand(function () {
var self = Container.call(this);
self.init = function (row, col, color) {
self.row = row;
self.col = col;
self.color = color;
self.piece = null;
var squareAsset = self.attachAsset(color === 'white' ? 'whiteSquare' : 'blackSquare', {
anchorX: 0,
anchorY: 0,
width: SQUARE_SIZE,
height: SQUARE_SIZE
});
self.highlight = self.attachAsset('highlight', {
anchorX: 0,
anchorY: 0,
width: SQUARE_SIZE,
height: SQUARE_SIZE,
alpha: 0
});
self.selected = self.attachAsset('selected', {
anchorX: 0,
anchorY: 0,
width: SQUARE_SIZE,
height: SQUARE_SIZE,
alpha: 0
});
self.lastMove = self.attachAsset('lastMove', {
anchorX: 0,
anchorY: 0,
width: SQUARE_SIZE,
height: SQUARE_SIZE,
alpha: 0
});
return self;
};
self.setHighlight = function (value) {
self.highlight.alpha = value ? 0.5 : 0;
};
self.setSelected = function (value) {
self.selected.alpha = value ? 0.5 : 0;
};
self.setLastMove = function (value) {
self.lastMove.alpha = value ? 0.3 : 0;
};
self.setPiece = function (piece) {
if (self.piece) {
self.removeChild(self.piece);
}
self.piece = piece;
if (piece) {
self.addChild(piece);
piece.x = SQUARE_SIZE / 2;
piece.y = SQUARE_SIZE / 2;
}
};
self.down = function (x, y, obj) {
chessGame.squareClicked(self);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x333333
});
/****
* Game Code
****/
// Constants
var SQUARE_SIZE = 200; // Increased square size
var BOARD_SIZE = SQUARE_SIZE * 8;
var AI_ENABLED = true;
// Center the board horizontally and vertically
var boardOffsetX = (2048 - BOARD_SIZE) / 2;
var boardOffsetY = (2732 - BOARD_SIZE) / 2 - 100; // Center vertically with offset for title
// Create chess game
var chessGame = new ChessGame().init();
chessGame.x = boardOffsetX;
chessGame.y = boardOffsetY;
game.addChild(chessGame);
// Add title
var title = new Text2("Play against MissPiece", {
size: 120,
// Increased text size
fill: 0xFFFFFF
});
title.anchor.set(0.5, 0);
title.x = 2048 / 2;
title.y = 50; // Adjusted position
game.addChild(title);
// No instructions text needed
// Play background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});