Ticket #4431: petra_ally_requests_v0.5.patch
File petra_ally_requests_v0.5.patch, 10.5 KB (added by , 7 years ago) |
---|
-
binaries/data/mods/public/simulation/ai/common-api/gamestate.js
384 384 return ret; 385 385 }; 386 386 387 m.GameState.prototype.getMutualAllies = function() 388 { 389 let ret = []; 390 for (let i in this.playerData.isMutualAlly) 391 if (this.playerData.isMutualAlly[i] && 392 this.sharedScript.playersData[i].isMutualAlly[this.player]) 393 ret.push(+i); 394 return ret; 395 }; 396 387 397 m.GameState.prototype.isEntityAlly = function(ent) 388 398 { 389 399 if (!ent) -
binaries/data/mods/public/simulation/ai/petra/chatHelper.js
63 63 ] 64 64 }; 65 65 66 m.chatAnswerAllyRequestMessages = { 67 "decline": [ 68 markForTranslation("I cannot accept your offer to be allies %(_player_)s.") 69 ], 70 "declineSuggestNeutral": [ 71 markForTranslation("I will not ally with you %(_player_)s, but I will consider a neutrality pact.") 72 ], 73 "declineRepeatedOffer": [ 74 markForTranslation("%(_player_)s, our previous alliance did not work out, so I must decline your offer.") 75 ], 76 "accept": [ 77 markForTranslation("I will accept your offer to become allies %(_player_)s. We will both benefit from this alliance.") 78 ], 79 "acceptWithTribute": [ 80 markForTranslation("I will ally with you %(_player_)s, but only if you send me a tribute of %(_amount_)s %(_resource_)s."), 81 markForTranslation("%(_player_)s, you must send me a tribute of %(_amount_)s %(_resource_)s for me to accept an alliance.") 82 ], 83 "waitingForTribute": [ 84 markForTranslation("%(_player_)s, my offer still stands. I will ally with you if you send me a tribute of %(_amount_)s %(_resource_)s.") 85 ] 86 }; 87 66 88 m.chatLaunchAttack = function(gameState, player, type) 67 89 { 68 90 Engine.PostCommand(PlayerID, { … … 140 162 }); 141 163 }; 142 164 165 m.chatAnswerRequestAlly = function(gameState, player, response, requiredTribute) 166 { 167 Engine.PostCommand(PlayerID, { 168 "type": "aichat", 169 "message": "/msg " + gameState.sharedScript.playersData[player].name + " " + 170 pickRandom(this.chatAnswerAllyRequestMessages[response]), 171 "translateMessage": true, 172 "translateParameters": requiredTribute ? ["_amount_", "_resource_", "_player_"] : ["_player_"], 173 "parameters": requiredTribute ? 174 { "_amount_": requiredTribute.wanted, "_resource_": requiredTribute.type, "_player_": player } : 175 { "_player_": player } 176 }); 177 }; 178 143 179 return m; 144 180 }(PETRA); -
binaries/data/mods/public/simulation/ai/petra/diplomacyManager.js
5 5 * Manage the diplomacy: 6 6 * update our cooperative trait 7 7 * sent tribute to allies 8 * decide which player to turn against in "Last Man Standing" mode 9 * respond to diplomacy requests 8 10 */ 9 11 12 /** 13 * If a player sends us an ally request, an Object in this.allyRequests will be created 14 * that includes the request status, and the amount and type of the resource tribute (if any) 15 * that they must send in order for us to accept their request. 16 * In addition, a message will be sent if the player has not sent us a tribute within a minute. 17 * If two minutes pass without a tribute, we will decline their request. 18 */ 10 19 m.DiplomacyManager = function(Config) 11 20 { 12 21 this.Config = Config; … … 15 24 this.nextTributeRequest.set("all", 240); 16 25 this.betrayLapseTime = -1; 17 26 this.waitingToBetray = false; 27 this.allyRequests = new Map(); 18 28 }; 19 29 20 30 /** 31 * If there are any players that are allied with us but we are not allied with them, 32 * treat this situation like an ally request. 33 */ 34 m.DiplomacyManager.prototype.init = function(gameState) 35 { 36 for (let i = 1; i < gameState.sharedScript.playersData.length; ++i) 37 { 38 if (i === PlayerID) 39 continue; 40 41 if (gameState.isPlayerMutualAlly(i)) 42 this.allyRequests.set(i, { "status": "accepted" }); 43 else if (gameState.sharedScript.playersData[i].isAlly[PlayerID] && !gameState.isPlayerAlly(i)) 44 this.handleAllyRequest(gameState, i); 45 } 46 }; 47 48 /** 21 49 * Check if any allied needs help (tribute) and sent it if we have enough resource 22 50 * or ask for a tribute if we are in need and one ally can help 23 51 */ … … 86 114 // or if our allies attack enemies inside our territory 87 115 for (let evt of events.TributeExchanged) 88 116 { 117 if (evt.to === PlayerID && !gameState.isPlayerAlly(evt.from) && this.allyRequests.has(evt.from)) 118 { 119 let request = this.allyRequests.get(evt.from); 120 if (request.status === "waitingForTribute") 121 { 122 request.wanted -= evt.amounts[request.type]; 123 124 if (request.wanted <= 0) 125 { 126 if (this.Config.debug > 1) 127 API3.warn("Player " + uneval(evt.from) + " has sent the required tribute amount"); 128 129 this.changePlayerDiplomacy(gameState, evt.from, "ally"); 130 request.status = "accepted"; 131 } 132 else 133 { 134 // Reset the warning sent to the player that reminds them to speed up the tributes 135 request.warnTime = gameState.ai.elapsedTime + 60; 136 request.sentWarning = false; 137 } 138 } 139 } 140 89 141 if (evt.to !== PlayerID || !gameState.isPlayerAlly(evt.from)) 90 142 continue; 91 143 let tributes = 0; … … 114 166 115 167 if (events.DiplomacyChanged.length || events.PlayerDefeated.length || events.CeasefireEnded.length) 116 168 this.lastManStandingCheck(gameState); 169 170 for (let evt of events.DiplomacyChanged) 171 { 172 if (evt.otherPlayer !== PlayerID) 173 continue; 174 175 if (this.allyRequests.has(evt.player) && !gameState.sharedScript.playersData[evt.player].isAlly[PlayerID]) 176 { 177 // a player that had requested to be allies changed their stance with us 178 let request = this.allyRequests.get(evt.player); 179 if (request.status === "accepted") 180 request.status = "allianceBroken"; 181 else if (request.status !== "allianceBroken") 182 request.status = "declinedRequest"; 183 } 184 else if (gameState.sharedScript.playersData[evt.player].isAlly[PlayerID] && gameState.isPlayerEnemy(evt.player)) 185 m.chatAnswerRequestAlly(gameState, evt.player, "declineSuggestNeutral"); 186 else if (gameState.sharedScript.playersData[evt.player].isAlly[PlayerID] && gameState.isPlayerNeutral(evt.player)) 187 this.handleAllyRequest(gameState, evt.player); 188 } 117 189 }; 118 190 119 191 /** … … 186 258 this.waitingToBetray = false; 187 259 }; 188 260 261 /** 262 * Do not become allies with a player if the game would be over. 263 * Overall, be reluctant to become allies with any one player. 264 */ 265 m.DiplomacyManager.prototype.handleAllyRequest = function(gameState, player) 266 { 267 let response; 268 let requiredTribute; 269 let request = this.allyRequests.get(player); 270 271 // For any given ally request be likely to permanently decline 272 if (!request && gameState.getPlayerCiv() !== gameState.getPlayerCiv(player) && Math.random() > 0.4 || 273 gameState.getEnemies().length < gameState.getMutualAllies().length || 274 gameState.ai.HQ.attackManager.currentEnemyPlayer === player) 275 { 276 this.allyRequests.set(player, { "status": "declinedRequest" }); 277 response = "decline"; 278 } 279 else if (request) 280 { 281 if (request.status === "declinedRequest") 282 response = "decline"; 283 else if (request.status === "allianceBroken") // Previous alliance was broken, so decline 284 response = "declineRepeatedOffer"; 285 else if (request.status === "waitingForTribute") 286 { 287 response = "waitingForTribute"; 288 requiredTribute = request; 289 } 290 } 291 else if (gameState.getEntities(player).length < gameState.getOwnEntities().length && Math.random() > 0.6) 292 { 293 response = "accept"; 294 this.changePlayerDiplomacy(gameState, player, "ally"); 295 this.allyRequests.set(player, { "status": "accepted" }); 296 } 297 else 298 { 299 response = "acceptWithTribute"; 300 requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState)[0]; 301 requiredTribute.wanted = Math.max(1000, gameState.getOwnUnits().length * 10); 302 this.allyRequests.set(player, { 303 "status": "waitingForTribute", 304 "wanted": requiredTribute.wanted, 305 "type": requiredTribute.type, 306 "warnTime": gameState.ai.elapsedTime + 60, 307 "sentWarning": false 308 }); 309 } 310 m.chatAnswerRequestAlly(gameState, player, response, requiredTribute); 311 }; 312 189 313 m.DiplomacyManager.prototype.changePlayerDiplomacy = function(gameState, player, newDiplomaticStance) 190 314 { 191 315 Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": player, "to": newDiplomaticStance }); … … 195 319 m.chatNewDiplomacy(gameState, player, newDiplomaticStance); 196 320 }; 197 321 322 m.DiplomacyManager.prototype.checkRequestedTributes = function(gameState) 323 { 324 for (let [player, data] of this.allyRequests.entries()) 325 if (data.status === "waitingForTribute" && gameState.ai.elapsedTime > data.warnTime) 326 { 327 if (data.sentWarning) 328 { 329 this.allyRequests.delete(player); 330 m.chatAnswerRequestAlly(gameState, player, "decline"); 331 } 332 else 333 { 334 data.sentWarning = true; 335 data.warnTime = gameState.ai.elapsedTime + 60; 336 m.chatAnswerRequestAlly(gameState, player, "waitingForTribute", { 337 "wanted": data.wanted, 338 "type": data.type 339 }); 340 } 341 } 342 }; 343 198 344 m.DiplomacyManager.prototype.update = function(gameState, events) 199 345 { 200 346 this.checkEvents(gameState, events); … … 204 350 205 351 if (this.waitingToBetray && gameState.ai.elapsedTime > this.betrayLapseTime) 206 352 this.lastManStandingCheck(gameState); 353 354 this.checkRequestedTributes(gameState); 207 355 }; 208 356 209 357 m.DiplomacyManager.prototype.Serialize = function() … … 212 360 "nextTributeUpdate": this.nextTributeUpdate, 213 361 "nextTributeRequest": this.nextTributeRequest, 214 362 "betrayLapseTime": this.betrayLapseTime, 215 "waitingToBetray": this.waitingToBetray 363 "waitingToBetray": this.waitingToBetray, 364 "allyRequests": this.allyRequests 216 365 }; 217 366 }; 218 367 -
binaries/data/mods/public/simulation/ai/petra/startingStrategy.js
13 13 this.attackManager.init(gameState); 14 14 this.navalManager.init(gameState); 15 15 this.tradeManager.init(gameState); 16 this.diplomacyManager.init(gameState); 16 17 17 18 // Make a list of buildable structures from the config file 18 19 this.structureAnalysis(gameState);