/**** * Classes ****/ var ActionButton = Container.expand(function () { var self = Container.call(this); self.init = function (text, action, x, y) { self.action = action; // Button graphics self.buttonGraphics = self.attachAsset('actionButton', { anchorX: 0.5, anchorY: 0.5 }); // Button text self.buttonText = new Text2(text, { size: 28, fill: 0xFFFFFF }); self.buttonText.anchor.set(0.5, 0.5); self.addChild(self.buttonText); self.x = x; self.y = y; return self; }; self.down = function (x, y, obj) { if (self.action) { self.action(); } }; return self; }); var DiplomacyPanel = Container.expand(function () { var self = Container.call(this); self.init = function (targetCountry) { self.targetCountry = targetCountry; self.visible = false; // Panel background self.panelBg = LK.getAsset('diplomacypanel', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 4 }); self.addChild(self.panelBg); // Panel title self.titleText = new Text2("Diplomacy with Country " + targetCountry, { size: 32, fill: 0x000000 }); self.titleText.anchor.set(0.5, 0.5); self.titleText.y = -80; self.addChild(self.titleText); // Declare war button self.warButton = new ActionButton(); self.warButton.init("Declare War", function () { declareWar(targetCountry); self.hide(); }, 0, 40); // Show declare war button in easy mode self.warButton.visible = true; self.addChild(self.warButton); // Peace treaty button self.peaceButton = new ActionButton(); self.peaceButton.init("Peace Treaty", function () { makePeace(targetCountry); self.hide(); }, 0, 100); self.addChild(self.peaceButton); // Show/hide peace button depending on war state and difficulty self.updateButtons = function () { if (selectedDifficulty === "hardcore") { self.peaceButton.visible = false; } else if (warDeclarations[self.targetCountry]) { self.peaceButton.visible = true; } else { self.peaceButton.visible = false; } }; self.updateButtons(); // Close button self.closeButton = new ActionButton(); self.closeButton.init("Close", function () { self.hide(); }, 0, 160); self.addChild(self.closeButton); // Position panel in center of screen self.x = 2048 / 2; self.y = 2732 / 2; return self; }; self.show = function () { self.visible = true; self.updateButtons && self.updateButtons(); game.addChild(self); }; self.hide = function () { self.visible = false; if (self.parent) { self.parent.removeChild(self); } }; return self; }); var Ship = Container.expand(function () { var self = Container.call(this); self.init = function (owner, x, y) { self.owner = owner; self.hp = 3; // Ships have more health than armies self.selected = false; // Armies carried by ship (default 2 for player, 0 for AI, can be changed) self.armies = owner === 1 ? 2 : 0; // Ship graphics self.shipGraphics = self.attachAsset('ship', { anchorX: 0.5, anchorY: 0.5 }); // Color based on owner if (owner === 1) { self.shipGraphics.tint = 0x27ae60; // Green for player } else if (owner === 2) { self.shipGraphics.tint = 0xe74c3c; // Red for enemy } else if (owner === 3) { self.shipGraphics.tint = 0x2a2f94; // Blue } else if (owner === 4) { self.shipGraphics.tint = 0x8e44ad; // Purple } else if (owner === 5) { self.shipGraphics.tint = 0xf39c12; // Orange } else if (owner === 6) { self.shipGraphics.tint = 0x00bcd4; // Cyan } // HP display self.hpText = new Text2(self.hp.toString(), { size: 48, fill: 0xFFFFFF }); self.hpText.anchor.set(0.5, 0.5); self.hpText.x = 0; self.hpText.y = -45; self.addChild(self.hpText); // Armies display (above ship) self.armyText = new Text2(self.armies.toString(), { size: 54, fill: 0x000000 }); self.armyText.anchor.set(0.5, 0.5); self.armyText.x = 0; self.armyText.y = -80; self.addChild(self.armyText); self.x = x; self.y = y; return self; }; self.takeDamage = function (damage) { self.hp -= damage; self.hpText.setText(self.hp.toString()); return self.hp <= 0; }; self.down = function (x, y, obj) { if (gameState === 'playing' && self.owner === 1) { selectShip(self); // Show possible moves for this ship (all sea territories) when clicked // Remove all previous highlights first for (var i = 0; i < territories.length; i++) { if (territories[i].isSea) { territories[i].showAsTarget = true; territories[i].updateGraphics(); } } } else if (gameState === 'playing' && selectedShip && selectedShip.owner === 1 && self.owner === 2) { // Check if ships are close enough for naval combat var distance = Math.abs(selectedShip.x - self.x) + Math.abs(selectedShip.y - self.y); if (distance < 200) { // Initiate naval combat navalCombat(selectedShip, self); selectedShip.selected = false; selectedShip.shipGraphics.tint = 0x27ae60; // Reset color selectedShip = null; endPlayerTurn(); } } }; return self; }); // Game state variables var Territory = Container.expand(function () { var self = Container.call(this); self.init = function (id, x, y, owner, isSea) { self.id = id; self.owner = owner; // 0 = neutral, 1 = player, 2 = enemy self.isSea = isSea || false; self.armies = owner === 0 || self.isSea ? 0 : Math.floor(Math.random() * 3) + 1; self.selected = false; self.lastSelected = false; // Track if this territory was ever colonizable (for attack logic) self.wasColonizable = !!self.isColonizable; // Create territory graphics self.updateGraphics(); // Position self.x = x; self.y = y; // Army display (only for land territories) if (!self.isSea) { self.armyText = new Text2(self.armies.toString(), { size: 24, fill: 0x000000 }); self.armyText.anchor.set(0.5, 0.5); self.armyText.x = 0; self.armyText.y = 0; self.addChild(self.armyText); } return self; }; self.updateGraphics = function () { // Remove existing graphics if (self.graphics) { self.removeChild(self.graphics); } var assetName = 'seaTerritory'; // Default to sea if (self.isSea) { assetName = 'seaTerritory'; } else if (self.selected) { assetName = 'selectedTerritory'; } else if (self.showAsTarget) { assetName = 'targetTerritory'; } else { // Assign different country colors based on owner if (self.owner === 1) { assetName = 'country1Territory'; // Green for player } else if (self.owner === 2) { assetName = 'country2Territory'; // Red for enemy } else if (self.owner === 3) { assetName = 'country3Territory'; // Blue } else if (self.owner === 4) { assetName = 'country4Territory'; // Purple } else if (self.owner === 5) { assetName = 'country5Territory'; // Orange } else if (self.owner === 6) { assetName = 'country6Territory'; // Cyan } else if (self.isColonizable) { assetName = 'colonizableTerritory'; // Use dedicated gray asset for colonizable territories } else { assetName = 'seaTerritory'; // Unassigned territories become sea } } self.graphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); }; self.setOwner = function (newOwner, armies) { self.owner = newOwner; if (!self.isSea) { self.armies = armies || 1; self.armyText.setText(self.armies.toString()); } self.updateGraphics(); }; self.addArmies = function (count) { if (!self.isSea) { self.armies += count; self.armyText.setText(self.armies.toString()); // Ensure army text is visible and on top after army change self.removeChild(self.armyText); self.addChild(self.armyText); } }; self.down = function (x, y, obj) { if (gameState === 'playing') { // Handle ship movement to sea territories if (selectedShip && self.isSea) { // Allow movement to any sea territory if (self.isSea) { // Move ship to any sea territory selectedShip.x = self.x; selectedShip.y = self.y; selectedShip.selected = false; selectedShip.shipGraphics.tint = 0x27ae60; // Reset color // Remove all sea highlights after move for (var i = 0; i < territories.length; i++) { if (territories[i].isSea && territories[i].showAsTarget) { territories[i].showAsTarget = false; territories[i].updateGraphics(); } } selectedShip = null; endPlayerTurn(); return; } } // Handle ship colonization of distant territories if (selectedShip && self.isColonizable && self.owner === 0 && !self.isSea) { // Check if ship is close enough to colonize (must be adjacent or very close) var distance = Math.abs(selectedShip.x - self.x) + Math.abs(selectedShip.y - self.y); if (distance <= territorySpacing * 1.5) { // Colonize the territory self.setOwner(selectedShip.owner, selectedShip.armies && selectedShip.armies > 0 ? selectedShip.armies : 2); // Use ship's armies if present, else 2 self.isColonizable = false; // No longer colonizable self.wasColonizable = true; // Mark as previously colonizable for attack logic // Ensure army text is visible and on top after colonization if (self.armyText) { self.armyText.setText(self.armies.toString()); self.removeChild(self.armyText); self.addChild(self.armyText); } if (selectedShip.owner === 1) { // Player gets money reward for colonization playerMoney += self.colonizationReward; if (playerMoneyText) { playerMoneyText.setText("Money: " + playerMoney); } if (instructionText) { instructionText.setText("Island colonized! Gained $" + self.colonizationReward); } } LK.getSound('capture').play(); selectedShip.selected = false; selectedShip.shipGraphics.tint = 0x27ae60; // Reset color // Remove all armies from ship after landing selectedShip.armies = 0; if (selectedShip.armyText) { selectedShip.armyText.setText("0"); } selectedShip = null; updateTerritoryCount(); endPlayerTurn(); return; } else { if (instructionText && selectedShip.owner === 1) { instructionText.setText("Ship must be closer to colonize this island"); } } } // Amphibious assault: allow attacking enemy territory from ship if at war and adjacent if (selectedShip && !self.isSea && self.owner > 1 && warDeclarations[self.owner]) { var distance = Math.abs(selectedShip.x - self.x) + Math.abs(selectedShip.y - self.y); if (distance <= territorySpacing * 1.5 && selectedShip.armies && selectedShip.armies > 0) { // Simple combat: if ship's armies > defender, take over, else reduce both var attackPower = selectedShip.armies; var defensePower = self.armies; if (attackPower > defensePower) { self.setOwner(selectedShip.owner, attackPower - defensePower); selectedShip.armies = 0; if (selectedShip.armyText) selectedShip.armyText.setText("0"); if (instructionText && selectedShip.owner === 1) { instructionText.setText("Amphibious assault successful!"); } LK.getSound('capture').play(); } else { selectedShip.armies = 0; if (selectedShip.armyText) selectedShip.armyText.setText("0"); if (defensePower > attackPower) { self.armies = defensePower - attackPower; if (self.armyText) self.armyText.setText(self.armies.toString()); } if (instructionText && selectedShip.owner === 1) { instructionText.setText("Amphibious assault failed!"); } LK.getSound('attack').play(); } selectedShip.selected = false; selectedShip.shipGraphics.tint = 0x27ae60; selectedShip = null; updateTerritoryCount(); endPlayerTurn(); return; } else if (distance <= territorySpacing * 1.5 && (!selectedShip.armies || selectedShip.armies === 0)) { if (instructionText && selectedShip.owner === 1) { instructionText.setText("Ship has no armies to land!"); } return; } } // Allow colonization of colonizable territory with armies (if adjacent and enough armies) if (!self.isSea && self.isColonizable && self.owner === 0 && selectedTerritory && selectedTerritory.owner === 1 && !selectedTerritory.isSea) { // Must be adjacent var neighbors = getNeighbors(self); var isNeighbor = false; for (var i = 0; i < neighbors.length; i++) { if (neighbors[i] === selectedTerritory) { isNeighbor = true; break; } } if (isNeighbor && selectedTerritory.armies > 1) { // Colonize with armies: move 2 armies, leave at least 1 behind self.setOwner(1, 2); self.isColonizable = false; self.wasColonizable = true; // Mark as previously colonizable for attack logic // Ensure army text is visible and on top after colonization if (self.armyText) { self.armyText.setText(self.armies.toString()); self.removeChild(self.armyText); self.addChild(self.armyText); } selectedTerritory.armies -= 2; selectedTerritory.armyText.setText(selectedTerritory.armies.toString()); playerMoney += self.colonizationReward; if (playerMoneyText) { playerMoneyText.setText("Money: " + playerMoney); } if (instructionText) { instructionText.setText("Island colonized with armies! Gained $" + self.colonizationReward); } LK.getSound('capture').play(); updateTerritoryCount(); endPlayerTurn(); return; } else if (isNeighbor && selectedTerritory.armies <= 1) { if (instructionText) { instructionText.setText("Need at least 2 armies to colonize with armies!"); } return; } } // Allow loading armies from player's territory onto ship if adjacent if (selectedShip && self.owner === 1 && !self.isSea && self.armies > 1) { var distance = Math.abs(selectedShip.x - self.x) + Math.abs(selectedShip.y - self.y); if (distance <= territorySpacing * 1.5) { // Move up to all but 1 army from territory to ship (max 5 on ship) var canLoad = Math.min(self.armies - 1, 5 - selectedShip.armies); if (canLoad > 0) { self.armies -= canLoad; selectedShip.armies += canLoad; if (self.armyText) self.armyText.setText(self.armies.toString()); if (selectedShip.armyText) selectedShip.armyText.setText(selectedShip.armies.toString()); if (instructionText) instructionText.setText("Loaded " + canLoad + " armies onto ship."); return; } else { if (instructionText) instructionText.setText("Ship is full or not enough armies to load."); return; } } } selectTerritory(self); } else if (gameState === 'selectingTarget' && self.showAsTarget) { executeAttack(self); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ // Difficulty selection var selectedDifficulty = null; // "easy", "medium", "hard" var difficultyButtons = []; var difficultyText = null; // Game state variables // Territory and game assets var gameState = 'playing'; // 'playing', 'gameOver', 'victory', 'selectingTarget' var attackTargets = []; // Available targets for attack var currentTurn = 1; // 1 = player, 2 = enemy var selectedTerritory = null; var territories = []; var playerTerritories = 0; var enemyTerritories = 0; var totalTerritories = 0; var playerMoney = 100; // Starting money var aiMoney = 100; // Starting AI money var incomePerTerritory = 10; // Money generated per territory per turn // Diplomacy variables var warDeclarations = {}; // Track which countries we're at war with var peaceOfferCooldowns = {}; // Track cooldowns for peace offers after rejection var diplomacyPanel = null; // Ship variables var ships = []; var selectedShip = null; // Power selection variables var selectedAttackPower = 1; var maxAttackPower = 1; var powerSelectionMode = false; // UI elements var turnText, scoreText, instructionText, playerArmyText, playerMoneyText; var powerText, powerDownButton, powerUpButton; var actionButtons = []; // Game settings var mapWidth = 8; var mapHeight = 12; var territorySpacing = 140; var startX = 2048 / 2 - mapWidth * territorySpacing / 2 + territorySpacing / 2; var startY = 300; // Create the game map function createMap() { var id = 0; // We'll store adjacency for sea territories here var seaAdjacency = {}; // Create contiguous regions for each country with sea territories // Divide the map into regions for 6 countries for (var row = 0; row < mapHeight; row++) { for (var col = 0; col < mapWidth; col++) { var x = startX + col * territorySpacing; var y = startY + row * territorySpacing; var isSea = false; var owner = 0; // default to neutral/sea // Create sea lanes (vertical strips) // Connect the two sea lanes at rows 5 and 6 (expanded connection) if (col === 2 || col === 5 || (row === 5 || row === 6) && (col === 3 || col === 4)) { isSea = true; owner = 0; // Neutral sea } else { // Determine owner based on map regions to create contiguous countries if (row < mapHeight / 3) { // Top third - countries 1 and 2 if (col < mapWidth / 2) { owner = 1; // Country 1 (Green) - top left } else { owner = 2; // Country 2 (Red) - top right } } else if (row < mapHeight * 2 / 3) { // Middle third - countries 3 and 4 if (col < mapWidth / 2) { owner = 3; // Country 3 (Blue) - middle left } else { owner = 4; // Country 4 (Purple) - middle right } } else { // Bottom third - countries 5 and 6 if (col < mapWidth / 2) { owner = 5; // Country 5 (Orange) - bottom left } else { owner = 6; // Country 6 (Cyan) - bottom right } } // If no specific owner assigned, make it sea if (owner === 0 && !isSea) { isSea = true; } } // --- Convert border sea to land --- // If this tile is at the border and would be sea, convert to land and assign to nearest country if ((row === 0 || row === mapHeight - 1 || col === 0 || col === mapWidth - 1) && isSea) { isSea = false; // Assign to nearest country by region logic if (row < mapHeight / 3) { owner = col < mapWidth / 2 ? 1 : 2; } else if (row < mapHeight * 2 / 3) { owner = col < mapWidth / 2 ? 3 : 4; } else { owner = col < mapWidth / 2 ? 5 : 6; } } var territory = new Territory(); territory.init(id, x, y, owner, isSea); territories.push(territory); game.addChild(territory); id++; } } // Build adjacency for sea territories (by index) for (var i = 0; i < territories.length; i++) { if (territories[i].isSea) { var neighbors = getNeighbors(territories[i]); seaAdjacency[i] = []; for (var j = 0; j < neighbors.length; j++) { if (neighbors[j].isSea) { var neighborIndex = territories.indexOf(neighbors[j]); if (neighborIndex !== -1) { seaAdjacency[i].push(neighborIndex); } } } } } // Attach adjacency info to each sea territory for easy access for (var i = 0; i < territories.length; i++) { if (territories[i].isSea) { territories[i].adjacentSeaIndices = seaAdjacency[i]; } } // (Colonizable islands removed) // Create initial ships for player and enemy createShips(); updateTerritoryCount(); } // Create initial ships function createShips() { // Find sea territories for ship placement var seaTerritories = []; for (var i = 0; i < territories.length; i++) { if (territories[i].isSea) { seaTerritories.push(territories[i]); } } // Place initial ships if (seaTerritories.length > 0) { // Player ship - automatically select it to start on the ship var playerShip = new Ship(); var playerSeaPos = seaTerritories[Math.floor(Math.random() * seaTerritories.length)]; playerShip.init(1, playerSeaPos.x, playerSeaPos.y); playerShip.armies = 2; if (playerShip.armyText) playerShip.armyText.setText("2"); ships.push(playerShip); // Auto-select the player ship so they start on it selectShip(playerShip); // Enemy ship var enemyShip = new Ship(); var enemySeaPos = seaTerritories[Math.floor(Math.random() * seaTerritories.length)]; enemyShip.init(2, enemySeaPos.x, enemySeaPos.y); enemyShip.armies = 0; if (enemyShip.armyText) enemyShip.armyText.setText("0"); ships.push(enemyShip); // Ensure ships are always rendered above sea territories by adding them after all territories are added game.addChild(playerShip); game.addChild(enemyShip); } } // Ship selection function selectShip(ship) { if (selectedDifficulty === null) return; if (currentTurn !== 1) return; // Deselect previous selections if (selectedTerritory) { selectedTerritory.selected = false; selectedTerritory.updateGraphics(); selectedTerritory = null; } if (selectedShip) { selectedShip.selected = false; selectedShip.shipGraphics.tint = 0x27ae60; // Reset to green } // Select new ship selectedShip = ship; ship.selected = true; ship.shipGraphics.tint = 0xf1c40f; // Yellow when selected // Update armyText in case it was changed if (ship.armyText) { ship.armyText.setText(ship.armies.toString()); } // Remove all possible move highlights when selecting a ship, only show on click for (var i = 0; i < territories.length; i++) { if (territories[i].isSea) { territories[i].showAsTarget = false; territories[i].updateGraphics(); } } // Do not show possible moves here; will be shown on ship click (down event) hidePowerSelection(); updateInstructions(); } // Generate income based on territories owned function generateIncome() { var income = playerTerritories * incomePerTerritory; playerMoney += income; if (playerMoneyText) { playerMoneyText.setText("Money: " + playerMoney + " (+$" + income + ")"); } } // Update territory ownership counts function updateTerritoryCount() { playerTerritories = 0; enemyTerritories = 0; var playerTotalArmies = 0; var country1Count = 0, country2Count = 0, country3Count = 0; var country4Count = 0, country5Count = 0, country6Count = 0; totalTerritories = territories.length; for (var i = 0; i < territories.length; i++) { if (territories[i].owner === 1) { playerTerritories++; country1Count++; playerTotalArmies += territories[i].armies; } else if (territories[i].owner === 2) { enemyTerritories++; country2Count++; } else if (territories[i].owner === 3) { country3Count++; } else if (territories[i].owner === 4) { country4Count++; } else if (territories[i].owner === 5) { country5Count++; } else if (territories[i].owner === 6) { country6Count++; } } // (Removed scoreText update for country colors and territory counts) // Update player army display if (playerArmyText) { playerArmyText.setText("Total Armies: " + playerTotalArmies); } // Update money display if (playerMoneyText) { playerMoneyText.setText("Money: " + playerMoney); } // Check victory conditions // Count total non-sea territories var totalNonSeaTerritories = 0; for (var i = 0; i < territories.length; i++) { if (!territories[i].isSea) { totalNonSeaTerritories++; } } if (playerTerritories === totalNonSeaTerritories) { gameState = 'victory'; LK.showYouWin(); } else if (enemyTerritories >= Math.floor(totalTerritories * 0.75)) { gameState = 'gameOver'; LK.showGameOver(); } else if (playerTerritories === 0) { gameState = 'gameOver'; LK.showGameOver(); } } // Declare war function function declareWar(countryId) { warDeclarations[countryId] = true; if (instructionText) { instructionText.setText("War declared on Country " + countryId + "! You can now attack their territories."); } // If diplomacyPanel is open, update buttons if (diplomacyPanel && diplomacyPanel.targetCountry === countryId) { diplomacyPanel.updateButtons(); } } // Make peace function function makePeace(countryId) { if (selectedDifficulty === "hardcore") { if (instructionText) { instructionText.setText("Peace treaties are disabled in Hardcore mode!"); } return; } // Prevent peace offer if cooldown is active if (peaceOfferCooldowns[countryId] && peaceOfferCooldowns[countryId] > 0) { if (instructionText) { instructionText.setText("You must wait " + peaceOfferCooldowns[countryId] + " turns before offering peace to Country " + countryId + " again."); } return; } if (warDeclarations[countryId]) { // In easy mode, always accept peace treaty if (selectedDifficulty === "easy" || Math.random() < 0.5) { warDeclarations[countryId] = false; if (instructionText) { instructionText.setText("Peace treaty signed with Country " + countryId + ". You can no longer attack their territories."); } // If diplomacyPanel is open, update buttons if (diplomacyPanel && diplomacyPanel.targetCountry === countryId) { diplomacyPanel.updateButtons(); } if (peaceOfferCooldowns[countryId]) peaceOfferCooldowns[countryId] = 0; // Reset cooldown on acceptance } else { if (instructionText) { instructionText.setText("Peace treaty rejected by Country " + countryId + "!"); } // Set cooldown for 10 turns after rejection peaceOfferCooldowns[countryId] = 10; } } } // Territory selection function selectTerritory(territory) { if (selectedDifficulty === null) return; if (currentTurn !== 1) return; // Only during player turn // If we're in target selection mode, cancel it if (gameState === 'selectingTarget') { // Clear target highlighting for (var i = 0; i < attackTargets.length; i++) { attackTargets[i].showAsTarget = false; attackTargets[i].updateGraphics(); } gameState = 'playing'; attackTargets = []; } // Deselect previous territory if (selectedTerritory) { selectedTerritory.selected = false; selectedTerritory.updateGraphics(); // Ensure previous territory's army text remains visible selectedTerritory.armyText.setText(selectedTerritory.armies.toString()); // Re-add army text to ensure it's visible selectedTerritory.removeChild(selectedTerritory.armyText); selectedTerritory.addChild(selectedTerritory.armyText); } // Handle enemy territory clicks - show diplomacy panel if (territory.owner !== 1 && territory.owner !== 0) { // Create diplomacy panel if it doesn't exist if (!diplomacyPanel) { diplomacyPanel = new DiplomacyPanel(); diplomacyPanel.init(territory.owner); } else { // Update existing panel for new country diplomacyPanel.targetCountry = territory.owner; diplomacyPanel.titleText.setText("Diplomacy with Country " + territory.owner); if (diplomacyPanel.updateButtons) diplomacyPanel.updateButtons(); } diplomacyPanel.show(); return; } // Select new territory if (territory.owner === 1) { // Only select player territories selectedTerritory = territory; territory.selected = true; territory.updateGraphics(); // Ensure army text is visible and updated territory.armyText.setText(territory.armies.toString()); // Bring army text to front to ensure it's visible territory.removeChild(territory.armyText); territory.addChild(territory.armyText); // Show power selection for territories with armies > 1 if (!territory.isSea && territory.armies > 1) { showPowerSelection(territory.armies - 1); } else { hidePowerSelection(); } updateInstructions(); } else { hidePowerSelection(); } } // Get neighboring territories function getNeighbors(territory) { var neighbors = []; var index = territories.indexOf(territory); var row = Math.floor(index / mapWidth); var col = index % mapWidth; // Check all 4 directions var directions = [{ row: -1, col: 0 }, // up { row: 1, col: 0 }, // down { row: 0, col: -1 }, // left { row: 0, col: 1 } // right ]; for (var i = 0; i < directions.length; i++) { var newRow = row + directions[i].row; var newCol = col + directions[i].col; if (newRow >= 0 && newRow < mapHeight && newCol >= 0 && newCol < mapWidth) { var neighborIndex = newRow * mapWidth + newCol; neighbors.push(territories[neighborIndex]); } } return neighbors; } // Attack action function attackTerritory() { if (selectedDifficulty === null) return; if (!selectedTerritory || selectedTerritory.armies <= 1) return; var neighbors = getNeighbors(selectedTerritory); var targets = []; for (var i = 0; i < neighbors.length; i++) { if (neighbors[i].owner !== 1) { // Allow attacking if: // - Neutral (owner 0) // - At war with the country // - The territory was previously colonizable and is now enemy-owned (owner 2-6) // - The territory was a neutral/colonizable territory, is now enemy-owned, and we are at war with that enemy var n = neighbors[i]; var canAttack = false; if (n.owner === 0) { canAttack = true; } else if (warDeclarations[n.owner]) { canAttack = true; } else if (n.owner > 1 && n.owner <= 6 && n.isColonizable === true) { canAttack = true; } else if (n.owner > 1 && n.owner <= 6 && typeof n.wasColonizable !== "undefined" && n.wasColonizable === true && warDeclarations[n.owner]) { // If this territory was previously colonizable, is now enemy-owned, and we are at war with that enemy canAttack = true; } if (canAttack) { targets.push(n); } } } if (targets.length > 0) { // Show target selection mode gameState = 'selectingTarget'; attackTargets = targets; // Highlight all possible targets for (var i = 0; i < targets.length; i++) { targets[i].showAsTarget = true; targets[i].updateGraphics(); } if (instructionText) { instructionText.setText("Select a territory to attack"); } } } // Execute attack on selected target function executeAttack(target) { if (!selectedTerritory || !target) return; // Clear target highlighting for (var i = 0; i < attackTargets.length; i++) { attackTargets[i].showAsTarget = false; attackTargets[i].updateGraphics(); } // Simple combat resolution using selected attack power var attackPower = selectedAttackPower; var defensePower = target.armies; if (attackPower > defensePower) { // Victory target.setOwner(1, attackPower - defensePower); selectedTerritory.armies = selectedTerritory.armies - attackPower; selectedTerritory.armyText.setText(selectedTerritory.armies.toString()); LK.getSound('capture').play(); } else { // Defeat - lose the armies used in attack selectedTerritory.armies = selectedTerritory.armies - attackPower; selectedTerritory.armyText.setText(selectedTerritory.armies.toString()); if (defensePower > attackPower) { target.armies = defensePower - attackPower; target.armyText.setText(target.armies.toString()); } } LK.getSound('attack').play(); updateTerritoryCount(); // Reset game state gameState = 'playing'; attackTargets = []; endPlayerTurn(); } // Recruit armies action function recruitArmies() { if (selectedDifficulty === null) return; if (!selectedTerritory) return; var recruitCost = 100; // Increased cost to recruit armies if (playerMoney >= recruitCost) { playerMoney -= recruitCost; selectedTerritory.addArmies(2); if (playerMoneyText) { playerMoneyText.setText("Money: " + playerMoney); } endPlayerTurn(); } else { // Not enough money - show feedback but don't end turn if (instructionText) { instructionText.setText("Not enough money! Need $" + recruitCost + " to recruit"); } } } // Build ship action function buildShip() { if (selectedDifficulty === null) return; if (!selectedTerritory || selectedTerritory.isSea) return; var shipCost = 200; //{4Z} // Increased cost // Determine which country's money to use var owner = selectedTerritory.owner; if (owner === 0 || owner === undefined) return; // Only countries can build ships // Only allow if the country has enough money var canBuild = false; if (owner === 1 && playerMoney >= shipCost) { canBuild = true; } else if (owner === 2 && aiMoney >= shipCost) { canBuild = true; } else if (owner > 2) { // For AI countries 3-6, give them their own money pool if not present if (typeof window['countryMoney' + owner] === "undefined") { window['countryMoney' + owner] = 100; } if (window['countryMoney' + owner] >= shipCost) { canBuild = true; } } if (canBuild) { // Find adjacent sea territory var neighbors = getNeighbors(selectedTerritory); var seaNeighbors = []; for (var i = 0; i < neighbors.length; i++) { if (neighbors[i].isSea) { seaNeighbors.push(neighbors[i]); } } if (seaNeighbors.length > 0) { // Deduct money from the correct pool if (owner === 1) { playerMoney -= shipCost; } else if (owner === 2) { aiMoney -= shipCost; } else if (owner > 2) { window['countryMoney' + owner] -= shipCost; } var seaPos = seaNeighbors[0]; var newShip = new Ship(); newShip.init(owner, seaPos.x, seaPos.y); ships.push(newShip); // Ensure new ships are rendered above sea territories game.addChild(newShip); if (owner === 1 && playerMoneyText) { playerMoneyText.setText("Money: " + playerMoney); } endPlayerTurn(); } else { if (instructionText && owner === 1) { instructionText.setText("No adjacent sea territory to build ship!"); } } } else { if (instructionText && owner === 1) { instructionText.setText("Not enough money! Need $" + shipCost + " to build ship"); } } } // Naval combat function navalCombat(attackerShip, defenderShip) { var damage = 1; var defenderDestroyed = defenderShip.takeDamage(damage); if (defenderDestroyed) { // Remove destroyed ship var index = ships.indexOf(defenderShip); if (index > -1) { ships.splice(index, 1); } defenderShip.destroy(); LK.getSound('capture').play(); } else { LK.getSound('attack').play(); } } // Per-country ship build timers for AI countries 2-6 // All countries (1-6) can build ships, recruit armies, declare war, and colonize var countryShipTimers = {}; // Per-country war declaration timers for AI countries 2-6 (enemy and other AIs) var countryWarTimers = {}; for (var c = 2; c <= 6; c++) { // For war timers: if not at war, 12 turns; if at war, 30 turns (will be set dynamically in aiTurn) countryWarTimers[c] = Math.floor(Math.random() * 3) + 10; // randomize initial timer between 10-12 } for (var c = 2; c <= 6; c++) { // All AI countries 2-6: build ships every 3-5 turns by default countryShipTimers[c] = Math.floor(Math.random() * 3) + 3; } // End player turn function endPlayerTurn() { if (selectedTerritory) { selectedTerritory.selected = false; selectedTerritory.updateGraphics(); selectedTerritory = null; hidePowerSelection(); } hidePowerSelection(); // Generate income based on territories owned generateIncome(); // Decrease peace offer cooldowns at end of player turn for (var k in peaceOfferCooldowns) { if (peaceOfferCooldowns.hasOwnProperty(k) && peaceOfferCooldowns[k] > 0) { peaceOfferCooldowns[k]--; } } currentTurn = 2; updateInstructions(); // AI turn after short delay LK.setTimeout(function () { aiTurn(); }, 1000); } // Helper: AI build ship for a country if possible function aiBuildShipForCountry(countryId) { // Find all territories owned by this country var owned = []; for (var i = 0; i < territories.length; i++) { if (territories[i].owner === countryId && !territories[i].isSea) { owned.push(territories[i]); } } // Try to build ship from a random owned territory with adjacent sea if (owned.length > 0) { var t = owned[Math.floor(Math.random() * owned.length)]; var neighbors = getNeighbors(t); var seaNeighbors = []; for (var j = 0; j < neighbors.length; j++) { if (neighbors[j].isSea) seaNeighbors.push(neighbors[j]); } if (seaNeighbors.length > 0) { // Deduct money if needed (handled in buildShip, but we do it here for AI) if (typeof window['countryMoney' + countryId] === "undefined") { window['countryMoney' + countryId] = 100; } var shipCost = 200; if (window['countryMoney' + countryId] >= shipCost) { window['countryMoney' + countryId] -= shipCost; var seaPos = seaNeighbors[0]; var newShip = new Ship(); newShip.init(countryId, seaPos.x, seaPos.y); ships.push(newShip); game.addChild(newShip); return true; } } } return false; } // Simple AI turn function aiTurn() { // Generate AI income var aiIncome = enemyTerritories * incomePerTerritory; aiMoney += aiIncome; var enemyTerrs = []; for (var i = 0; i < territories.length; i++) { if (territories[i].owner === 2) { enemyTerrs.push(territories[i]); } } if (enemyTerrs.length > 0) { var aiTerritory = enemyTerrs[Math.floor(Math.random() * enemyTerrs.length)]; var neighbors = getNeighbors(aiTerritory); var playerTargets = []; // In easy mode, AI never attacks if (selectedDifficulty === "easy") { // AI does not attack, just does economy/ship/army actions below playerTargets = []; } else { for (var j = 0; j < neighbors.length; j++) { // AI can attack player territories if war is declared on AI (country 2) if (neighbors[j].owner === 1 && warDeclarations[2]) { playerTargets.push(neighbors[j]); } } } if (playerTargets.length > 0 && aiTerritory.armies > 1) { // AI attacks var target = playerTargets[Math.floor(Math.random() * playerTargets.length)]; var attackPower = aiTerritory.armies - 1; var defensePower = target.armies; if (attackPower > defensePower) { target.setOwner(2, attackPower - defensePower); aiTerritory.armies = 1; aiTerritory.armyText.setText(aiTerritory.armies.toString()); } else { aiTerritory.armies = 1; aiTerritory.armyText.setText(aiTerritory.armies.toString()); if (defensePower > attackPower) { target.armies = defensePower - attackPower; target.armyText.setText(target.armies.toString()); } } } else { // AI decides what to do based on money and strategy var action = Math.random(); var recruitCost = 50; var shipCost = 100; if (action < 0.4 && aiMoney >= recruitCost) { // 40% chance to recruit armies if affordable aiMoney -= recruitCost; aiTerritory.addArmies(2); } else if (action < 0.7 && aiMoney >= shipCost) { // 30% chance to build ship if possible and affordable var seaNeighbors = []; for (var k = 0; k < neighbors.length; k++) { if (neighbors[k].isSea) { seaNeighbors.push(neighbors[k]); } } if (seaNeighbors.length > 0) { // Build ship in adjacent sea aiMoney -= shipCost; var seaPos = seaNeighbors[0]; var newShip = new Ship(); newShip.init(2, seaPos.x, seaPos.y); ships.push(newShip); // Ensure AI ships are rendered above sea territories game.addChild(newShip); } else { // No sea nearby, recruit if affordable or just add basic army if (aiMoney >= recruitCost) { aiMoney -= recruitCost; aiTerritory.addArmies(2); } else { aiTerritory.addArmies(1); } } } else { // Default action - add basic army (free) aiTerritory.addArmies(1); } } } // AI war declaration logic for hard difficulty if (selectedDifficulty === "hard") { // --- Special: Country 6 always declares war on country 5 every 5 turns --- if (typeof window.country6War5Timer === "undefined") { window.country6War5Timer = 5; } window.country6War5Timer--; if (window.country6War5Timer <= 0) { if (!warDeclarations[5]) { warDeclarations[5] = true; if (instructionText) { instructionText.setText("Country 6 has declared war on Country 5!"); } } window.country6War5Timer = 5; } // --- New: AI countries declare war on weaker neighbors if stronger --- for (var c = 2; c <= 6; c++) { // Only consider if not already at war with all other countries for (var i = 0; i < territories.length; i++) { if (territories[i].owner === c && !territories[i].isSea) { var neighbors = getNeighbors(territories[i]); for (var j = 0; j < neighbors.length; j++) { var neighbor = neighbors[j]; // Only consider land neighbors owned by another country (not self, not neutral, not sea) if (neighbor.owner !== c && neighbor.owner > 0 && neighbor.owner <= 6 && !neighbor.isSea && !warDeclarations[neighbor.owner]) { // If AI's territory has more armies than neighbor, declare war if (territories[i].armies > neighbor.armies) { warDeclarations[neighbor.owner] = true; if (neighbor.owner === 1 && instructionText) { instructionText.setText("Country " + c + " has declared war on you due to your weak border!"); } } } } } } } // --- AI peace offer logic (not in hardcore) --- if (selectedDifficulty !== "hardcore") { for (var c = 2; c <= 6; c++) { // If AI country is at war with player, has lost territories, and random chance, offer peace if (warDeclarations[c]) { // Count AI's territories var aiTerrCount = 0; for (var i = 0; i < territories.length; i++) { if (territories[i].owner === c && !territories[i].isSea) { aiTerrCount++; } } // If AI is weak (few territories) or random chance, offer peace if (aiTerrCount < 3 || Math.random() < 0.15) { // 50% chance player accepts, always accept in easy mode if (selectedDifficulty === "easy" || Math.random() < 0.5) { warDeclarations[c] = false; if (instructionText) { instructionText.setText("Country " + c + " has offered a peace treaty. Peace has been established!"); } if (diplomacyPanel && diplomacyPanel.targetCountry === c) { diplomacyPanel.updateButtons(); } } else { if (instructionText) { instructionText.setText("Country " + c + " has offered a peace treaty, but you rejected it!"); } } } } } } // AI countries 2-6 may declare war more frequently for (var c = 2; c <= 6; c++) { // Only consider declaring war on countries we are not already at war with if (!warDeclarations[c]) { countryWarTimers[c]--; if (countryWarTimers[c] <= 0) { // Declare war on a random other country (not self) var possibleTargets = []; for (var t = 1; t <= 6; t++) { if (t !== c && !warDeclarations[t]) { possibleTargets.push(t); } } if (possibleTargets.length > 0) { var target = possibleTargets[Math.floor(Math.random() * possibleTargets.length)]; warDeclarations[target] = true; // Optionally, show a message if the player is the target if (target === 1 && instructionText) { instructionText.setText("Country " + c + " has declared war on you!"); } } // Reset timer for next declaration (12 turns if not at war, 30 if at war) if (warDeclarations[c]) { countryWarTimers[c] = 30; } else { countryWarTimers[c] = 12; } } } else { // If already at war, use longer timer before next declaration countryWarTimers[c]--; if (countryWarTimers[c] <= 0) { // Try to declare war on another country (not self, not already at war) var possibleTargets = []; for (var t = 1; t <= 6; t++) { if (t !== c && !warDeclarations[t]) { possibleTargets.push(t); } } if (possibleTargets.length > 0) { var target = possibleTargets[Math.floor(Math.random() * possibleTargets.length)]; warDeclarations[target] = true; if (target === 1 && instructionText) { instructionText.setText("Country " + c + " has declared war on you!"); } } // Reset timer for next declaration (30 turns if at war) countryWarTimers[c] = 30; } } } } // In easy mode, AI never declares war (handled by not attacking above) // AI countries 2-6: build ships every 3-5 turns if possible for (var c = 2; c <= 6; c++) { if (typeof countryShipTimers[c] === "undefined") { countryShipTimers[c] = Math.floor(Math.random() * 3) + 3; } countryShipTimers[c]--; if (countryShipTimers[c] <= 0) { var built = aiBuildShipForCountry(c); countryShipTimers[c] = Math.floor(Math.random() * 3) + 3; } } // All AI countries 2-6: recruit armies every turn if possible for (var c = 2; c <= 6; c++) { for (var i = 0; i < territories.length; i++) { if (territories[i].owner === c && !territories[i].isSea) { if (typeof window['countryMoney' + c] === "undefined") { window['countryMoney' + c] = 100; } var recruitCost = 50; if (window['countryMoney' + c] >= recruitCost) { window['countryMoney' + c] -= recruitCost; territories[i].addArmies(2); } } } } // AI ship movement and naval combat // Loop for all AI countries (2-6) to give each their own ship logic for (var aiCountry = 2; aiCountry <= 6; aiCountry++) { var aiShips = []; for (var i = 0; i < ships.length; i++) { if (ships[i].owner === aiCountry) { aiShips.push(ships[i]); } } if (aiShips.length > 0) { var aiShip = aiShips[Math.floor(Math.random() * aiShips.length)]; // Look for enemy ships to attack (player or any other country at war) var enemyShips = []; for (var i = 0; i < ships.length; i++) { if (ships[i].owner !== aiCountry && ships[i].owner !== 0) { // Only attack if at war or if player (for country 2) if (aiCountry === 2) { if (ships[i].owner === 1 && warDeclarations[2]) { var distance = Math.abs(ships[i].x - aiShip.x) + Math.abs(ships[i].y - aiShip.y); if (distance < 200) { enemyShips.push(ships[i]); } } } else { // For AI countries 3-6, attack ships of any country at war if (warDeclarations[aiCountry] || warDeclarations[ships[i].owner]) { var distance = Math.abs(ships[i].x - aiShip.x) + Math.abs(ships[i].y - aiShip.y); if (distance < 200) { enemyShips.push(ships[i]); } } } } } if (enemyShips.length > 0) { // Attack nearest enemy ship var target = enemyShips[0]; navalCombat(aiShip, target); } else { // Look for colonizable territories var colonizableTargets = []; for (var i = 0; i < territories.length; i++) { if (territories[i].isColonizable && territories[i].owner === 0 && !territories[i].isSea) { var distance = Math.abs(territories[i].x - aiShip.x) + Math.abs(territories[i].y - aiShip.y); if (distance <= territorySpacing * 1.5) { colonizableTargets.push(territories[i]); } } } if (colonizableTargets.length > 0) { // Colonize nearest available territory var target = colonizableTargets[0]; target.setOwner(aiCountry, 2); target.isColonizable = false; // No longer colonizable target.wasColonizable = true; // Mark as previously colonizable for attack logic // Give money to correct AI pool if (aiCountry === 2) { aiMoney += target.colonizationReward; } else { if (typeof window['countryMoney' + aiCountry] === "undefined") { window['countryMoney' + aiCountry] = 100; } window['countryMoney' + aiCountry] += target.colonizationReward; } } else { // Move to random sea territory or towards colonizable islands var moveTargets = []; // Add sea territories for (var i = 0; i < territories.length; i++) { if (territories[i].isSea) { moveTargets.push(territories[i]); } } // Add positions near colonizable islands for (var i = 0; i < territories.length; i++) { if (territories[i].isColonizable && territories[i].owner === 0) { moveTargets.push(territories[i]); } } if (moveTargets.length > 0) { var newPos = moveTargets[Math.floor(Math.random() * moveTargets.length)]; aiShip.x = newPos.x; aiShip.y = newPos.y; } } } } } updateTerritoryCount(); // Decrease peace offer cooldowns at end of AI turn for (var k in peaceOfferCooldowns) { if (peaceOfferCooldowns.hasOwnProperty(k) && peaceOfferCooldowns[k] > 0) { peaceOfferCooldowns[k]--; } } currentTurn = 1; updateInstructions(); } // Create UI elements function createUI() { // Turn indicator turnText = new Text2("Your Turn", { size: 40, fill: 0xFFFFFF }); turnText.anchor.set(0.5, 0); LK.gui.top.addChild(turnText); turnText.y = 100; // (Removed scoreText display for country colors and territory counts) // Player army count display playerArmyText = new Text2("Total Armies: 0", { size: 32, fill: 0x7ed321 }); playerArmyText.anchor.set(0.5, 0); LK.gui.top.addChild(playerArmyText); playerArmyText.y = 190; // Player money display playerMoneyText = new Text2("Money: " + playerMoney, { size: 32, fill: 0xf5a623 }); playerMoneyText.anchor.set(0.5, 0); LK.gui.top.addChild(playerMoneyText); playerMoneyText.y = 230; // Instructions instructionText = new Text2("Select your territory, then choose an action", { size: 28, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 1); LK.gui.bottom.addChild(instructionText); instructionText.y = -200; // Action buttons var attackBtn = new ActionButton(); attackBtn.init("Attack", attackTerritory, 2048 / 2 - 200, 2732 - 120); actionButtons.push(attackBtn); game.addChild(attackBtn); var recruitBtn = new ActionButton(); recruitBtn.init("Recruit", recruitArmies, 2048 / 2 - 60, 2732 - 120); actionButtons.push(recruitBtn); game.addChild(recruitBtn); var buildShipBtn = new ActionButton(); buildShipBtn.init("Build Ship", buildShip, 2048 / 2 + 80, 2732 - 120); actionButtons.push(buildShipBtn); game.addChild(buildShipBtn); // Skip Turn button var skipTurnBtn = new ActionButton(); skipTurnBtn.init("Skip Turn", function () { if (selectedDifficulty === null) return; if (currentTurn === 1) { endPlayerTurn(); } }, 2048 / 2 + 220, 2732 - 120); actionButtons.push(skipTurnBtn); game.addChild(skipTurnBtn); // Power selection display powerText = new Text2("Attack Power: 1/1", { size: 28, fill: 0xffff00 }); powerText.anchor.set(0.5, 1); LK.gui.bottom.addChild(powerText); powerText.y = -240; powerText.visible = false; // Power adjustment buttons var powerDownBtn = new ActionButton(); powerDownBtn.init("-", decreasePower, 2048 / 2 - 100, 2732 - 180); actionButtons.push(powerDownBtn); game.addChild(powerDownBtn); powerDownBtn.visible = false; var powerUpBtn = new ActionButton(); powerUpBtn.init("+", increasePower, 2048 / 2 + 100, 2732 - 180); actionButtons.push(powerUpBtn); game.addChild(powerUpBtn); powerUpBtn.visible = false; // Store power buttons for visibility control powerDownButton = powerDownBtn; powerUpButton = powerUpBtn; } // Power selection functions function decreasePower() { if (selectedDifficulty === null) return; if (selectedAttackPower > 1) { selectedAttackPower--; updatePowerDisplay(); } } function increasePower() { if (selectedDifficulty === null) return; if (selectedAttackPower < maxAttackPower) { selectedAttackPower++; updatePowerDisplay(); } } function updatePowerDisplay() { if (powerText) { powerText.setText("Attack Power: " + selectedAttackPower + "/" + maxAttackPower); } } function showPowerSelection(maxPower) { maxAttackPower = maxPower; selectedAttackPower = Math.min(selectedAttackPower, maxAttackPower); powerSelectionMode = true; if (powerText) { powerText.visible = true; updatePowerDisplay(); } if (powerDownButton && powerUpButton) { powerDownButton.visible = true; powerUpButton.visible = true; } } function hidePowerSelection() { powerSelectionMode = false; if (powerText) { powerText.visible = false; } if (powerDownButton && powerUpButton) { powerDownButton.visible = false; powerUpButton.visible = false; } } // Update instruction text function updateInstructions() { if (selectedDifficulty === null) { if (instructionText) { instructionText.setText("Please select a difficulty (Easy, Medium, Hard)"); } return; } if (currentTurn === 1) { if (turnText) { turnText.setText("Your Turn"); } if (instructionText) { if (selectedShip) { instructionText.setText("Ship selected - Move to sea or attack enemy ships"); } else if (selectedTerritory) { if (selectedTerritory.isSea) { instructionText.setText("Sea territory selected - Ships can move here"); } else if (powerSelectionMode) { instructionText.setText("Use +/- to choose attack power, then Attack, Recruit ($100), or Build Ship ($200)"); } else { instructionText.setText("Territory selected - Attack, Recruit ($100), or Build Ship ($200)"); } } else { instructionText.setText("Select your territory/ship (green), then choose an action"); } } } else { if (turnText) { turnText.setText("Enemy Turn"); } if (instructionText) { instructionText.setText("Enemy is thinking..."); } } } // Game update loop for naval combat highlighting game.update = function () { // Highlight enemy ships in combat range when player ship is selected if (selectedShip && selectedShip.owner === 1) { for (var i = 0; i < ships.length; i++) { if (ships[i].owner === 2) { var distance = Math.abs(selectedShip.x - ships[i].x) + Math.abs(selectedShip.y - ships[i].y); if (distance < 200) { // Highlight enemy ship in range ships[i].shipGraphics.tint = 0xff6b6b; // Red tint for attackable } else { ships[i].shipGraphics.tint = 0xe74c3c; // Default red for enemy } } } } else { // Reset all ship colors when no ship selected for (var i = 0; i < ships.length; i++) { if (ships[i].owner === 2) { ships[i].shipGraphics.tint = 0xe74c3c; // Default red for enemy } else if (ships[i].owner === 1 && ships[i] !== selectedShip) { ships[i].shipGraphics.tint = 0x27ae60; // Default green for player } } } }; // Difficulty selection UI function showDifficultySelection() { // Block all game actions until difficulty is selected gameState = "selectingDifficulty"; // Hide all action buttons for (var i = 0; i < actionButtons.length; i++) { actionButtons[i].visible = false; } // Hide power selection hidePowerSelection(); // Create a full-screen overlay container for difficulty selection if (typeof difficultyOverlay !== "undefined" && difficultyOverlay.parent) { difficultyOverlay.parent.removeChild(difficultyOverlay); } difficultyOverlay = new Container(); difficultyOverlay.x = 0; difficultyOverlay.y = 0; // Add a semi-transparent background to block game interaction var overlayBg = LK.getAsset('selectedTerritory', { anchorX: 0, anchorY: 0, scaleX: 2048 / 120, scaleY: 2732 / 120 }); overlayBg.alpha = 0.85; overlayBg.tint = 0x222222; difficultyOverlay.addChild(overlayBg); // Show difficulty selection text difficultyText = new Text2("Select Difficulty", { size: 60, fill: 0xffffff }); difficultyText.anchor.set(0.5, 0.5); difficultyText.x = 2048 / 2; difficultyText.y = 2732 / 2 - 200; difficultyOverlay.addChild(difficultyText); // Button positions var btnY = 2732 / 2; var btnSpacing = 220; var btnLabels = [{ label: "Easy", value: "easy" }, { label: "Medium", value: "medium" }, { label: "Hard", value: "hard" }, { label: "Hardcore", value: "hardcore" }]; for (var i = 0; i < btnLabels.length; i++) { var btn = new ActionButton(); btn.init(btnLabels[i].label, function (difficulty) { return function () { selectDifficulty(difficulty); }; }(btnLabels[i].value), 2048 / 2 + (i - 1.5) * btnSpacing, btnY); difficultyButtons.push(btn); difficultyOverlay.addChild(btn); } // Add overlay to game game.addChild(difficultyOverlay); } // Remove difficulty selection UI and start the game function selectDifficulty(difficulty) { selectedDifficulty = difficulty; // If hardcore, set war with all countries (2-6) and block peace if (selectedDifficulty === "hardcore") { for (var c = 2; c <= 6; c++) { warDeclarations[c] = true; } } // Remove difficulty UI overlay if (typeof difficultyOverlay !== "undefined" && difficultyOverlay.parent) { difficultyOverlay.parent.removeChild(difficultyOverlay); } difficultyButtons = []; // Show action buttons for (var i = 0; i < actionButtons.length; i++) { actionButtons[i].visible = true; } // Set game state to playing and update UI gameState = "playing"; updateInstructions(); } // Initialize the game createMap(); createUI(); showDifficultySelection(); updateInstructions();
/****
* Classes
****/
var ActionButton = Container.expand(function () {
var self = Container.call(this);
self.init = function (text, action, x, y) {
self.action = action;
// Button graphics
self.buttonGraphics = self.attachAsset('actionButton', {
anchorX: 0.5,
anchorY: 0.5
});
// Button text
self.buttonText = new Text2(text, {
size: 28,
fill: 0xFFFFFF
});
self.buttonText.anchor.set(0.5, 0.5);
self.addChild(self.buttonText);
self.x = x;
self.y = y;
return self;
};
self.down = function (x, y, obj) {
if (self.action) {
self.action();
}
};
return self;
});
var DiplomacyPanel = Container.expand(function () {
var self = Container.call(this);
self.init = function (targetCountry) {
self.targetCountry = targetCountry;
self.visible = false;
// Panel background
self.panelBg = LK.getAsset('diplomacypanel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 4
});
self.addChild(self.panelBg);
// Panel title
self.titleText = new Text2("Diplomacy with Country " + targetCountry, {
size: 32,
fill: 0x000000
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.y = -80;
self.addChild(self.titleText);
// Declare war button
self.warButton = new ActionButton();
self.warButton.init("Declare War", function () {
declareWar(targetCountry);
self.hide();
}, 0, 40);
// Show declare war button in easy mode
self.warButton.visible = true;
self.addChild(self.warButton);
// Peace treaty button
self.peaceButton = new ActionButton();
self.peaceButton.init("Peace Treaty", function () {
makePeace(targetCountry);
self.hide();
}, 0, 100);
self.addChild(self.peaceButton);
// Show/hide peace button depending on war state and difficulty
self.updateButtons = function () {
if (selectedDifficulty === "hardcore") {
self.peaceButton.visible = false;
} else if (warDeclarations[self.targetCountry]) {
self.peaceButton.visible = true;
} else {
self.peaceButton.visible = false;
}
};
self.updateButtons();
// Close button
self.closeButton = new ActionButton();
self.closeButton.init("Close", function () {
self.hide();
}, 0, 160);
self.addChild(self.closeButton);
// Position panel in center of screen
self.x = 2048 / 2;
self.y = 2732 / 2;
return self;
};
self.show = function () {
self.visible = true;
self.updateButtons && self.updateButtons();
game.addChild(self);
};
self.hide = function () {
self.visible = false;
if (self.parent) {
self.parent.removeChild(self);
}
};
return self;
});
var Ship = Container.expand(function () {
var self = Container.call(this);
self.init = function (owner, x, y) {
self.owner = owner;
self.hp = 3; // Ships have more health than armies
self.selected = false;
// Armies carried by ship (default 2 for player, 0 for AI, can be changed)
self.armies = owner === 1 ? 2 : 0;
// Ship graphics
self.shipGraphics = self.attachAsset('ship', {
anchorX: 0.5,
anchorY: 0.5
});
// Color based on owner
if (owner === 1) {
self.shipGraphics.tint = 0x27ae60; // Green for player
} else if (owner === 2) {
self.shipGraphics.tint = 0xe74c3c; // Red for enemy
} else if (owner === 3) {
self.shipGraphics.tint = 0x2a2f94; // Blue
} else if (owner === 4) {
self.shipGraphics.tint = 0x8e44ad; // Purple
} else if (owner === 5) {
self.shipGraphics.tint = 0xf39c12; // Orange
} else if (owner === 6) {
self.shipGraphics.tint = 0x00bcd4; // Cyan
}
// HP display
self.hpText = new Text2(self.hp.toString(), {
size: 48,
fill: 0xFFFFFF
});
self.hpText.anchor.set(0.5, 0.5);
self.hpText.x = 0;
self.hpText.y = -45;
self.addChild(self.hpText);
// Armies display (above ship)
self.armyText = new Text2(self.armies.toString(), {
size: 54,
fill: 0x000000
});
self.armyText.anchor.set(0.5, 0.5);
self.armyText.x = 0;
self.armyText.y = -80;
self.addChild(self.armyText);
self.x = x;
self.y = y;
return self;
};
self.takeDamage = function (damage) {
self.hp -= damage;
self.hpText.setText(self.hp.toString());
return self.hp <= 0;
};
self.down = function (x, y, obj) {
if (gameState === 'playing' && self.owner === 1) {
selectShip(self);
// Show possible moves for this ship (all sea territories) when clicked
// Remove all previous highlights first
for (var i = 0; i < territories.length; i++) {
if (territories[i].isSea) {
territories[i].showAsTarget = true;
territories[i].updateGraphics();
}
}
} else if (gameState === 'playing' && selectedShip && selectedShip.owner === 1 && self.owner === 2) {
// Check if ships are close enough for naval combat
var distance = Math.abs(selectedShip.x - self.x) + Math.abs(selectedShip.y - self.y);
if (distance < 200) {
// Initiate naval combat
navalCombat(selectedShip, self);
selectedShip.selected = false;
selectedShip.shipGraphics.tint = 0x27ae60; // Reset color
selectedShip = null;
endPlayerTurn();
}
}
};
return self;
});
// Game state variables
var Territory = Container.expand(function () {
var self = Container.call(this);
self.init = function (id, x, y, owner, isSea) {
self.id = id;
self.owner = owner; // 0 = neutral, 1 = player, 2 = enemy
self.isSea = isSea || false;
self.armies = owner === 0 || self.isSea ? 0 : Math.floor(Math.random() * 3) + 1;
self.selected = false;
self.lastSelected = false;
// Track if this territory was ever colonizable (for attack logic)
self.wasColonizable = !!self.isColonizable;
// Create territory graphics
self.updateGraphics();
// Position
self.x = x;
self.y = y;
// Army display (only for land territories)
if (!self.isSea) {
self.armyText = new Text2(self.armies.toString(), {
size: 24,
fill: 0x000000
});
self.armyText.anchor.set(0.5, 0.5);
self.armyText.x = 0;
self.armyText.y = 0;
self.addChild(self.armyText);
}
return self;
};
self.updateGraphics = function () {
// Remove existing graphics
if (self.graphics) {
self.removeChild(self.graphics);
}
var assetName = 'seaTerritory'; // Default to sea
if (self.isSea) {
assetName = 'seaTerritory';
} else if (self.selected) {
assetName = 'selectedTerritory';
} else if (self.showAsTarget) {
assetName = 'targetTerritory';
} else {
// Assign different country colors based on owner
if (self.owner === 1) {
assetName = 'country1Territory'; // Green for player
} else if (self.owner === 2) {
assetName = 'country2Territory'; // Red for enemy
} else if (self.owner === 3) {
assetName = 'country3Territory'; // Blue
} else if (self.owner === 4) {
assetName = 'country4Territory'; // Purple
} else if (self.owner === 5) {
assetName = 'country5Territory'; // Orange
} else if (self.owner === 6) {
assetName = 'country6Territory'; // Cyan
} else if (self.isColonizable) {
assetName = 'colonizableTerritory'; // Use dedicated gray asset for colonizable territories
} else {
assetName = 'seaTerritory'; // Unassigned territories become sea
}
}
self.graphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
};
self.setOwner = function (newOwner, armies) {
self.owner = newOwner;
if (!self.isSea) {
self.armies = armies || 1;
self.armyText.setText(self.armies.toString());
}
self.updateGraphics();
};
self.addArmies = function (count) {
if (!self.isSea) {
self.armies += count;
self.armyText.setText(self.armies.toString());
// Ensure army text is visible and on top after army change
self.removeChild(self.armyText);
self.addChild(self.armyText);
}
};
self.down = function (x, y, obj) {
if (gameState === 'playing') {
// Handle ship movement to sea territories
if (selectedShip && self.isSea) {
// Allow movement to any sea territory
if (self.isSea) {
// Move ship to any sea territory
selectedShip.x = self.x;
selectedShip.y = self.y;
selectedShip.selected = false;
selectedShip.shipGraphics.tint = 0x27ae60; // Reset color
// Remove all sea highlights after move
for (var i = 0; i < territories.length; i++) {
if (territories[i].isSea && territories[i].showAsTarget) {
territories[i].showAsTarget = false;
territories[i].updateGraphics();
}
}
selectedShip = null;
endPlayerTurn();
return;
}
}
// Handle ship colonization of distant territories
if (selectedShip && self.isColonizable && self.owner === 0 && !self.isSea) {
// Check if ship is close enough to colonize (must be adjacent or very close)
var distance = Math.abs(selectedShip.x - self.x) + Math.abs(selectedShip.y - self.y);
if (distance <= territorySpacing * 1.5) {
// Colonize the territory
self.setOwner(selectedShip.owner, selectedShip.armies && selectedShip.armies > 0 ? selectedShip.armies : 2); // Use ship's armies if present, else 2
self.isColonizable = false; // No longer colonizable
self.wasColonizable = true; // Mark as previously colonizable for attack logic
// Ensure army text is visible and on top after colonization
if (self.armyText) {
self.armyText.setText(self.armies.toString());
self.removeChild(self.armyText);
self.addChild(self.armyText);
}
if (selectedShip.owner === 1) {
// Player gets money reward for colonization
playerMoney += self.colonizationReward;
if (playerMoneyText) {
playerMoneyText.setText("Money: " + playerMoney);
}
if (instructionText) {
instructionText.setText("Island colonized! Gained $" + self.colonizationReward);
}
}
LK.getSound('capture').play();
selectedShip.selected = false;
selectedShip.shipGraphics.tint = 0x27ae60; // Reset color
// Remove all armies from ship after landing
selectedShip.armies = 0;
if (selectedShip.armyText) {
selectedShip.armyText.setText("0");
}
selectedShip = null;
updateTerritoryCount();
endPlayerTurn();
return;
} else {
if (instructionText && selectedShip.owner === 1) {
instructionText.setText("Ship must be closer to colonize this island");
}
}
}
// Amphibious assault: allow attacking enemy territory from ship if at war and adjacent
if (selectedShip && !self.isSea && self.owner > 1 && warDeclarations[self.owner]) {
var distance = Math.abs(selectedShip.x - self.x) + Math.abs(selectedShip.y - self.y);
if (distance <= territorySpacing * 1.5 && selectedShip.armies && selectedShip.armies > 0) {
// Simple combat: if ship's armies > defender, take over, else reduce both
var attackPower = selectedShip.armies;
var defensePower = self.armies;
if (attackPower > defensePower) {
self.setOwner(selectedShip.owner, attackPower - defensePower);
selectedShip.armies = 0;
if (selectedShip.armyText) selectedShip.armyText.setText("0");
if (instructionText && selectedShip.owner === 1) {
instructionText.setText("Amphibious assault successful!");
}
LK.getSound('capture').play();
} else {
selectedShip.armies = 0;
if (selectedShip.armyText) selectedShip.armyText.setText("0");
if (defensePower > attackPower) {
self.armies = defensePower - attackPower;
if (self.armyText) self.armyText.setText(self.armies.toString());
}
if (instructionText && selectedShip.owner === 1) {
instructionText.setText("Amphibious assault failed!");
}
LK.getSound('attack').play();
}
selectedShip.selected = false;
selectedShip.shipGraphics.tint = 0x27ae60;
selectedShip = null;
updateTerritoryCount();
endPlayerTurn();
return;
} else if (distance <= territorySpacing * 1.5 && (!selectedShip.armies || selectedShip.armies === 0)) {
if (instructionText && selectedShip.owner === 1) {
instructionText.setText("Ship has no armies to land!");
}
return;
}
}
// Allow colonization of colonizable territory with armies (if adjacent and enough armies)
if (!self.isSea && self.isColonizable && self.owner === 0 && selectedTerritory && selectedTerritory.owner === 1 && !selectedTerritory.isSea) {
// Must be adjacent
var neighbors = getNeighbors(self);
var isNeighbor = false;
for (var i = 0; i < neighbors.length; i++) {
if (neighbors[i] === selectedTerritory) {
isNeighbor = true;
break;
}
}
if (isNeighbor && selectedTerritory.armies > 1) {
// Colonize with armies: move 2 armies, leave at least 1 behind
self.setOwner(1, 2);
self.isColonizable = false;
self.wasColonizable = true; // Mark as previously colonizable for attack logic
// Ensure army text is visible and on top after colonization
if (self.armyText) {
self.armyText.setText(self.armies.toString());
self.removeChild(self.armyText);
self.addChild(self.armyText);
}
selectedTerritory.armies -= 2;
selectedTerritory.armyText.setText(selectedTerritory.armies.toString());
playerMoney += self.colonizationReward;
if (playerMoneyText) {
playerMoneyText.setText("Money: " + playerMoney);
}
if (instructionText) {
instructionText.setText("Island colonized with armies! Gained $" + self.colonizationReward);
}
LK.getSound('capture').play();
updateTerritoryCount();
endPlayerTurn();
return;
} else if (isNeighbor && selectedTerritory.armies <= 1) {
if (instructionText) {
instructionText.setText("Need at least 2 armies to colonize with armies!");
}
return;
}
}
// Allow loading armies from player's territory onto ship if adjacent
if (selectedShip && self.owner === 1 && !self.isSea && self.armies > 1) {
var distance = Math.abs(selectedShip.x - self.x) + Math.abs(selectedShip.y - self.y);
if (distance <= territorySpacing * 1.5) {
// Move up to all but 1 army from territory to ship (max 5 on ship)
var canLoad = Math.min(self.armies - 1, 5 - selectedShip.armies);
if (canLoad > 0) {
self.armies -= canLoad;
selectedShip.armies += canLoad;
if (self.armyText) self.armyText.setText(self.armies.toString());
if (selectedShip.armyText) selectedShip.armyText.setText(selectedShip.armies.toString());
if (instructionText) instructionText.setText("Loaded " + canLoad + " armies onto ship.");
return;
} else {
if (instructionText) instructionText.setText("Ship is full or not enough armies to load.");
return;
}
}
}
selectTerritory(self);
} else if (gameState === 'selectingTarget' && self.showAsTarget) {
executeAttack(self);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
// Difficulty selection
var selectedDifficulty = null; // "easy", "medium", "hard"
var difficultyButtons = [];
var difficultyText = null;
// Game state variables
// Territory and game assets
var gameState = 'playing'; // 'playing', 'gameOver', 'victory', 'selectingTarget'
var attackTargets = []; // Available targets for attack
var currentTurn = 1; // 1 = player, 2 = enemy
var selectedTerritory = null;
var territories = [];
var playerTerritories = 0;
var enemyTerritories = 0;
var totalTerritories = 0;
var playerMoney = 100; // Starting money
var aiMoney = 100; // Starting AI money
var incomePerTerritory = 10; // Money generated per territory per turn
// Diplomacy variables
var warDeclarations = {}; // Track which countries we're at war with
var peaceOfferCooldowns = {}; // Track cooldowns for peace offers after rejection
var diplomacyPanel = null;
// Ship variables
var ships = [];
var selectedShip = null;
// Power selection variables
var selectedAttackPower = 1;
var maxAttackPower = 1;
var powerSelectionMode = false;
// UI elements
var turnText, scoreText, instructionText, playerArmyText, playerMoneyText;
var powerText, powerDownButton, powerUpButton;
var actionButtons = [];
// Game settings
var mapWidth = 8;
var mapHeight = 12;
var territorySpacing = 140;
var startX = 2048 / 2 - mapWidth * territorySpacing / 2 + territorySpacing / 2;
var startY = 300;
// Create the game map
function createMap() {
var id = 0;
// We'll store adjacency for sea territories here
var seaAdjacency = {};
// Create contiguous regions for each country with sea territories
// Divide the map into regions for 6 countries
for (var row = 0; row < mapHeight; row++) {
for (var col = 0; col < mapWidth; col++) {
var x = startX + col * territorySpacing;
var y = startY + row * territorySpacing;
var isSea = false;
var owner = 0; // default to neutral/sea
// Create sea lanes (vertical strips)
// Connect the two sea lanes at rows 5 and 6 (expanded connection)
if (col === 2 || col === 5 || (row === 5 || row === 6) && (col === 3 || col === 4)) {
isSea = true;
owner = 0; // Neutral sea
} else {
// Determine owner based on map regions to create contiguous countries
if (row < mapHeight / 3) {
// Top third - countries 1 and 2
if (col < mapWidth / 2) {
owner = 1; // Country 1 (Green) - top left
} else {
owner = 2; // Country 2 (Red) - top right
}
} else if (row < mapHeight * 2 / 3) {
// Middle third - countries 3 and 4
if (col < mapWidth / 2) {
owner = 3; // Country 3 (Blue) - middle left
} else {
owner = 4; // Country 4 (Purple) - middle right
}
} else {
// Bottom third - countries 5 and 6
if (col < mapWidth / 2) {
owner = 5; // Country 5 (Orange) - bottom left
} else {
owner = 6; // Country 6 (Cyan) - bottom right
}
}
// If no specific owner assigned, make it sea
if (owner === 0 && !isSea) {
isSea = true;
}
}
// --- Convert border sea to land ---
// If this tile is at the border and would be sea, convert to land and assign to nearest country
if ((row === 0 || row === mapHeight - 1 || col === 0 || col === mapWidth - 1) && isSea) {
isSea = false;
// Assign to nearest country by region logic
if (row < mapHeight / 3) {
owner = col < mapWidth / 2 ? 1 : 2;
} else if (row < mapHeight * 2 / 3) {
owner = col < mapWidth / 2 ? 3 : 4;
} else {
owner = col < mapWidth / 2 ? 5 : 6;
}
}
var territory = new Territory();
territory.init(id, x, y, owner, isSea);
territories.push(territory);
game.addChild(territory);
id++;
}
}
// Build adjacency for sea territories (by index)
for (var i = 0; i < territories.length; i++) {
if (territories[i].isSea) {
var neighbors = getNeighbors(territories[i]);
seaAdjacency[i] = [];
for (var j = 0; j < neighbors.length; j++) {
if (neighbors[j].isSea) {
var neighborIndex = territories.indexOf(neighbors[j]);
if (neighborIndex !== -1) {
seaAdjacency[i].push(neighborIndex);
}
}
}
}
}
// Attach adjacency info to each sea territory for easy access
for (var i = 0; i < territories.length; i++) {
if (territories[i].isSea) {
territories[i].adjacentSeaIndices = seaAdjacency[i];
}
}
// (Colonizable islands removed)
// Create initial ships for player and enemy
createShips();
updateTerritoryCount();
}
// Create initial ships
function createShips() {
// Find sea territories for ship placement
var seaTerritories = [];
for (var i = 0; i < territories.length; i++) {
if (territories[i].isSea) {
seaTerritories.push(territories[i]);
}
}
// Place initial ships
if (seaTerritories.length > 0) {
// Player ship - automatically select it to start on the ship
var playerShip = new Ship();
var playerSeaPos = seaTerritories[Math.floor(Math.random() * seaTerritories.length)];
playerShip.init(1, playerSeaPos.x, playerSeaPos.y);
playerShip.armies = 2;
if (playerShip.armyText) playerShip.armyText.setText("2");
ships.push(playerShip);
// Auto-select the player ship so they start on it
selectShip(playerShip);
// Enemy ship
var enemyShip = new Ship();
var enemySeaPos = seaTerritories[Math.floor(Math.random() * seaTerritories.length)];
enemyShip.init(2, enemySeaPos.x, enemySeaPos.y);
enemyShip.armies = 0;
if (enemyShip.armyText) enemyShip.armyText.setText("0");
ships.push(enemyShip);
// Ensure ships are always rendered above sea territories by adding them after all territories are added
game.addChild(playerShip);
game.addChild(enemyShip);
}
}
// Ship selection
function selectShip(ship) {
if (selectedDifficulty === null) return;
if (currentTurn !== 1) return;
// Deselect previous selections
if (selectedTerritory) {
selectedTerritory.selected = false;
selectedTerritory.updateGraphics();
selectedTerritory = null;
}
if (selectedShip) {
selectedShip.selected = false;
selectedShip.shipGraphics.tint = 0x27ae60; // Reset to green
}
// Select new ship
selectedShip = ship;
ship.selected = true;
ship.shipGraphics.tint = 0xf1c40f; // Yellow when selected
// Update armyText in case it was changed
if (ship.armyText) {
ship.armyText.setText(ship.armies.toString());
}
// Remove all possible move highlights when selecting a ship, only show on click
for (var i = 0; i < territories.length; i++) {
if (territories[i].isSea) {
territories[i].showAsTarget = false;
territories[i].updateGraphics();
}
}
// Do not show possible moves here; will be shown on ship click (down event)
hidePowerSelection();
updateInstructions();
}
// Generate income based on territories owned
function generateIncome() {
var income = playerTerritories * incomePerTerritory;
playerMoney += income;
if (playerMoneyText) {
playerMoneyText.setText("Money: " + playerMoney + " (+$" + income + ")");
}
}
// Update territory ownership counts
function updateTerritoryCount() {
playerTerritories = 0;
enemyTerritories = 0;
var playerTotalArmies = 0;
var country1Count = 0,
country2Count = 0,
country3Count = 0;
var country4Count = 0,
country5Count = 0,
country6Count = 0;
totalTerritories = territories.length;
for (var i = 0; i < territories.length; i++) {
if (territories[i].owner === 1) {
playerTerritories++;
country1Count++;
playerTotalArmies += territories[i].armies;
} else if (territories[i].owner === 2) {
enemyTerritories++;
country2Count++;
} else if (territories[i].owner === 3) {
country3Count++;
} else if (territories[i].owner === 4) {
country4Count++;
} else if (territories[i].owner === 5) {
country5Count++;
} else if (territories[i].owner === 6) {
country6Count++;
}
}
// (Removed scoreText update for country colors and territory counts)
// Update player army display
if (playerArmyText) {
playerArmyText.setText("Total Armies: " + playerTotalArmies);
}
// Update money display
if (playerMoneyText) {
playerMoneyText.setText("Money: " + playerMoney);
}
// Check victory conditions
// Count total non-sea territories
var totalNonSeaTerritories = 0;
for (var i = 0; i < territories.length; i++) {
if (!territories[i].isSea) {
totalNonSeaTerritories++;
}
}
if (playerTerritories === totalNonSeaTerritories) {
gameState = 'victory';
LK.showYouWin();
} else if (enemyTerritories >= Math.floor(totalTerritories * 0.75)) {
gameState = 'gameOver';
LK.showGameOver();
} else if (playerTerritories === 0) {
gameState = 'gameOver';
LK.showGameOver();
}
}
// Declare war function
function declareWar(countryId) {
warDeclarations[countryId] = true;
if (instructionText) {
instructionText.setText("War declared on Country " + countryId + "! You can now attack their territories.");
}
// If diplomacyPanel is open, update buttons
if (diplomacyPanel && diplomacyPanel.targetCountry === countryId) {
diplomacyPanel.updateButtons();
}
}
// Make peace function
function makePeace(countryId) {
if (selectedDifficulty === "hardcore") {
if (instructionText) {
instructionText.setText("Peace treaties are disabled in Hardcore mode!");
}
return;
}
// Prevent peace offer if cooldown is active
if (peaceOfferCooldowns[countryId] && peaceOfferCooldowns[countryId] > 0) {
if (instructionText) {
instructionText.setText("You must wait " + peaceOfferCooldowns[countryId] + " turns before offering peace to Country " + countryId + " again.");
}
return;
}
if (warDeclarations[countryId]) {
// In easy mode, always accept peace treaty
if (selectedDifficulty === "easy" || Math.random() < 0.5) {
warDeclarations[countryId] = false;
if (instructionText) {
instructionText.setText("Peace treaty signed with Country " + countryId + ". You can no longer attack their territories.");
}
// If diplomacyPanel is open, update buttons
if (diplomacyPanel && diplomacyPanel.targetCountry === countryId) {
diplomacyPanel.updateButtons();
}
if (peaceOfferCooldowns[countryId]) peaceOfferCooldowns[countryId] = 0; // Reset cooldown on acceptance
} else {
if (instructionText) {
instructionText.setText("Peace treaty rejected by Country " + countryId + "!");
}
// Set cooldown for 10 turns after rejection
peaceOfferCooldowns[countryId] = 10;
}
}
}
// Territory selection
function selectTerritory(territory) {
if (selectedDifficulty === null) return;
if (currentTurn !== 1) return; // Only during player turn
// If we're in target selection mode, cancel it
if (gameState === 'selectingTarget') {
// Clear target highlighting
for (var i = 0; i < attackTargets.length; i++) {
attackTargets[i].showAsTarget = false;
attackTargets[i].updateGraphics();
}
gameState = 'playing';
attackTargets = [];
}
// Deselect previous territory
if (selectedTerritory) {
selectedTerritory.selected = false;
selectedTerritory.updateGraphics();
// Ensure previous territory's army text remains visible
selectedTerritory.armyText.setText(selectedTerritory.armies.toString());
// Re-add army text to ensure it's visible
selectedTerritory.removeChild(selectedTerritory.armyText);
selectedTerritory.addChild(selectedTerritory.armyText);
}
// Handle enemy territory clicks - show diplomacy panel
if (territory.owner !== 1 && territory.owner !== 0) {
// Create diplomacy panel if it doesn't exist
if (!diplomacyPanel) {
diplomacyPanel = new DiplomacyPanel();
diplomacyPanel.init(territory.owner);
} else {
// Update existing panel for new country
diplomacyPanel.targetCountry = territory.owner;
diplomacyPanel.titleText.setText("Diplomacy with Country " + territory.owner);
if (diplomacyPanel.updateButtons) diplomacyPanel.updateButtons();
}
diplomacyPanel.show();
return;
}
// Select new territory
if (territory.owner === 1) {
// Only select player territories
selectedTerritory = territory;
territory.selected = true;
territory.updateGraphics();
// Ensure army text is visible and updated
territory.armyText.setText(territory.armies.toString());
// Bring army text to front to ensure it's visible
territory.removeChild(territory.armyText);
territory.addChild(territory.armyText);
// Show power selection for territories with armies > 1
if (!territory.isSea && territory.armies > 1) {
showPowerSelection(territory.armies - 1);
} else {
hidePowerSelection();
}
updateInstructions();
} else {
hidePowerSelection();
}
}
// Get neighboring territories
function getNeighbors(territory) {
var neighbors = [];
var index = territories.indexOf(territory);
var row = Math.floor(index / mapWidth);
var col = index % mapWidth;
// Check all 4 directions
var directions = [{
row: -1,
col: 0
},
// up
{
row: 1,
col: 0
},
// down
{
row: 0,
col: -1
},
// left
{
row: 0,
col: 1
} // right
];
for (var i = 0; i < directions.length; i++) {
var newRow = row + directions[i].row;
var newCol = col + directions[i].col;
if (newRow >= 0 && newRow < mapHeight && newCol >= 0 && newCol < mapWidth) {
var neighborIndex = newRow * mapWidth + newCol;
neighbors.push(territories[neighborIndex]);
}
}
return neighbors;
}
// Attack action
function attackTerritory() {
if (selectedDifficulty === null) return;
if (!selectedTerritory || selectedTerritory.armies <= 1) return;
var neighbors = getNeighbors(selectedTerritory);
var targets = [];
for (var i = 0; i < neighbors.length; i++) {
if (neighbors[i].owner !== 1) {
// Allow attacking if:
// - Neutral (owner 0)
// - At war with the country
// - The territory was previously colonizable and is now enemy-owned (owner 2-6)
// - The territory was a neutral/colonizable territory, is now enemy-owned, and we are at war with that enemy
var n = neighbors[i];
var canAttack = false;
if (n.owner === 0) {
canAttack = true;
} else if (warDeclarations[n.owner]) {
canAttack = true;
} else if (n.owner > 1 && n.owner <= 6 && n.isColonizable === true) {
canAttack = true;
} else if (n.owner > 1 && n.owner <= 6 && typeof n.wasColonizable !== "undefined" && n.wasColonizable === true && warDeclarations[n.owner]) {
// If this territory was previously colonizable, is now enemy-owned, and we are at war with that enemy
canAttack = true;
}
if (canAttack) {
targets.push(n);
}
}
}
if (targets.length > 0) {
// Show target selection mode
gameState = 'selectingTarget';
attackTargets = targets;
// Highlight all possible targets
for (var i = 0; i < targets.length; i++) {
targets[i].showAsTarget = true;
targets[i].updateGraphics();
}
if (instructionText) {
instructionText.setText("Select a territory to attack");
}
}
}
// Execute attack on selected target
function executeAttack(target) {
if (!selectedTerritory || !target) return;
// Clear target highlighting
for (var i = 0; i < attackTargets.length; i++) {
attackTargets[i].showAsTarget = false;
attackTargets[i].updateGraphics();
}
// Simple combat resolution using selected attack power
var attackPower = selectedAttackPower;
var defensePower = target.armies;
if (attackPower > defensePower) {
// Victory
target.setOwner(1, attackPower - defensePower);
selectedTerritory.armies = selectedTerritory.armies - attackPower;
selectedTerritory.armyText.setText(selectedTerritory.armies.toString());
LK.getSound('capture').play();
} else {
// Defeat - lose the armies used in attack
selectedTerritory.armies = selectedTerritory.armies - attackPower;
selectedTerritory.armyText.setText(selectedTerritory.armies.toString());
if (defensePower > attackPower) {
target.armies = defensePower - attackPower;
target.armyText.setText(target.armies.toString());
}
}
LK.getSound('attack').play();
updateTerritoryCount();
// Reset game state
gameState = 'playing';
attackTargets = [];
endPlayerTurn();
}
// Recruit armies action
function recruitArmies() {
if (selectedDifficulty === null) return;
if (!selectedTerritory) return;
var recruitCost = 100; // Increased cost to recruit armies
if (playerMoney >= recruitCost) {
playerMoney -= recruitCost;
selectedTerritory.addArmies(2);
if (playerMoneyText) {
playerMoneyText.setText("Money: " + playerMoney);
}
endPlayerTurn();
} else {
// Not enough money - show feedback but don't end turn
if (instructionText) {
instructionText.setText("Not enough money! Need $" + recruitCost + " to recruit");
}
}
}
// Build ship action
function buildShip() {
if (selectedDifficulty === null) return;
if (!selectedTerritory || selectedTerritory.isSea) return;
var shipCost = 200; //{4Z} // Increased cost
// Determine which country's money to use
var owner = selectedTerritory.owner;
if (owner === 0 || owner === undefined) return; // Only countries can build ships
// Only allow if the country has enough money
var canBuild = false;
if (owner === 1 && playerMoney >= shipCost) {
canBuild = true;
} else if (owner === 2 && aiMoney >= shipCost) {
canBuild = true;
} else if (owner > 2) {
// For AI countries 3-6, give them their own money pool if not present
if (typeof window['countryMoney' + owner] === "undefined") {
window['countryMoney' + owner] = 100;
}
if (window['countryMoney' + owner] >= shipCost) {
canBuild = true;
}
}
if (canBuild) {
// Find adjacent sea territory
var neighbors = getNeighbors(selectedTerritory);
var seaNeighbors = [];
for (var i = 0; i < neighbors.length; i++) {
if (neighbors[i].isSea) {
seaNeighbors.push(neighbors[i]);
}
}
if (seaNeighbors.length > 0) {
// Deduct money from the correct pool
if (owner === 1) {
playerMoney -= shipCost;
} else if (owner === 2) {
aiMoney -= shipCost;
} else if (owner > 2) {
window['countryMoney' + owner] -= shipCost;
}
var seaPos = seaNeighbors[0];
var newShip = new Ship();
newShip.init(owner, seaPos.x, seaPos.y);
ships.push(newShip);
// Ensure new ships are rendered above sea territories
game.addChild(newShip);
if (owner === 1 && playerMoneyText) {
playerMoneyText.setText("Money: " + playerMoney);
}
endPlayerTurn();
} else {
if (instructionText && owner === 1) {
instructionText.setText("No adjacent sea territory to build ship!");
}
}
} else {
if (instructionText && owner === 1) {
instructionText.setText("Not enough money! Need $" + shipCost + " to build ship");
}
}
}
// Naval combat
function navalCombat(attackerShip, defenderShip) {
var damage = 1;
var defenderDestroyed = defenderShip.takeDamage(damage);
if (defenderDestroyed) {
// Remove destroyed ship
var index = ships.indexOf(defenderShip);
if (index > -1) {
ships.splice(index, 1);
}
defenderShip.destroy();
LK.getSound('capture').play();
} else {
LK.getSound('attack').play();
}
}
// Per-country ship build timers for AI countries 2-6
// All countries (1-6) can build ships, recruit armies, declare war, and colonize
var countryShipTimers = {};
// Per-country war declaration timers for AI countries 2-6 (enemy and other AIs)
var countryWarTimers = {};
for (var c = 2; c <= 6; c++) {
// For war timers: if not at war, 12 turns; if at war, 30 turns (will be set dynamically in aiTurn)
countryWarTimers[c] = Math.floor(Math.random() * 3) + 10; // randomize initial timer between 10-12
}
for (var c = 2; c <= 6; c++) {
// All AI countries 2-6: build ships every 3-5 turns by default
countryShipTimers[c] = Math.floor(Math.random() * 3) + 3;
}
// End player turn
function endPlayerTurn() {
if (selectedTerritory) {
selectedTerritory.selected = false;
selectedTerritory.updateGraphics();
selectedTerritory = null;
hidePowerSelection();
}
hidePowerSelection();
// Generate income based on territories owned
generateIncome();
// Decrease peace offer cooldowns at end of player turn
for (var k in peaceOfferCooldowns) {
if (peaceOfferCooldowns.hasOwnProperty(k) && peaceOfferCooldowns[k] > 0) {
peaceOfferCooldowns[k]--;
}
}
currentTurn = 2;
updateInstructions();
// AI turn after short delay
LK.setTimeout(function () {
aiTurn();
}, 1000);
}
// Helper: AI build ship for a country if possible
function aiBuildShipForCountry(countryId) {
// Find all territories owned by this country
var owned = [];
for (var i = 0; i < territories.length; i++) {
if (territories[i].owner === countryId && !territories[i].isSea) {
owned.push(territories[i]);
}
}
// Try to build ship from a random owned territory with adjacent sea
if (owned.length > 0) {
var t = owned[Math.floor(Math.random() * owned.length)];
var neighbors = getNeighbors(t);
var seaNeighbors = [];
for (var j = 0; j < neighbors.length; j++) {
if (neighbors[j].isSea) seaNeighbors.push(neighbors[j]);
}
if (seaNeighbors.length > 0) {
// Deduct money if needed (handled in buildShip, but we do it here for AI)
if (typeof window['countryMoney' + countryId] === "undefined") {
window['countryMoney' + countryId] = 100;
}
var shipCost = 200;
if (window['countryMoney' + countryId] >= shipCost) {
window['countryMoney' + countryId] -= shipCost;
var seaPos = seaNeighbors[0];
var newShip = new Ship();
newShip.init(countryId, seaPos.x, seaPos.y);
ships.push(newShip);
game.addChild(newShip);
return true;
}
}
}
return false;
}
// Simple AI turn
function aiTurn() {
// Generate AI income
var aiIncome = enemyTerritories * incomePerTerritory;
aiMoney += aiIncome;
var enemyTerrs = [];
for (var i = 0; i < territories.length; i++) {
if (territories[i].owner === 2) {
enemyTerrs.push(territories[i]);
}
}
if (enemyTerrs.length > 0) {
var aiTerritory = enemyTerrs[Math.floor(Math.random() * enemyTerrs.length)];
var neighbors = getNeighbors(aiTerritory);
var playerTargets = [];
// In easy mode, AI never attacks
if (selectedDifficulty === "easy") {
// AI does not attack, just does economy/ship/army actions below
playerTargets = [];
} else {
for (var j = 0; j < neighbors.length; j++) {
// AI can attack player territories if war is declared on AI (country 2)
if (neighbors[j].owner === 1 && warDeclarations[2]) {
playerTargets.push(neighbors[j]);
}
}
}
if (playerTargets.length > 0 && aiTerritory.armies > 1) {
// AI attacks
var target = playerTargets[Math.floor(Math.random() * playerTargets.length)];
var attackPower = aiTerritory.armies - 1;
var defensePower = target.armies;
if (attackPower > defensePower) {
target.setOwner(2, attackPower - defensePower);
aiTerritory.armies = 1;
aiTerritory.armyText.setText(aiTerritory.armies.toString());
} else {
aiTerritory.armies = 1;
aiTerritory.armyText.setText(aiTerritory.armies.toString());
if (defensePower > attackPower) {
target.armies = defensePower - attackPower;
target.armyText.setText(target.armies.toString());
}
}
} else {
// AI decides what to do based on money and strategy
var action = Math.random();
var recruitCost = 50;
var shipCost = 100;
if (action < 0.4 && aiMoney >= recruitCost) {
// 40% chance to recruit armies if affordable
aiMoney -= recruitCost;
aiTerritory.addArmies(2);
} else if (action < 0.7 && aiMoney >= shipCost) {
// 30% chance to build ship if possible and affordable
var seaNeighbors = [];
for (var k = 0; k < neighbors.length; k++) {
if (neighbors[k].isSea) {
seaNeighbors.push(neighbors[k]);
}
}
if (seaNeighbors.length > 0) {
// Build ship in adjacent sea
aiMoney -= shipCost;
var seaPos = seaNeighbors[0];
var newShip = new Ship();
newShip.init(2, seaPos.x, seaPos.y);
ships.push(newShip);
// Ensure AI ships are rendered above sea territories
game.addChild(newShip);
} else {
// No sea nearby, recruit if affordable or just add basic army
if (aiMoney >= recruitCost) {
aiMoney -= recruitCost;
aiTerritory.addArmies(2);
} else {
aiTerritory.addArmies(1);
}
}
} else {
// Default action - add basic army (free)
aiTerritory.addArmies(1);
}
}
}
// AI war declaration logic for hard difficulty
if (selectedDifficulty === "hard") {
// --- Special: Country 6 always declares war on country 5 every 5 turns ---
if (typeof window.country6War5Timer === "undefined") {
window.country6War5Timer = 5;
}
window.country6War5Timer--;
if (window.country6War5Timer <= 0) {
if (!warDeclarations[5]) {
warDeclarations[5] = true;
if (instructionText) {
instructionText.setText("Country 6 has declared war on Country 5!");
}
}
window.country6War5Timer = 5;
}
// --- New: AI countries declare war on weaker neighbors if stronger ---
for (var c = 2; c <= 6; c++) {
// Only consider if not already at war with all other countries
for (var i = 0; i < territories.length; i++) {
if (territories[i].owner === c && !territories[i].isSea) {
var neighbors = getNeighbors(territories[i]);
for (var j = 0; j < neighbors.length; j++) {
var neighbor = neighbors[j];
// Only consider land neighbors owned by another country (not self, not neutral, not sea)
if (neighbor.owner !== c && neighbor.owner > 0 && neighbor.owner <= 6 && !neighbor.isSea && !warDeclarations[neighbor.owner]) {
// If AI's territory has more armies than neighbor, declare war
if (territories[i].armies > neighbor.armies) {
warDeclarations[neighbor.owner] = true;
if (neighbor.owner === 1 && instructionText) {
instructionText.setText("Country " + c + " has declared war on you due to your weak border!");
}
}
}
}
}
}
}
// --- AI peace offer logic (not in hardcore) ---
if (selectedDifficulty !== "hardcore") {
for (var c = 2; c <= 6; c++) {
// If AI country is at war with player, has lost territories, and random chance, offer peace
if (warDeclarations[c]) {
// Count AI's territories
var aiTerrCount = 0;
for (var i = 0; i < territories.length; i++) {
if (territories[i].owner === c && !territories[i].isSea) {
aiTerrCount++;
}
}
// If AI is weak (few territories) or random chance, offer peace
if (aiTerrCount < 3 || Math.random() < 0.15) {
// 50% chance player accepts, always accept in easy mode
if (selectedDifficulty === "easy" || Math.random() < 0.5) {
warDeclarations[c] = false;
if (instructionText) {
instructionText.setText("Country " + c + " has offered a peace treaty. Peace has been established!");
}
if (diplomacyPanel && diplomacyPanel.targetCountry === c) {
diplomacyPanel.updateButtons();
}
} else {
if (instructionText) {
instructionText.setText("Country " + c + " has offered a peace treaty, but you rejected it!");
}
}
}
}
}
}
// AI countries 2-6 may declare war more frequently
for (var c = 2; c <= 6; c++) {
// Only consider declaring war on countries we are not already at war with
if (!warDeclarations[c]) {
countryWarTimers[c]--;
if (countryWarTimers[c] <= 0) {
// Declare war on a random other country (not self)
var possibleTargets = [];
for (var t = 1; t <= 6; t++) {
if (t !== c && !warDeclarations[t]) {
possibleTargets.push(t);
}
}
if (possibleTargets.length > 0) {
var target = possibleTargets[Math.floor(Math.random() * possibleTargets.length)];
warDeclarations[target] = true;
// Optionally, show a message if the player is the target
if (target === 1 && instructionText) {
instructionText.setText("Country " + c + " has declared war on you!");
}
}
// Reset timer for next declaration (12 turns if not at war, 30 if at war)
if (warDeclarations[c]) {
countryWarTimers[c] = 30;
} else {
countryWarTimers[c] = 12;
}
}
} else {
// If already at war, use longer timer before next declaration
countryWarTimers[c]--;
if (countryWarTimers[c] <= 0) {
// Try to declare war on another country (not self, not already at war)
var possibleTargets = [];
for (var t = 1; t <= 6; t++) {
if (t !== c && !warDeclarations[t]) {
possibleTargets.push(t);
}
}
if (possibleTargets.length > 0) {
var target = possibleTargets[Math.floor(Math.random() * possibleTargets.length)];
warDeclarations[target] = true;
if (target === 1 && instructionText) {
instructionText.setText("Country " + c + " has declared war on you!");
}
}
// Reset timer for next declaration (30 turns if at war)
countryWarTimers[c] = 30;
}
}
}
}
// In easy mode, AI never declares war (handled by not attacking above)
// AI countries 2-6: build ships every 3-5 turns if possible
for (var c = 2; c <= 6; c++) {
if (typeof countryShipTimers[c] === "undefined") {
countryShipTimers[c] = Math.floor(Math.random() * 3) + 3;
}
countryShipTimers[c]--;
if (countryShipTimers[c] <= 0) {
var built = aiBuildShipForCountry(c);
countryShipTimers[c] = Math.floor(Math.random() * 3) + 3;
}
}
// All AI countries 2-6: recruit armies every turn if possible
for (var c = 2; c <= 6; c++) {
for (var i = 0; i < territories.length; i++) {
if (territories[i].owner === c && !territories[i].isSea) {
if (typeof window['countryMoney' + c] === "undefined") {
window['countryMoney' + c] = 100;
}
var recruitCost = 50;
if (window['countryMoney' + c] >= recruitCost) {
window['countryMoney' + c] -= recruitCost;
territories[i].addArmies(2);
}
}
}
}
// AI ship movement and naval combat
// Loop for all AI countries (2-6) to give each their own ship logic
for (var aiCountry = 2; aiCountry <= 6; aiCountry++) {
var aiShips = [];
for (var i = 0; i < ships.length; i++) {
if (ships[i].owner === aiCountry) {
aiShips.push(ships[i]);
}
}
if (aiShips.length > 0) {
var aiShip = aiShips[Math.floor(Math.random() * aiShips.length)];
// Look for enemy ships to attack (player or any other country at war)
var enemyShips = [];
for (var i = 0; i < ships.length; i++) {
if (ships[i].owner !== aiCountry && ships[i].owner !== 0) {
// Only attack if at war or if player (for country 2)
if (aiCountry === 2) {
if (ships[i].owner === 1 && warDeclarations[2]) {
var distance = Math.abs(ships[i].x - aiShip.x) + Math.abs(ships[i].y - aiShip.y);
if (distance < 200) {
enemyShips.push(ships[i]);
}
}
} else {
// For AI countries 3-6, attack ships of any country at war
if (warDeclarations[aiCountry] || warDeclarations[ships[i].owner]) {
var distance = Math.abs(ships[i].x - aiShip.x) + Math.abs(ships[i].y - aiShip.y);
if (distance < 200) {
enemyShips.push(ships[i]);
}
}
}
}
}
if (enemyShips.length > 0) {
// Attack nearest enemy ship
var target = enemyShips[0];
navalCombat(aiShip, target);
} else {
// Look for colonizable territories
var colonizableTargets = [];
for (var i = 0; i < territories.length; i++) {
if (territories[i].isColonizable && territories[i].owner === 0 && !territories[i].isSea) {
var distance = Math.abs(territories[i].x - aiShip.x) + Math.abs(territories[i].y - aiShip.y);
if (distance <= territorySpacing * 1.5) {
colonizableTargets.push(territories[i]);
}
}
}
if (colonizableTargets.length > 0) {
// Colonize nearest available territory
var target = colonizableTargets[0];
target.setOwner(aiCountry, 2);
target.isColonizable = false; // No longer colonizable
target.wasColonizable = true; // Mark as previously colonizable for attack logic
// Give money to correct AI pool
if (aiCountry === 2) {
aiMoney += target.colonizationReward;
} else {
if (typeof window['countryMoney' + aiCountry] === "undefined") {
window['countryMoney' + aiCountry] = 100;
}
window['countryMoney' + aiCountry] += target.colonizationReward;
}
} else {
// Move to random sea territory or towards colonizable islands
var moveTargets = [];
// Add sea territories
for (var i = 0; i < territories.length; i++) {
if (territories[i].isSea) {
moveTargets.push(territories[i]);
}
}
// Add positions near colonizable islands
for (var i = 0; i < territories.length; i++) {
if (territories[i].isColonizable && territories[i].owner === 0) {
moveTargets.push(territories[i]);
}
}
if (moveTargets.length > 0) {
var newPos = moveTargets[Math.floor(Math.random() * moveTargets.length)];
aiShip.x = newPos.x;
aiShip.y = newPos.y;
}
}
}
}
}
updateTerritoryCount();
// Decrease peace offer cooldowns at end of AI turn
for (var k in peaceOfferCooldowns) {
if (peaceOfferCooldowns.hasOwnProperty(k) && peaceOfferCooldowns[k] > 0) {
peaceOfferCooldowns[k]--;
}
}
currentTurn = 1;
updateInstructions();
}
// Create UI elements
function createUI() {
// Turn indicator
turnText = new Text2("Your Turn", {
size: 40,
fill: 0xFFFFFF
});
turnText.anchor.set(0.5, 0);
LK.gui.top.addChild(turnText);
turnText.y = 100;
// (Removed scoreText display for country colors and territory counts)
// Player army count display
playerArmyText = new Text2("Total Armies: 0", {
size: 32,
fill: 0x7ed321
});
playerArmyText.anchor.set(0.5, 0);
LK.gui.top.addChild(playerArmyText);
playerArmyText.y = 190;
// Player money display
playerMoneyText = new Text2("Money: " + playerMoney, {
size: 32,
fill: 0xf5a623
});
playerMoneyText.anchor.set(0.5, 0);
LK.gui.top.addChild(playerMoneyText);
playerMoneyText.y = 230;
// Instructions
instructionText = new Text2("Select your territory, then choose an action", {
size: 28,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(instructionText);
instructionText.y = -200;
// Action buttons
var attackBtn = new ActionButton();
attackBtn.init("Attack", attackTerritory, 2048 / 2 - 200, 2732 - 120);
actionButtons.push(attackBtn);
game.addChild(attackBtn);
var recruitBtn = new ActionButton();
recruitBtn.init("Recruit", recruitArmies, 2048 / 2 - 60, 2732 - 120);
actionButtons.push(recruitBtn);
game.addChild(recruitBtn);
var buildShipBtn = new ActionButton();
buildShipBtn.init("Build Ship", buildShip, 2048 / 2 + 80, 2732 - 120);
actionButtons.push(buildShipBtn);
game.addChild(buildShipBtn);
// Skip Turn button
var skipTurnBtn = new ActionButton();
skipTurnBtn.init("Skip Turn", function () {
if (selectedDifficulty === null) return;
if (currentTurn === 1) {
endPlayerTurn();
}
}, 2048 / 2 + 220, 2732 - 120);
actionButtons.push(skipTurnBtn);
game.addChild(skipTurnBtn);
// Power selection display
powerText = new Text2("Attack Power: 1/1", {
size: 28,
fill: 0xffff00
});
powerText.anchor.set(0.5, 1);
LK.gui.bottom.addChild(powerText);
powerText.y = -240;
powerText.visible = false;
// Power adjustment buttons
var powerDownBtn = new ActionButton();
powerDownBtn.init("-", decreasePower, 2048 / 2 - 100, 2732 - 180);
actionButtons.push(powerDownBtn);
game.addChild(powerDownBtn);
powerDownBtn.visible = false;
var powerUpBtn = new ActionButton();
powerUpBtn.init("+", increasePower, 2048 / 2 + 100, 2732 - 180);
actionButtons.push(powerUpBtn);
game.addChild(powerUpBtn);
powerUpBtn.visible = false;
// Store power buttons for visibility control
powerDownButton = powerDownBtn;
powerUpButton = powerUpBtn;
}
// Power selection functions
function decreasePower() {
if (selectedDifficulty === null) return;
if (selectedAttackPower > 1) {
selectedAttackPower--;
updatePowerDisplay();
}
}
function increasePower() {
if (selectedDifficulty === null) return;
if (selectedAttackPower < maxAttackPower) {
selectedAttackPower++;
updatePowerDisplay();
}
}
function updatePowerDisplay() {
if (powerText) {
powerText.setText("Attack Power: " + selectedAttackPower + "/" + maxAttackPower);
}
}
function showPowerSelection(maxPower) {
maxAttackPower = maxPower;
selectedAttackPower = Math.min(selectedAttackPower, maxAttackPower);
powerSelectionMode = true;
if (powerText) {
powerText.visible = true;
updatePowerDisplay();
}
if (powerDownButton && powerUpButton) {
powerDownButton.visible = true;
powerUpButton.visible = true;
}
}
function hidePowerSelection() {
powerSelectionMode = false;
if (powerText) {
powerText.visible = false;
}
if (powerDownButton && powerUpButton) {
powerDownButton.visible = false;
powerUpButton.visible = false;
}
}
// Update instruction text
function updateInstructions() {
if (selectedDifficulty === null) {
if (instructionText) {
instructionText.setText("Please select a difficulty (Easy, Medium, Hard)");
}
return;
}
if (currentTurn === 1) {
if (turnText) {
turnText.setText("Your Turn");
}
if (instructionText) {
if (selectedShip) {
instructionText.setText("Ship selected - Move to sea or attack enemy ships");
} else if (selectedTerritory) {
if (selectedTerritory.isSea) {
instructionText.setText("Sea territory selected - Ships can move here");
} else if (powerSelectionMode) {
instructionText.setText("Use +/- to choose attack power, then Attack, Recruit ($100), or Build Ship ($200)");
} else {
instructionText.setText("Territory selected - Attack, Recruit ($100), or Build Ship ($200)");
}
} else {
instructionText.setText("Select your territory/ship (green), then choose an action");
}
}
} else {
if (turnText) {
turnText.setText("Enemy Turn");
}
if (instructionText) {
instructionText.setText("Enemy is thinking...");
}
}
}
// Game update loop for naval combat highlighting
game.update = function () {
// Highlight enemy ships in combat range when player ship is selected
if (selectedShip && selectedShip.owner === 1) {
for (var i = 0; i < ships.length; i++) {
if (ships[i].owner === 2) {
var distance = Math.abs(selectedShip.x - ships[i].x) + Math.abs(selectedShip.y - ships[i].y);
if (distance < 200) {
// Highlight enemy ship in range
ships[i].shipGraphics.tint = 0xff6b6b; // Red tint for attackable
} else {
ships[i].shipGraphics.tint = 0xe74c3c; // Default red for enemy
}
}
}
} else {
// Reset all ship colors when no ship selected
for (var i = 0; i < ships.length; i++) {
if (ships[i].owner === 2) {
ships[i].shipGraphics.tint = 0xe74c3c; // Default red for enemy
} else if (ships[i].owner === 1 && ships[i] !== selectedShip) {
ships[i].shipGraphics.tint = 0x27ae60; // Default green for player
}
}
}
};
// Difficulty selection UI
function showDifficultySelection() {
// Block all game actions until difficulty is selected
gameState = "selectingDifficulty";
// Hide all action buttons
for (var i = 0; i < actionButtons.length; i++) {
actionButtons[i].visible = false;
}
// Hide power selection
hidePowerSelection();
// Create a full-screen overlay container for difficulty selection
if (typeof difficultyOverlay !== "undefined" && difficultyOverlay.parent) {
difficultyOverlay.parent.removeChild(difficultyOverlay);
}
difficultyOverlay = new Container();
difficultyOverlay.x = 0;
difficultyOverlay.y = 0;
// Add a semi-transparent background to block game interaction
var overlayBg = LK.getAsset('selectedTerritory', {
anchorX: 0,
anchorY: 0,
scaleX: 2048 / 120,
scaleY: 2732 / 120
});
overlayBg.alpha = 0.85;
overlayBg.tint = 0x222222;
difficultyOverlay.addChild(overlayBg);
// Show difficulty selection text
difficultyText = new Text2("Select Difficulty", {
size: 60,
fill: 0xffffff
});
difficultyText.anchor.set(0.5, 0.5);
difficultyText.x = 2048 / 2;
difficultyText.y = 2732 / 2 - 200;
difficultyOverlay.addChild(difficultyText);
// Button positions
var btnY = 2732 / 2;
var btnSpacing = 220;
var btnLabels = [{
label: "Easy",
value: "easy"
}, {
label: "Medium",
value: "medium"
}, {
label: "Hard",
value: "hard"
}, {
label: "Hardcore",
value: "hardcore"
}];
for (var i = 0; i < btnLabels.length; i++) {
var btn = new ActionButton();
btn.init(btnLabels[i].label, function (difficulty) {
return function () {
selectDifficulty(difficulty);
};
}(btnLabels[i].value), 2048 / 2 + (i - 1.5) * btnSpacing, btnY);
difficultyButtons.push(btn);
difficultyOverlay.addChild(btn);
}
// Add overlay to game
game.addChild(difficultyOverlay);
}
// Remove difficulty selection UI and start the game
function selectDifficulty(difficulty) {
selectedDifficulty = difficulty;
// If hardcore, set war with all countries (2-6) and block peace
if (selectedDifficulty === "hardcore") {
for (var c = 2; c <= 6; c++) {
warDeclarations[c] = true;
}
}
// Remove difficulty UI overlay
if (typeof difficultyOverlay !== "undefined" && difficultyOverlay.parent) {
difficultyOverlay.parent.removeChild(difficultyOverlay);
}
difficultyButtons = [];
// Show action buttons
for (var i = 0; i < actionButtons.length; i++) {
actionButtons[i].visible = true;
}
// Set game state to playing and update UI
gameState = "playing";
updateInstructions();
}
// Initialize the game
createMap();
createUI();
showDifficultySelection();
updateInstructions();
green grass. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
cyan grass. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
gray grass. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
sea territory. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
soldier. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
blue grass. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
white grass. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
red grass. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
yellow grass. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
pixelart empty button. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
paper piece pixel. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
pixel ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
swords pixelart. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat