User prompt
make the map bigger
User prompt
Ensure that a diplomacy panel opens when clicking on the territory of enemy countries. Through that panel, a declaration of war can be made.
User prompt
Ensure that the states of the countries are side by side.
User prompt
Add countries in different colors.
User prompt
1- Add countries in different colors. 2- I should be able to choose the state I want to attack.
User prompt
When you click on the state and then click on another state, the number of armies written in the first clicked state disappears. Can you fix it?
User prompt
The number of soldiers visible when clicking on the province disappears, fix that.
User prompt
1- Make it possible for us to recruit soldiers with money. 2- The number of soldiers visible when clicking on the province disappears, fix that.
User prompt
Make sure to bring in money every time according to the number of states.
User prompt
remove the neutral territories
User prompt
make the number of soldiers of the player I played visible
User prompt
Generate the first version of the source code of my game: Empire Builder: Strategic Conquest.
User prompt
Empire Builder: Strategic Conquest
Initial prompt
make me a game like age of history 2
/**** * 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