User prompt
Even if I choose different alternative pieces, the pawn always turns into a knight
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'charAt')' in or related to this line: 'var assetName = color + type.charAt(0).toUpperCase() + type.slice(1);' Line Number: 42
User prompt
If a black or white pawn reaches the opponent's first square, he will have to choose between his pawn (queen, rook, bishop, knight) and when he chooses one, that pawn will turn into the piece he chose.
Code edit (1 edits merged)
Please save this source code
User prompt
Twisted Chess
Initial prompt
We will play chess but; the rook will move like a bishop, the bishop will move like a knight, the knight will move like a rook. The pawns will take diagonal steps and capture straight pieces.
/****
* 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.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;
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;
button.down = function (x, y, obj) {
self.onSelect(button.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
****/
// Black pieces
// White 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;
// 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);
square.x = boardOffsetX + col * 200 + 100;
square.y = boardOffsetY + row * 200 + 100;
squares[row][col] = square;
game.addChild(square);
}
}
// 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) {
validMoves = piece.getValidMoves();
for (var i = 0; i < validMoves.length; i++) {
var move = validMoves[i];
squares[move.row][move.col].setValidMove(true);
}
}
function handleSquareClick(row, col) {
if (gameOver) return;
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';
// Check for game over conditions
checkGameOver();
}
} 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) {
// Store promotion details
pendingPromotion = {
piece: piece,
row: toRow,
col: toCol
};
// Show promotion dialog
showPromotionDialog(piece.color);
return; // Don't switch players yet
}
}
}
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
if (!whiteKing) {
gameOver = true;
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
} else if (!blackKing) {
gameOver = true;
LK.setTimeout(function () {
LK.showYouWin();
}, 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';
// Check for game over conditions
checkGameOver();
}
// Initialize the game
initializePieces();
// Add turn indicator
var 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);
game.update = function () {
// Update turn indicator
if (currentPlayer === 'white') {
turnText.setText('White to move');
} else {
turnText.setText('Black to move');
}
}; ===================================================================
--- original.js
+++ change.js
@@ -266,9 +266,9 @@
button.x = (i - 1.5) * 180;
button.y = 0;
button.pieceType = pieceType;
button.down = function (x, y, obj) {
- self.onSelect(obj.pieceType);
+ self.onSelect(button.pieceType);
};
buttons.push(button);
self.addChild(button);
}