Ticket #4431: 4431_petra_neutral_requests_v0.1.patch

File 4431_petra_neutral_requests_v0.1.patch, 13.7 KB (added by Sandarac, 7 years ago)

Handle neutral requests from enemies.

  • binaries/data/mods/public/simulation/ai/petra/attackManager.js

     
    455455    return enemyPlayer;
    456456};
    457457
     458/** f.e. if we have changed diplomacy with another player. */
     459m.AttackManager.prototype.cancelAttacksAgainstPlayer = function(player)
     460{
     461    for (let attackType in this.upcomingAttacks)
     462        for (let i = 0; i < this.upcomingAttacks[attackType].length; ++i)
     463        {
     464            let attack = this.upcomingAttacks[attackType][i];
     465            if (attack.targetPlayer === player)
     466            {
     467                attack.Abort(gameState);
     468                this.upcomingAttacks[attackType].splice(i--, 1);
     469            }
     470        }
     471
     472    for (let attackType in this.startedAttacks)
     473        for (let i = 0; i < this.startedAttacks[attackType].length; ++i)
     474        {
     475            let attack = this.startedAttacks[attackType][i];
     476            if (attack.targetPlayer === player)
     477            {
     478                attack.Abort(gameState);
     479                this.startedAttacks[attackType].splice(i--, 1);
     480            }
     481        }
     482};
     483
    458484m.AttackManager.prototype.Serialize = function()
    459485{
    460486    let properties = {
  • binaries/data/mods/public/simulation/ai/petra/chatHelper.js

     
    8181        markForTranslation("%(_player_)s, you must send me a tribute of %(_amount_)s %(_resource_)s for me to accept an alliance.")
    8282    ],
    8383    "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.")
     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        markForTranslation("%(_player_)s, if you do not send me part of the %(_amount_)s %(_resource_)s tribute soon, I will break off our negotiations.")
    8586    ]
    8687};
    8788
     89m.answerNeutralRequestMessages = {
     90    "decline": [
     91        markForTranslation("I will not become neutral with you %(_player_)s."),
     92        markForTranslation("%(_player_)s, I must decline your request for a neutrality pact.")
     93    ],
     94    "declineRepeatedOffer": [
     95        markForTranslation("Our previous neutrality agreement ended in failure %(_player_)s; I will not consider another one.")
     96    ],
     97    "accept": [
     98        markForTranslation("I welcome your request for peace between our civilizations %(_player_)s. I will accept."),
     99        markForTranslation("%(_player_)s, I will accept your neutrality request. May both our civilizations benefit.")
     100    ],
     101    "acceptWithTribute": [
     102        markForTranslation("If you tribute me %(_amount_)s %(_resource_)s, I will accept your neutrality request %(_player_)s."),
     103        markForTranslation("%(_player_)s, if you send me %(_amount_)s %(_resource_)s, I will accept a neutrality pact.")
     104    ],
     105    "waitingForTribute": [
     106        markForTranslation("%(_player_)s, I will not accept your neutrality request unless you tribute me %(_amount_)s %(_resource_)s soon."),
     107        markForTranslation("%(_player_)s, if you do not send me part of the %(_amount_)s %(_resource_)s tribute soon, I will break off our negotiations.")
     108    ]
     109};
     110
    88111m.chatLaunchAttack = function(gameState, player, type)
    89112{
    90113    Engine.PostCommand(PlayerID, {
     
    162185    });
    163186};
    164187
    165 m.chatAnswerRequestAlly = function(gameState, player, response, requiredTribute)
     188m.chatAnswerRequestDiplomacy = function(gameState, player, response, requestType, requiredTribute)
    166189{
    167190    Engine.PostCommand(PlayerID, {
    168191        "type": "aichat",
    169192        "message": "/msg " + gameState.sharedScript.playersData[player].name + " " +
    170             pickRandom(this.answerAllyRequestMessages[response]),
     193            pickRandom(requestType === "ally" ? this.answerAllyRequestMessages[response] : this.answerNeutralRequestMessages[response]),
    171194        "translateMessage": true,
    172195        "translateParameters": requiredTribute ? ["_amount_", "_resource_", "_player_"] : ["_player_"],
    173196        "parameters": requiredTribute ?
  • binaries/data/mods/public/simulation/ai/petra/diplomacyManager.js

     
    1010 */
    1111
    1212/**
    13  * If a player sends us an ally request, an Object in this.allyRequests will be created
     13 * If a player sends us an ally or neutral request, an Object in this.diplomacyRequests will be created
    1414 * that includes the request status, and the amount and type of the resource tribute (if any)
    1515 * that they must send in order for us to accept their request.
    1616 * In addition, a message will be sent if the player has not sent us a tribute within a minute.
     
    2424    this.nextTributeRequest.set("all", 240);
    2525    this.betrayLapseTime = -1;
    2626    this.waitingToBetray = false;
    27     this.allyRequests = new Map();
     27    this.diplomacyRequests = new Map();
    2828};
    2929
    3030/**
     
    3333 */
    3434m.DiplomacyManager.prototype.init = function(gameState)
    3535{
     36    if (!gameState.getAlliedVictory() && !gameState.isCeasefireActive())
     37        this.lastManStandingCheck(gameState);
     38
    3639    for (let i = 1; i < gameState.sharedScript.playersData.length; ++i)
    3740    {
    3841        if (i === PlayerID)
     
    3942            continue;
    4043
    4144        if (gameState.isPlayerMutualAlly(i))
    42             this.allyRequests.set(i, { "status": "accepted" });
     45            this.diplomacyRequests.set(i, { "requestType": "ally", "status": "accepted" });
    4346        else if (gameState.sharedScript.playersData[i].isAlly[PlayerID])
    44             this.handleAllyRequest(gameState, i);
     47            this.handleDiplomacyRequest(gameState, i, "ally");
    4548    }
    4649};
    4750
     
    114117    // or if our allies attack enemies inside our territory
    115118    for (let evt of events.TributeExchanged)
    116119    {
    117         if (evt.to === PlayerID && !gameState.isPlayerAlly(evt.from) && this.allyRequests.has(evt.from))
     120        if (evt.to === PlayerID && !gameState.isPlayerAlly(evt.from) && this.diplomacyRequests.has(evt.from))
    118121        {
    119             let request = this.allyRequests.get(evt.from);
     122            let request = this.diplomacyRequests.get(evt.from);
    120123            if (request.status === "waitingForTribute")
    121124            {
    122125                request.wanted -= evt.amounts[request.type];
     
    126129                    if (this.Config.debug > 1)
    127130                        API3.warn("Player " + uneval(evt.from) + " has sent the required tribute amount");
    128131
    129                     this.changePlayerDiplomacy(gameState, evt.from, "ally");
     132                    this.changePlayerDiplomacy(gameState, evt.from, request.requestType);
    130133                    request.status = "accepted";
    131134                }
    132135                else
     
    172175        if (evt.otherPlayer !== PlayerID)
    173176            continue;
    174177
    175         if (this.allyRequests.has(evt.player) && !gameState.sharedScript.playersData[evt.player].isAlly[PlayerID])
     178        if (this.diplomacyRequests.has(evt.player) && !gameState.sharedScript.playersData[evt.player].isAlly[PlayerID])
    176179        {
    177180            // a player that had requested to be allies changed their stance with us
    178             let request = this.allyRequests.get(evt.player);
     181            let request = this.diplomacyRequests.get(evt.player);
    179182            if (request.status === "accepted")
    180183                request.status = "allianceBroken";
    181184            else if (request.status !== "allianceBroken")
     
    182185                request.status = "declinedRequest";
    183186        }
    184187        else if (gameState.sharedScript.playersData[evt.player].isAlly[PlayerID] && gameState.isPlayerEnemy(evt.player))
    185             m.chatAnswerRequestAlly(gameState, evt.player, "declineSuggestNeutral");
     188            m.chatAnswerRequestDiplomacy(gameState, evt.player, "declineSuggestNeutral", "ally");
    186189        else if (gameState.sharedScript.playersData[evt.player].isAlly[PlayerID] && gameState.isPlayerNeutral(evt.player))
    187             this.handleAllyRequest(gameState, evt.player);
     190            this.handleDiplomacyRequest(gameState, evt.player, "ally");
     191        else if (gameState.sharedScript.playersData[evt.player].isNeutral[PlayerID] && gameState.isPlayerEnemy(evt.player))
     192            this.handleDiplomacyRequest(gameState, evt.player, "neutral");
    188193    }
    189194};
    190195
    191196/**
    192  * Check the diplomacy at the start of the game
    193  */
    194 m.DiplomacyManager.prototype.diplomacyCheck = function(gameState)
    195 {
    196     if (!gameState.getAlliedVictory() && !gameState.isCeasefireActive())
    197         this.lastManStandingCheck(gameState);
    198 };
    199 
    200 /**
    201197 * If the "Last Man Standing" option is enabled, check if the only remaining players are allies or neutral.
    202198 * If so, turn against the strongest first, but be more likely to first turn against neutral players, if there are any.
    203199 */
     
    253249    }
    254250
    255251    if (playerToTurnAgainst)
     252    {
    256253        this.changePlayerDiplomacy(gameState, playerToTurnAgainst, "enemy");
     254        let request = this.diplomacyRequests.get(playerToTurnAgainst);
     255        if (request && request.status !== "allianceBroken")
     256        {
     257            if (request.status === "waitingForTribute")
     258                m.chatAnswerRequestDiplomacy(gameState, player, "decline", request.requestType);
     259            request.status = request.status === "accepted" ? "allianceBroken" : "declinedRequest";
     260        }
     261    }
    257262    this.betrayLapseTime = -1;
    258263    this.waitingToBetray = false;
    259264};
     
    260265
    261266/**
    262267 * Do not become allies with a player if the game would be over.
    263  * Overall, be reluctant to become allies with any one player.
     268 * Overall, be reluctant to become allies with any one player, but be more likely to accept neutral requests.
    264269 */
    265 m.DiplomacyManager.prototype.handleAllyRequest = function(gameState, player)
     270m.DiplomacyManager.prototype.handleDiplomacyRequest = function(gameState, player, requestType)
    266271{
    267272    let response;
    268273    let requiredTribute;
    269     let request = this.allyRequests.get(player);
     274    let request = this.diplomacyRequests.get(player);
    270275
    271     // For any given ally request be likely to permanently decline
     276    // For any given diplomacy request be likely to permanently decline
    272277    if (!request && gameState.getPlayerCiv() !== gameState.getPlayerCiv(player) && Math.random() > 0.4 ||
    273278        gameState.getEnemies().length < gameState.getMutualAllies().length ||
    274279        gameState.ai.HQ.attackManager.currentEnemyPlayer === player)
    275280    {
    276         this.allyRequests.set(player, { "status": "declinedRequest" });
     281        this.diplomacyRequests.set(player, { "requestType": requestType, "status": "declinedRequest" });
    277282        response = "decline";
    278283    }
    279     else if (request)
     284    else if (request && request.status !== "accepted" && request.requestType !== "ally")
    280285    {
    281286        if (request.status === "declinedRequest")
    282287            response = "decline";
     
    288293            requiredTribute = request;
    289294        }
    290295    }
    291     else if (gameState.getEntities(player).length < gameState.getOwnEntities().length && Math.random() > 0.6)
     296    else if (requestType === "ally" && gameState.getEntities(player).length < gameState.getOwnEntities().length && Math.random() > 0.6)
    292297    {
    293298        response = "accept";
    294         this.changePlayerDiplomacy(gameState, player, "ally");
    295         this.allyRequests.set(player, { "status": "accepted" });
     299        this.changePlayerDiplomacy(gameState, player, requestType);
     300        this.diplomacyRequests.set(player, { "requestType": requestType, "status": "accepted" });
    296301    }
    297302    else
    298303    {
    299304        response = "acceptWithTribute";
    300305        requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState)[0];
    301         requiredTribute.wanted = Math.max(1000, gameState.getOwnUnits().length * 10);
    302         this.allyRequests.set(player, {
     306        requiredTribute.wanted = Math.max(1000, gameState.getOwnUnits().length * requestType === "ally" ? 10 : 5)
     307        this.diplomacyRequests.set(player, {
    303308            "status": "waitingForTribute",
    304309            "wanted": requiredTribute.wanted,
    305310            "type": requiredTribute.type,
    306311            "warnTime": gameState.ai.elapsedTime + 60,
    307             "sentWarning": false
     312            "sentWarning": false,
     313            "requestType": requestType
    308314        });
    309315    }
    310     m.chatAnswerRequestAlly(gameState, player, response, requiredTribute);
     316    m.chatAnswerRequestDiplomacy(gameState, player, response, requestType, requiredTribute);
    311317};
    312318
    313319m.DiplomacyManager.prototype.changePlayerDiplomacy = function(gameState, player, newDiplomaticStance)
    314320{
     321    if (gameState.isPlayerEnemy(player) && (newDiplomaticStance === "ally" || newDiplomaticStance === "neutral"))
     322        gameState.ai.HQ.attackManager.cancelAttacksAgainstPlayer(player);
    315323    Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": player, "to": newDiplomaticStance });
    316324    if (this.Config.debug > 1)
    317325        API3.warn("diplomacy stance with player " + player + " is now " + newDiplomaticStance);
     
    321329
    322330m.DiplomacyManager.prototype.checkRequestedTributes = function(gameState)
    323331{
    324     for (let [player, data] of this.allyRequests.entries())
     332    for (let [player, data] of this.diplomacyRequests.entries())
    325333        if (data.status === "waitingForTribute" && gameState.ai.elapsedTime > data.warnTime)
    326334        {
    327335            if (data.sentWarning)
    328336            {
    329                 this.allyRequests.delete(player);
    330                 m.chatAnswerRequestAlly(gameState, player, "decline");
     337                this.diplomacyRequests.delete(player);
     338                m.chatAnswerRequestDiplomacy(gameState, player, "decline", data.requestType);
    331339            }
    332340            else
    333341            {
    334342                data.sentWarning = true;
    335343                data.warnTime = gameState.ai.elapsedTime + 60;
    336                 m.chatAnswerRequestAlly(gameState, player, "waitingForTribute", {
     344                m.chatAnswerRequestDiplomacy(gameState, player, data.requestType, "waitingForTribute", {
    337345                    "wanted": data.wanted,
    338346                    "type": data.type
    339347                });
     
    361369        "nextTributeRequest": this.nextTributeRequest,
    362370        "betrayLapseTime": this.betrayLapseTime,
    363371        "waitingToBetray": this.waitingToBetray,
    364         "allyRequests": this.allyRequests
     372        "diplomacyRequests": this.diplomacyRequests
    365373    };
    366374};
    367375
  • binaries/data/mods/public/simulation/ai/petra/startingStrategy.js

     
    5555    // configure our first base strategy
    5656    if (this.baseManagers.length > 1)
    5757        this.configFirstBase(gameState);
    58 
    59     this.diplomacyManager.diplomacyCheck(gameState);
    6058};
    6159
    6260/**