User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of null (reading 'piece')' in or related to this line: 'if (square.piece && square.piece.color === attackerColor) {' Line Number: 2450
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of null (reading 'piece')' in or related to this line: 'if (square.piece && square.piece.type === 'king' && square.piece.color === color) {' Line Number: 2538
User prompt
Add new daily challenges: Phoenix boss fight: the black king has trained a phoenix! Every 10 moves, the pheonix will shoot a fireball at a random piece, taking it! (The pheonix is flying all around the board and is NOT a piece); Dragon warriors: Both yours and your enemy's queen is replaced with a dragon; however, to upkeep the dragon's power, every 3 moves a random piece, that is not a king or the dragon, will be sacrificed!; Western chess: all of your pawns are replaced with cowboys! Cowboys move exactly like pawns but when attacking they don't need to move and when they die they make a knight!
User prompt
Add a new game modes for daily challenges: Rooks of hell
User prompt
Make the board bigger in size
User prompt
Now you can tap on a river square to turn it into a normal square, but it will cost 1 move
User prompt
You can tap on a river square to turn it into a normal square
User prompt
Add new special gamemodes for the daily challenges: Maze (Move your king to escape the maze! Avoid traps and other pieces that whould capture him!); River (the center row is replaced with a river, knights can jump over it easily, but you will need to build a bridge to pass, wasting 1 turn); Elite knights (knights can now also move like a king and a knight combined and can't be taken by bishops)
User prompt
Add a button to skip the ad
User prompt
In "fog of war", the fog isn't there, fix it so that there's fog
User prompt
Add a new mode: Friends mode! Play a game of chess with your friends (note that this mode is exclusive to classic mode)
User prompt
Add a new mode: Friends mode! Play a classic chess game with your friends! ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
I still draw from the 50 move rule; REMOVE ALL OF ITS CODE
User prompt
Burger king ads aren't showing; FIX THAT
User prompt
Now the "BKad" Song Is played when in a burger king ad; It Will stop After that ad
User prompt
Now, when tapping which bot you wanna play against, you will be forced to watch a 30 second Burger King ad screen before playing(add assets for it too!)
User prompt
Now, when tapping which bot you wanna play against, you will be forced to watch a 30 second Burger King ad before playing(add assets for it too!)
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'open')' in or related to this line: 'LK.link.open('https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link');' Line Number: 1026
User prompt
Tapping the more games button shows another screen with a button that leads you to this link: https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link
User prompt
Add a button in the title screen that says "More games" that leads you to a screen with this link: https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link
User prompt
Please fix the bug: 'Uncaught TypeError: moreGamesButton.containsPoint is not a function' in or related to this line: 'if (!moreGamesButton.containsPoint(localPos)) {' Line Number: 1022
User prompt
Add a button in the title screen that says "More games" with this link: https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link
User prompt
Please fix the bug: 'Uncaught TypeError: LK.openURL is not a function' in or related to this line: 'LK.openURL('https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link');' Line Number: 1026
User prompt
Add a button in the title screen that says "More games" with this link: https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link
User prompt
Please fix the bug: 'Uncaught TypeError: LK.openLink is not a function' in or related to this line: 'LK.openLink('https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link');' Line Number: 1044
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var BotSelectionScreen = Container.expand(function () { var self = Container.call(this); // Bot descriptions and icons var botData = { Martin: { description: 'Martin makes many bad moves.', icon: 'martinIcon' }, Lina: { description: 'Lina has an offensive strategy.', icon: 'linaIcon' }, Carl: { description: 'Carl tries to stall the game.', icon: 'carlIcon' }, Wizard: { description: 'Wizard uses magic for great moves.', icon: 'wizardIcon' }, King: { description: 'King plays optimally but lacks a Queen.', icon: 'kingIcon' } }; var bots = ['Martin', 'Lina', 'Carl', 'Wizard', 'King']; // Assume these assets ('martinIcon', 'linaIcon', etc.) are defined or will be auto-created by the engine. // Example sizes used here are 80x80. var startY = -350; // Adjusted start Y for more spacing overall var spacingY = 180; // Increased vertical spacing between buttons // Create title text var titleText = new Text2('Select Your Opponent', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = startY - 100; // Position title above the first button container self.addChild(titleText); // Store button containers and backgrounds for interaction setup var buttonContainers = []; var buttonBackgrounds = []; // Create bot buttons with icons and descriptions using Containers for (var i = 0; i < bots.length; i++) { var botName = bots[i]; var currentBotData = botData[botName]; // Create a container for each button entry var buttonContainer = new Container(); buttonContainer.x = 0; // Center container horizontally relative to parent (BotSelectionScreen) buttonContainer.y = startY + i * spacingY; // Position container vertically self.addChild(buttonContainer); buttonContainers.push(buttonContainer); // Store the container // Get icon asset var icon = LK.getAsset(currentBotData.icon, { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80 }); icon.x = -200; // Position icon significantly to the left within the container icon.y = 0; // Center icon vertically within the container // Get bot name text asset var botButtonText = new Text2(botName.toUpperCase(), { size: 60, fill: 0xFFFFFF }); botButtonText.anchor.set(0, 0.5); // Anchor text to its left-middle botButtonText.x = icon.x + icon.width / 2 + 20; // Position text right of the icon center + padding botButtonText.y = -15; // Position text slightly above the vertical center // Get description text asset var descriptionText = new Text2(currentBotData.description, { size: 30, fill: 0xCCCCCC }); descriptionText.anchor.set(0, 0.5); // Anchor text to its left-middle descriptionText.x = botButtonText.x; // Align description start with bot name start descriptionText.y = 15; // Position description below the vertical center // Calculate dynamic width/height needed for the background based on content var textBlockWidth = Math.max(botButtonText.width, descriptionText.width); var contentWidth = icon.width + 20 + textBlockWidth; // Icon width + padding + max text width var contentHeight = Math.max(icon.height, botButtonText.height + descriptionText.height + 10); // Max of icon height or combined text height + spacing var bgWidth = contentWidth + 80; // Add horizontal padding to content width var bgHeight = contentHeight + 40; // Add vertical padding to content height // Create background asset var bg = LK.getAsset('blackSquare', { anchorX: 0.5, anchorY: 0.5, width: bgWidth, height: bgHeight, tint: 0x3a3a3a }); bg.alpha = 0.7; // Center the background horizontally around the content block bg.x = icon.x - icon.width / 2 + contentWidth / 2; bg.y = 0; // Center background vertically in the container buttonContainer.addChild(bg); // Add background first so text/icon are on top buttonBackgrounds.push(bg); // Store background reference for interaction effects // Add icon and text elements on top of the background buttonContainer.addChild(icon); buttonContainer.addChild(botButtonText); buttonContainer.addChild(descriptionText); // Make the entire container interactive buttonContainer.interactive = true; buttonContainer.botIndex = i; // Store the bot index on the container for the click handler } // Create Back button text var backButton = new Text2('< BACK', { size: 60, fill: 0xFFFFFF }); backButton.anchor.set(0.5, 0.5); // Position back button below the last bot container, accounting for increased spacing backButton.y = startY + bots.length * spacingY + 60; self.addChild(backButton); // Create Back button background var backBg = LK.getAsset('blackSquare', { anchorX: 0.5, anchorY: 0.5, width: backButton.width + 80, height: backButton.height + 40, tint: 0x3a3a3a }); backBg.alpha = 0.7; backBg.x = backButton.x; // Align background center with text center backBg.y = backButton.y; // Align background center with text center self.addChild(backBg); // Add background first self.addChild(backButton); // Add text on top of background // --- Interaction Setup --- // Bot button interactions (using stored containers and backgrounds) for (var i = 0; i < buttonContainers.length; i++) { (function (index) { var btnContainer = buttonContainers[index]; var bg = buttonBackgrounds[index]; // Get the corresponding background // Attach down event to the container btnContainer.down = function (x, y, obj) { // Flash the background alpha on click tween(bg, { alpha: 1 }, { duration: 100, onFinish: function onComplete() { // Return alpha to normal after flash tween(bg, { alpha: 0.7 }, { duration: 100 }); } }); // Handle button action: select bot and start game game.selectedBot = bots[index]; // Use stored index to get bot name game.startGame(); }; })(i); } // Back button interaction (function () { var btn = backButton; // Reference to the Text2 object var bg = backBg; // Reference to the background shape btn.interactive = true; // Make the Text2 object interactive // Attach down event to the text object btn.down = function (x, y, obj) { // Flash the background alpha on click tween(bg, { alpha: 1 }, { duration: 100, onFinish: function onComplete() { // Return alpha to normal after flash tween(bg, { alpha: 0.7 }, { duration: 100 }); } }); // Handle back button action: show the previous screen game.showGameModeScreen(); }; })(); // Update function (can be used for animations later if needed) self.update = function () { // Optional: Add animations like pulsing if needed }; return self; }); var ChessPiece = Container.expand(function (type, color) { var self = Container.call(this); self.type = type; self.color = color; self.hasMoved = false; var pieceId = color + type.charAt(0).toUpperCase() + type.slice(1); var pieceGraphics = self.attachAsset(pieceId, { anchorX: 0.5, anchorY: 0.5 }); var label; switch (type) { case 'pawn': label = ''; break; case 'rook': label = 'R'; break; case 'knight': label = 'N'; break; case 'bishop': label = 'B'; break; case 'queen': label = 'Q'; break; case 'king': label = 'K'; break; } if (label) { var text = new Text2(label, { size: 40, fill: color === 'white' ? "#000000" : "#ffffff" }); text.anchor.set(0.5, 0.5); self.addChild(text); } return self; }); var ChessSquare = Container.expand(function (row, col, color) { var self = Container.call(this); self.row = row; self.col = col; self.color = color; self.piece = null; var squareGraphics = self.attachAsset(color === 'white' ? 'whiteSquare' : 'blackSquare', { anchorX: 0, anchorY: 0 }); self.highlight = function (type) { if (type === 'selected') { squareGraphics.tint = 0x829769; } else if (type === 'validMove') { squareGraphics.tint = 0xcdd26a; } else { // Reset to original color squareGraphics.tint = color === 'white' ? 0xf0d9b5 : 0xb58863; } }; self.setPiece = function (piece) { if (self.piece) { self.removeChild(self.piece); } self.piece = piece; if (piece) { self.addChild(piece); piece.x = squareGraphics.width / 2; piece.y = squareGraphics.height / 2; } }; self.down = function (x, y, obj) { game.selectSquare(self); }; return self; }); var CrazyAbility = Container.expand(function () { var self = Container.call(this); // Available abilities self.abilities = [{ name: 'Freeze', description: 'Freezes a white piece for 2 turns' }, { name: 'Instant Promotion', description: 'Promotes a black pawn to a powerful piece' }, { name: 'Stampede', description: 'Removes 3 random pieces from the board' }, { name: 'Summon', description: 'Summons a black rook on an empty square' }, { name: 'Teleport', description: 'Teleports one of your pieces to danger!' }, { name: 'Goatify', description: 'Turns a piece into a goat that moves like a king for 2 turns' }, { name: 'Trap', description: 'Places a bear trap that captures pieces that land on it' }]; // Stores pieces that are frozen self.frozenPieces = []; // Use a random ability self.useRandomAbility = function () { var randomIndex = Math.floor(Math.random() * self.abilities.length); var ability = self.abilities[randomIndex]; // Show ability notification self.showAbilityNotification(ability.name); // Execute ability switch (ability.name) { case 'Freeze': self.freezeRandomPiece(); break; case 'Instant Promotion': self.instantPromotion(); break; case 'Stampede': self.stampede(); break; case 'Summon': self.summonRook(); break; case 'Teleport': self.teleport(); break; case 'Goatify': self.goatifyPiece(); break; case 'Trap': self.placeTrap(); break; } }; // Show notification of ability used self.showAbilityNotification = function (abilityName) { var notification = new Text2('AI USED: ' + abilityName + '!', { size: 50, fill: 0xFF0000 }); notification.anchor.set(0.5, 0.5); notification.x = 2048 / 2; notification.y = 2732 / 2 - 300; game.addChild(notification); // Flash effect LK.effects.flashObject(notification, 0xFF0000, 500); // Remove after delay LK.setTimeout(function () { game.removeChild(notification); }, 2000); }; // Freeze a random white piece for 2 turns self.freezeRandomPiece = function () { var whitePieces = []; // Find all white pieces for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece && square.piece.color === 'white') { whitePieces.push({ square: square, row: row, col: col }); } } } if (whitePieces.length > 0) { // Select random white piece var randomIndex = Math.floor(Math.random() * whitePieces.length); var targetPiece = whitePieces[randomIndex]; // Add to frozen list with 2 turns duration self.frozenPieces.push({ row: targetPiece.row, col: targetPiece.col, turnsLeft: 2 }); // Visual effect - tint blue targetPiece.square.piece.tint = 0x00AAFF; } }; // Turn a random black pawn into a queen, bishop or rook self.instantPromotion = function () { var blackPawns = []; // Find all black pawns for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece && square.piece.color === 'black' && square.piece.type === 'pawn') { blackPawns.push({ square: square }); } } } if (blackPawns.length > 0) { // Select random black pawn var randomIndex = Math.floor(Math.random() * blackPawns.length); var targetPawn = blackPawns[randomIndex]; // Choose random promotion type var promotionTypes = ['queen', 'bishop', 'rook']; var randomType = promotionTypes[Math.floor(Math.random() * promotionTypes.length)]; // Promote the pawn targetPawn.square.setPiece(new ChessPiece(randomType, 'black')); LK.getSound('promotion').play(); } }; // Remove 3 random pieces from the board self.stampede = function () { var allPieces = []; // Find all pieces, excluding all kings for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece && square.piece.type !== 'king') { allPieces.push({ square: square }); } } } // Remove up to 3 random pieces var removeCount = Math.min(3, allPieces.length); for (var i = 0; i < removeCount; i++) { if (allPieces.length > 0) { var randomIndex = Math.floor(Math.random() * allPieces.length); var targetPiece = allPieces[randomIndex]; // Remove piece targetPiece.square.setPiece(null); // Remove from array allPieces.splice(randomIndex, 1); } } LK.getSound('capture').play(); }; // Summon a black rook on a random empty square self.summonRook = function () { var emptySquares = []; // Find all empty squares for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (!square.piece) { emptySquares.push({ square: square }); } } } if (emptySquares.length > 0) { // Select random empty square var randomIndex = Math.floor(Math.random() * emptySquares.length); var targetSquare = emptySquares[randomIndex]; // Add new rook targetSquare.square.setPiece(new ChessPiece('rook', 'black')); } }; // Decrement frozen piece counters self.updateFrozenPieces = function () { for (var i = self.frozenPieces.length - 1; i >= 0; i--) { self.frozenPieces[i].turnsLeft--; // If no turns left, unfreeze the piece if (self.frozenPieces[i].turnsLeft <= 0) { var row = self.frozenPieces[i].row; var col = self.frozenPieces[i].col; // Only unfreeze if piece still exists at that position if (board[row][col].piece && board[row][col].piece.color === 'white') { board[row][col].piece.tint = 0xFFFFFF; } self.frozenPieces.splice(i, 1); } } }; // Teleport a white piece to a dangerous position self.teleport = function () { var whitePieces = []; var dangerSquares = []; // Find all white pieces (except king) for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece && square.piece.color === 'white' && square.piece.type !== 'king') { whitePieces.push({ square: square, row: row, col: col }); } } } // Find all squares under attack by black pieces for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { // Check if this square is attacked by any black piece if (isSquareAttacked(row, col, 'black') && !board[row][col].piece) { dangerSquares.push({ row: row, col: col }); } } } // If we have white pieces and danger squares if (whitePieces.length > 0 && dangerSquares.length > 0) { // Select random white piece var randomPieceIndex = Math.floor(Math.random() * whitePieces.length); var targetPiece = whitePieces[randomPieceIndex]; // Select random danger square var randomSquareIndex = Math.floor(Math.random() * dangerSquares.length); var dangerSquare = dangerSquares[randomSquareIndex]; // Teleport the piece var piece = targetPiece.square.piece; targetPiece.square.setPiece(null); board[dangerSquare.row][dangerSquare.col].setPiece(piece); // Visual effect - flash the teleported piece LK.effects.flashObject(board[dangerSquare.row][dangerSquare.col].piece, 0xFF00FF, 500); } }; // Stores goatified pieces data self.goatifiedPieces = []; // Turn a white piece into a goat (moves like king) self.goatifyPiece = function () { var whitePieces = []; // Find all white pieces except the king (king is immune) for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece && square.piece.color === 'white' && square.piece.type !== 'king') { whitePieces.push({ square: square, row: row, col: col, type: square.piece.type }); } } } if (whitePieces.length > 0) { // Select random white piece var randomIndex = Math.floor(Math.random() * whitePieces.length); var targetPiece = whitePieces[randomIndex]; // Add to goatified list with 2 turns duration self.goatifiedPieces.push({ row: targetPiece.row, col: targetPiece.col, originalType: targetPiece.type, turnsLeft: 2 }); // Visual effect - tint piece to goat color targetPiece.square.piece.tint = 0x88BB33; // Show a goat indicator var goatText = new Text2("🐐", { size: 30, fill: 0xFFFFFF }); goatText.anchor.set(0.5, 0.5); goatText.x = targetPiece.square.x + SQUARE_SIZE / 2; goatText.y = targetPiece.square.y + SQUARE_SIZE / 2 - 30; game.addChild(goatText); // Remove indicator after a short time LK.setTimeout(function () { game.removeChild(goatText); }, 1500); } }; // Array to track trap positions self.trapSquares = []; // Place a bear trap on a random empty square self.placeTrap = function () { var emptySquares = []; // Find all empty squares for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (!square.piece) { emptySquares.push({ row: row, col: col }); } } } if (emptySquares.length > 0) { // Select random empty square var randomIndex = Math.floor(Math.random() * emptySquares.length); var trapSquare = emptySquares[randomIndex]; // Add trap to the list self.trapSquares.push({ row: trapSquare.row, col: trapSquare.col }); // Visual indication of trap var trapIndicator = new Text2("⚠️", { size: 40, fill: 0xFF5500 }); trapIndicator.anchor.set(0.5, 0.5); trapIndicator.x = board[trapSquare.row][trapSquare.col].x + SQUARE_SIZE / 2; trapIndicator.y = board[trapSquare.row][trapSquare.col].y + SQUARE_SIZE / 2; game.addChild(trapIndicator); board[trapSquare.row][trapSquare.col].trapIndicator = trapIndicator; } }; // Update goatified pieces counters self.updateGoatifiedPieces = function () { for (var i = self.goatifiedPieces.length - 1; i >= 0; i--) { self.goatifiedPieces[i].turnsLeft--; // If no turns left, restore the piece to its original type if (self.goatifiedPieces[i].turnsLeft <= 0) { var row = self.goatifiedPieces[i].row; var col = self.goatifiedPieces[i].col; var originalType = self.goatifiedPieces[i].originalType; // Only restore if piece still exists at that position and is white if (board[row][col].piece && board[row][col].piece.color === 'white') { // Reset tint board[row][col].piece.tint = 0xFFFFFF; } self.goatifiedPieces.splice(i, 1); } } }; // Check if a piece is goatified self.isPieceGoatified = function (row, col) { for (var i = 0; i < self.goatifiedPieces.length; i++) { if (self.goatifiedPieces[i].row === row && self.goatifiedPieces[i].col === col) { return true; } } return false; }; // Check if a square has a trap self.hasTrap = function (row, col) { for (var i = 0; i < self.trapSquares.length; i++) { if (self.trapSquares[i].row === row && self.trapSquares[i].col === col) { return true; } } return false; }; // Trigger trap on a square and remove it self.triggerTrap = function (row, col) { for (var i = 0; i < self.trapSquares.length; i++) { if (self.trapSquares[i].row === row && self.trapSquares[i].col === col) { // Remove the trap indicator if (board[row][col].trapIndicator) { game.removeChild(board[row][col].trapIndicator); board[row][col].trapIndicator = null; } // Remove the trap from our list self.trapSquares.splice(i, 1); return true; } } return false; }; // Check if a piece is frozen self.isPieceFrozen = function (row, col) { for (var i = 0; i < self.frozenPieces.length; i++) { if (self.frozenPieces[i].row === row && self.frozenPieces[i].col === col) { return true; } } return false; }; return self; }); var DailyChallengeScreen = Container.expand(function () { var self = Container.call(this); // Special rules collection - now the only focus of daily challenges var specialRules = [{ name: 'Fog of War', description: 'You can only see squares your pieces can move to.', id: 'fogOfWar' }, { name: 'Backwards Pawns', description: 'Pawns can move and capture backwards.', id: 'backwardsPawns' }, { name: 'Capture the King', description: 'No check/checkmate. Capture the enemy king to win!', id: 'captureKing' }, { name: 'SHREDR Bishops', description: 'Bishops can jump over pieces and move one square horizontally.', id: 'shredrBishops' }, { name: 'Small Chess', description: 'Play on a 4x8 board without knights or bishops.', id: 'smallChess' }, { name: 'Transformo-fest', description: 'Pieces (except kings) randomly transform after moving!', id: 'transformoFest' }, { name: 'Dragon Boss', description: 'Capture the Dragon (Queen+Knight moves) using 3 Knights & 4 Bishops.', id: 'dragonBoss' }, { name: 'GOAT-ed Challenge', description: 'Your pieces (except king) are goats! Survive 25 turns.', id: 'goatedChallenge' }, { name: 'Icy Day', description: 'Pieces may freeze after moving! Some pawns are immune Yetis.', id: 'icyDay' }]; // Select a random special rule for the "day" var selectedSpecialRule = specialRules[Math.floor(Math.random() * specialRules.length)]; // --- UI Elements --- // Title Text var titleText = new Text2('Daily Challenge: Special Game', { size: 70, fill: 0xFFFFFF, wordWrap: true, // Enable word wrap wordWrapWidth: 1800 // Set max width before wrapping }); titleText.anchor.set(0.5, 0.5); titleText.y = -350; // Position higher up self.addChild(titleText); // Compile description for the selected special rule var finalDescription = 'Special Rule: ' + selectedSpecialRule.name + '\n' + selectedSpecialRule.description; // Description Text var descriptionText = new Text2(finalDescription, { size: 45, fill: 0xCCCCCC, align: 'center', // Center align text wordWrap: true, // Enable word wrap wordWrapWidth: 1600 // Set max width before wrapping }); descriptionText.anchor.set(0.5, 0.5); descriptionText.y = -150; // Position below title self.addChild(descriptionText); // Start Challenge Button var startButton = new Text2('START CHALLENGE', { size: 70, fill: 0xFFFFFF }); startButton.anchor.set(0.5, 0.5); startButton.y = 100; self.addChild(startButton); // Back Button var backButton = new Text2('< BACK', { size: 60, fill: 0xFFFFFF }); backButton.anchor.set(0.5, 0.5); backButton.y = 300; // Position further down self.addChild(backButton); // Add backgrounds for buttons var buttons = [startButton, backButton]; var buttonBackgrounds = []; for (var i = 0; i < buttons.length; i++) { var btn = buttons[i]; var bg = LK.getAsset('blackSquare', { anchorX: 0.5, anchorY: 0.5, width: btn.width + 80, height: btn.height + 40, tint: 0x3a3a3a }); bg.alpha = 0.7; bg.x = btn.x; bg.y = btn.y; buttonBackgrounds.push(bg); self.addChild(bg); self.addChild(btn); // Re-add button to put it on top } // --- Interactions --- // Start Button Interaction (function (index) { var btn = buttons[index]; var bg = buttonBackgrounds[index]; btn.interactive = true; btn.down = function (x, y, obj) { // Flash effect tween(bg, { alpha: 1 }, { duration: 100, onFinish: function onComplete() { tween(bg, { alpha: 0.7 }, { duration: 100 }); } }); // Set the game mode and the specific rule game.gameMode = 'specialGame'; game.specialRule = selectedSpecialRule.id; // Store the ID of the rule // Remove this screen if (game.dailyChallengeScreen) { game.removeChild(game.dailyChallengeScreen); game.dailyChallengeScreen = null; } game.showBotSelectionScreen(); // Go to bot selection for special game }; })(0); // Index 0 is the start button // Back Button Interaction (function (index) { var btn = buttons[index]; var bg = buttonBackgrounds[index]; btn.interactive = true; btn.down = function (x, y, obj) { // Flash effect tween(bg, { alpha: 1 }, { duration: 100, onFinish: function onComplete() { tween(bg, { alpha: 0.7 }, { duration: 100 }); } }); // Go back to the game mode selection screen game.showGameModeScreen(); }; })(1); // Index 1 is the back button self.update = function () { // Optional: Add animations if needed }; return self; }); var GameModeScreen = Container.expand(function () { var self = Container.call(this); // Create title text var titleText = new Text2('Select Game Mode', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -250; self.addChild(titleText); // Create mode buttons var classicButton = new Text2('CLASSIC', { size: 80, fill: 0xFFFFFF }); classicButton.anchor.set(0.5, 0.5); classicButton.y = -150; self.addChild(classicButton); var crazyButton = new Text2('CRAZY MODE', { size: 80, fill: 0xFFFFFF }); crazyButton.anchor.set(0.5, 0.5); crazyButton.y = 0; self.addChild(crazyButton); var dailyChallengeButton = new Text2('DAILY CHALLENGE', { size: 80, fill: 0xFFFFFF }); dailyChallengeButton.anchor.set(0.5, 0.5); dailyChallengeButton.y = 150; self.addChild(dailyChallengeButton); var backButton = new Text2('< BACK', { size: 60, fill: 0xFFFFFF }); backButton.anchor.set(0.5, 0.5); backButton.y = 350; self.addChild(backButton); // Add highlighting for buttons var buttons = [classicButton, crazyButton, dailyChallengeButton, backButton]; var buttonBackgrounds = []; // Create button backgrounds for (var i = 0; i < buttons.length; i++) { var btn = buttons[i]; var bg = LK.getAsset('blackSquare', { anchorX: 0.5, anchorY: 0.5, width: btn.width + 80, height: btn.height + 40, tint: 0x3a3a3a }); bg.alpha = 0.7; bg.x = btn.x; bg.y = btn.y; buttonBackgrounds.push(bg); self.addChild(bg); self.addChild(btn); // Re-add button to put it on top } // Add button hover effects for (var i = 0; i < buttons.length; i++) { (function (index) { var btn = buttons[index]; var bg = buttonBackgrounds[index]; btn.interactive = true; btn.down = function (x, y, obj) { // Flash button when clicked tween(bg, { alpha: 1 }, { duration: 100, onFinish: function onComplete() { tween(bg, { alpha: 0.7 }, { duration: 100 }); } }); // Handle button action if (index === 0) { // Classic mode game.gameMode = 'classic'; game.showBotSelectionScreen(); // Go to bot selection } else if (index === 1) { // Crazy mode game.gameMode = 'crazy'; game.showBotSelectionScreen(); // Go to bot selection } else if (index === 2) { // Daily Challenge mode game.gameMode = 'dailyChallenge'; game.showDailyChallengeScreen(); // Show the dedicated screen } else if (index === 3) { // Back button game.showTitleScreen(); } }; })(i); } // Pulse animation for the first button var pulseScale = 1; var increasing = true; self.update = function () { // Pulse effect for the Classic button if (increasing) { pulseScale += 0.002; if (pulseScale >= 1.05) { increasing = false; } } else { pulseScale -= 0.002; if (pulseScale <= 0.95) { increasing = true; } } classicButton.scale.set(pulseScale); buttonBackgrounds[0].scale.set(pulseScale); }; return self; }); var TitleScreen = Container.expand(function () { var self = Container.call(this); // Create title text var titleText = new Text2('Crazy Chess', { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); self.addChild(titleText); // Create start button var startButton = new Text2('TAP TO START', { size: 90, fill: 0xFFFFFF }); startButton.anchor.set(0.5, 0.5); startButton.y = 200; // Move start button up slightly self.addChild(startButton); // Create More Games button var moreGamesButton = new Text2('MORE GAMES', { size: 70, fill: 0xCCCCCC // Slightly dimmer color }); moreGamesButton.anchor.set(0.5, 0.5); moreGamesButton.y = 350; // Position below start button self.addChild(moreGamesButton); // Add pulsing animation to the start button var pulseScale = 1; var increasing = true; self.update = function () { // Pulse effect for start button if (increasing) { pulseScale += 0.003; if (pulseScale >= 1.1) { increasing = false; } } else { pulseScale -= 0.003; if (pulseScale <= 0.9) { increasing = true; } } startButton.scale.set(pulseScale); // Also pulse the More Games button slightly out of phase for visual interest moreGamesButton.scale.set(1 + (pulseScale - 1) * 0.8); // Smaller pulse }; // Handle tap anywhere to start // Make start button interactive separately startButton.interactive = true; startButton.down = function () { game.showGameModeScreen(); }; // Make More Games button interactive moreGamesButton.interactive = true; moreGamesButton.down = function () { // Open the specified link LK.link.open('https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link'); // Optional: Add visual feedback like a quick flash LK.effects.flashObject(moreGamesButton, 0xFFFFFF, 150); }; // Keep the main screen tap for starting the game as well (optional) self.interactive = true; // Make the whole screen interactive self.down = function (x, y, obj) { // Check if the tap landed on one of the buttons; if so, their handlers already ran. // If the tap is elsewhere on the screen, treat it like tapping "Start". if (obj.target !== startButton && obj.target !== moreGamesButton) { game.showGameModeScreen(); } }; //{8c} // Keep original line ID if relevant, but content changed return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ // No title, no description // Always backgroundColor is black backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game constants - Default to 8x8 var BOARD_SIZE = 8; // Default board size var BOARD_SIZE_X = 8; var BOARD_SIZE_Y = 8; var SQUARE_SIZE = 100; var BOARD_OFFSET_X = (2048 - BOARD_SIZE_X * SQUARE_SIZE) / 2; var BOARD_OFFSET_Y = (2732 - BOARD_SIZE_Y * SQUARE_SIZE) / 2; var BOARD_START_COL = 0; // For small chess adjustment var BOARD_END_COL = 7; // For small chess adjustment // Game state variables var board = []; var selectedSquare = null; var validMoves = []; var currentPlayer = 'white'; var gameState = 'title'; // 'title', 'modeSelect', 'botSelect', 'playing', 'check', 'checkmate', 'stalemate', 'dailyChallenge', 'specialGame' var specialRule = null; // Stores the active special rule for daily challenges var aiThinking = false; var titleScreen = null; var gameModeScreen = null; var botSelectionScreen = null; // Add variable for the bot selection screen var dailyChallengeScreen = null; // Add variable for the daily challenge screen var selectedBot = ''; // Add variable to store the selected bot // gameMode is now set on the game object, not as a separate variable var crazyAbilities = new CrazyAbility(); var crazyAbilityChance = 0.4; // 40% chance of AI using ability after a move // Special Mode Variables var goatedTurnCounter = 0; var ICY_DAY_FREEZE_CHANCE = 0.3; // 30% chance to freeze var ICY_DAY_FREEZE_TURNS = 2; // Freeze duration var icyDayFrozenPieces = []; // Stores { row, col, turnsLeft } for Icy Day var yetiPawns = []; // Stores { row, col } of Yeti pawns // Variables for draw conditions var movesSinceCaptureOrPawn = 0; // For 50-move rule var lastMove = null; // To track piece captures and pawn moves // Initialize the chess board function initializeBoard() { board = []; // Adjust board size and offsets for Small Chess if (game.gameMode === 'specialGame' && game.specialRule === 'smallChess') { BOARD_SIZE_X = 4; BOARD_SIZE_Y = 8; BOARD_START_COL = 2; BOARD_END_COL = 5; BOARD_OFFSET_X = (2048 - BOARD_SIZE_X * SQUARE_SIZE) / 2; BOARD_OFFSET_Y = (2732 - BOARD_SIZE_Y * SQUARE_SIZE) / 2; } else { // Reset to default if not small chess BOARD_SIZE_X = 8; BOARD_SIZE_Y = 8; BOARD_START_COL = 0; BOARD_END_COL = 7; BOARD_OFFSET_X = (2048 - BOARD_SIZE_X * SQUARE_SIZE) / 2; BOARD_OFFSET_Y = (2732 - BOARD_SIZE_Y * SQUARE_SIZE) / 2; } // Create the chess board based on dimensions for (var row = 0; row < BOARD_SIZE_Y; row++) { board[row] = []; for (var col = 0; col < BOARD_SIZE_X; col++) { var boardCol = col + BOARD_START_COL; // Map visual column to board array column var squareColor = (row + boardCol) % 2 === 0 ? 'white' : 'black'; var square = new ChessSquare(row, boardCol, squareColor); // Store the actual board column square.x = BOARD_OFFSET_X + col * SQUARE_SIZE; // Visual position based on 0 to BOARD_SIZE_X-1 square.y = BOARD_OFFSET_Y + row * SQUARE_SIZE; // Initialize board array slots, only add visible squares to game board[row][boardCol] = square; // Use actual board column index game.addChild(square); } // Initialize non-visible columns for internal logic if needed (e.g. full 8x8 array) if (game.gameMode !== 'specialGame' || game.specialRule !== 'smallChess') { // Standard 8x8 initialization already covered } else { // For small chess, fill the rest of the 8x8 array rows with null or placeholder if needed by logic // This example assumes logic primarily uses BOARD_START_COL and BOARD_END_COL checks for (var r = 0; r < BOARD_SIZE_Y; ++r) { for (var c = 0; c < 8; ++c) { if (c < BOARD_START_COL || c > BOARD_END_COL) { if (!board[r]) { board[r] = []; } board[r][c] = null; // Or a placeholder indicating off-board } } } } } // Place the pieces on the board placePieces(); } // Place all chess pieces in their starting positions function placePieces() { if (game.gameMode === 'specialGame' && game.specialRule === 'smallChess') { // Small Chess Setup (4x8 board, cols 2-5) // Place pawns for (var col = BOARD_START_COL; col <= BOARD_END_COL; col++) { board[1][col].setPiece(new ChessPiece('pawn', 'black')); board[6][col].setPiece(new ChessPiece('pawn', 'white')); } // Place rooks board[0][BOARD_START_COL].setPiece(new ChessPiece('rook', 'black')); // Col 2 board[0][BOARD_END_COL].setPiece(new ChessPiece('rook', 'black')); // Col 5 board[7][BOARD_START_COL].setPiece(new ChessPiece('rook', 'white')); // Col 2 board[7][BOARD_END_COL].setPiece(new ChessPiece('rook', 'white')); // Col 5 // Place queens board[0][BOARD_START_COL + 1].setPiece(new ChessPiece('queen', 'black')); // Col 3 board[7][BOARD_START_COL + 1].setPiece(new ChessPiece('queen', 'white')); // Col 3 // Place kings board[0][BOARD_START_COL + 2].setPiece(new ChessPiece('king', 'black')); // Col 4 board[7][BOARD_START_COL + 2].setPiece(new ChessPiece('king', 'white')); // Col 4 // No knights or bishops } else if (game.gameMode === 'specialGame' && game.specialRule === 'dragonBoss') { // Dragon Boss Setup // White: King, 4 Bishops, 3 Knights board[7][4].setPiece(new ChessPiece('king', 'white')); // e1 board[7][2].setPiece(new ChessPiece('bishop', 'white')); // c1 board[7][3].setPiece(new ChessPiece('bishop', 'white')); // d1 board[7][5].setPiece(new ChessPiece('bishop', 'white')); // f1 board[7][6].setPiece(new ChessPiece('bishop', 'white')); // g1 board[7][1].setPiece(new ChessPiece('knight', 'white')); // b1 board[7][7].setPiece(new ChessPiece('knight', 'white')); // h1 board[6][4].setPiece(new ChessPiece('knight', 'white')); // e2 - One knight forward // Black: Dragon (use Queen asset for now, moves handled separately) board[0][4].setPiece(new ChessPiece('queen', 'black')); // Dragon on e8 board[0][4].piece.isDragon = true; // Mark as Dragon } else { // Standard Setup // Place pawns for (var col = 0; col < 8; col++) { //{8q} // Use 8 explicitly board[1][col].setPiece(new ChessPiece('pawn', 'black')); board[6][col].setPiece(new ChessPiece('pawn', 'white')); } // Place rooks board[0][0].setPiece(new ChessPiece('rook', 'black')); board[0][7].setPiece(new ChessPiece('rook', 'black')); board[7][0].setPiece(new ChessPiece('rook', 'white')); board[7][7].setPiece(new ChessPiece('rook', 'white')); // Place knights board[0][1].setPiece(new ChessPiece('knight', 'black')); board[0][6].setPiece(new ChessPiece('knight', 'black')); board[7][1].setPiece(new ChessPiece('knight', 'white')); board[7][6].setPiece(new ChessPiece('knight', 'white')); // Place bishops board[0][2].setPiece(new ChessPiece('bishop', 'black')); board[0][5].setPiece(new ChessPiece('bishop', 'black')); board[7][2].setPiece(new ChessPiece('bishop', 'white')); board[7][5].setPiece(new ChessPiece('bishop', 'white')); // Place queens board[0][3].setPiece(new ChessPiece('queen', 'black')); board[7][3].setPiece(new ChessPiece('queen', 'white')); // Place kings board[0][4].setPiece(new ChessPiece('king', 'black')); board[7][4].setPiece(new ChessPiece('king', 'white')); } // GOAT-ed Challenge: Make all white pieces (except king) goatified if (game.gameMode === 'specialGame' && game.specialRule === 'goatedChallenge') { for (var r = 0; r < 8; r++) { for (var c = 0; c < 8; c++) { if (board[r][c] && board[r][c].piece && board[r][c].piece.color === 'white' && board[r][c].piece.type !== 'king') { board[r][c].piece.isPermanentlyGoatified = true; board[r][c].piece.tint = 0x88BB33; // Goat color tint } } } goatedTurnCounter = 0; // Reset turn counter } // Icy Day: Designate some white pawns as Yetis if (game.gameMode === 'specialGame' && game.specialRule === 'icyDay') { icyDayFrozenPieces = []; // Reset frozen list yetiPawns = []; // Reset yeti list // Make pawns on b, d, e, g Yetis var yetiCols = [1, 3, 4, 6]; // b, d, e, g columns for (var i = 0; i < yetiCols.length; i++) { var col = yetiCols[i]; if (board[6][col] && board[6][col].piece && board[6][col].piece.type === 'pawn') { board[6][col].piece.isYeti = true; board[6][col].piece.tint = 0xADD8E6; // Light blue tint for Yetis yetiPawns.push({ row: 6, col: col }); } } } // Special rule for 'King' bot: remove the black queen if (game.selectedBot === 'King' && game.gameMode !== 'specialGame') { // Don't apply if it's a special game if (board[0][3].piece && board[0][3].piece.type === 'queen' && board[0][3].piece.color === 'black') { board[0][3].setPiece(null); } } } // Select a square on the chess board game.selectSquare = function (square) { // If AI is thinking, don't allow moves if (aiThinking || gameState === 'checkmate' || gameState === 'stalemate') { return; } // If the current player is not the human player, don't allow moves if (currentPlayer !== 'white') { return; } // Check if piece is frozen (Only in Crazy Mode) if (game.gameMode === 'crazy' && square.piece && square.piece.color === 'white' && crazyAbilities.isPieceFrozen(square.row, square.col)) { // Show notification that piece is frozen var notification = new Text2('This piece is frozen!', { size: 40, fill: 0x00AAFF }); notification.anchor.set(0.5, 0.5); notification.x = 2048 / 2; notification.y = 2732 / 2 - 200; game.addChild(notification); // Remove notification after delay LK.setTimeout(function () { game.removeChild(notification); }, 1500); return; } // Check if piece is frozen (Icy Day Mode) if (game.gameMode === 'specialGame' && game.specialRule === 'icyDay' && square.piece && square.piece.isFrozenIcy) { // Show notification that piece is frozen var notificationIcy = new Text2('This piece is frozen!', { size: 40, //{90} // Reuse ID if appropriate fill: 0x00AAFF }); //{91} // Reuse ID if appropriate notificationIcy.anchor.set(0.5, 0.5); //{92} // Reuse ID if appropriate notificationIcy.x = 2048 / 2; //{93} // Reuse ID if appropriate notificationIcy.y = 2732 / 2 - 200; game.addChild(notificationIcy); //{94} // Reuse ID if appropriate // Remove notification after delay LK.setTimeout(function () { //{95} // Reuse ID if appropriate game.removeChild(notificationIcy); //{96} // Reuse ID if appropriate }, 1500); //{97} // Reuse ID if appropriate return; // Don't allow selection } // Clear previous selections clearHighlights(); // If a square is already selected and the new square is a valid move if (selectedSquare && isValidMove(square)) { // Move the piece var from = selectedSquare; var to = square; movePiece(from, to); // Reset selection state selectedSquare = null; validMoves = []; clearHighlights(); // Clear highlights after move // Check if the move ended the game via specific rules (like king capture) // gameState might have been updated in movePiece if (gameState === 'checkmate' || gameState === 'stalemate') { // endGame was already called in movePiece return; } // Switch to the next player switchPlayer(); //{9C} // currentPlayer is now the opponent ('black') // Now check the state for the player whose turn it just became checkGameState(); //{9B} // Checks state for 'black' // If the game ended due to checkmate/stalemate after the switch if (gameState === 'checkmate' || gameState === 'stalemate') { // Game end message already shown by checkGameState -> endGame return; } // If it's AI's turn (now black) and game is still going if (currentPlayer === 'black') { aiThinking = true; LK.setTimeout(makeAIMove, 1000); } } // If clicking on a piece of the current player else if (square.piece && square.piece.color === currentPlayer) { // Select the square selectedSquare = square; square.highlight('selected'); // Calculate valid moves validMoves = calculateValidMoves(square); // Highlight valid moves for (var i = 0; i < validMoves.length; i++) { var move = validMoves[i]; board[move.row][move.col].highlight('validMove'); } } }; // Check if a move to the target square is valid function isValidMove(targetSquare) { for (var i = 0; i < validMoves.length; i++) { var move = validMoves[i]; if (move.row === targetSquare.row && move.col === targetSquare.col) { return true; } } return false; } // Move a piece from one square to another function movePiece(fromSquare, toSquare) { var piece = fromSquare.piece; // Check for pawn move or capture (for 50-move rule) var isPawnMove = piece.type === 'pawn'; var isCapture = toSquare.piece !== null; // Check for trap only in crazy mode var trapTriggered = false; if (game.gameMode === 'crazy' && crazyAbilities.hasTrap(toSquare.row, toSquare.col)) { // Trigger trap effect trapTriggered = crazyAbilities.triggerTrap(toSquare.row, toSquare.col); // If trap is triggered and the piece is white (not king - king is immune) if (trapTriggered && piece.color === 'white' && piece.type !== 'king') { // Show trap activation message var trapMessage = new Text2("TRAP TRIGGERED!", { size: 50, fill: 0xFF0000 }); trapMessage.anchor.set(0.5, 0.5); trapMessage.x = 2048 / 2; trapMessage.y = 2732 / 2 - 250; game.addChild(trapMessage); // Remove message after delay LK.setTimeout(function () { game.removeChild(trapMessage); }, 1500); // Piece is captured by the trap fromSquare.setPiece(null); LK.getSound('capture').play(); // Update move counter for 50-move rule movesSinceCaptureOrPawn = 0; // Store last move information lastMove = { from: { row: fromSquare.row, col: fromSquare.col }, to: { row: toSquare.row, col: toSquare.col }, piece: piece.type, color: piece.color, isCapture: true, isTrap: true }; return; // Skip the rest of the move logic } } // Handle capture if (isCapture) { LK.getSound('capture').play(); } else { LK.getSound('move').play(); } // Move the piece var capturedPiece = toSquare.piece; // Store captured piece before overwriting fromSquare.setPiece(null); toSquare.setPiece(piece); // Mark piece as moved (for castling and pawn double move) piece.hasMoved = true; // Capture the King Rule: Check if a king was captured if (game.gameMode === 'specialGame' && game.specialRule === 'captureKing' && capturedPiece && capturedPiece.type === 'king') { gameState = 'checkmate'; // Use checkmate state to signify win endGame('King Captured! ' + piece.color + ' wins!'); return; // End the move function early } // Handle pawn promotion if (piece.type === 'pawn' && (toSquare.row === 0 || toSquare.row === 7)) { promotePawn(toSquare); } // Update move counter for 50-move rule if (isPawnMove || isCapture) { movesSinceCaptureOrPawn = 0; } else { movesSinceCaptureOrPawn++; } // Store last move information lastMove = { from: { row: fromSquare.row, col: fromSquare.col }, to: { row: toSquare.row, col: toSquare.col }, piece: piece.type, color: piece.color, isCapture: isCapture }; // --- Special Mode Post-Move Actions --- // Transformo-fest: Transform piece after moving (if not king) if (game.gameMode === 'specialGame' && game.specialRule === 'transformoFest' && piece.type !== 'king') { var possibleTypes = ['pawn', 'rook', 'knight', 'bishop', 'queen']; var randomType = possibleTypes[Math.floor(Math.random() * possibleTypes.length)]; toSquare.setPiece(new ChessPiece(randomType, piece.color)); // Add a small visual indicator? Maybe flash? LK.effects.flashObject(toSquare.piece, 0xFFFF00, 300); } // Icy Day: Chance to freeze moved piece (if not king or yeti) if (game.gameMode === 'specialGame' && game.specialRule === 'icyDay' && piece.type !== 'king' && !piece.isYeti) { if (Math.random() < ICY_DAY_FREEZE_CHANCE) { // Check if already frozen var alreadyFrozen = false; for (var i = 0; i < icyDayFrozenPieces.length; i++) { if (icyDayFrozenPieces[i].row === toSquare.row && icyDayFrozenPieces[i].col === toSquare.col) { alreadyFrozen = true; break; } } // Freeze if not already frozen if (!alreadyFrozen) { icyDayFrozenPieces.push({ row: toSquare.row, col: toSquare.col, turnsLeft: ICY_DAY_FREEZE_TURNS }); if (toSquare.piece) { // Check if piece still exists (could have transformed?) toSquare.piece.tint = 0x00AAFF; // Blue tint for frozen toSquare.piece.isFrozenIcy = true; // Mark as frozen } // Optional: Add notification text var freezeText = new Text2("FROZEN!", { size: 30, fill: 0x00AAFF }); freezeText.anchor.set(0.5, 1.0); freezeText.x = toSquare.x + SQUARE_SIZE / 2; freezeText.y = toSquare.y; // Position above the square game.addChild(freezeText); LK.setTimeout(function () { game.removeChild(freezeText); }, 1000); } } } // Increment GOAT-ed turn counter after white moves if (game.gameMode === 'specialGame' && game.specialRule === 'goatedChallenge' && piece.color === 'white') { goatedTurnCounter++; } } // Promote a pawn to a queen function promotePawn(square) { var piece = square.piece; square.setPiece(new ChessPiece('queen', piece.color)); LK.getSound('promotion').play(); } // Clear highlights from all squares function clearHighlights() { for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { if (board[row][col]) { board[row][col].highlight(); } } } } // Calculate valid moves for a piece function calculateValidMoves(square) { var piece = square.piece; var moves = []; if (!piece) { return moves; } var row = square.row; var col = square.col; // Check for special movement rules first // GOAT-ed Challenge: Permanently goatified white pieces move like kings if (game.gameMode === 'specialGame' && game.specialRule === 'goatedChallenge' && piece.color === 'white' && piece.isPermanentlyGoatified) { calculateKingMoves(row, col, piece, moves); } // Dragon Boss: Dragon piece moves like Queen + Knight else if (game.gameMode === 'specialGame' && game.specialRule === 'dragonBoss' && piece.isDragon) { calculateRookMoves(row, col, piece, moves); // Queen part 1 calculateBishopMoves(row, col, piece, moves); // Queen part 2 calculateKnightMoves(row, col, piece, moves); // Knight part } // Check if piece is temporarily goatified (Crazy Mode) else if (game.gameMode === 'crazy' && piece.color === 'white' && crazyAbilities.isPieceGoatified(row, col)) { // Goatified pieces move like kings calculateKingMoves(row, col, piece, moves); } else { // Regular move calculation based on piece type (apply special rules within these) switch (piece.type) { case 'pawn': calculatePawnMoves(row, col, piece, moves); break; case 'rook': calculateRookMoves(row, col, piece, moves); break; case 'knight': calculateKnightMoves(row, col, piece, moves); break; case 'bishop': calculateBishopMoves(row, col, piece, moves); break; case 'queen': calculateRookMoves(row, col, piece, moves); calculateBishopMoves(row, col, piece, moves); break; case 'king': calculateKingMoves(row, col, piece, moves); break; } } // Filter out moves that would put the king in check return filterCheckMoves(square, moves); } // Calculate valid moves for a pawn function calculatePawnMoves(row, col, piece, moves) { var direction = piece.color === 'white' ? -1 : 1; // Move forward one square if (isValidSquare(row + direction, col) && !board[row + direction][col].piece) { moves.push({ row: row + direction, col: col }); // Move forward two squares from starting position if (!piece.hasMoved && isValidSquare(row + 2 * direction, col) && !board[row + 2 * direction][col].piece) { moves.push({ row: row + 2 * direction, col: col }); } } // Captures var captureDirections = [{ row: direction, col: -1 }, { row: direction, col: 1 }]; for (var i = 0; i < captureDirections.length; i++) { var dir = captureDirections[i]; var newRow = row + dir.row; var newCol = col + dir.col; if (isValidSquare(newRow, newCol) && board[newRow][newCol].piece && board[newRow][newCol].piece.color !== piece.color) { moves.push({ row: newRow, col: newCol }); } } // Backwards Pawns Rule if (game.gameMode === 'specialGame' && game.specialRule === 'backwardsPawns') { var backwardDirection = -direction; // Opposite direction // Move backward one square if (isValidSquare(row + backwardDirection, col) && !board[row + backwardDirection][col].piece) { moves.push({ row: row + backwardDirection, col: col }); // No double move backwards } // Backward captures var backwardCaptureDirections = [{ row: backwardDirection, col: -1 }, { row: backwardDirection, col: 1 }]; for (var i = 0; i < backwardCaptureDirections.length; i++) { var bDir = backwardCaptureDirections[i]; var bNewRow = row + bDir.row; var bNewCol = col + bDir.col; if (isValidSquare(bNewRow, bNewCol) && board[bNewRow][bNewCol].piece && board[bNewRow][bNewCol].piece.color !== piece.color) { moves.push({ row: bNewRow, col: bNewCol }); } } } } // Calculate valid moves for a rook function calculateRookMoves(row, col, piece, moves) { var directions = [{ row: -1, col: 0 }, // up { row: 1, col: 0 }, // down { row: 0, col: -1 }, // left { row: 0, col: 1 } // right ]; calculateSlidingMoves(row, col, piece, moves, directions); } // Calculate valid moves for a bishop function calculateBishopMoves(row, col, piece, moves) { var directions = [{ row: -1, col: -1 }, // up-left { row: -1, col: 1 }, // up-right { row: 1, col: -1 }, // down-left { row: 1, col: 1 } // down-right ]; var diagonalMoves = []; // Store initial diagonal moves before filtering/adding horizontal calculateSlidingMoves(row, col, piece, moves, directions); // SHREDR Bishops: Add horizontal move option if (game.gameMode === 'specialGame' && game.specialRule === 'shredrBishops') { var shredrMoves = []; for (var i = 0; i < moves.length; i++) { var move = moves[i]; shredrMoves.push(move); // Keep the original diagonal move // Add horizontal moves from the landing square var landingRow = move.row; var landingCol = move.col; // Check horizontal left if (isValidSquare(landingRow, landingCol - 1)) { var leftSquare = board[landingRow][landingCol - 1]; if (!leftSquare || !leftSquare.piece || leftSquare.piece.color !== piece.color) { shredrMoves.push({ row: landingRow, col: landingCol - 1 }); } } // Check horizontal right if (isValidSquare(landingRow, landingCol + 1)) { var rightSquare = board[landingRow][landingCol + 1]; if (!rightSquare || !rightSquare.piece || rightSquare.piece.color !== piece.color) { shredrMoves.push({ row: landingRow, col: landingCol + 1 }); } } } // Replace original moves with shredr moves (includes original + horizontal) // Need to clear original moves and add shredrMoves back. // The 'moves' array is passed by reference, modify it directly. moves.length = 0; // Clear the array for (var k = 0; k < shredrMoves.length; k++) { // Avoid duplicates (simple check, might need improvement for complex scenarios) var exists = false; for (var j = 0; j < moves.length; j++) { if (moves[j].row === shredrMoves[k].row && moves[j].col === shredrMoves[k].col) { exists = true; break; } } if (!exists) { moves.push(shredrMoves[k]); } } } } // Calculate valid moves for sliding pieces (rook, bishop, queen) function calculateSlidingMoves(row, col, piece, moves, directions) { for (var i = 0; i < directions.length; i++) { var dir = directions[i]; var newRow = row + dir.row; var newCol = col + dir.col; while (isValidSquare(newRow, newCol)) { var targetSquare = board[newRow][newCol]; if (!targetSquare.piece) { // Empty square, can move here moves.push({ row: newRow, col: newCol }); } else { // Found a piece if (targetSquare.piece.color !== piece.color) { // Can capture opponent's piece moves.push({ row: newRow, col: newCol }); } // SHREDR Bishops can jump, so don't break here for them if (!(game.gameMode === 'specialGame' && game.specialRule === 'shredrBishops' && piece.type === 'bishop')) { // Can't move past a piece (unless SHREDR bishop) break; } } newRow += dir.row; newCol += dir.col; } } } // Calculate valid moves for a knight function calculateKnightMoves(row, col, piece, moves) { var knightDirections = [{ row: -2, col: -1 }, { row: -2, col: 1 }, { row: -1, col: -2 }, { row: -1, col: 2 }, { row: 1, col: -2 }, { row: 1, col: 2 }, { row: 2, col: -1 }, { row: 2, col: 1 }]; for (var i = 0; i < knightDirections.length; i++) { var dir = knightDirections[i]; var newRow = row + dir.row; var newCol = col + dir.col; if (isValidSquare(newRow, newCol)) { var targetSquare = board[newRow][newCol]; if (!targetSquare.piece || targetSquare.piece.color !== piece.color) { moves.push({ row: newRow, col: newCol }); } } } } // Calculate valid moves for a king function calculateKingMoves(row, col, piece, moves) { var kingDirections = [{ row: -1, col: -1 }, { row: -1, col: 0 }, { row: -1, col: 1 }, { row: 0, col: -1 }, { row: 0, col: 1 }, { row: 1, col: -1 }, { row: 1, col: 0 }, { row: 1, col: 1 }]; for (var i = 0; i < kingDirections.length; i++) { var dir = kingDirections[i]; var newRow = row + dir.row; var newCol = col + dir.col; if (isValidSquare(newRow, newCol)) { var targetSquare = board[newRow][newCol]; if (!targetSquare.piece || targetSquare.piece.color !== piece.color) { moves.push({ row: newRow, col: newCol }); } } } // Castling if (!piece.hasMoved) { // Kingside castling if (canCastle(row, col, 0, 3)) { moves.push({ row: row, col: col + 2 }); } // Queenside castling if (canCastle(row, col, 0, -4)) { moves.push({ row: row, col: col - 2 }); } } } // Check if castling is possible function canCastle(row, col, rowOffset, colOffset) { var rookCol = colOffset > 0 ? 7 : 0; var rookRow = row; // Check if there's a rook in the corner var rookSquare = board[rookRow][rookCol]; if (!rookSquare.piece || rookSquare.piece.type !== 'rook' || rookSquare.piece.hasMoved) { return false; } // Check if there are pieces between the king and the rook var startCol = Math.min(col, rookCol) + 1; var endCol = Math.max(col, rookCol) - 1; for (var c = startCol; c <= endCol; c++) { if (board[row][c].piece) { return false; } } // Check if the king would move through or into check var direction = colOffset > 0 ? 1 : -1; if (isSquareAttacked(row, col, otherPlayer(currentPlayer)) || isSquareAttacked(row, col + direction, otherPlayer(currentPlayer)) || isSquareAttacked(row, col + 2 * direction, otherPlayer(currentPlayer))) { return false; } return true; } // Filter out moves that would put the king in check function filterCheckMoves(fromSquare, moves) { var validMoves = []; var piece = fromSquare.piece; // Capture the King Rule: King doesn't care about checks, skip filtering if (game.gameMode === 'specialGame' && game.specialRule === 'captureKing') { // Return all moves unfiltered for check for (var i = 0; i < moves.length; i++) { validMoves.push(moves[i]); } return validMoves; } // Standard check filtering for (var i = 0; i < moves.length; i++) { var move = moves[i]; // Make sure the move exists and has valid row/col properties if (!move || !board[move.row] || !board[move.row][move.col]) { continue; } // Simulate the move var originalPiece = board[move.row][move.col].piece; board[move.row][move.col].piece = piece; board[fromSquare.row][fromSquare.col].piece = null; // Check if the king is in check after the move var inCheck = isKingInCheck(piece.color); // Undo the move board[fromSquare.row][fromSquare.col].piece = piece; board[move.row][move.col].piece = originalPiece; if (!inCheck) { validMoves.push(move); } } return validMoves; } // Check if a square is valid (within the board) function isValidSquare(row, col) { // Use dynamic board sizes and column limits return row >= 0 && row < BOARD_SIZE_Y && col >= BOARD_START_COL && col <= BOARD_END_COL; } // Check if the king is in check function isKingInCheck(color) { // Find the king var kingSquare = findKing(color); if (!kingSquare) { return false; } // Check if the king is attacked by any opponent's piece return isSquareAttacked(kingSquare.row, kingSquare.col, otherPlayer(color)); } // Check if a square is attacked by any piece of the given color function isSquareAttacked(row, col, attackerColor) { for (var r = 0; r < BOARD_SIZE; r++) { for (var c = 0; c < BOARD_SIZE; c++) { var square = board[r][c]; if (square.piece && square.piece.color === attackerColor) { var moves = []; switch (square.piece.type) { case 'pawn': // Pawns attack diagonally var direction = square.piece.color === 'white' ? -1 : 1; var attackDirections = [{ row: direction, col: -1 }, { row: direction, col: 1 }]; for (var i = 0; i < attackDirections.length; i++) { var dir = attackDirections[i]; var attackRow = r + dir.row; var attackCol = c + dir.col; if (attackRow === row && attackCol === col) { return true; } } break; case 'rook': calculateRookMoves(r, c, square.piece, moves); break; case 'knight': calculateKnightMoves(r, c, square.piece, moves); break; case 'bishop': calculateBishopMoves(r, c, square.piece, moves); break; case 'queen': calculateRookMoves(r, c, square.piece, moves); calculateBishopMoves(r, c, square.piece, moves); break; case 'king': var kingDirections = [{ row: -1, col: -1 }, { row: -1, col: 0 }, { row: -1, col: 1 }, { row: 0, col: -1 }, { row: 0, col: 1 }, { row: 1, col: -1 }, { row: 1, col: 0 }, { row: 1, col: 1 }]; for (var i = 0; i < kingDirections.length; i++) { var dir = kingDirections[i]; var attackRow = r + dir.row; var attackCol = c + dir.col; if (attackRow === row && attackCol === col) { return true; } } break; } // Check if the square is in the list of moves for (var i = 0; i < moves.length; i++) { var move = moves[i]; if (move.row === row && move.col === col) { return true; } } } } } return false; } // Find the king of the given color function findKing(color) { for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece && square.piece.type === 'king' && square.piece.color === color) { return { row: row, col: col }; } } } return null; } // Get the other player's color function otherPlayer(color) { return color === 'white' ? 'black' : 'white'; } // Switch the current player function switchPlayer() { currentPlayer = otherPlayer(currentPlayer); // Icy Day: Update frozen piece counters at the start of the next player's turn if (game.gameMode === 'specialGame' && game.specialRule === 'icyDay') { updateIcyDayFrozenPieces(); } } // Helper function to update Icy Day frozen pieces function updateIcyDayFrozenPieces() { for (var i = icyDayFrozenPieces.length - 1; i >= 0; i--) { var frozen = icyDayFrozenPieces[i]; frozen.turnsLeft--; if (frozen.turnsLeft <= 0) { var square = board[frozen.row][frozen.col]; // Unfreeze if the piece is still there and marked as frozen if (square && square.piece && square.piece.isFrozenIcy) { // Reset tint based on whether it's a Yeti or regular piece if (square.piece.isYeti) { square.piece.tint = 0xADD8E6; // Yeti tint } else { square.piece.tint = 0xFFFFFF; // Default tint } square.piece.isFrozenIcy = false; // Unmark } icyDayFrozenPieces.splice(i, 1); // Remove from list } } } // Check the game state (check, checkmate, stalemate) function checkGameState() { // Capture the King Rule: Check/Checkmate logic is different if (game.gameMode === 'specialGame' && game.specialRule === 'captureKing') { // Stalemate can still occur if no legal moves (excluding king capture scenario handled in movePiece) var allMovesCtK = getAllPossibleMoves(currentPlayer); if (allMovesCtK.length === 0) { // Stalemate if no moves and king not captured gameState = 'stalemate'; //{eT} // Reuse stalemate code line ID if appropriate endGame('Draw by stalemate!'); return; } // Check for 50-move rule - REMOVED /* if (movesSinceCaptureOrPawn >= 50) { //{gH} // Keep line ID comment for history gameState = 'stalemate'; endGame('Draw by 50-move rule!'); return; } */ // Check for insufficient material still applies if (hasInsufficientMaterial()) { gameState = 'stalemate'; endGame('Draw by insufficient material!'); return; } // No check state in this mode gameState = 'playing'; //{eV} // Reuse playing state code line ID return; // Skip standard check/checkmate logic } // GOAT-ed Challenge: Check for survival win if (game.gameMode === 'specialGame' && game.specialRule === 'goatedChallenge') { if (goatedTurnCounter >= 25) { gameState = 'checkmate'; // Use checkmate state to signify player win endGame('Survived 25 turns! You win!'); return; } // Check if AI king is captured (AI loses) - should not happen if AI plays normally var blackKing = findKing('black'); if (!blackKing) { gameState = 'checkmate'; endGame('AI King lost! You win!'); return; } // Check if player king is captured (Player loses) var whiteKing = findKing('white'); if (!whiteKing) { gameState = 'checkmate'; // Player lost endGame('Your King was captured! AI wins!'); return; } } // Dragon Boss: Check if Dragon is captured (Player wins) if (game.gameMode === 'specialGame' && game.specialRule === 'dragonBoss') { var dragonFound = false; for (var r = 0; r < BOARD_SIZE_Y; r++) { for (var c = BOARD_START_COL; c <= BOARD_END_COL; c++) { if (board[r][c] && board[r][c].piece && board[r][c].piece.isDragon) { dragonFound = true; break; } } if (dragonFound) { break; } } if (!dragonFound) { gameState = 'checkmate'; // Player wins endGame('Dragon Captured! You win!'); return; } // Check if player king is captured (Player loses) var whiteKingDragon = findKing('white'); if (!whiteKingDragon) { gameState = 'checkmate'; // Player lost endGame('Your King was captured! Dragon wins!'); return; } } // --- Standard Check/Checkmate/Stalemate Logic --- // Check if the current player's king is in check var inCheck = isKingInCheck(currentPlayer); // Get all possible moves for the current player var allMoves = getAllPossibleMoves(currentPlayer); // Check for 50-move rule - REMOVED /* if (movesSinceCaptureOrPawn >= 50) { //{hh} // Keep line ID comment for history gameState = 'stalemate'; endGame('Draw by 50-move rule!'); return; } */ // Check for insufficient material if (hasInsufficientMaterial()) { gameState = 'stalemate'; endGame('Draw by insufficient material!'); return; } // Check crazy mode king only frozen situation if (game.gameMode === 'crazy' && isKingOnlyFrozen()) { gameState = 'stalemate'; endGame('Draw! King is frozen and alone.'); return; } if (inCheck) { if (allMoves.length === 0) { // Checkmate gameState = 'checkmate'; endGame('Checkmate! ' + otherPlayer(currentPlayer) + ' wins!'); } else { // Check gameState = 'check'; LK.getSound('check').play(); } } else if (allMoves.length === 0) { // Stalemate gameState = 'stalemate'; endGame('Draw by stalemate!'); } else { gameState = 'playing'; } } // Get all possible moves for a player function getAllPossibleMoves(color) { var allMoves = []; for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece && square.piece.color === color) { var moves = calculateValidMoves(square); for (var i = 0; i < moves.length; i++) { allMoves.push({ fromRow: row, fromCol: col, toRow: moves[i].row, toCol: moves[i].col }); } } } } return allMoves; } // Check for insufficient material (K vs K, K vs KB, K vs KN) function hasInsufficientMaterial() { var pieces = { white: { count: 0, bishop: 0, knight: 0 }, black: { count: 0, bishop: 0, knight: 0 } }; // Count all pieces on the board for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece) { var piece = square.piece; pieces[piece.color].count++; if (piece.type === 'bishop') { pieces[piece.color].bishop++; } else if (piece.type === 'knight') { pieces[piece.color].knight++; } else if (piece.type !== 'king') { // If there's any other piece (pawn, rook, queen), material is sufficient if (piece.type === 'pawn' || piece.type === 'rook' || piece.type === 'queen') { return false; } } } } } // K vs K if (pieces.white.count === 1 && pieces.black.count === 1) { return true; } // K vs KB or K vs KN if (pieces.white.count === 1 && pieces.black.count === 2 && (pieces.black.bishop === 1 || pieces.black.knight === 1) || pieces.black.count === 1 && pieces.white.count === 2 && (pieces.white.bishop === 1 || pieces.white.knight === 1)) { return true; } return false; } // Check for king-only frozen situation in crazy mode function isKingOnlyFrozen() { if (game.gameMode !== 'crazy') { return false; } var whiteCount = 0; var whiteKingRow = -1; var whiteKingCol = -1; var blackCount = 0; // Count pieces and find white king for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { var square = board[row][col]; if (square.piece) { if (square.piece.color === 'white') { whiteCount++; if (square.piece.type === 'king') { whiteKingRow = row; whiteKingCol = col; } } else { blackCount++; } } } } // If white only has the king and it's frozen return whiteCount === 1 && whiteKingRow !== -1 && crazyAbilities.isPieceFrozen(whiteKingRow, whiteKingCol); } // End the game function endGame(message) { var gameOverText = new Text2(message, { size: 60, fill: 0xFFFFFF }); gameOverText.anchor.set(0.5, 0.5); gameOverText.x = 2048 / 2; gameOverText.y = 200; game.addChild(gameOverText); // Update score based on winner if (gameState === 'checkmate') { if (currentPlayer === 'black') { // White wins LK.setScore(100); } else { // Black wins (AI wins) LK.setScore(0); } } else { // Draw LK.setScore(50); } // Show game over after a short delay LK.setTimeout(function () { LK.showGameOver(); }, 3000); } // Make an AI move function makeAIMove() { if (gameState === 'checkmate' || gameState === 'stalemate') { aiThinking = false; return; } // Get all possible moves for the AI var possibleMoves = getAllPossibleMoves('black'); if (possibleMoves.length === 0) { aiThinking = false; return; } // Simple AI: pick a random move var randomMove = possibleMoves[Math.floor(Math.random() * possibleMoves.length)]; // Make the move var fromSquare = board[randomMove.fromRow][randomMove.fromCol]; var toSquare = board[randomMove.toRow][randomMove.toCol]; // Highlight the selected square fromSquare.highlight('selected'); // Wait a bit before making the move LK.setTimeout(function () { // Move the piece movePiece(fromSquare, toSquare); // Clear highlights clearHighlights(); // Check if the move ended the game (e.g., king capture) // gameState might have been updated in movePiece if (gameState === 'checkmate' || gameState === 'stalemate') { aiThinking = false; return; // Exit if movePiece ended the game } // Use crazy ability ONLY in crazy mode if (game.gameMode === 'crazy' && Math.random() < crazyAbilityChance) { // Use ability after a short delay LK.setTimeout(function () { crazyAbilities.useRandomAbility(); // Note: Ability might change game state, but we check again after switch anyway }, 500); } // Switch back to player switchPlayer(); //{iS} // currentPlayer is now 'white' // Check for check/checkmate/stalemate for the player whose turn it now is checkGameState(); //{iR} // Checks state for 'white' // If game ended after check if (gameState === 'checkmate' || gameState === 'stalemate') { aiThinking = false; return; } // Update crazy mode frozen and goatified pieces ONLY in crazy mode if (game.gameMode === 'crazy') { crazyAbilities.updateFrozenPieces(); crazyAbilities.updateGoatifiedPieces(); } // AI turn is over aiThinking = false; }, 500); } // Create score display var scoreTxt = new Text2('Crazy Chess', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Create turn display var turnText = new Text2('Your Turn', { size: 40, fill: 0xFFFFFF }); turnText.anchor.set(0.5, 0); turnText.y = 70; LK.gui.top.addChild(turnText); // Game update function game.update = function () { // If in title screen, update title screen if (gameState === 'title' && titleScreen) { titleScreen.update(); return; } // If in game mode selection screen, update that screen if (gameState === 'modeSelect' && gameModeScreen) { gameModeScreen.update(); return; } // If in bot selection screen, update that screen if (gameState === 'botSelect' && botSelectionScreen) { botSelectionScreen.update(); return; } // If in daily challenge screen, update that screen if (gameState === 'dailyChallenge' && dailyChallengeScreen) { dailyChallengeScreen.update(); return; // Stop further updates if in this screen } // Fog of War visual update (placeholder) if (game.gameMode === 'specialGame' && game.specialRule === 'fogOfWar') { // updateFogOfWar(); // TODO: Implement visual fog logic } // Update UI Text for Special Modes if (game.gameMode === 'specialGame') { if (game.specialRule === 'goatedChallenge') { scoreTxt.setText('GOAT-ed Challenge'); turnText.setText('Turn: ' + goatedTurnCounter + '/25'); if (gameState === 'checkmate' && goatedTurnCounter >= 25) { turnText.setText('You Win!'); } else if (gameState === 'checkmate') { turnText.setText('AI Wins!'); // Player lost before 25 turns } else if (aiThinking) { turnText.setText('AI Thinking...'); } // Don't overwrite win/loss text immediately return; // Skip default turn text logic for this mode if not thinking } else if (game.specialRule === 'dragonBoss') { scoreTxt.setText('Dragon Boss'); if (gameState === 'checkmate') { var whiteKingDragon = findKing('white'); turnText.setText(whiteKingDragon ? 'You Win!' : 'Dragon Wins!'); } else if (aiThinking) { turnText.setText('Dragon Thinking...'); } else { turnText.setText('Your Turn'); } return; // Skip default turn text logic } else if (game.specialRule === 'icyDay') { scoreTxt.setText('Icy Day'); // Use default turn text logic below } else if (game.specialRule === 'transformoFest') { scoreTxt.setText('Transformo-fest'); // Use default turn text logic below } // Add other special rule title updates here if needed } // Update turn text (Default logic, handles standard game and some special modes) if (gameState === 'checkmate') { // Capture the King uses 'checkmate' state for win, adjust text if (game.gameMode === 'specialGame' && game.specialRule === 'captureKing') { // Winner determined in endGame, turnText might be showing winner already } else if (currentPlayer === 'black') { turnText.setText('You Win!'); } else { turnText.setText('AI Wins!'); } } else if (gameState === 'stalemate') { turnText.setText('Draw!'); } else if (aiThinking) { turnText.setText('AI Thinking...'); } else { turnText.setText(currentPlayer === 'white' ? 'Your Turn' : 'AI Turn'); } }; // Method to show the game mode selection screen game.showGameModeScreen = function () { // Remove title screen if it exists if (titleScreen) { game.removeChild(titleScreen); titleScreen = null; } // Remove game mode screen if it already exists if (gameModeScreen) { game.removeChild(gameModeScreen); gameModeScreen = null; // Clear reference } // Remove bot selection screen if it exists if (botSelectionScreen) { game.removeChild(botSelectionScreen); botSelectionScreen = null; } // Remove daily challenge screen if it exists if (dailyChallengeScreen) { game.removeChild(dailyChallengeScreen); dailyChallengeScreen = null; } // Create and add game mode screen gameModeScreen = new GameModeScreen(); gameModeScreen.x = 2048 / 2; gameModeScreen.y = 2732 / 2; game.addChild(gameModeScreen); // Update game state gameState = 'modeSelect'; }; // Method to show the title screen // Method to show the bot selection screen game.showBotSelectionScreen = function () { // Remove game mode screen if it exists if (gameModeScreen) { game.removeChild(gameModeScreen); gameModeScreen = null; } // Remove title screen just in case (shouldn't happen in normal flow) if (titleScreen) { game.removeChild(titleScreen); titleScreen = null; } // Remove existing bot selection screen if present if (botSelectionScreen) { game.removeChild(botSelectionScreen); botSelectionScreen = null; } // Create and add bot selection screen botSelectionScreen = new BotSelectionScreen(); botSelectionScreen.x = 2048 / 2; botSelectionScreen.y = 2732 / 2; game.addChild(botSelectionScreen); // Update game state gameState = 'botSelect'; }; // Method to show the daily challenge screen game.showDailyChallengeScreen = function () { // Remove other screens if (titleScreen) { game.removeChild(titleScreen); titleScreen = null; } if (gameModeScreen) { game.removeChild(gameModeScreen); gameModeScreen = null; } if (botSelectionScreen) { game.removeChild(botSelectionScreen); botSelectionScreen = null; } if (dailyChallengeScreen) { game.removeChild(dailyChallengeScreen); dailyChallengeScreen = null; } // Create and add daily challenge screen dailyChallengeScreen = new DailyChallengeScreen(); dailyChallengeScreen.x = 2048 / 2; dailyChallengeScreen.y = 2732 / 2; game.addChild(dailyChallengeScreen); // Update game state gameState = 'dailyChallenge'; }; game.showTitleScreen = function () { // Remove game mode screen if it exists if (gameModeScreen) { game.removeChild(gameModeScreen); gameModeScreen = null; } // Remove bot selection screen if it exists if (botSelectionScreen) { game.removeChild(botSelectionScreen); botSelectionScreen = null; } // Remove daily challenge screen if it exists if (dailyChallengeScreen) { game.removeChild(dailyChallengeScreen); dailyChallengeScreen = null; } // Create and add title screen titleScreen = new TitleScreen(); titleScreen.x = 2048 / 2; titleScreen.y = 2732 / 2; game.addChild(titleScreen); // Update game state gameState = 'title'; }; // Method to start the game from mode selection screen game.startGame = function () { // Remove game mode screen if it exists if (gameModeScreen) { game.removeChild(gameModeScreen); gameModeScreen = null; } // Remove bot selection screen if it exists if (botSelectionScreen) { game.removeChild(botSelectionScreen); botSelectionScreen = null; } // Remove daily challenge screen if it exists (shouldn't be possible to start game from here, but for safety) if (dailyChallengeScreen) { game.removeChild(dailyChallengeScreen); dailyChallengeScreen = null; } // Change state based on mode if (game.gameMode === 'specialGame') { gameState = 'specialGame'; // Or keep as 'playing' and rely on game.specialRule scoreTxt.setText('Daily Challenge - ' + selectedBot.toUpperCase()); // Or show special rule name? } else { gameState = 'playing'; // Update game title based on selected mode scoreTxt.setText('Crazy Chess - ' + game.gameMode.toUpperCase()); } // Initialize the chess board initializeBoard(); // Reset special mode variables goatedTurnCounter = 0; icyDayFrozenPieces = []; yetiPawns = []; // Show the score and turn text scoreTxt.visible = true; turnText.visible = true; }; // Show title screen first titleScreen = new TitleScreen(); titleScreen.x = 2048 / 2; titleScreen.y = 2732 / 2; game.addChild(titleScreen); // Hide score and turn text initially scoreTxt.visible = false; turnText.visible = false; ;
===================================================================
--- original.js
+++ change.js
@@ -956,10 +956,18 @@
size: 90,
fill: 0xFFFFFF
});
startButton.anchor.set(0.5, 0.5);
- startButton.y = 250;
+ startButton.y = 200; // Move start button up slightly
self.addChild(startButton);
+ // Create More Games button
+ var moreGamesButton = new Text2('MORE GAMES', {
+ size: 70,
+ fill: 0xCCCCCC // Slightly dimmer color
+ });
+ moreGamesButton.anchor.set(0.5, 0.5);
+ moreGamesButton.y = 350; // Position below start button
+ self.addChild(moreGamesButton);
// Add pulsing animation to the start button
var pulseScale = 1;
var increasing = true;
self.update = function () {
@@ -975,52 +983,34 @@
increasing = true;
}
}
startButton.scale.set(pulseScale);
+ // Also pulse the More Games button slightly out of phase for visual interest
+ moreGamesButton.scale.set(1 + (pulseScale - 1) * 0.8); // Smaller pulse
};
- // Create "More games" button
- var moreGamesButton = new Text2('More games', {
- size: 60,
- // Smaller size than start button
- fill: 0xCCCCCC // Greyish color
- });
- moreGamesButton.anchor.set(0.5, 0.5);
- moreGamesButton.y = startButton.y + 150; // Position below start button
- self.addChild(moreGamesButton);
- // Handle tap on start button (main area)
- self.down = function (x, y, obj) {
- // Check if the tap is NOT on the 'More games' button to avoid triggering both
- var localPos = self.toLocal({
- x: x,
- y: y
- });
- var buttonBounds = {
- left: moreGamesButton.x - moreGamesButton.width * moreGamesButton.anchor.x,
- right: moreGamesButton.x + moreGamesButton.width * (1 - moreGamesButton.anchor.x),
- top: moreGamesButton.y - moreGamesButton.height * moreGamesButton.anchor.y,
- bottom: moreGamesButton.y + moreGamesButton.height * (1 - moreGamesButton.anchor.y)
- };
- var isInsideButton = localPos.x >= buttonBounds.left && localPos.x <= buttonBounds.right && localPos.y >= buttonBounds.top && localPos.y <= buttonBounds.bottom;
- if (!isInsideButton) {
- game.showGameModeScreen();
- }
+ // Handle tap anywhere to start
+ // Make start button interactive separately
+ startButton.interactive = true;
+ startButton.down = function () {
+ game.showGameModeScreen();
};
- // Handle tap on "More games" button
+ // Make More Games button interactive
moreGamesButton.interactive = true;
moreGamesButton.down = function () {
- // Flash effect for feedback
- tween(moreGamesButton, {
- alpha: 0.5
- }, {
- duration: 100,
- yoyo: true,
- repeat: 1
- });
- // LK.openURL is not available in the sandbox.
- // We cannot open the external link directly.
- // This button will just provide visual feedback.
- console.log("More Games button clicked - URL opening not supported.");
+ // Open the specified link
+ LK.link.open('https://upit.com/@unnamedguy/play/fwVmrts7uJ?utm_medium=share&utm_source=link');
+ // Optional: Add visual feedback like a quick flash
+ LK.effects.flashObject(moreGamesButton, 0xFFFFFF, 150);
};
+ // Keep the main screen tap for starting the game as well (optional)
+ self.interactive = true; // Make the whole screen interactive
+ self.down = function (x, y, obj) {
+ // Check if the tap landed on one of the buttons; if so, their handlers already ran.
+ // If the tap is elsewhere on the screen, treat it like tapping "Start".
+ if (obj.target !== startButton && obj.target !== moreGamesButton) {
+ game.showGameModeScreen();
+ }
+ }; //{8c} // Keep original line ID if relevant, but content changed
return self;
});
/****
Black horse. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
White horse. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Black lawnmower. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
White lawnmower. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Black crown. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
White crown. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
White cannon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Black cannon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Black queen. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
White queen. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Black pawn. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
White pawn. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
White goat. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Bear trap. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows