Index: binaries/data/mods/public/simulation/ai/common-api/gamestate.js =================================================================== --- binaries/data/mods/public/simulation/ai/common-api/gamestate.js +++ binaries/data/mods/public/simulation/ai/common-api/gamestate.js @@ -23,6 +23,7 @@ this.alliedVictory = SharedScript.alliedVictory; this.ceasefireActive = SharedScript.ceasefireActive; this.ceasefireTimeRemaining = SharedScript.ceasefireTimeRemaining; + this.emergencyState = new Map(); // get the list of possible phases for this civ: // we assume all of them are researchable from the civil center Index: binaries/data/mods/public/simulation/ai/petra/chatHelper.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/chatHelper.js +++ binaries/data/mods/public/simulation/ai/petra/chatHelper.js @@ -234,3 +234,11 @@ "parameters": { "_player_": player } }); }; +PETRA.chatEmergency = function(gameState) +{ + Engine.PostCommand(PlayerID, { + "type": "aichat", + "message": "/allies Please help me", + "translateMessage": true + }); +}; Index: binaries/data/mods/public/simulation/ai/petra/config.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/config.js +++ binaries/data/mods/public/simulation/ai/petra/config.js @@ -175,6 +175,24 @@ "Market/InternationalBonus", "Player/sharedDropsites" ]; + + this.criticalPopulationFactor = [ + 0.8, + 0.8, + 0.7, + 0.6, + 0.5, + 0.35 + ][difficulty]; + + this.criticalStructureFactor = [ + 0.8, + 0.8, + 0.7, + 0.6, + 0.5, + 0.35 + ][difficulty]; }; PETRA.Config.prototype.setConfig = function(gameState) Index: binaries/data/mods/public/simulation/ai/petra/emergencyManager.js =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/ai/petra/emergencyManager.js @@ -0,0 +1,57 @@ +/** + * Checks for emergencies and acts accordingly + */ +PETRA.EmergencyManager = function(Config) +{ + this.Config = Config; + // Initialized in initPhases + // Maximum population size during the game + this.referencePopulation = 0; + // Maximum number of structures during the game + this.referenceStructureCount = 0; + // Maximum number of territory roots + this.numRoots = 0; +}; + +PETRA.EmergencyManager.prototype.initPhases = function(gameState) +{ + this.referencePopulation = gameState.getPopulation(); + this.referenceStructureCount = gameState.getOwnStructures().length; + this.numRoots = this.rootCount(gameState); +}; + +PETRA.EmergencyManager.prototype.checkForEmergency = function(gameState) +{ + if (gameState.emergencyState[PlayerID]) + return; + const pop = gameState.getPopulation(); + const criticalPopulationChange = (this.referencePopulation / pop) < this.Config.criticalPopulationFactor || pop == 0; + const nStructures = gameState.getOwnStructures().length; + const criticalStructureChange = (this.referenceStructureCount / nStructures) < this.Config.criticalStructureFactor || nStructures == 0; + const nRoots = this.rootCount(gameState); + const criticalRootChange = (this.numRoots - nRoots) >= 2 || nRoots == 0; + + if (criticalPopulationChange && criticalStructureChange) + gameState.emergencyState[PlayerID] = true; + else if (criticalRootChange) + gameState.emergencyState[PlayerID] = true; + + if (pop > this.referencePopulation) + this.referencePopulation = pop; + if (nStructures > this.referenceStructureCount) + this.referenceStructureCount = nStructures; + if (nRoots > this.numRoots) + this.numRoots = nRoots; + + if (gameState.emergencyState[PlayerID]) + PETRA.chatEmergency(gameState); +}; +PETRA.EmergencyManager.prototype.rootCount = function(gameState) +{ + let roots = 0; + gameState.getOwnStructures().toEntityArray().forEach(ent => { + if (ent && ent.get("TerritoryInfluence") !== undefined && ent.get("TerritoryInfluence").Root) + roots++; + }); + return roots; +}; Index: binaries/data/mods/public/simulation/ai/petra/headquarters.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/headquarters.js +++ binaries/data/mods/public/simulation/ai/petra/headquarters.js @@ -44,6 +44,7 @@ this.diplomacyManager = new PETRA.DiplomacyManager(this.Config); this.garrisonManager = new PETRA.GarrisonManager(this.Config); this.victoryManager = new PETRA.VictoryManager(this.Config); + this.emergencyManager = new PETRA.EmergencyManager(this.Config); this.capturableTargets = new Map(); this.capturableTargetsTime = 0; @@ -66,6 +67,7 @@ this.treasures.registerUpdates(); this.currentPhase = gameState.currentPhase(); this.decayingStructures = new Set(); + this.emergencyManager.initPhases(gameState); }; /** @@ -2190,6 +2192,7 @@ PETRA.HQ.prototype.update = function(gameState, queues, events) { Engine.ProfileStart("Headquarters update"); + this.emergencyManager.checkForEmergency(gameState); this.turnCache = {}; this.territoryMap = PETRA.createTerritoryMap(gameState); this.canBarter = gameState.getOwnEntitiesByClass("Market", true).filter(API3.Filters.isBuilt()).hasEntities();