Ticket #4143: petra_lastmanstanding_v1.3_rebased.patch
File petra_lastmanstanding_v1.3_rebased.patch, 15.7 KB (added by , 7 years ago) |
---|
-
binaries/data/mods/public/simulation/ai/common-api/gamestate.js
m.GameState.prototype.init = function(Sh 19 19 this.entities = SharedScript.entities; 20 20 this.player = player; 21 21 this.playerData = SharedScript.playersData[this.player]; 22 22 this.barterPrices = SharedScript.barterPrices; 23 23 this.gameType = SharedScript.gameType; 24 this.alliedVictory = SharedScript.alliedVictory; 25 this.ceasefireActive = SharedScript.ceasefireActive; 24 26 25 27 // get the list of possible phases for this civ: 26 28 // we assume all of them are researchable from the civil centre 27 29 this.phases = [ { name: "phase_village" }, { name: "phase_town" }, { name: "phase_city" } ]; 28 30 let cctemplate = this.getTemplate(this.applyCiv("structures/{civ}_civil_centre")); … … m.GameState.prototype.init = function(Sh 53 55 m.GameState.prototype.update = function(SharedScript) 54 56 { 55 57 this.timeElapsed = SharedScript.timeElapsed; 56 58 this.playerData = SharedScript.playersData[this.player]; 57 59 this.barterPrices = SharedScript.barterPrices; 60 this.ceasefireActive = SharedScript.ceasefireActive; 58 61 }; 59 62 60 63 m.GameState.prototype.updatingCollection = function(id, filter, collection) 61 64 { 62 65 let gid = this.player + "-" + id; // automatically add the player ID … … m.GameState.prototype.getBarterPrices = 115 118 m.GameState.prototype.getGameType = function() 116 119 { 117 120 return this.gameType; 118 121 }; 119 122 123 m.GameState.prototype.getAlliedVictory = function() 124 { 125 return this.alliedVictory; 126 }; 127 128 m.GameState.prototype.isCeasefireActive = function() 129 { 130 return this.ceasefireActive; 131 }; 132 120 133 m.GameState.prototype.getTemplate = function(type) 121 134 { 122 135 if (this.techTemplates[type] !== undefined) 123 136 return new m.Technology(this.techTemplates, type); 124 137 … … m.GameState.prototype.getPlayerID = func 289 302 }; 290 303 291 304 m.GameState.prototype.hasAllies = function() 292 305 { 293 306 for (let i in this.playerData.isAlly) 294 if (this.playerData.isAlly[i] && +i !== this.player) 307 if (this.playerData.isAlly[i] && +i !== this.player && 308 this.sharedScript.playersData[i].state !== "defeated") 295 309 return true; 296 310 return false; 297 311 }; 298 312 313 m.GameState.prototype.hasEnemies = function() 314 { 315 for (let i in this.playerData.isEnemy) 316 if (this.playerData.isEnemy[i] && +i !== 0 && 317 this.sharedScript.playersData[i].state !== "defeated") 318 return true; 319 return false; 320 }; 321 322 m.GameState.prototype.hasNeutrals = function() 323 { 324 for (let i in this.playerData.isNeutral) 325 if (this.playerData.isNeutral[i] && 326 this.sharedScript.playersData[i].state !== "defeated") 327 return true; 328 return false; 329 }; 330 331 m.GameState.prototype.isPlayerNeutral = function(id) 332 { 333 return this.playerData.isNeutral[id]; 334 }; 335 299 336 m.GameState.prototype.isPlayerAlly = function(id) 300 337 { 301 338 return this.playerData.isAlly[id]; 302 339 }; 303 340 … … m.GameState.prototype.getEntityById = fu 381 418 return this.entities._entities.get(+id); 382 419 383 420 return undefined; 384 421 }; 385 422 386 m.GameState.prototype.getEntities = function( )423 m.GameState.prototype.getEntities = function(id) 387 424 { 388 return this.entities; 425 if (id === undefined) 426 return this.entities; 427 428 return this.updatingGlobalCollection("" + id + "-entities", m.Filters.byOwner(id)); 389 429 }; 390 430 391 431 m.GameState.prototype.getStructures = function() 392 432 { 393 433 return this.updatingGlobalCollection("structures", m.Filters.byClass("Structure"), this.entities); -
binaries/data/mods/public/simulation/ai/common-api/shared.js
m.SharedScript.prototype.init = function 140 140 this.timeElapsed = state.timeElapsed; 141 141 this.circularMap = state.circularMap; 142 142 this.mapSize = state.mapSize; 143 143 this.gameType = state.gameType; 144 144 this.barterPrices = state.barterPrices; 145 this.alliedVictory = state.alliedVictory; 146 this.ceasefireActive = state.ceasefireActive; 145 147 146 148 this.passabilityMap = state.passabilityMap; 147 149 if (this.mapSize % this.passabilityMap.width !== 0) 148 150 error("AI shared component inconsistent sizes: map=" + this.mapSize + " while passability=" + this.passabilityMap.width); 149 151 this.passabilityMap.cellSize = this.mapSize / this.passabilityMap.width; … … m.SharedScript.prototype.onUpdate = func 239 241 this.events = state.events; 240 242 this.passabilityClasses = state.passabilityClasses; 241 243 this.playersData = state.players; 242 244 this.timeElapsed = state.timeElapsed; 243 245 this.barterPrices = state.barterPrices; 246 this.ceasefireActive = state.ceasefireActive; 244 247 245 248 this.passabilityMap = state.passabilityMap; 246 249 this.passabilityMap.cellSize = this.mapSize / this.passabilityMap.width; 247 250 this.territoryMap = state.territoryMap; 248 251 this.territoryMap.cellSize = this.mapSize / this.territoryMap.width; -
binaries/data/mods/public/simulation/ai/petra/chatHelper.js
m.chatNewPhase = function(gameState, pha 128 128 "translateParameters": ["phase"], 129 129 "parameters": { "phase": phase } 130 130 }); 131 131 }; 132 132 133 m.chatNewDiplomacy = function(gameState, player, enemy) 134 { 135 let message; 136 if (enemy) 137 message = markForTranslation("%(_player_)s and I are now enemies."); 138 else 139 message = markForTranslation("%(_player_)s and I are now allies."); 140 141 Engine.PostCommand(PlayerID, { 142 "type": "aichat", 143 "message": message, 144 "translateMessage": true, 145 "translateParameters": ["_player_"], 146 "parameters": {"_player_": player} 147 }); 148 }; 149 133 150 return m; 134 151 }(PETRA); -
binaries/data/mods/public/simulation/ai/petra/diplomacyManager.js
m.DiplomacyManager = function(Config) 11 11 { 12 12 this.Config = Config; 13 13 this.nextTributeUpdate = -1; 14 14 this.nextTributeRequest = new Map(); 15 15 this.nextTributeRequest.set("all", 240); 16 this.betrayLapseTime = -1; 17 this.waitingToBetray = false; 16 18 }; 17 19 18 20 /** 19 21 * Check if any allied needs help (tribute) and sent it if we have enough resource 20 22 * or ask for a tribute if we are in need and one ally can help … … m.DiplomacyManager.prototype.checkEvents 106 108 let attacker = gameState.getEntityById(evt.attacker); 107 109 if (!attacker || attacker.owner() === PlayerID || !gameState.isPlayerAlly(attacker.owner())) 108 110 continue; 109 111 this.Config.personality.cooperative = Math.min(1, this.Config.personality.cooperative + 0.003); 110 112 } 113 114 if (events.DiplomacyChanged.length || events.PlayerDefeated.length || events.CeasefireEnded.length) 115 this.lastManStandingCheck(gameState); 116 }; 117 118 /** 119 * Check the diplomacy at the start of the game 120 */ 121 m.DiplomacyManager.prototype.diplomacyCheck = function(gameState) 122 { 123 if (!gameState.getAlliedVictory() && !gameState.isCeasefireActive()) 124 this.lastManStandingCheck(gameState); 111 125 }; 112 126 127 /** 128 * If the "Last Man Standing" option is enabled, check if the only remaining players are allies or neutral. 129 * If so, turn against the strongest first, but be more likely to first turn against neutral players, if there are any. 130 */ 131 m.DiplomacyManager.prototype.lastManStandingCheck = function(gameState) 132 { 133 if (gameState.getAlliedVictory() || gameState.isCeasefireActive()) 134 return; 135 136 if (gameState.hasEnemies()) 137 { 138 this.waitingToBetray = false; 139 return; 140 } 141 142 if (!gameState.hasAllies() && !gameState.hasNeutrals()) 143 return; 144 145 // wait a bit before turning 146 if (!this.waitingToBetray) 147 { 148 this.betrayLapseTime = gameState.ai.elapsedTime + Math.random() * 100 + 10; 149 this.waitingToBetray = true; 150 return; 151 } 152 153 // do not turn against a player yet if we are not strong enough 154 if (gameState.getOwnUnits().length < 50) 155 { 156 this.betrayLapseTime += 60; 157 return; 158 } 159 160 let playerToTurnAgainst; 161 let turnFactor = 0; 162 let max = 0; 163 164 // count the amount of entities remaining players have 165 for (let i = 1; i < gameState.sharedScript.playersData.length; ++i) 166 { 167 if (i === PlayerID || gameState.ai.HQ.attackManager.defeated[i]) 168 continue; 169 170 turnFactor = gameState.getEntities(i).length; 171 172 if (gameState.isPlayerNeutral(i)) // be more inclined to turn against neutral players 173 turnFactor += 150; 174 175 if (turnFactor < max) 176 continue; 177 178 max = turnFactor; 179 playerToTurnAgainst = i; 180 } 181 182 if (playerToTurnAgainst) 183 { 184 Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": playerToTurnAgainst, "to": "enemy" }); 185 if (this.Config.debug > 1) 186 API3.warn("player " + playerToTurnAgainst + " is now an enemy"); 187 if (this.Config.chat) 188 m.chatNewDiplomacy(gameState, playerToTurnAgainst, true); 189 } 190 this.betrayLapseTime = -1; 191 this.waitingToBetray = false; 192 }; 113 193 114 194 m.DiplomacyManager.prototype.update = function(gameState, events) 115 195 { 116 196 this.checkEvents(gameState, events); 117 197 118 198 if (!gameState.ai.HQ.saveResources && gameState.ai.elapsedTime > this.nextTributeUpdate) 119 199 this.tributes(gameState); 200 201 if (this.waitingToBetray && gameState.ai.elapsedTime > this.betrayLapseTime) 202 this.lastManStandingCheck(gameState); 120 203 }; 121 204 122 205 m.DiplomacyManager.prototype.Serialize = function() 123 206 { 124 return { "nextTributeUpdate": this.nextTributeUpdate, "nextTributeRequest": this.nextTributeRequest }; 207 return { 208 "nextTributeUpdate": this.nextTributeUpdate, 209 "nextTributeRequest": this.nextTributeRequest, 210 "betrayLapseTime": this.betrayLapseTime, 211 "waitingToBetray": this.waitingToBetray 212 }; 125 213 }; 126 214 127 215 m.DiplomacyManager.prototype.Deserialize = function(data) 128 216 { 129 this.nextTributeUpdate = data.nextTributeUpdate;130 this.nextTributeRequest = data.nextTributeRequest;217 for (let key in data) 218 this[key] = data[key]; 131 219 }; 132 220 133 221 return m; 134 222 }(PETRA); -
binaries/data/mods/public/simulation/ai/petra/startingStrategy.js
m.HQ.prototype.gameAnalysis = function(g 52 52 } 53 53 54 54 // configure our first base strategy 55 55 if (this.baseManagers.length > 1) 56 56 this.configFirstBase(gameState); 57 this.diplomacyManager.diplomacyCheck(gameState); 57 58 }; 58 59 59 60 /** 60 61 * Assign the starting entities to the different bases 61 62 */ -
binaries/data/mods/public/simulation/components/AIInterface.js
AIInterface.prototype.EventNames = [ 18 18 "Garrison", 19 19 "UnGarrison", 20 20 "TerritoriesChanged", 21 21 "TerritoryDecayChanged", 22 22 "TributeExchanged", 23 "AttackRequest" 23 "AttackRequest", 24 "CeasefireEnded" 24 25 ]; 25 26 26 27 AIInterface.prototype.Init = function() 27 28 { 28 29 this.events = {}; … … AIInterface.prototype.OnGlobalTributeExc 195 196 AIInterface.prototype.OnTerritoriesChanged = function(msg) 196 197 { 197 198 this.events.TerritoriesChanged.push(msg); 198 199 }; 199 200 201 AIInterface.prototype.OnCeasefireEnded = function(msg) 202 { 203 this.events.CeasefireEnded.push(msg); 204 }; 205 200 206 /** 201 207 * When a new technology is researched, check which templates it affects, 202 208 * and send the updated values to the AI. 203 209 * this relies on the fact that any "value" in a technology can only ever change 204 210 * one template value, and that the naming is the same (with / in place of .) -
binaries/data/mods/public/simulation/components/EndGameManager.js
EndGameManager.prototype.MarkPlayerAsWon 74 74 EndGameManager.prototype.SetAlliedVictory = function(flag) 75 75 { 76 76 this.alliedVictory = flag; 77 77 }; 78 78 79 EndGameManager.prototype.GetAlliedVictory = function() 80 { 81 return this.alliedVictory; 82 }; 83 79 84 EndGameManager.prototype.AlliedVictoryCheck = function() 80 85 { 81 86 if (this.skipAlliedVictoryCheck) 82 87 return; 83 88 -
binaries/data/mods/public/simulation/components/GuiInterface.js
GuiInterface.prototype.GetSimulationStat 142 142 { 143 143 ret.ceasefireActive = cmpCeasefireManager.IsCeasefireActive(); 144 144 ret.ceasefireTimeRemaining = ret.ceasefireActive ? cmpCeasefireManager.GetCeasefireStartedTime() + cmpCeasefireManager.GetCeasefireTime() - ret.timeElapsed : 0; 145 145 } 146 146 147 // Add the game type 147 // Add the game type and allied victory 148 148 let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); 149 149 ret.gameType = cmpEndGameManager.GetGameType(); 150 ret.alliedVictory = cmpEndGameManager.GetAlliedVictory(); 150 151 151 152 // Add bartering prices 152 153 let cmpBarter = Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter); 153 154 ret.barterPrices = cmpBarter.GetPrices(); 154 155 -
binaries/data/mods/public/simulation/components/tests/test_EndGameManager.js
AddMock(playerEnt1, IID_Player, { 20 20 "GetState": () => "active", 21 21 }); 22 22 23 23 TS_ASSERT_EQUALS(cmpEndGameManager.skipAlliedVictoryCheck, true); 24 24 cmpEndGameManager.SetAlliedVictory(true); 25 TS_ASSERT_EQUALS(cmpEndGameManager. alliedVictory, true);25 TS_ASSERT_EQUALS(cmpEndGameManager.GetAlliedVictory(), true); 26 26 cmpEndGameManager.SetGameType("wonder", { "wonderDuration": wonderDuration }); 27 27 TS_ASSERT_EQUALS(cmpEndGameManager.CheckGameType("regicide"), false); 28 28 TS_ASSERT_EQUALS(cmpEndGameManager.skipAlliedVictoryCheck, false); 29 29 TS_ASSERT(cmpEndGameManager.GetGameType() == "wonder"); 30 30 TS_ASSERT_EQUALS(cmpEndGameManager.GetGameTypeSettings().wonderDuration, wonderDuration); -
binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js
AddMock(SYSTEM_ENTITY, IID_Barter, { 45 45 }; 46 46 } 47 47 }); 48 48 49 49 AddMock(SYSTEM_ENTITY, IID_EndGameManager, { 50 GetGameType: function() { return "conquest"; } 50 GetGameType: function() { return "conquest"; }, 51 GetAlliedVictory: function() { return false; } 51 52 }); 52 53 53 54 AddMock(SYSTEM_ENTITY, IID_PlayerManager, { 54 55 GetNumPlayers: function() { return 2; }, 55 56 GetPlayerByID: function(id) { TS_ASSERT(id === 0 || id === 1); return 100+id; }, … … TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulatio 329 330 } 330 331 ], 331 332 circularMap: false, 332 333 timeElapsed: 0, 333 334 gameType: "conquest", 335 alliedVictory: false, 334 336 barterPrices: {buy: {food: 150}, sell: {food: 25}} 335 337 }); 336 338 337 339 TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), { 338 340 players: [ … … TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedS 448 450 } 449 451 ], 450 452 circularMap: false, 451 453 timeElapsed: 0, 452 454 gameType: "conquest", 455 alliedVictory: false, 453 456 barterPrices: {buy: {food: 150}, sell: {food: 25}} 454 457 }); 455 458 456 459 457 460 AddMock(10, IID_Builder, {