User prompt
Make the levels going hard slowly from 1-50
User prompt
Remove the start text on the button of level background
User prompt
Fill the screen with max levels
User prompt
Make the levels background after the intro and before game start
User prompt
Create a background before starting game have 20 button of levels, when player choose the level show a button start above the background to start that level.
User prompt
Remove start game text from the button in the intro
User prompt
the introbackground and startbutton must be before the game start not in game
User prompt
Add introbackground with startbutton close to the bottom by 200px
User prompt
remove text of coordinate button
User prompt
add two texts below the boardBg one for the player on the left size 80 and one for the AI on the right showing how many pieces are on the table
User prompt
make the AI easy
User prompt
don't do win or gameover on the start of the game!!!
User prompt
if no moves for player or AI do gameover
User prompt
the orange when flip it stay orange and same for grey please fix that
User prompt
Add Ai to play with grey
User prompt
make the cells smaller to do some spacing but let it with same size of the boardBg
User prompt
make the cells table as the same size of the boardBg
User prompt
make the table 1850x1850 and so the board
User prompt
do more spacing between cells
User prompt
change the game table to 1900x1900
User prompt
change the board size from 2000x2000 to 1900x1900
User prompt
make the coordinate background 2000x2000px and its history text size 60 and "move History" text size 65
User prompt
make it 2000x2000 and resize the text of it and text of the coordinates background too
User prompt
make the game bigger to 1200x1200so the pieces and background of coordinates make it 1000x1000
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'playerText.style.fill = color;' Line Number: 286
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Cell = Container.expand(function () { var self = Container.call(this); var cellGraphics = self.attachAsset('cell', { anchorX: 0.5, anchorY: 0.5 }); self.row = 0; self.col = 0; self.piece = null; self.down = function (x, y, obj) { if (!self.piece && currentPlayer === 0) { placePiece(self.row, self.col); } }; return self; }); var CoordButton = Container.expand(function () { var self = Container.call(this); var buttonBg = self.attachAsset('coordButton', { anchorX: 0.5, anchorY: 0.5 }); self.down = function (x, y, obj) { toggleHistory(); }; return self; }); var HistoryPanel = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('historyBg', { anchorX: 0.5, anchorY: 0.5 }); var titleText = new Text2('Move History', { size: 65, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0); titleText.y = -960; self.addChild(titleText); self.historyText = new Text2('', { size: 60, fill: 0xFFFFFF }); self.historyText.anchor.set(0.5, 0); self.historyText.y = -880; self.addChild(self.historyText); self.updateHistory = function () { var historyString = ''; for (var i = 0; i < moveHistory.length; i++) { var move = moveHistory[i]; var player = move.player === 0 ? 'Orange' : 'Grey'; historyString += player + ': ' + move.coord + '\n'; } self.historyText.setText(historyString); }; self.down = function (x, y, obj) { toggleHistory(); }; return self; }); var IntroButton = Container.expand(function () { var self = Container.call(this); var buttonBg = self.attachAsset('startButton', { anchorX: 0.5, anchorY: 0.5 }); self.down = function (x, y, obj) { if (introScreen && !levelSelectionScreen) { introScreen.destroy(); introScreen = null; createLevelSelection(); } }; return self; }); var LevelButton = Container.expand(function () { var self = Container.call(this); self.levelNumber = 1; self.isSelected = false; self.buttonBg = self.attachAsset('levelButton', { anchorX: 0.5, anchorY: 0.5 }); self.levelText = new Text2('1', { size: 60, fill: 0xFFFFFF }); self.levelText.anchor.set(0.5, 0.5); self.addChild(self.levelText); self.setLevel = function (level) { self.levelNumber = level; self.levelText.setText(level.toString()); }; self.setSelected = function (selected) { if (self.isSelected === selected) return; self.isSelected = selected; self.removeChild(self.buttonBg); if (selected) { self.buttonBg = self.attachAsset('selectedLevelButton', { anchorX: 0.5, anchorY: 0.5 }); } else { self.buttonBg = self.attachAsset('levelButton', { anchorX: 0.5, anchorY: 0.5 }); } // Make sure text is on top self.removeChild(self.levelText); self.addChild(self.levelText); }; self.down = function (x, y, obj) { if (!gameStarted && levelSelectionScreen) { selectLevel(self.levelNumber); } }; return self; }); var Piece = Container.expand(function () { var self = Container.call(this); self.player = 0; // 0 for orange, 1 for grey self.graphics = null; self.setPlayer = function (player) { if (self.graphics) { self.graphics.destroy(); } self.player = player; var assetId = player === 0 ? 'orangePiece' : 'greyPiece'; self.graphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; self.flip = function () { tween(self, { scaleX: 0 }, { duration: 150, onFinish: function onFinish() { self.setPlayer(1 - self.player); tween(self, { scaleX: 1 }, { duration: 150 }); } }); }; return self; }); var StartButton = Container.expand(function () { var self = Container.call(this); var buttonBg = self.attachAsset('startButton', { anchorX: 0.5, anchorY: 0.5 }); self.down = function (x, y, obj) { if (levelSelectionScreen && !gameStarted && selectedLevel > 0) { levelSelectionScreen.destroy(); levelSelectionScreen = null; gameStarted = true; initializeGame(); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a3a1a }); /**** * Game Code ****/ var BOARD_SIZE = 10; var board = []; var cells = []; var currentPlayer = 0; // 0 for orange, 1 for grey var moveHistory = []; var historyPanel = null; var historyVisible = false; var introScreen = null; var levelSelectionScreen = null; var gameStarted = false; var boardContainer = null; var selectedLevel = 0; var levelButtons = []; var levelStartButton = null; var currentDifficulty = 1; // Stores the calculated difficulty for current level // Create intro screen introScreen = new Container(); game.addChild(introScreen); // Add intro background var introBg = LK.getAsset('introBackground', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); introScreen.addChild(introBg); // Add intro button var introButton = new IntroButton(); introButton.x = 1024; introButton.y = 2732 - 200; // 200px from bottom introScreen.addChild(introButton); // Game variables that need to be accessible var orangeCountText = null; var greyCountText = null; var playerText = null; var coordButton = null; var letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']; var setupMode = false; function createLevelSelection() { // Create level selection screen levelSelectionScreen = new Container(); game.addChild(levelSelectionScreen); // Add level selection background var levelBg = LK.getAsset('levelsBackground', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 }); levelSelectionScreen.addChild(levelBg); // Add title text var titleText = new Text2('SELECT LEVEL', { size: 100, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; levelSelectionScreen.addChild(titleText); // Create 50 level buttons in a 5x10 grid to fill the screen var buttonSpacing = 180; var startX = 1024 - (5 * buttonSpacing - buttonSpacing) / 2; var startY = 650; levelButtons = []; // Reset level buttons array for (var i = 0; i < 50; i++) { var levelButton = new LevelButton(); levelButton.setLevel(i + 1); var row = Math.floor(i / 5); var col = i % 5; levelButton.x = startX + col * buttonSpacing; levelButton.y = startY + row * buttonSpacing; levelButtons.push(levelButton); levelSelectionScreen.addChild(levelButton); } // Add start button (initially hidden) levelStartButton = new StartButton(); levelStartButton.x = 1024; levelStartButton.y = 2732 - 200; // 200px from bottom levelStartButton.visible = false; levelSelectionScreen.addChild(levelStartButton); } function getDifficultySettings(level) { // Progressive difficulty scaling from level 1-50 var settings = { aiType: 'easy', // easy, medium, hard, expert startingPieces: 4, // Number of starting pieces (2x2, 3x3, etc.) aiDelay: 500, // AI thinking time in ms cornerBonus: 0, // Strategic corner bonus for AI edgeBonus: 0, // Strategic edge bonus for AI mobilityWeight: 0 // How much AI considers limiting opponent moves }; if (level <= 10) { // Levels 1-10: Easy AI, standard setup settings.aiType = 'easy'; settings.aiDelay = 500; } else if (level <= 20) { // Levels 11-20: Medium AI with slight strategic thinking settings.aiType = 'medium'; settings.aiDelay = 400; settings.cornerBonus = 10; } else if (level <= 35) { // Levels 21-35: Hard AI with better strategy settings.aiType = 'hard'; settings.aiDelay = 300; settings.cornerBonus = 20; settings.edgeBonus = 5; settings.mobilityWeight = 5; } else { // Levels 36-50: Expert AI with advanced strategy settings.aiType = 'expert'; settings.aiDelay = 200; settings.cornerBonus = 30; settings.edgeBonus = 10; settings.mobilityWeight = 10; } // Adjust starting pieces based on level if (level <= 15) { settings.startingPieces = 4; // 2x2 center } else if (level <= 30) { settings.startingPieces = 6; // 2x3 center } else { settings.startingPieces = 8; // 2x4 center - more challenging start } return settings; } function selectLevel(level) { selectedLevel = level; currentDifficulty = getDifficultySettings(level); // Update all buttons - deselect all first for (var i = 0; i < levelButtons.length; i++) { levelButtons[i].setSelected(false); } // Select the chosen level button if (level >= 1 && level <= 50) { levelButtons[level - 1].setSelected(true); } // Show start button if (levelStartButton) { levelStartButton.visible = true; } } function initializeGame() { // Create board container boardContainer = new Container(); boardContainer.x = 1024; boardContainer.y = 1366; game.addChild(boardContainer); // Create board background var boardBg = LK.getAsset('boardBg', { anchorX: 0.5, anchorY: 0.5 }); boardContainer.addChild(boardBg); // Create piece count texts orangeCountText = new Text2('Orange: 2', { size: 80, fill: 0xFF8C00 }); orangeCountText.anchor.set(0, 0.5); orangeCountText.x = -900; orangeCountText.y = 1000; boardContainer.addChild(orangeCountText); greyCountText = new Text2('Grey: 2', { size: 80, fill: 0x808080 }); greyCountText.anchor.set(1, 0.5); greyCountText.x = 900; greyCountText.y = 1000; boardContainer.addChild(greyCountText); // Initialize board array and create cells var cellSpacing = 1850 / BOARD_SIZE; for (var row = 0; row < BOARD_SIZE; row++) { board[row] = []; cells[row] = []; for (var col = 0; col < BOARD_SIZE; col++) { board[row][col] = null; var cell = new Cell(); cell.row = row; cell.col = col; cell.x = (col - 4.5) * cellSpacing; cell.y = (row - 4.5) * cellSpacing; boardContainer.addChild(cell); cells[row][col] = cell; } } // Create coordinate labels var cellSpacing = 1850 / BOARD_SIZE; for (var i = 0; i < BOARD_SIZE; i++) { // Column labels (A-J) var colLabel = new Text2(letters[i], { size: 40, fill: 0xFFFFFF }); colLabel.anchor.set(0.5, 0.5); colLabel.x = (i - 4.5) * cellSpacing; colLabel.y = -945; boardContainer.addChild(colLabel); // Row labels (1-10) var rowLabel = new Text2((i + 1).toString(), { size: 40, fill: 0xFFFFFF }); rowLabel.anchor.set(0.5, 0.5); rowLabel.x = -945; rowLabel.y = (i - 4.5) * cellSpacing; boardContainer.addChild(rowLabel); } // Create current player indicator playerText = new Text2('Current Player: Orange', { size: 60, fill: 0xFF8C00 }); playerText.anchor.set(0.5, 0); playerText.y = 100; LK.gui.top.addChild(playerText); // Create coordinates button coordButton = new CoordButton(); coordButton.x = -100; coordButton.y = 100; LK.gui.topRight.addChild(coordButton); // Create history panel (initially hidden) historyPanel = new HistoryPanel(); historyPanel.visible = false; game.addChild(historyPanel); historyPanel.x = 1024; historyPanel.y = 1366; // Initialize with starting pieces based on difficulty setupMode = true; var difficulty = getDifficultySettings(selectedLevel); if (difficulty.startingPieces === 4) { // Standard 2x2 center placePiece(4, 4); placePiece(4, 5); placePiece(5, 5); placePiece(5, 4); } else if (difficulty.startingPieces === 6) { // 2x3 center setup - more challenging placePiece(4, 4); placePiece(4, 5); placePiece(5, 4); placePiece(5, 5); placePiece(4, 6); placePiece(5, 6); } else if (difficulty.startingPieces === 8) { // 2x4 center setup - most challenging placePiece(4, 3); placePiece(4, 4); placePiece(4, 5); placePiece(4, 6); placePiece(5, 3); placePiece(5, 4); placePiece(5, 5); placePiece(5, 6); } setupMode = false; // Reset to orange player's turn currentPlayer = 0; updatePlayerText(); updatePieceCounts(); } // Game functions function getCoordinate(row, col) { return letters[col] + (row + 1); } function placePiece(row, col) { if (!gameStarted || board[row][col] !== null) return; // Create and place piece var piece = new Piece(); piece.setPlayer(currentPlayer); cells[row][col].addChild(piece); cells[row][col].piece = piece; board[row][col] = currentPlayer; // Play place sound LK.getSound('place').play(); // Add to move history moveHistory.push({ player: currentPlayer, coord: getCoordinate(row, col) }); // Update history panel if visible if (historyVisible && historyPanel) { historyPanel.updateHistory(); } // Check for flips in all directions var directions = [[-1, 0], [1, 0], [0, -1], [0, 1], // vertical and horizontal [-1, -1], [-1, 1], [1, -1], [1, 1] // diagonals ]; var totalFlips = 0; for (var d = 0; d < directions.length; d++) { var flips = checkDirection(row, col, directions[d][0], directions[d][1]); if (flips.length > 0) { flipPieces(flips); totalFlips += flips.length; } } if (totalFlips > 0) { LK.getSound('flip').play(); } // Update piece counts updatePieceCounts(); // Switch player currentPlayer = 1 - currentPlayer; updatePlayerText(); // Check for game over checkGameOver(); // If it's now grey's turn (AI), make AI move if (currentPlayer === 1 && !setupMode) { makeAIMove(); } } function checkDirection(row, col, dRow, dCol) { var flips = []; var r = row + dRow; var c = col + dCol; // Find opponent pieces while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE) { if (board[r][c] === null) { return []; } if (board[r][c] === currentPlayer) { return flips; } flips.push([r, c]); r += dRow; c += dCol; } return []; } function flipPieces(positions) { for (var i = 0; i < positions.length; i++) { var row = positions[i][0]; var col = positions[i][1]; board[row][col] = currentPlayer; cells[row][col].piece.flip(); } } function updatePlayerText() { var player = currentPlayer === 0 ? 'Orange' : 'Grey'; var color = currentPlayer === 0 ? 0xff8c00 : 0x808080; playerText.setText('Current Player: ' + player); // Remove old text and create new one with updated color LK.gui.top.removeChild(playerText); playerText = new Text2('Current Player: ' + player, { size: 60, fill: color }); playerText.anchor.set(0.5, 0); playerText.y = 100; LK.gui.top.addChild(playerText); } function updatePieceCounts() { var orangeCount = 0; var greyCount = 0; for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { if (board[row][col] === 0) { orangeCount++; } else if (board[row][col] === 1) { greyCount++; } } } orangeCountText.setText('Orange: ' + orangeCount); greyCountText.setText('Grey: ' + greyCount); } function checkGameOver() { // Don't check for game over during initial setup if (setupMode) return; var hasEmpty = false; var orangeCount = 0; var greyCount = 0; var hasValidMove = false; for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { if (board[row][col] === null) { hasEmpty = true; // Check if current player has valid move at this position if (!hasValidMove && isValidMove(row, col, currentPlayer)) { hasValidMove = true; } } else if (board[row][col] === 0) { orangeCount++; } else { greyCount++; } } } // Check for game over conditions if (!hasEmpty || !hasValidMove) { if (orangeCount > greyCount) { LK.showYouWin(); } else { LK.showGameOver(); } } } function toggleHistory() { historyVisible = !historyVisible; if (historyPanel) { historyPanel.visible = historyVisible; if (historyVisible) { historyPanel.updateHistory(); } } } // AI functions function isValidMove(row, col, player) { if (board[row][col] !== null) return false; var directions = [[-1, 0], [1, 0], [0, -1], [0, 1], [-1, -1], [-1, 1], [1, -1], [1, 1]]; for (var d = 0; d < directions.length; d++) { var flips = checkDirectionForPlayer(row, col, directions[d][0], directions[d][1], player); if (flips.length > 0) { return true; } } return false; } function checkDirectionForPlayer(row, col, dRow, dCol, player) { var flips = []; var r = row + dRow; var c = col + dCol; while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE) { if (board[r][c] === null) { return []; } if (board[r][c] === player) { return flips; } flips.push([r, c]); r += dRow; c += dCol; } return []; } function evaluateMove(row, col, player) { var directions = [[-1, 0], [1, 0], [0, -1], [0, 1], [-1, -1], [-1, 1], [1, -1], [1, 1]]; var totalFlips = 0; for (var d = 0; d < directions.length; d++) { var flips = checkDirectionForPlayer(row, col, directions[d][0], directions[d][1], player); totalFlips += flips.length; } var difficulty = getDifficultySettings(selectedLevel); var score = totalFlips; // Apply strategic bonuses based on difficulty level if (difficulty.aiType !== 'easy') { // Corner bonus - corners are very valuable if ((row === 0 || row === BOARD_SIZE - 1) && (col === 0 || col === BOARD_SIZE - 1)) { score += difficulty.cornerBonus; } // Edge bonus - edges are somewhat valuable else if (row === 0 || row === BOARD_SIZE - 1 || col === 0 || col === BOARD_SIZE - 1) { score += difficulty.edgeBonus; } // Mobility consideration - how many moves will opponent have after this move if (difficulty.mobilityWeight > 0) { var opponentMoves = countValidMovesAfterMove(row, col, player); score -= opponentMoves * difficulty.mobilityWeight; } // Avoid positions next to corners (they give opponent corner access) if (difficulty.aiType === 'hard' || difficulty.aiType === 'expert') { if (isNextToCorner(row, col)) { score -= 15; // Penalty for moves next to corners } } } return score; } function countValidMovesAfterMove(row, col, player) { // Simulate placing the piece and count opponent's valid moves var originalValue = board[row][col]; board[row][col] = player; var opponentPlayer = 1 - player; var count = 0; for (var r = 0; r < BOARD_SIZE; r++) { for (var c = 0; c < BOARD_SIZE; c++) { if (isValidMove(r, c, opponentPlayer)) { count++; } } } board[row][col] = originalValue; // Restore original state return count; } function isNextToCorner(row, col) { // Check if position is adjacent to a corner (bad strategic move) var corners = [[0, 0], [0, BOARD_SIZE - 1], [BOARD_SIZE - 1, 0], [BOARD_SIZE - 1, BOARD_SIZE - 1]]; for (var i = 0; i < corners.length; i++) { var cornerRow = corners[i][0]; var cornerCol = corners[i][1]; var rowDiff = Math.abs(row - cornerRow); var colDiff = Math.abs(col - cornerCol); if (rowDiff === 1 && colDiff === 0 || rowDiff === 0 && colDiff === 1 || rowDiff === 1 && colDiff === 1) { // Only penalize if the corner is empty (don't avoid if corner is already taken) if (board[cornerRow][cornerCol] === null) { return true; } } } return false; } function makeAIMove() { var validMoves = []; var difficulty = getDifficultySettings(selectedLevel); // Find all valid moves for (var row = 0; row < BOARD_SIZE; row++) { for (var col = 0; col < BOARD_SIZE; col++) { if (isValidMove(row, col, 1)) { validMoves.push({ row: row, col: col, score: evaluateMove(row, col, 1) }); } } } if (validMoves.length > 0) { var chosenMove; if (difficulty.aiType === 'easy') { // Easy AI: pick randomly from moves that flip at least 1 piece var movesWithFlips = []; for (var i = 0; i < validMoves.length; i++) { if (validMoves[i].score > 0) { movesWithFlips.push(validMoves[i]); } } if (movesWithFlips.length === 0) { movesWithFlips = validMoves; } var randomIndex = Math.floor(Math.random() * movesWithFlips.length); chosenMove = movesWithFlips[randomIndex]; } else if (difficulty.aiType === 'medium') { // Medium AI: pick from top 50% of moves validMoves.sort(function (a, b) { return b.score - a.score; }); var topHalf = Math.ceil(validMoves.length / 2); var randomIndex = Math.floor(Math.random() * topHalf); chosenMove = validMoves[randomIndex]; } else if (difficulty.aiType === 'hard') { // Hard AI: pick from top 25% of moves validMoves.sort(function (a, b) { return b.score - a.score; }); var topQuarter = Math.max(1, Math.ceil(validMoves.length / 4)); var randomIndex = Math.floor(Math.random() * topQuarter); chosenMove = validMoves[randomIndex]; } else { // expert // Expert AI: always pick the best move (with small randomness for variety) validMoves.sort(function (a, b) { return b.score - a.score; }); var bestScore = validMoves[0].score; var bestMoves = []; for (var i = 0; i < validMoves.length; i++) { if (validMoves[i].score === bestScore) { bestMoves.push(validMoves[i]); } else { break; // Stop when we leave the best moves } } var randomIndex = Math.floor(Math.random() * bestMoves.length); chosenMove = bestMoves[randomIndex]; } // Add difficulty-based delay to make AI move visible LK.setTimeout(function () { placePiece(chosenMove.row, chosenMove.col); }, difficulty.aiDelay); } } ;
===================================================================
--- original.js
+++ change.js
@@ -199,8 +199,9 @@
var boardContainer = null;
var selectedLevel = 0;
var levelButtons = [];
var levelStartButton = null;
+var currentDifficulty = 1; // Stores the calculated difficulty for current level
// Create intro screen
introScreen = new Container();
game.addChild(introScreen);
// Add intro background
@@ -265,10 +266,60 @@
levelStartButton.y = 2732 - 200; // 200px from bottom
levelStartButton.visible = false;
levelSelectionScreen.addChild(levelStartButton);
}
+function getDifficultySettings(level) {
+ // Progressive difficulty scaling from level 1-50
+ var settings = {
+ aiType: 'easy',
+ // easy, medium, hard, expert
+ startingPieces: 4,
+ // Number of starting pieces (2x2, 3x3, etc.)
+ aiDelay: 500,
+ // AI thinking time in ms
+ cornerBonus: 0,
+ // Strategic corner bonus for AI
+ edgeBonus: 0,
+ // Strategic edge bonus for AI
+ mobilityWeight: 0 // How much AI considers limiting opponent moves
+ };
+ if (level <= 10) {
+ // Levels 1-10: Easy AI, standard setup
+ settings.aiType = 'easy';
+ settings.aiDelay = 500;
+ } else if (level <= 20) {
+ // Levels 11-20: Medium AI with slight strategic thinking
+ settings.aiType = 'medium';
+ settings.aiDelay = 400;
+ settings.cornerBonus = 10;
+ } else if (level <= 35) {
+ // Levels 21-35: Hard AI with better strategy
+ settings.aiType = 'hard';
+ settings.aiDelay = 300;
+ settings.cornerBonus = 20;
+ settings.edgeBonus = 5;
+ settings.mobilityWeight = 5;
+ } else {
+ // Levels 36-50: Expert AI with advanced strategy
+ settings.aiType = 'expert';
+ settings.aiDelay = 200;
+ settings.cornerBonus = 30;
+ settings.edgeBonus = 10;
+ settings.mobilityWeight = 10;
+ }
+ // Adjust starting pieces based on level
+ if (level <= 15) {
+ settings.startingPieces = 4; // 2x2 center
+ } else if (level <= 30) {
+ settings.startingPieces = 6; // 2x3 center
+ } else {
+ settings.startingPieces = 8; // 2x4 center - more challenging start
+ }
+ return settings;
+}
function selectLevel(level) {
selectedLevel = level;
+ currentDifficulty = getDifficultySettings(level);
// Update all buttons - deselect all first
for (var i = 0; i < levelButtons.length; i++) {
levelButtons[i].setSelected(false);
}
@@ -366,14 +417,36 @@
historyPanel.visible = false;
game.addChild(historyPanel);
historyPanel.x = 1024;
historyPanel.y = 1366;
- // Initialize with starting pieces in center
+ // Initialize with starting pieces based on difficulty
setupMode = true;
- placePiece(4, 4);
- placePiece(4, 5);
- placePiece(5, 5);
- placePiece(5, 4);
+ var difficulty = getDifficultySettings(selectedLevel);
+ if (difficulty.startingPieces === 4) {
+ // Standard 2x2 center
+ placePiece(4, 4);
+ placePiece(4, 5);
+ placePiece(5, 5);
+ placePiece(5, 4);
+ } else if (difficulty.startingPieces === 6) {
+ // 2x3 center setup - more challenging
+ placePiece(4, 4);
+ placePiece(4, 5);
+ placePiece(5, 4);
+ placePiece(5, 5);
+ placePiece(4, 6);
+ placePiece(5, 6);
+ } else if (difficulty.startingPieces === 8) {
+ // 2x4 center setup - most challenging
+ placePiece(4, 3);
+ placePiece(4, 4);
+ placePiece(4, 5);
+ placePiece(4, 6);
+ placePiece(5, 3);
+ placePiece(5, 4);
+ placePiece(5, 5);
+ placePiece(5, 6);
+ }
setupMode = false;
// Reset to orange player's turn
currentPlayer = 0;
updatePlayerText();
@@ -560,13 +633,70 @@
for (var d = 0; d < directions.length; d++) {
var flips = checkDirectionForPlayer(row, col, directions[d][0], directions[d][1], player);
totalFlips += flips.length;
}
- // Easy AI: no strategic bonuses, just count flips
- return totalFlips;
+ var difficulty = getDifficultySettings(selectedLevel);
+ var score = totalFlips;
+ // Apply strategic bonuses based on difficulty level
+ if (difficulty.aiType !== 'easy') {
+ // Corner bonus - corners are very valuable
+ if ((row === 0 || row === BOARD_SIZE - 1) && (col === 0 || col === BOARD_SIZE - 1)) {
+ score += difficulty.cornerBonus;
+ }
+ // Edge bonus - edges are somewhat valuable
+ else if (row === 0 || row === BOARD_SIZE - 1 || col === 0 || col === BOARD_SIZE - 1) {
+ score += difficulty.edgeBonus;
+ }
+ // Mobility consideration - how many moves will opponent have after this move
+ if (difficulty.mobilityWeight > 0) {
+ var opponentMoves = countValidMovesAfterMove(row, col, player);
+ score -= opponentMoves * difficulty.mobilityWeight;
+ }
+ // Avoid positions next to corners (they give opponent corner access)
+ if (difficulty.aiType === 'hard' || difficulty.aiType === 'expert') {
+ if (isNextToCorner(row, col)) {
+ score -= 15; // Penalty for moves next to corners
+ }
+ }
+ }
+ return score;
}
+function countValidMovesAfterMove(row, col, player) {
+ // Simulate placing the piece and count opponent's valid moves
+ var originalValue = board[row][col];
+ board[row][col] = player;
+ var opponentPlayer = 1 - player;
+ var count = 0;
+ for (var r = 0; r < BOARD_SIZE; r++) {
+ for (var c = 0; c < BOARD_SIZE; c++) {
+ if (isValidMove(r, c, opponentPlayer)) {
+ count++;
+ }
+ }
+ }
+ board[row][col] = originalValue; // Restore original state
+ return count;
+}
+function isNextToCorner(row, col) {
+ // Check if position is adjacent to a corner (bad strategic move)
+ var corners = [[0, 0], [0, BOARD_SIZE - 1], [BOARD_SIZE - 1, 0], [BOARD_SIZE - 1, BOARD_SIZE - 1]];
+ for (var i = 0; i < corners.length; i++) {
+ var cornerRow = corners[i][0];
+ var cornerCol = corners[i][1];
+ var rowDiff = Math.abs(row - cornerRow);
+ var colDiff = Math.abs(col - cornerCol);
+ if (rowDiff === 1 && colDiff === 0 || rowDiff === 0 && colDiff === 1 || rowDiff === 1 && colDiff === 1) {
+ // Only penalize if the corner is empty (don't avoid if corner is already taken)
+ if (board[cornerRow][cornerCol] === null) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
function makeAIMove() {
var validMoves = [];
+ var difficulty = getDifficultySettings(selectedLevel);
// Find all valid moves
for (var row = 0; row < BOARD_SIZE; row++) {
for (var col = 0; col < BOARD_SIZE; col++) {
if (isValidMove(row, col, 1)) {
@@ -578,26 +708,59 @@
}
}
}
if (validMoves.length > 0) {
- // Easy AI: pick randomly from moves that flip at least 1 piece
- // Filter out moves that don't flip any pieces
- var movesWithFlips = [];
- for (var i = 0; i < validMoves.length; i++) {
- if (validMoves[i].score > 0) {
- movesWithFlips.push(validMoves[i]);
+ var chosenMove;
+ if (difficulty.aiType === 'easy') {
+ // Easy AI: pick randomly from moves that flip at least 1 piece
+ var movesWithFlips = [];
+ for (var i = 0; i < validMoves.length; i++) {
+ if (validMoves[i].score > 0) {
+ movesWithFlips.push(validMoves[i]);
+ }
}
+ if (movesWithFlips.length === 0) {
+ movesWithFlips = validMoves;
+ }
+ var randomIndex = Math.floor(Math.random() * movesWithFlips.length);
+ chosenMove = movesWithFlips[randomIndex];
+ } else if (difficulty.aiType === 'medium') {
+ // Medium AI: pick from top 50% of moves
+ validMoves.sort(function (a, b) {
+ return b.score - a.score;
+ });
+ var topHalf = Math.ceil(validMoves.length / 2);
+ var randomIndex = Math.floor(Math.random() * topHalf);
+ chosenMove = validMoves[randomIndex];
+ } else if (difficulty.aiType === 'hard') {
+ // Hard AI: pick from top 25% of moves
+ validMoves.sort(function (a, b) {
+ return b.score - a.score;
+ });
+ var topQuarter = Math.max(1, Math.ceil(validMoves.length / 4));
+ var randomIndex = Math.floor(Math.random() * topQuarter);
+ chosenMove = validMoves[randomIndex];
+ } else {
+ // expert
+ // Expert AI: always pick the best move (with small randomness for variety)
+ validMoves.sort(function (a, b) {
+ return b.score - a.score;
+ });
+ var bestScore = validMoves[0].score;
+ var bestMoves = [];
+ for (var i = 0; i < validMoves.length; i++) {
+ if (validMoves[i].score === bestScore) {
+ bestMoves.push(validMoves[i]);
+ } else {
+ break; // Stop when we leave the best moves
+ }
+ }
+ var randomIndex = Math.floor(Math.random() * bestMoves.length);
+ chosenMove = bestMoves[randomIndex];
}
- // If all moves flip pieces, use all valid moves
- if (movesWithFlips.length === 0) {
- movesWithFlips = validMoves;
- }
- // Pick a random move
- var randomIndex = Math.floor(Math.random() * movesWithFlips.length);
- var chosenMove = movesWithFlips[randomIndex];
- // Add small delay to make AI move visible
+ // Add difficulty-based delay to make AI move visible
LK.setTimeout(function () {
placePiece(chosenMove.row, chosenMove.col);
- }, 500);
+ }, difficulty.aiDelay);
}
}
;
\ No newline at end of file
Modern App Store icon, high definition, square with rounded corners, different othello game squares cells of wood, different wood, different colors, HD colors, for a game titled "Chorizora Othello" and without the description "A territorial strategy game where players flip opponent pieces by trapping them between their own pieces on a 10x10 grid.". with text on the middle of the icon "Chorizora Othello"!
Button "Coordinate". orange color In-Game asset. High contrast. No shadows. 3D