Ticket #4431: petra_ally_requests_v0.2.patch

File petra_ally_requests_v0.2.patch, 9.8 KB (added by Sandarac, 7 years ago)

Fix issues.

  • binaries/data/mods/public/gui/session/messages.js

     
    185185        g_IsObserver,
    186186
    187187    "/msg": (senderID, addresseeGUID) =>
    188         addresseeGUID == Engine.GetPlayerGUID()
     188        addresseeGUID == (Engine.GetPlayerGUID() || "local")
    189189};
    190190
    191191/**
  • binaries/data/mods/public/simulation/ai/common-api/gamestate.js

     
    146146    return str.replace(/\{civ\}/g, this.playerData.civ);
    147147};
    148148
     149m.GameState.prototype.getPlayerCiv = function(player)
     150{
     151    if (player === undefined)
     152        return this.playerData.civ;
     153
     154    return this.sharedScript.playersData[player].civ;
     155}
     156
    149157m.GameState.prototype.civ = function()
    150158{
    151     return this.playerData.civ;
     159    return this.getPlayerCiv();
    152160};
    153161
    154162m.GameState.prototype.currentPhase = function()
  • binaries/data/mods/public/simulation/ai/petra/chatHelper.js

     
    11var PETRA = function(m)
    22{
    33
     4m.chatNewDiplomacyMessages = {
     5    "enemy": [
     6        markForTranslation("%(_player_)s and I are now enemies.")
     7    ],
     8    "ally": [
     9        markForTranslation("%(_player_)s and I are now allies.")
     10    ],
     11    "neutral": [
     12        markForTranslation("%(_player_)s and I are now neutral.")
     13    ]
     14};
     15
     16m.chatAnswerAllyRequestMessages = {
     17    "decline": [
     18        markForTranslation("I cannot accept your offer to be allies %(_player_)s.")
     19    ],
     20    "declineRepeatedOffer": [
     21        markForTranslation("%(_player_)s, our previous alliance did not work out, so I must decline your offer.")
     22    ],
     23    "accept": [
     24        markForTranslation("I will accept your offer to become allies %(_player_)s. We will both benefit from this alliance.")
     25    ],
     26    "acceptWithTribute": [
     27        markForTranslation("I will ally with you %(_player_)s, but only if you send me a tribute of %(_amount_)s %(_resource_)s."),
     28        markForTranslation("%(_player_)s, you must send me a tribute of %(_amount_)s %(_resource_)s for me to consider an alliance.")
     29    ],
     30    "waitingForTribute": [
     31        markForTranslation("%(_player_)s, my offer still stands. I will ally with you if you send me a tribute of %(_amount_)s %(_resource_)s.")
     32    ]
     33};
     34
    435m.chatLaunchAttack = function(gameState, player, type)
    536{
    637    let message;
     
    128159    });
    129160};
    130161
    131 m.chatNewDiplomacy = function(gameState, player, enemy)
     162m.chatNewDiplomacy = function(gameState, player, newDiplomaticStance)
    132163{
    133     let message = enemy ?
    134         markForTranslation("%(_player_)s and I are now enemies.") :
    135         markForTranslation("%(_player_)s and I are now allies.");
    136 
    137164    Engine.PostCommand(PlayerID, {
    138165        "type": "aichat",
    139         "message": message,
     166        "message": API3.PickRandom(this.chatNewDiplomacyMessages[newDiplomaticStance]),
    140167        "translateMessage": true,
    141168        "translateParameters": ["_player_"],
    142         "parameters": {"_player_": player}
     169        "parameters": { "_player_": player }
    143170    });
    144171};
    145172
     173m.chatAnswerRequestAlly = function(gameState, player, response, requiredTribute)
     174{
     175    Engine.PostCommand(PlayerID, {
     176        "type": "aichat",
     177        "message": "/msg " + gameState.sharedScript.playersData[player].name + " " +
     178            API3.PickRandom(this.chatAnswerAllyRequestMessages[response]),
     179        "translateMessage": true,
     180        "translateParameters": requiredTribute ? ["_amount_", "_resource_", "_player_"] : ["_player_"],
     181        "parameters": requiredTribute ?
     182            {"_amount_": requiredTribute.wanted, "_resource_": requiredTribute.type, "_player_": player } :
     183            { "_player_": player }
     184    });
     185};
     186
    146187return m;
    147188}(PETRA);
  • binaries/data/mods/public/simulation/ai/petra/diplomacyManager.js

     
    55 * Manage the diplomacy:
    66 *     update our cooperative trait
    77 *     sent tribute to allies
     8 *     decide which player to turn against in "Last Man Standing" mode
     9 *     respond to diplomacy requests
    810 */
    911
     12/**
     13 * If a player sends us an ally request, an Object in this.allyRequests will be created
     14 * containing 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 * f.e. { "status": 1, "type": "metal", "wanted": 1000 }.
     17 * Status is -1 for decline, -2 for decline repeated request, 1 for waiting for tributes.
     18 */
    1019m.DiplomacyManager = function(Config)
    1120{
    1221    this.Config = Config;
     
    1524    this.nextTributeRequest.set("all", 240);
    1625    this.betrayLapseTime = -1;
    1726    this.waitingToBetray = false;
     27    this.allyRequests = new Map();
    1828};
    1929
    2030/**
     
    8696    // or if our allies attack enemies inside our territory
    8797    for (let evt of events.TributeExchanged)
    8898    {
     99        if (evt.to === PlayerID && !gameState.isPlayerAlly(evt.from) && this.allyRequests.has(evt.from))
     100        {
     101            let request = this.allyRequests.get(evt.from);
     102            if (request.status === -1 || request.status === -2)
     103                continue;
     104
     105            request.wanted -= evt.amounts[request.type];
     106
     107            if (request.wanted <= 0)
     108            {
     109                if (this.Config.debug > 1)
     110                    API3.warn("Player " + uneval(evt.from) + " has sent the required tribute amount");
     111
     112                this.changePlayerDiplomacy(gameState, evt.from, "ally");
     113                // if this new ally turns on us later and requests to ally again, we will decline
     114                request.status = -2;
     115            }
     116        }
     117
    89118        if (evt.to !== PlayerID || !gameState.isPlayerAlly(evt.from))
    90119            continue;
    91120        let tributes = 0;
     
    114143
    115144    if (events.DiplomacyChanged.length || events.PlayerDefeated.length || events.CeasefireEnded.length)
    116145        this.lastManStandingCheck(gameState);
     146
     147    if (gameState.getAlliedVictory())
     148        return;
     149
     150    for (let evt of events.DiplomacyChanged)
     151        if (evt.otherPlayer === PlayerID && !gameState.isPlayerAlly(evt.player))
     152            if (gameState.sharedScript.playersData[evt.player].isAlly[PlayerID])
     153                this.handleAllyRequest(gameState, evt.player);
     154            else if (this.allyRequests.has(evt.player)) // a player that had requested to be allies changed their stance with us
     155                this.allyRequests.get(evt.player).status = -2;
    117156};
    118157
    119158/**
     
    181220    }
    182221
    183222    if (playerToTurnAgainst)
    184     {
    185         Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": playerToTurnAgainst, "to": "enemy" });
    186         if (this.Config.debug > 1)
    187             API3.warn("player " + playerToTurnAgainst + " is now an enemy");
    188         if (this.Config.chat)
    189             m.chatNewDiplomacy(gameState, playerToTurnAgainst, true);
    190     }
     223        this.changePlayerDiplomacy(gameState, playerToTurnAgainst, "enemy");
    191224    this.betrayLapseTime = -1;
    192225    this.waitingToBetray = false;
    193226};
    194227
     228/**
     229 * Do not become allies with a player if the game would be over.
     230 * Overall, be reluctant to become allies with any one player; be more likely to
     231 * demand a tribute if the requesting player is not as strong as us.
     232 */
     233m.DiplomacyManager.prototype.handleAllyRequest = function(gameState, player)
     234{
     235    let response;
     236    let requiredTribute;
     237    let request = this.allyRequests.get(player);
     238
     239    // for any given ally request be likely to permanently decline
     240    if (!request && gameState.getPlayerCiv() !== gameState.getPlayerCiv(player) && Math.random() > 0.4)
     241    {
     242        this.allyRequests.set(player, { "status": -1 });
     243        response = "decline";
     244    }
     245    else if (request)
     246    {
     247        if (request.status === -1)
     248            response = "decline";
     249        else if (request.status === -2) // we had become allies with this player and the alliance was broken, so decline
     250            response = "declineRepeatedOffer";
     251        else if (request.wanted > 0) // already sent ally request, and has not yet sent the required tributes
     252        {
     253            response = "waitingForTribute";
     254            requiredTribute = request;
     255        }
     256    }
     257    else if (gameState.getEnemies().length < 3 || gameState.ai.HQ.attackManager.currentEnemyPlayer === player)
     258    {
     259        response = "decline";
     260        this.allyRequests.set(player, { "status": -1 });
     261    }
     262    else if (gameState.getEntities(player).length < gameState.getOwnEntities().length && Math.random() > 0.6)
     263    {
     264        // if this player has less entities than us, be less likely to demand a tribute
     265        response = "accept";
     266        this.changePlayerDiplomacy(gameState, player, "ally");
     267        this.allyRequests.set(player, { "status": -2 });
     268    }
     269    else
     270    {
     271        response = "acceptWithTribute";
     272        requiredTribute = gameState.ai.HQ.pickMostNeededResources(gameState)[0];
     273        requiredTribute.wanted = Math.max(1000, gameState.getOwnUnits().length * 10);
     274        this.allyRequests.set(player, {
     275            "status": 1,
     276            "wanted": requiredTribute.wanted,
     277            "type": requiredTribute.type,
     278        });
     279    }
     280    m.chatAnswerRequestAlly(gameState, player, response, requiredTribute);
     281};
     282
     283/**
     284 * Change our diplomacy stance with a player, and send a chat message
     285 */
     286m.DiplomacyManager.prototype.changePlayerDiplomacy = function(gameState, player, newDiplomaticStance)
     287{
     288    Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": player, "to": newDiplomaticStance });
     289    if (this.Config.debug > 1)
     290        API3.warn("diplomacy stance with player " + player + " is now " + newDiplomaticStance);
     291    if (this.Config.chat)
     292        m.chatNewDiplomacy(gameState, player, newDiplomaticStance);
     293};
     294
    195295m.DiplomacyManager.prototype.update = function(gameState, events)
    196296{
    197297    this.checkEvents(gameState, events);
     
    209309        "nextTributeUpdate": this.nextTributeUpdate,
    210310        "nextTributeRequest": this.nextTributeRequest,
    211311        "betrayLapseTime": this.betrayLapseTime,
    212         "waitingToBetray": this.waitingToBetray
     312        "waitingToBetray": this.waitingToBetray,
     313        "allyRequests": this.allyRequests
    213314    };
    214315};
    215316