Ticket #4143: petra_lastmanstanding_v1.patch

File petra_lastmanstanding_v1.patch, 8.1 KB (added by Sandarac, 7 years ago)

Petra will turn against the ally with the highest population when only allies remain.

  • binaries/data/mods/public/simulation/ai/common-api/gamestate.js

     
    2121    this.playerData = SharedScript.playersData[this.player];
    2222    this.barterPrices = SharedScript.barterPrices;
    2323    this.gameType = SharedScript.gameType;
     24    this.alliedVictory = SharedScript.alliedVictory;
    2425
    2526    // get the list of possible phases for this civ:
    2627    // we assume all of them are researchable from the civil centre
     
    117118    return this.gameType;
    118119};
    119120
     121m.GameState.prototype.getAlliedVictory = function()
     122{
     123    return this.alliedVictory;
     124};
     125
    120126m.GameState.prototype.getTemplate = function(type)
    121127{
    122128    if (this.techTemplates[type] !== undefined)
     
    408414    return this.updatingGlobalCollection("" + this.player + "-units", m.Filters.byClass("Unit"), this.getOwnEntities());
    409415};
    410416
    411 m.GameState.prototype.getAllyEntities = function()
     417m.GameState.prototype.getAllyEntities = function(allyID)
    412418{
    413     return this.entities.filter(m.Filters.byOwners(this.getAllies()));
     419    if (allyID === undefined)
     420        return this.entities.filter(m.Filters.byOwners(this.getAllies()));
     421
     422    return this.updatingGlobalCollection("" + allyID + "-entities", m.Filters.byOwner(allyID));
    414423};
    415424
    416425m.GameState.prototype.getExclusiveAllyEntities = function()
  • binaries/data/mods/public/simulation/ai/common-api/shared.js

     
    142142    this.mapSize = state.mapSize;
    143143    this.gameType = state.gameType;
    144144    this.barterPrices = state.barterPrices;
     145    this.alliedVictory = state.alliedVictory;
    145146
    146147    this.passabilityMap = state.passabilityMap;
    147148    if (this.mapSize % this.passabilityMap.width !== 0)
  • binaries/data/mods/public/simulation/ai/petra/chatHelper.js

     
    130130    });
    131131};
    132132
     133m.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": "/allies " + message,
     144        "translateMessage": true,
     145        "translateParameters": ["_player_"],
     146        "parameters": {"_player_": player}
     147    });
     148};
     149
    133150return m;
    134151}(PETRA);
  • binaries/data/mods/public/simulation/ai/petra/diplomacyManager.js

     
    1313    this.nextTributeUpdate = -1;
    1414    this.nextTributeRequest = new Map();
    1515    this.nextTributeRequest.set("all", 240);
     16    this.allyBetrayLapseTime = -1;
     17    this.waitingToBetray = false;
    1618};
    1719
    1820/**
     
    108110            continue;
    109111        this.Config.personality.cooperative = Math.min(1, this.Config.personality.cooperative + 0.003);
    110112    }
     113
     114    for (let evt of events.DiplomacyChanged)
     115        this.lastManStandingCheck(gameState);
     116
     117    for (let evt of events.PlayerDefeated)
     118        this.lastManStandingCheck(gameState);
    111119};
    112120
     121/**
     122 * Check if the only remaining players are allies. If so, turn against the strongest first
     123 * if "Last Man Standing" is enabled
     124 */
     125m.DiplomacyManager.prototype.lastManStandingCheck = function(gameState)
     126{
     127    if (gameState.getAlliedVictory())
     128        return;
    113129
     130    let allyToTurnAgainst;
     131    let allyUnits = 0;
     132    let max = 0;
     133
     134    // do not turn against an ally if there are still non-allied players
     135    for (let i = 1; i < gameState.sharedScript.playersData.length; ++i)
     136    {
     137        if (i === PlayerID || gameState.ai.HQ.attackManager.defeated[i])
     138            continue;
     139
     140        if (!gameState.isPlayerAlly(i))
     141            return;
     142
     143        // count the amount of units this ally has
     144        for (let ent of gameState.getAllyEntities(i).values())
     145            allyUnits++;
     146
     147        if (allyUnits < max)
     148            continue;
     149
     150        max = allyUnits;
     151        allyToTurnAgainst = i;
     152    }
     153
     154     // wait a bit before turning
     155    if (!this.waitingToBetray)
     156    {
     157        this.allyBetrayLapseTime = gameState.ai.elapsedTime + Math.random() * 100 + 10;;
     158        this.waitingToBetray = true;
     159        return;
     160    }
     161
     162    if (this.allyBetrayLapseTime != -1 && this.waitingToBetray)
     163    {
     164        // do not turn against an ally yet if we are not strong enough
     165        if (gameState.getOwnUnits().length < 50)
     166        {
     167            this.allyBetrayLapseTime += 60;
     168            return;
     169        }
     170
     171        if (allyToTurnAgainst)
     172        {
     173            Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": allyToTurnAgainst, "to": "enemy" });
     174            if (this.Config.debug > 1)
     175                API3.warn("player " + allyToTurnAgainst + " is now an enemy");
     176            if (this.Config.chat)
     177                m.chatNewDiplomacy(gameState, allyToTurnAgainst, true);
     178        }
     179        this.allyBetrayLapseTime = -1;
     180        this.waitingToBetray = false;
     181    }
     182};
     183
    114184m.DiplomacyManager.prototype.update = function(gameState, events)
    115185{
    116186    this.checkEvents(gameState, events);
     
    117187
    118188    if (!gameState.ai.HQ.saveResources && gameState.ai.elapsedTime > this.nextTributeUpdate)
    119189        this.tributes(gameState);
     190
     191    if (this.allyBetrayLapseTime != -1 && gameState.ai.elapsedTime > this.allyBetrayLapseTime)
     192        this.lastManStandingCheck(gameState);
    120193};
    121194
    122195m.DiplomacyManager.prototype.Serialize = function()
    123196{
    124     return { "nextTributeUpdate": this.nextTributeUpdate, "nextTributeRequest": this.nextTributeRequest };
     197    return {
     198        "nextTributeUpdate": this.nextTributeUpdate,
     199        "nextTributeRequest": this.nextTributeRequest,
     200        "allyBetrayLapseTime": this.allyBetrayLapseTime,
     201        "waitingToBetray": this.waitingToBetray
     202    };
    125203};
    126204
    127205m.DiplomacyManager.prototype.Deserialize = function(data)
     
    128206{
    129207    this.nextTributeUpdate = data.nextTributeUpdate;
    130208    this.nextTributeRequest = data.nextTributeRequest;
     209    this.allyBetrayLapseTime = data.allyBetrayLapseTime;
     210    this.waitingToBetray = data.waitingToBetray;
    131211};
    132212
    133213return m;
  • binaries/data/mods/public/simulation/ai/petra/headquarters.js

     
    8282    this.treasures.registerUpdates();
    8383    this.currentPhase = gameState.currentPhase();
    8484    this.decayingStructures = new Set();
     85    this.diplomacyManager.lastManStandingCheck(gameState);
    8586};
    8687
    8788/**
  • binaries/data/mods/public/simulation/components/EndGameManager.js

     
    7676    this.alliedVictory = flag;
    7777};
    7878
     79EndGameManager.prototype.GetAlliedVictory = function()
     80{
     81    return this.alliedVictory;
     82};
     83
    7984EndGameManager.prototype.AlliedVictoryCheck = function()
    8085{
    8186    if (this.skipAlliedVictoryCheck)
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    144144        ret.ceasefireTimeRemaining = ret.ceasefireActive ? cmpCeasefireManager.GetCeasefireStartedTime() + cmpCeasefireManager.GetCeasefireTime() - ret.timeElapsed : 0;
    145145    }
    146146
    147     // Add the game type
     147    // Add the game type and allied victory
    148148    let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
    149149    ret.gameType = cmpEndGameManager.GetGameType();
     150    ret.alliedVictory = cmpEndGameManager.GetAlliedVictory();
    150151
    151152    // Add bartering prices
    152153    let cmpBarter = Engine.QueryInterface(SYSTEM_ENTITY, IID_Barter);