User prompt
add a cooldown for the player so that the ai can have enough time to schoose
Code edit (1 edits merged)
Please save this source code
User prompt
make sure the ai uses the indicator that is in the asset tab
User prompt
make sure the indicator color outline is blue
User prompt
make sure the indicator outline is red
User prompt
Fix Bug: 'Timeout.tick error: LK.Shape is not a constructor' in or related to this line: 'var outline = new LK.Shape('box', {' Line Number: 175
User prompt
add an indication to where the ai is gonna choose like an outline
User prompt
add new feature to ai without breaking the ai and game
User prompt
make the ai smarter when deciding
User prompt
make it so that the ai can observe and remember where the player choose and also make it work even if there was a game over make sure this doesn't break anything
User prompt
i have a question is it possible to add a main menu to choose if you want to battle ai or human local multiplayer?
User prompt
add a retry screen only when the player gets a tie
User prompt
Fix Bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'stringify')' in or related to this line: 'LK.setCloudData(key, JSON.stringify(data));' Line Number: 315
User prompt
Fix Bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'stringify')' in or related to this line: 'LK.setCloudData(key, JSON.stringify(data));' Line Number: 314
User prompt
add a simple cloud save system so that it can save in the frvr platform
User prompt
fix where the ai freezes after the player won and fix the ai when the player choses on cell the ai freezes after the player won
User prompt
fix where the ai freezes and can't decide improve the ai and make it smarter
User prompt
fix where the player can't choose a cell after the ai choose a cell
User prompt
add logic so that the ai works all the time
User prompt
fix the ai using two cells at the same time instead of one
User prompt
fix the ai by adding vars and logic to improve it
User prompt
fix where when after the tie when the player takes a cell the game freezes and the ai doesn't work
User prompt
fix where when its a tie the game don't freeze after the reset of the game
User prompt
fix the ai not working sometimes
User prompt
fix where the ai chooses the already taken cell from the player and also make sure it works correctly so that it doesn't freeze the game
/****
* Classes
****/
var Decision = Container.expand(function () {
var self = Container.call(this);
self.availableCells = [];
self.playerMoves = [];
self.aiMoves = [];
self.observe = function (playerMoveIndex) {
self.playerMoves.push(playerMoveIndex);
self.availableCells.splice(self.availableCells.indexOf(playerMoveIndex), 1);
};
self.decide = function (callback) {
// AI decision-making logic to choose the best cell
// First, check if the player is about to win and block them
var winningMoveIndex = -1;
var blockMoveIndex = -1;
winConditions.forEach(function (condition) {
var aiCount = condition.filter(function (index) {
return self.aiMoves.includes(index);
}).length;
var playerCount = condition.filter(function (index) {
return self.playerMoves.includes(index);
}).length;
var availableCount = condition.filter(function (index) {
return self.availableCells.includes(index);
}).length;
if (aiCount === 2 && availableCount === 1) {
// If AI can win in the next move, prioritize that move
winningMoveIndex = condition.find(function (index) {
return self.availableCells.includes(index);
});
if (winningMoveIndex !== -1) {
if (typeof callback === 'function') {
callback(winningMoveIndex);
}
return;
}
}
if (playerCount === 2 && availableCount === 1) {
blockMoveIndex = condition.find(function (index) {
return self.availableCells.includes(index);
});
}
});
var opponentForkMoveIndex = self.findForkMove('player');
var chosenCell = winningMoveIndex !== -1 ? winningMoveIndex : blockMoveIndex !== -1 ? blockMoveIndex : opponentForkMoveIndex !== -1 ? opponentForkMoveIndex : self.availableCells[Math.floor(Math.random() * self.availableCells.length)];
// Execute the callback with the chosen cell index
if (typeof callback === 'function') {
callback(chosenCell);
}
};
self.findForkMove = function (playerType) {
var moves = playerType === 'ai' ? self.aiMoves : self.playerMoves;
var forkMoveIndex = -1;
self.availableCells.some(function (cellIndex) {
var forkCount = 0;
winConditions.forEach(function (condition) {
if (condition.includes(cellIndex)) {
var playerCount = condition.filter(function (index) {
return moves.includes(index);
}).length;
var availableCount = condition.filter(function (index) {
return self.availableCells.includes(index) && index !== cellIndex;
}).length;
if (playerCount === 1 && availableCount === 2) {
forkCount++;
}
}
});
if (forkCount > 1) {
forkMoveIndex = cellIndex;
return true;
}
return false;
});
return forkMoveIndex;
};
// Initialize available cells with all cell indices
for (var i = 0; i < 9; i++) {
self.availableCells.push(i);
}
});
// Define the Cell class for the tic tac toe grid
var Cell = Container.expand(function (x, y, index) {
var self = Container.call(this);
self.index = index;
self.taken = false;
self.value = null;
var cellGraphics = self.attachAsset('cell', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.interactive = true;
self.on('down', function () {
if (!self.taken && !game.aiTurn) {
self.setPlayerValue('X');
game.checkGameState();
if (!game.gameOver) {
game.aiPlayer.observePlayer(self.index);
game.aiTurn = true;
game.aiPlay();
}
}
});
self.setPlayerValue = function (value) {
self.taken = true;
self.value = value;
var shape = value === 'X' ? 'xShape' : 'oShape';
var color = value === 'X' ? 0xFF0000 : 0x0000FF;
var playerShape = self.attachAsset(shape, {
anchorX: 0.5,
anchorY: 0.5,
color: color
});
};
});
var AIPlayer = Container.expand(function () {
var self = Container.call(this);
self.decision = new Decision();
self.observePlayer = function (playerMoveIndex) {
// AI logic to observe player's move and decide next move
self.decision.observe(playerMoveIndex);
};
self.makeMove = function () {
// Use the Decision class to choose the best cell for the AI's move
if (!game.gameOver) {
self.decision.decide(function (chosenIndex) {
if (chosenIndex >= 0 && chosenIndex < grid.length) {
if (!grid[chosenIndex].taken) {
grid[chosenIndex].setPlayerValue('O');
self.decision.aiMoves.push(chosenIndex);
self.decision.availableCells.splice(self.decision.availableCells.indexOf(chosenIndex), 1);
} else {
// If the chosen cell is already taken, find the first available cell
var availableCellIndex = self.decision.availableCells[0];
if (availableCellIndex !== undefined) {
grid[availableCellIndex].setPlayerValue('O');
self.decision.aiMoves.push(availableCellIndex);
self.decision.availableCells.splice(0, 1);
}
}
game.aiTurn = false;
game.checkGameState();
}
});
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Init game with black background
});
/****
* Game Code
****/
// Define the assets for the tic tac toe game
var grid = [];
// Initialize the tic tac toe grid
function initializeGrid() {
var gridSize = 3;
var cellSize = 200;
var startX = (2048 - gridSize * cellSize) / 2 + cellSize / 2;
var startY = (2732 - gridSize * cellSize) / 2 + cellSize / 2;
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
var index = i * gridSize + j;
var cell = new Cell(startX + j * cellSize, startY + i * cellSize, index);
game.addChild(cell);
grid.push(cell);
}
}
}
game.aiPlayer = new AIPlayer();
initializeGrid();
// Define win conditions
var winConditions = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
// Rows
[0, 3, 6], [1, 4, 7], [2, 5, 8],
// Columns
[0, 4, 8], [2, 4, 6] // Diagonals
];
// Define game logic
game.aiTurn = false;
game.aiCooldown = 500; // Cooldown time in milliseconds
game.gameOver = false;
game.checkGameState = function () {
// Check for win conditions
var winConditions = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
// Rows
[0, 3, 6], [1, 4, 7], [2, 5, 8],
// Columns
[0, 4, 8], [2, 4, 6] // Diagonals
];
for (var i = 0; i < winConditions.length; i++) {
var condition = winConditions[i];
if (grid[condition[0]].value && grid[condition[0]].value === grid[condition[1]].value && grid[condition[0]].value === grid[condition[2]].value) {
game.gameOver = true;
for (var i = 0; i < 3; i++) {
LK.setTimeout(function () {
LK.effects.flashScreen(0x00FF00, 300);
}, i * 600);
}
var winner = grid[condition[0]].value === 'X' ? 'You Win!' : 'AI Wins!';
var winText = new Text2(winner, {
size: 150,
fill: "#ffffff"
});
winText.anchor.set(0.5, 0.5);
winText.x = 2048 / 2;
winText.y = 2732 / 2;
LK.gui.center.addChild(winText);
if (grid[condition[0]].value === 'O') {
for (var i = 0; i < 3; i++) {
LK.setTimeout(function () {
LK.effects.flashScreen(0xFF0000, 300);
}, i * 600);
}
LK.setTimeout(function () {
LK.showGameOver();
}, 1800);
} else {
LK.setTimeout(function () {
grid.forEach(function (cell) {
cell.destroy();
});
grid = [];
game.aiTurn = false; // Reset AI turn state
game.gameOver = false; // Reset game over state
initializeGrid();
}, 2000);
}
return;
}
}
// Check for draw
var draw = grid.every(function (cell) {
return cell.taken;
});
if (draw) {
game.gameOver = true;
var flashCount = 0;
var flashInterval = LK.setInterval(function () {
LK.effects.flashScreen(0xA52A2A, 300);
flashCount++;
if (flashCount >= 4) {
LK.clearInterval(flashInterval);
grid.forEach(function (cell) {
cell.destroy();
});
grid = [];
game.aiTurn = false; // Reset AI turn state
game.gameOver = false; // Reset game over state
initializeGrid();
}
}, 600);
}
};
game.aiPlay = function () {
if (game.aiTurn) {
LK.setTimeout(function () {
game.aiPlayer.makeMove();
}, game.aiCooldown);
}
};
// Start the game with the player's turn
game.aiTurn = false;