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