User prompt
Remove the lion's L movement to the right and left
User prompt
Add the L movement to Lion
User prompt
The lion can jump a maximum of 3 squares
User prompt
The lion can only jump 3 squares
User prompt
New piece = Lion Movement = Can jump 3 squares diagonally or at least 1 square diagonally, 1 square forward, and 1 square diagonally
User prompt
giraffe Moves diagonally across a square and then horizontally or vertically at least three times, but the squares it passes through must be empty
User prompt
New piece = Giraffe Position = Next to the Vizier and Minister Movements = Moves diagonally one square and then horizontally or vertically at least three squares, or four squares if desired, but the squares it passes through must be empty
User prompt
royalGuard cannot move one step in a column or row
User prompt
royalGuard cannot move to the left or right L
User prompt
Change royalGuard moves: Move = can move up to 3 squares diagonally with the blockage of a friendly piece, or only 2 squares along rows and columns, or only forward or backward in an L shape
User prompt
Change royalGuard moves: Move = can move up to 3 squares diagonally or 2 squares along rows and columns, blocked by a friendly piece, or can only move forward and backward in an L shape
User prompt
Change royalGuard moves: Move = can jump up to 3 squares diagonally with the help of a friendly piece, or move up to 2 squares along rows and columns, or simply move forward and backward in an L shape
User prompt
Change royalGuard moves: Move = can jump up to 3 squares diagonally or 2 squares along rows and columns, or can only move forward and backward in an L shape
User prompt
Change royalGuard moves: Move = 3 squares diagonally or 2 squares along a row or column, or 1 square diagonally then 1 column
User prompt
Change the bishop's moves: Move = 1 square row, column, or at least 2 squares diagonally. If there are friendly pieces in the path, the bishop cannot move further.
User prompt
Change the bishop's moves: Move = 1 square row, column, or at least 2 squares diagonally. If there are friendly pieces in the path, the pieces cannot move further
User prompt
Change the bishop's moves: Move = 1 square row, column, or at least 2 squares diagonally. If there are other pieces in the way, it cannot jump over them
User prompt
Change the bishop's moves: Move = 1 square row, column, or as many diagonal squares as desired, provided they are at least 2 squares apart. If there are other pieces in the way, the bishop cannot jump over them
User prompt
Change the bishop's moves: Move = 1 square row, column, or as many diagonal squares as desired, at least 2 squares; cannot jump over pieces
User prompt
Change the bishop's moves: Move = 1 square row, column, or as many diagonal squares as desired, provided they are at least 2 squares apart
User prompt
Change the movements of the siegeTower: Movement = Must move 1 square in a row or column, then 1 square diagonally. If there is a friendly piece in the path, it can move 1 step in a row or column. Special ability = Captures enemy pieces in its path while moving.
User prompt
Change the movements of the War Machine: Movement = Must move 1 step in a row or column, then 1 step diagonally. If there is a friendly piece in the path, it can move 1 step in a row or column. Special ability = Captures enemy pieces in its path while moving
User prompt
Change the elephant's movements: Movement = 1 step row, column, and diagonal or 2 steps row, column, and diagonal. During this movement, the elephant can jump over pieces
User prompt
Change the elephant's movements: Movement = 1 step row and column or 2 steps row and column. During this movement, the elephant can jump over peices
Code edit (1 edits merged)
Please save this source code
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ChessPiece = Container.expand(function (type, color, row, col) {
var self = Container.call(this);
self.pieceType = type;
self.pieceColor = color; // 0 = white, 1 = black
self.boardRow = row;
self.boardCol = col;
self.hasMoved = false;
self.isPromoted = false; // Track permanent promotion status for vizier
var pieceGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
if (color === 1) {
pieceGraphics.tint = 0x333333;
}
self.moveTo = function (newRow, newCol) {
self.boardRow = newRow;
self.boardCol = newCol;
self.hasMoved = true;
var boardPos = getBoardPosition(newRow, newCol);
tween(self, {
x: boardPos.x,
y: boardPos.y
}, {
duration: 300
});
};
self.getRawMoves = function () {
var moves = [];
var directions = [];
switch (self.pieceType) {
case 'pawn':
var direction = self.pieceColor === 0 ? -1 : 1;
var startRow = self.pieceColor === 0 ? 7 : 2;
// Forward move
if (isValidSquare(self.boardRow + direction, self.boardCol) && !getPieceAt(self.boardRow + direction, self.boardCol)) {
moves.push({
row: self.boardRow + direction,
col: self.boardCol
});
// Double move from start
if (self.boardRow === startRow && !getPieceAt(self.boardRow + 2 * direction, self.boardCol)) {
moves.push({
row: self.boardRow + 2 * direction,
col: self.boardCol
});
}
}
// Diagonal captures
for (var dc = -1; dc <= 1; dc += 2) {
var newRow = self.boardRow + direction;
var newCol = self.boardCol + dc;
if (isValidSquare(newRow, newCol)) {
var piece = getPieceAt(newRow, newCol);
if (piece && piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
// En passant
if (lastMove && lastMove.piece.pieceType === 'pawn' && Math.abs(lastMove.fromRow - lastMove.toRow) === 2) {
if (lastMove.toRow === self.boardRow && Math.abs(lastMove.toCol - self.boardCol) === 1) {
moves.push({
row: self.boardRow + direction,
col: lastMove.toCol,
isEnPassant: true,
captureRow: lastMove.toRow,
captureCol: lastMove.toCol
});
}
}
}
break;
case 'rook':
directions = [{
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
for (var dist = 1; dist < 11; dist++) {
var newRow = self.boardRow + dir.dr * dist;
var newCol = self.boardCol + dir.dc * dist;
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
if (piece) {
if (piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
moves.push({
row: newRow,
col: newCol
});
}
}
break;
case 'bishop':
// Bishop: 1 square row/column or at least 2 squares diagonally
// Orthogonal moves (1 square only)
var orthogonalDirections = [{
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}];
for (var i = 0; i < orthogonalDirections.length; i++) {
var dir = orthogonalDirections[i];
var newRow = self.boardRow + dir.dr;
var newCol = self.boardCol + dir.dc;
if (isValidSquare(newRow, newCol)) {
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
// Diagonal moves (at least 2 squares)
var diagonalDirections = [{
dr: 1,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: -1,
dc: 1
}, {
dr: -1,
dc: -1
}];
for (var i = 0; i < diagonalDirections.length; i++) {
var dir = diagonalDirections[i];
for (var dist = 2; dist < 11; dist++) {
var newRow = self.boardRow + dir.dr * dist;
var newCol = self.boardCol + dir.dc * dist;
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
if (piece) {
if (piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
break;
} else {
// Check if path is blocked by friendly pieces
var blocked = false;
for (var checkDist = 1; checkDist < dist; checkDist++) {
var checkRow = self.boardRow + dir.dr * checkDist;
var checkCol = self.boardCol + dir.dc * checkDist;
var pathPiece = getPieceAt(checkRow, checkCol);
if (pathPiece && pathPiece.pieceColor === self.pieceColor) {
blocked = true;
break;
}
}
if (blocked) {
break;
}
moves.push({
row: newRow,
col: newCol
});
}
}
}
break;
case 'queen':
// Vizier: restricted to one square, enhanced to eight squares when promoted
// Diagonal movement is closed at the beginning (only orthogonal moves allowed)
// When promoted, both orthogonal and diagonal moves are allowed
if (self.isPromoted) {
directions = [{
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}, {
dr: 1,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: -1,
dc: 1
}, {
dr: -1,
dc: -1
}];
} else {
// Only orthogonal moves at the beginning (diagonals closed)
directions = [{
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}];
}
var maxDistance = self.isPromoted ? 8 : 1;
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
for (var dist = 1; dist <= maxDistance; dist++) {
var newRow = self.boardRow + dir.dr * dist;
var newCol = self.boardCol + dir.dc * dist;
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
if (piece) {
if (piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
moves.push({
row: newRow,
col: newCol
});
}
}
break;
case 'king':
directions = [{
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}, {
dr: 1,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: -1,
dc: 1
}, {
dr: -1,
dc: -1
}];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
var newRow = self.boardRow + dir.dr;
var newCol = self.boardCol + dir.dc;
if (isValidSquare(newRow, newCol)) {
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
break;
case 'knight':
var knightMoves = [{
dr: 2,
dc: 1
}, {
dr: 2,
dc: -1
}, {
dr: -2,
dc: 1
}, {
dr: -2,
dc: -1
}, {
dr: 1,
dc: 2
}, {
dr: 1,
dc: -2
}, {
dr: -1,
dc: 2
}, {
dr: -1,
dc: -2
}];
for (var i = 0; i < knightMoves.length; i++) {
var move = knightMoves[i];
var newRow = self.boardRow + move.dr;
var newCol = self.boardCol + move.dc;
if (isValidSquare(newRow, newCol)) {
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
break;
case 'warElephant':
// Moves 1 or 2 steps row, column, and diagonal with jumping ability
directions = [{
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}, {
dr: 1,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: -1,
dc: 1
}, {
dr: -1,
dc: -1
}];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
for (var dist = 1; dist <= 2; dist++) {
var newRow = self.boardRow + dir.dr * dist;
var newCol = self.boardCol + dir.dc * dist;
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
break;
case 'siegeTower':
// Must move 1 square in row/column, then 1 square diagonally
// If friendly piece in path, can move 1 step in row/column
// Captures enemy pieces in its path
var orthogonalDirections = [{
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}, {
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}];
var diagonalDirections = [{
dr: 1,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: -1,
dc: 1
}, {
dr: -1,
dc: -1
}];
// Try L-shaped moves: orthogonal then diagonal
for (var i = 0; i < orthogonalDirections.length; i++) {
var orthDir = orthogonalDirections[i];
var firstRow = self.boardRow + orthDir.dr;
var firstCol = self.boardCol + orthDir.dc;
if (!isValidSquare(firstRow, firstCol)) {
continue;
}
var firstPiece = getPieceAt(firstRow, firstCol);
// If friendly piece blocks first step, can only move orthogonally
if (firstPiece && firstPiece.pieceColor === self.pieceColor) {
// Can't move through friendly piece, skip this direction
continue;
}
// Try diagonal moves from the orthogonal position
for (var j = 0; j < diagonalDirections.length; j++) {
var diagDir = diagonalDirections[j];
var finalRow = firstRow + diagDir.dr;
var finalCol = firstCol + diagDir.dc;
if (!isValidSquare(finalRow, finalCol)) {
continue;
}
var finalPiece = getPieceAt(finalRow, finalCol);
if (!finalPiece || finalPiece.pieceColor !== self.pieceColor) {
var moveData = {
row: finalRow,
col: finalCol,
capturesInPath: []
};
// Add captured pieces in path
if (firstPiece && firstPiece.pieceColor !== self.pieceColor) {
moveData.capturesInPath.push({
row: firstRow,
col: firstCol
});
}
if (finalPiece && finalPiece.pieceColor !== self.pieceColor) {
moveData.capturesInPath.push({
row: finalRow,
col: finalCol
});
}
moves.push(moveData);
}
}
}
// If friendly piece in orthogonal path, allow simple orthogonal move
for (var i = 0; i < orthogonalDirections.length; i++) {
var orthDir = orthogonalDirections[i];
var newRow = self.boardRow + orthDir.dr;
var newCol = self.boardCol + orthDir.dc;
if (!isValidSquare(newRow, newCol)) {
continue;
}
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
break;
case 'minister':
// Minister: 1 square diagonally, when promoted moves like rook and knight with jumping
if (self.isPromoted) {
// Rook-like moves (can jump over pieces when promoted)
var rookDirections = [{
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}];
for (var i = 0; i < rookDirections.length; i++) {
var dir = rookDirections[i];
for (var dist = 1; dist < 11; dist++) {
var newRow = self.boardRow + dir.dr * dist;
var newCol = self.boardCol + dir.dc * dist;
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
// Knight-like moves (can jump over pieces)
var knightMoves = [{
dr: 2,
dc: 1
}, {
dr: 2,
dc: -1
}, {
dr: -2,
dc: 1
}, {
dr: -2,
dc: -1
}, {
dr: 1,
dc: 2
}, {
dr: 1,
dc: -2
}, {
dr: -1,
dc: 2
}, {
dr: -1,
dc: -2
}];
for (var i = 0; i < knightMoves.length; i++) {
var move = knightMoves[i];
var newRow = self.boardRow + move.dr;
var newCol = self.boardCol + move.dc;
if (isValidSquare(newRow, newCol)) {
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
} else {
// Standard minister: 1 square diagonally
directions = [{
dr: 1,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: -1,
dc: 1
}, {
dr: -1,
dc: -1
}];
for (var i = 0; i < directions.length; i++) {
var dir = directions[i];
var newRow = self.boardRow + dir.dr;
var newCol = self.boardCol + dir.dc;
if (isValidSquare(newRow, newCol)) {
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
}
break;
case 'royalGuard':
// Royal Guard moves: 3-square diagonal jumps with friendly pieces, 2-square row/column, L-shaped forward/backward
// 1. Diagonal jumps up to 3 squares with friendly piece assistance
var diagonalDirections = [{
dr: 1,
dc: 1
}, {
dr: 1,
dc: -1
}, {
dr: -1,
dc: 1
}, {
dr: -1,
dc: -1
}];
for (var i = 0; i < diagonalDirections.length; i++) {
var dir = diagonalDirections[i];
var hasFriendlyPiece = false;
// Check for friendly pieces in the path for assistance
for (var dist = 1; dist <= 3; dist++) {
var newRow = self.boardRow + dir.dr * dist;
var newCol = self.boardCol + dir.dc * dist;
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
if (piece) {
if (piece.pieceColor === self.pieceColor) {
hasFriendlyPiece = true;
} else {
// Enemy piece - can capture if we have friendly assistance
if (hasFriendlyPiece) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
} else {
// Empty square - can move if we have friendly assistance or it's distance 1
if (hasFriendlyPiece || dist === 1) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
}
// 2. Row and column moves up to 2 squares
var orthogonalDirections = [{
dr: 0,
dc: 1
}, {
dr: 0,
dc: -1
}, {
dr: 1,
dc: 0
}, {
dr: -1,
dc: 0
}];
for (var i = 0; i < orthogonalDirections.length; i++) {
var dir = orthogonalDirections[i];
for (var dist = 1; dist <= 2; dist++) {
var newRow = self.boardRow + dir.dr * dist;
var newCol = self.boardCol + dir.dc * dist;
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
if (piece) {
if (piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
break;
}
moves.push({
row: newRow,
col: newCol
});
}
}
// 3. L-shaped moves forward and backward
var lMoves = [];
// Forward L-shapes (toward enemy)
var forwardDir = self.pieceColor === 0 ? -1 : 1;
lMoves.push({
dr: forwardDir * 2,
dc: 1
});
lMoves.push({
dr: forwardDir * 2,
dc: -1
});
lMoves.push({
dr: forwardDir,
dc: 2
});
lMoves.push({
dr: forwardDir,
dc: -2
});
// Backward L-shapes (toward own side)
var backwardDir = -forwardDir;
lMoves.push({
dr: backwardDir * 2,
dc: 1
});
lMoves.push({
dr: backwardDir * 2,
dc: -1
});
lMoves.push({
dr: backwardDir,
dc: 2
});
lMoves.push({
dr: backwardDir,
dc: -2
});
for (var i = 0; i < lMoves.length; i++) {
var move = lMoves[i];
var newRow = self.boardRow + move.dr;
var newCol = self.boardCol + move.dc;
if (isValidSquare(newRow, newCol)) {
var piece = getPieceAt(newRow, newCol);
if (!piece || piece.pieceColor !== self.pieceColor) {
moves.push({
row: newRow,
col: newCol
});
}
}
}
break;
}
return moves;
};
self.getValidMoves = function () {
var moves = self.getRawMoves();
// Add castling for king after getting raw moves
if (self.pieceType === 'king' && !self.hasMoved && !isInCheck(self.pieceColor)) {
// Kingside castling
var kingsideRook = getPieceAt(self.boardRow, self.boardCol + 3);
if (kingsideRook && kingsideRook.pieceType === 'rook' && !kingsideRook.hasMoved) {
var canCastle = true;
for (var c = self.boardCol + 1; c < self.boardCol + 3; c++) {
if (getPieceAt(self.boardRow, c) || isSquareAttacked(self.boardRow, c, 1 - self.pieceColor)) {
canCastle = false;
break;
}
}
if (canCastle) {
moves.push({
row: self.boardRow,
col: self.boardCol + 2,
isCastling: true,
rookFromCol: self.boardCol + 3,
rookToCol: self.boardCol + 1
});
}
}
// Queenside castling
var queensideRook = getPieceAt(self.boardRow, self.boardCol - 4);
if (queensideRook && queensideRook.pieceType === 'rook' && !queensideRook.hasMoved) {
var canCastle = true;
for (var c = self.boardCol - 1; c > self.boardCol - 4; c--) {
if (getPieceAt(self.boardRow, c) || isSquareAttacked(self.boardRow, c, 1 - self.pieceColor)) {
canCastle = false;
break;
}
}
if (canCastle) {
moves.push({
row: self.boardRow,
col: self.boardCol - 2,
isCastling: true,
rookFromCol: self.boardCol - 4,
rookToCol: self.boardCol - 1
});
}
}
}
// Filter moves that would leave the king in check
var validMoves = [];
for (var i = 0; i < moves.length; i++) {
if (isValidMoveConsideringCheck(self, moves[i].row, moves[i].col)) {
validMoves.push(moves[i]);
}
}
return validMoves;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
var BOARD_WIDTH = 11;
var BOARD_HEIGHT = 10;
var SQUARE_SIZE = 180;
var BOARD_START_X = (2048 - BOARD_WIDTH * SQUARE_SIZE) / 2;
var BOARD_START_Y = (2732 - BOARD_HEIGHT * SQUARE_SIZE) / 2;
var boardSquares = [];
var pieces = [];
var selectedPiece = null;
var highlightedSquares = [];
var currentPlayer = 0; // 0 = white, 1 = black
var gameStarted = false;
var lastMove = null;
function getBoardPosition(row, col) {
return {
x: BOARD_START_X + col * SQUARE_SIZE + SQUARE_SIZE / 2,
y: BOARD_START_Y + row * SQUARE_SIZE + SQUARE_SIZE / 2
};
}
function getBoardCoordinates(x, y) {
var col = Math.floor((x - BOARD_START_X) / SQUARE_SIZE);
var row = Math.floor((y - BOARD_START_Y) / SQUARE_SIZE);
return {
row: row,
col: col
};
}
function isValidSquare(row, col) {
return row >= 0 && row < BOARD_HEIGHT && col >= 0 && col < BOARD_WIDTH;
}
function getPieceAt(row, col) {
for (var i = 0; i < pieces.length; i++) {
if (pieces[i].boardRow === row && pieces[i].boardCol === col) {
return pieces[i];
}
}
return null;
}
function createBoard() {
for (var row = 0; row < BOARD_HEIGHT; row++) {
boardSquares[row] = [];
for (var col = 0; col < BOARD_WIDTH; col++) {
var isLight = (row + col) % 2 === 0;
var square = game.addChild(LK.getAsset(isLight ? 'lightSquare' : 'darkSquare', {
anchorX: 0.5,
anchorY: 0.5
}));
var pos = getBoardPosition(row, col);
square.x = pos.x;
square.y = pos.y;
square.boardRow = row;
square.boardCol = col;
boardSquares[row][col] = square;
}
}
}
function createPieces() {
// Create pieces for both players
var pieceSetup = [
// White pieces (bottom)
{
type: 'rook',
color: 0,
row: 8,
col: 0
}, {
type: 'knight',
color: 0,
row: 8,
col: 1
}, {
type: 'warElephant',
color: 0,
row: 9,
col: 0
}, {
type: 'warElephant',
color: 0,
row: 9,
col: 10
}, {
type: 'bishop',
color: 0,
row: 8,
col: 2
}, {
type: 'queen',
color: 0,
row: 8,
col: 4
}, {
type: 'king',
color: 0,
row: 8,
col: 5
}, {
type: 'bishop',
color: 0,
row: 8,
col: 8
}, {
type: 'siegeTower',
color: 0,
row: 9,
col: 6
}, {
type: 'siegeTower',
color: 0,
row: 9,
col: 4
}, {
type: 'minister',
color: 0,
row: 8,
col: 6
}, {
type: 'knight',
color: 0,
row: 8,
col: 9
}, {
type: 'rook',
color: 0,
row: 8,
col: 10
},
// White royal guards
{
type: 'royalGuard',
color: 0,
row: 9,
col: 5
},
// Black pieces (top)
{
type: 'rook',
color: 1,
row: 1,
col: 0
}, {
type: 'knight',
color: 1,
row: 1,
col: 1
}, {
type: 'warElephant',
color: 1,
row: 0,
col: 0
}, {
type: 'warElephant',
color: 1,
row: 0,
col: 10
}, {
type: 'bishop',
color: 1,
row: 1,
col: 2
}, {
type: 'queen',
color: 1,
row: 1,
col: 6
}, {
type: 'king',
color: 1,
row: 1,
col: 5
}, {
type: 'bishop',
color: 1,
row: 1,
col: 8
}, {
type: 'siegeTower',
color: 1,
row: 0,
col: 6
}, {
type: 'siegeTower',
color: 1,
row: 0,
col: 4
}, {
type: 'minister',
color: 1,
row: 1,
col: 4
}, {
type: 'knight',
color: 1,
row: 1,
col: 9
}, {
type: 'rook',
color: 1,
row: 1,
col: 10
},
// Black royal guards
{
type: 'royalGuard',
color: 1,
row: 0,
col: 5
}];
// Add pawns
for (var col = 0; col < BOARD_WIDTH; col++) {
pieceSetup.push({
type: 'pawn',
color: 0,
row: 7,
col: col
}); // White pawns
pieceSetup.push({
type: 'pawn',
color: 1,
row: 2,
col: col
}); // Black pawns
}
for (var i = 0; i < pieceSetup.length; i++) {
var setup = pieceSetup[i];
var piece = game.addChild(new ChessPiece(setup.type, setup.color, setup.row, setup.col));
var pos = getBoardPosition(setup.row, setup.col);
piece.x = pos.x;
piece.y = pos.y;
pieces.push(piece);
}
}
function clearHighlights() {
for (var i = 0; i < highlightedSquares.length; i++) {
highlightedSquares[i].destroy();
}
highlightedSquares = [];
}
function highlightMoves(moves) {
clearHighlights();
for (var i = 0; i < moves.length; i++) {
var move = moves[i];
var highlight = game.addChild(LK.getAsset('highlightSquare', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
}));
var pos = getBoardPosition(move.row, move.col);
highlight.x = pos.x;
highlight.y = pos.y;
highlightedSquares.push(highlight);
}
}
function selectPiece(piece) {
if (selectedPiece) {
selectedPiece.removeChild(selectedPiece.selectionHighlight);
selectedPiece.selectionHighlight = null;
}
selectedPiece = piece;
if (piece) {
piece.selectionHighlight = piece.addChild(LK.getAsset('selectedSquare', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
}));
var validMoves = piece.getValidMoves();
highlightMoves(validMoves);
} else {
clearHighlights();
}
}
function makeMove(piece, targetRow, targetCol, moveData) {
var originalRow = piece.boardRow;
var originalCol = piece.boardCol;
var capturedPiece = null;
var capturedPieces = [];
// Handle special moves
if (moveData && moveData.isCastling) {
// Move the rook for castling
var rook = getPieceAt(originalRow, moveData.rookFromCol);
if (rook) {
rook.moveTo(originalRow, moveData.rookToCol);
}
} else if (moveData && moveData.isEnPassant) {
// Capture the pawn for en passant
capturedPiece = getPieceAt(moveData.captureRow, moveData.captureCol);
if (capturedPiece) {
capturedPieces.push(capturedPiece);
}
} else if (moveData && moveData.capturesInPath) {
// Handle siegeTower path captures
for (var k = 0; k < moveData.capturesInPath.length; k++) {
var capturePos = moveData.capturesInPath[k];
var pathPiece = getPieceAt(capturePos.row, capturePos.col);
if (pathPiece) {
capturedPieces.push(pathPiece);
}
}
} else {
capturedPiece = getPieceAt(targetRow, targetCol);
if (capturedPiece) {
capturedPieces.push(capturedPiece);
}
}
// Remove all captured pieces
for (var k = 0; k < capturedPieces.length; k++) {
var capPiece = capturedPieces[k];
var index = pieces.indexOf(capPiece);
if (index > -1) {
pieces.splice(index, 1);
}
capPiece.destroy();
}
if (capturedPieces.length > 0) {
LK.getSound('capture').play();
} else {
LK.getSound('move').play();
}
// Store move for en passant detection
lastMove = {
piece: piece,
fromRow: originalRow,
fromCol: originalCol,
toRow: targetRow,
toCol: targetCol
};
piece.moveTo(targetRow, targetCol);
// Check for vizier promotion
if (piece.pieceType === 'queen' && !piece.isPromoted) {
var opponentLastRow = piece.pieceColor === 0 ? 0 : BOARD_HEIGHT - 1;
if (targetRow === opponentLastRow) {
piece.isPromoted = true;
// Visual feedback for promotion
LK.effects.flashObject(piece, 0xFFD700, 1000); // Flash gold
}
}
// Check for minister promotion
if (piece.pieceType === 'minister' && !piece.isPromoted) {
var opponentLastRow = piece.pieceColor === 0 ? 0 : BOARD_HEIGHT - 1;
if (targetRow === opponentLastRow) {
piece.isPromoted = true;
// Visual feedback for promotion
LK.effects.flashObject(piece, 0x9932CC, 1000); // Flash purple
}
}
currentPlayer = 1 - currentPlayer;
selectPiece(null);
// Check for victory conditions
checkGameEnd();
}
function isSquareAttacked(row, col, byColor) {
for (var i = 0; i < pieces.length; i++) {
var piece = pieces[i];
if (piece.pieceColor !== byColor) {
continue;
}
var moves = piece.getRawMoves();
for (var j = 0; j < moves.length; j++) {
if (moves[j].row === row && moves[j].col === col) {
return true;
}
}
}
return false;
}
function findKing(color) {
for (var i = 0; i < pieces.length; i++) {
if (pieces[i].pieceType === 'king' && pieces[i].pieceColor === color) {
return pieces[i];
}
}
return null;
}
function isInCheck(color) {
var king = findKing(color);
if (!king) {
return false;
}
return isSquareAttacked(king.boardRow, king.boardCol, 1 - color);
}
function isValidMoveConsideringCheck(piece, targetRow, targetCol) {
// Simulate the move
var originalRow = piece.boardRow;
var originalCol = piece.boardCol;
var capturedPiece = getPieceAt(targetRow, targetCol);
var capturedIndex = -1;
if (capturedPiece) {
capturedIndex = pieces.indexOf(capturedPiece);
pieces.splice(capturedIndex, 1);
}
piece.boardRow = targetRow;
piece.boardCol = targetCol;
var stillInCheck = isInCheck(piece.pieceColor);
// Restore the position
piece.boardRow = originalRow;
piece.boardCol = originalCol;
if (capturedPiece && capturedIndex > -1) {
pieces.splice(capturedIndex, 0, capturedPiece);
}
return !stillInCheck;
}
function hasValidMoves(color) {
for (var i = 0; i < pieces.length; i++) {
var piece = pieces[i];
if (piece.pieceColor !== color) {
continue;
}
var moves = piece.getRawMoves();
for (var j = 0; j < moves.length; j++) {
if (isValidMoveConsideringCheck(piece, moves[j].row, moves[j].col)) {
return true;
}
}
}
return false;
}
function checkGameEnd() {
var whiteKing = findKing(0);
var blackKing = findKing(1);
if (!whiteKing) {
LK.setScore(1);
LK.showGameOver();
return;
}
if (!blackKing) {
LK.setScore(1);
LK.showGameOver();
return;
}
var inCheck = isInCheck(currentPlayer);
var hasValid = hasValidMoves(currentPlayer);
if (!hasValid) {
if (inCheck) {
// Checkmate
LK.setScore(1);
LK.showGameOver();
} else {
// Stalemate
LK.setScore(0);
LK.showGameOver();
}
}
}
function initializeGame() {
createBoard();
createPieces();
gameStarted = true;
}
// Player turn indicator
var turnText = new Text2('White to move', {
size: 80,
fill: 0xFFFFFF
});
turnText.anchor.set(0.5, 0);
LK.gui.top.addChild(turnText);
game.down = function (x, y, obj) {
if (!gameStarted) {
return;
}
var coords = getBoardCoordinates(x, y);
if (!isValidSquare(coords.row, coords.col)) {
return;
}
var clickedPiece = getPieceAt(coords.row, coords.col);
if (selectedPiece) {
var validMoves = selectedPiece.getValidMoves();
var isValidMove = false;
for (var i = 0; i < validMoves.length; i++) {
if (validMoves[i].row === coords.row && validMoves[i].col === coords.col) {
isValidMove = true;
break;
}
}
if (isValidMove) {
var moveData = null;
for (var i = 0; i < validMoves.length; i++) {
if (validMoves[i].row === coords.row && validMoves[i].col === coords.col) {
moveData = validMoves[i];
break;
}
}
makeMove(selectedPiece, coords.row, coords.col, moveData);
return;
}
}
if (clickedPiece && clickedPiece.pieceColor === currentPlayer) {
selectPiece(clickedPiece);
} else {
selectPiece(null);
}
};
game.update = function () {
if (!gameStarted) {
initializeGame();
}
var playerText = currentPlayer === 0 ? 'White to move' : 'Black to move';
if (isInCheck(currentPlayer)) {
playerText += ' (Check!)';
}
turnText.setText(playerText);
}; ===================================================================
--- original.js
+++ change.js
@@ -601,9 +601,10 @@
}
}
break;
case 'royalGuard':
- // Can jump up to 3 squares diagonally
+ // Royal Guard moves: 3-square diagonal jumps with friendly pieces, 2-square row/column, L-shaped forward/backward
+ // 1. Diagonal jumps up to 3 squares with friendly piece assistance
var diagonalDirections = [{
dr: 1,
dc: 1
}, {
@@ -617,24 +618,42 @@
dc: -1
}];
for (var i = 0; i < diagonalDirections.length; i++) {
var dir = diagonalDirections[i];
+ var hasFriendlyPiece = false;
+ // Check for friendly pieces in the path for assistance
for (var dist = 1; dist <= 3; dist++) {
var newRow = self.boardRow + dir.dr * dist;
var newCol = self.boardCol + dir.dc * dist;
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
- if (!piece || piece.pieceColor !== self.pieceColor) {
- moves.push({
- row: newRow,
- col: newCol
- });
+ if (piece) {
+ if (piece.pieceColor === self.pieceColor) {
+ hasFriendlyPiece = true;
+ } else {
+ // Enemy piece - can capture if we have friendly assistance
+ if (hasFriendlyPiece) {
+ moves.push({
+ row: newRow,
+ col: newCol
+ });
+ }
+ break;
+ }
+ } else {
+ // Empty square - can move if we have friendly assistance or it's distance 1
+ if (hasFriendlyPiece || dist === 1) {
+ moves.push({
+ row: newRow,
+ col: newCol
+ });
+ }
}
}
}
- // Can jump up to 2 squares along rows and columns
+ // 2. Row and column moves up to 2 squares
var orthogonalDirections = [{
dr: 0,
dc: 1
}, {
@@ -655,49 +674,63 @@
if (!isValidSquare(newRow, newCol)) {
break;
}
var piece = getPieceAt(newRow, newCol);
- if (!piece || piece.pieceColor !== self.pieceColor) {
- moves.push({
- row: newRow,
- col: newCol
- });
+ if (piece) {
+ if (piece.pieceColor !== self.pieceColor) {
+ moves.push({
+ row: newRow,
+ col: newCol
+ });
+ }
+ break;
}
+ moves.push({
+ row: newRow,
+ col: newCol
+ });
}
}
- // L-shape moves only forward and backward
- var direction = self.pieceColor === 0 ? -1 : 1; // Forward direction based on color
- // Forward L-shapes
- var forwardLMoves = [{
- dr: 2 * direction,
+ // 3. L-shaped moves forward and backward
+ var lMoves = [];
+ // Forward L-shapes (toward enemy)
+ var forwardDir = self.pieceColor === 0 ? -1 : 1;
+ lMoves.push({
+ dr: forwardDir * 2,
dc: 1
- }, {
- dr: 2 * direction,
+ });
+ lMoves.push({
+ dr: forwardDir * 2,
dc: -1
- }, {
- dr: 1 * direction,
+ });
+ lMoves.push({
+ dr: forwardDir,
dc: 2
- }, {
- dr: 1 * direction,
+ });
+ lMoves.push({
+ dr: forwardDir,
dc: -2
- }];
- // Backward L-shapes
- var backwardLMoves = [{
- dr: -2 * direction,
+ });
+ // Backward L-shapes (toward own side)
+ var backwardDir = -forwardDir;
+ lMoves.push({
+ dr: backwardDir * 2,
dc: 1
- }, {
- dr: -2 * direction,
+ });
+ lMoves.push({
+ dr: backwardDir * 2,
dc: -1
- }, {
- dr: -1 * direction,
+ });
+ lMoves.push({
+ dr: backwardDir,
dc: 2
- }, {
- dr: -1 * direction,
+ });
+ lMoves.push({
+ dr: backwardDir,
dc: -2
- }];
- var lShapeMoves = forwardLMoves.concat(backwardLMoves);
- for (var i = 0; i < lShapeMoves.length; i++) {
- var move = lShapeMoves[i];
+ });
+ for (var i = 0; i < lMoves.length; i++) {
+ var move = lMoves[i];
var newRow = self.boardRow + move.dr;
var newCol = self.boardCol + move.dc;
if (isValidSquare(newRow, newCol)) {
var piece = getPieceAt(newRow, newCol);