Ticket #4143: petra_lastmanstanding_v1.1.patch

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

Some fixes.

  • 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;
     25    this.ceasefireActive = SharedScript.ceasefireActive;
    2426
    2527    // get the list of possible phases for this civ:
    2628    // we assume all of them are researchable from the civil centre
     
    5557    this.timeElapsed = SharedScript.timeElapsed;
    5658    this.playerData = SharedScript.playersData[this.player];
    5759    this.barterPrices = SharedScript.barterPrices;
     60    this.ceasefireActive = SharedScript.ceasefireActive;
    5861};
    5962
    6063m.GameState.prototype.updatingCollection = function(id, filter, collection)
     
    117120    return this.gameType;
    118121};
    119122
     123m.GameState.prototype.getAlliedVictory = function()
     124{
     125    return this.alliedVictory;
     126};
     127
     128m.GameState.prototype.isCeasefireActive = function()
     129{
     130    return this.ceasefireActive;
     131};
     132
    120133m.GameState.prototype.getTemplate = function(type)
    121134{
    122135    if (this.techTemplates[type] !== undefined)
     
    291304m.GameState.prototype.hasAllies = function()
    292305{
    293306    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")
    295309            return true;
    296310    return false;
    297311};
    298312
     313m.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
    299322m.GameState.prototype.isPlayerAlly = function(id)
    300323{
    301324    return this.playerData.isAlly[id];
     
    408431    return this.updatingGlobalCollection("" + this.player + "-units", m.Filters.byClass("Unit"), this.getOwnEntities());
    409432};
    410433
    411 m.GameState.prototype.getAllyEntities = function()
     434m.GameState.prototype.getAllyEntities = function(allyID)
    412435{
    413     return this.entities.filter(m.Filters.byOwners(this.getAllies()));
     436    if (allyID === undefined)
     437        return this.entities.filter(m.Filters.byOwners(this.getAllies()));
     438
     439    return this.updatingGlobalCollection("" + allyID + "-entities", m.Filters.byOwner(allyID));
    414440};
    415441
    416442m.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;
     146    this.ceasefireActive = state.ceasefireActive;
    145147
    146148    this.passabilityMap = state.passabilityMap;
    147149    if (this.mapSize % this.passabilityMap.width !== 0)
     
    241243    this.playersData = state.players;
    242244    this.timeElapsed = state.timeElapsed;
    243245    this.barterPrices = state.barterPrices;
     246    this.ceasefireActive = state.ceasefireActive;
    244247
    245248    this.passabilityMap = state.passabilityMap;
    246249    this.passabilityMap.cellSize = this.mapSize / this.passabilityMap.width;
  • 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": 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    if (events.DiplomacyChanged.length || events.PlayerDefeated.length || events.CeasefireEnded.length)
     115        this.lastManStandingCheck(gameState);
    111116};
    112117
     118/**
     119 * Check if the only remaining players are allies. If so, turn against the strongest first
     120 * if the "Last Man Standing" option is enabled
     121 */
     122m.DiplomacyManager.prototype.lastManStandingCheck = function(gameState)
     123{
     124    if (gameState.getAlliedVictory() || gameState.isCeasefireActive())
     125        return;
    113126
     127    if (gameState.hasEnemies())
     128    {
     129        this.waitingToBetray = false;
     130        return;
     131    }
     132
     133    if (!gameState.hasAllies())
     134        return;
     135
     136    // wait a bit before turning
     137    if (!this.waitingToBetray)
     138    {
     139        this.allyBetrayLapseTime = gameState.ai.elapsedTime + Math.random() * 100 + 10;
     140        this.waitingToBetray = true;
     141        return;
     142    }
     143
     144    // do not turn against an ally yet if we are not strong enough
     145    if (gameState.getOwnUnits().length < 50)
     146    {
     147        this.allyBetrayLapseTime += 60;
     148        return;
     149    }
     150
     151    let allyToTurnAgainst;
     152    let allyEntities = 0;
     153    let max = 0;
     154
     155    // count the amount of entities our allies have
     156    for (let i = 1; i < gameState.sharedScript.playersData.length; ++i)
     157    {
     158        if (i === PlayerID || gameState.ai.HQ.attackManager.defeated[i])
     159            continue;
     160
     161        allyEntities = gameState.getAllyEntities(i).length;
     162
     163        if (allyEntities < max)
     164            continue;
     165
     166        max = allyEntities;
     167        allyToTurnAgainst = i;
     168    }
     169
     170    if (allyToTurnAgainst)
     171    {
     172        Engine.PostCommand(PlayerID, { "type": "diplomacy", "player": allyToTurnAgainst, "to": "enemy" });
     173        if (this.Config.debug > 1)
     174            API3.warn("player " + allyToTurnAgainst + " is now an enemy");
     175        if (this.Config.chat)
     176            m.chatNewDiplomacy(gameState, allyToTurnAgainst, true);
     177    }
     178    this.allyBetrayLapseTime = -1;
     179    this.waitingToBetray = false;
     180};
     181
    114182m.DiplomacyManager.prototype.update = function(gameState, events)
    115183{
    116184    this.checkEvents(gameState, events);
     
    117185
    118186    if (!gameState.ai.HQ.saveResources && gameState.ai.elapsedTime > this.nextTributeUpdate)
    119187        this.tributes(gameState);
     188
     189    if (this.waitingToBetray && gameState.ai.elapsedTime > this.allyBetrayLapseTime)
     190        this.lastManStandingCheck(gameState);
    120191};
    121192
    122193m.DiplomacyManager.prototype.Serialize = function()
    123194{
    124     return { "nextTributeUpdate": this.nextTributeUpdate, "nextTributeRequest": this.nextTributeRequest };
     195    return {
     196        "nextTributeUpdate": this.nextTributeUpdate,
     197        "nextTributeRequest": this.nextTributeRequest,
     198        "allyBetrayLapseTime": this.allyBetrayLapseTime,
     199        "waitingToBetray": this.waitingToBetray
     200    };
    125201};
    126202
    127203m.DiplomacyManager.prototype.Deserialize = function(data)
    128204{
    129     this.nextTributeUpdate = data.nextTributeUpdate;
    130     this.nextTributeRequest = data.nextTributeRequest;
     205    for (let key in data)
     206        this[key] = data[key];
    131207};
    132208
    133209return 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/AIInterface.js

     
    2020    "TerritoriesChanged",
    2121    "TerritoryDecayChanged",
    2222    "TributeExchanged",
    23     "AttackRequest"
     23    "AttackRequest",
     24    "CeasefireEnded"
    2425];
    2526
    2627AIInterface.prototype.Init = function()
     
    197198    this.events.TerritoriesChanged.push(msg);
    198199};
    199200
     201AIInterface.prototype.OnCeasefireEnded = function(msg)
     202{
     203    this.events.CeasefireEnded.push(msg);
     204};
     205
    200206/**
    201207 * When a new technology is researched, check which templates it affects,
    202208 * and send the updated values to the AI.
  • 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);
  • binaries/data/mods/public/simulation/components/tests/test_EndGameManager.js

     
     1Engine.LoadComponentScript("interfaces/Player.js");
     2Engine.LoadComponentScript("interfaces/EndGameManager.js");
     3Engine.LoadComponentScript("Player.js");
     4
     5Engine.LoadComponentScript("PlayerManager.js");
     6Engine.LoadComponentScript("EndGameManager.js");
     7Engine.LoadComponentScript("GuiInterface.js");
     8
     9let cmpEndGameManager = ConstructComponent(SYSTEM_ENTITY, "EndGameManager");
     10let playerEnt1 = 1;
     11let wonderDuration = 1;
     12
     13let gameTypeSettings = {};
     14gameTypeSettings.wonderDuration = wonderDuration * 60 * 1000;
     15
     16AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
     17    "GetNumPlayers": () => 4
     18});
     19
     20AddMock(SYSTEM_ENTITY, IID_GuiInterface, {
     21    "DeleteTimeNotification": () => null,
     22    "AddTimeNotification": () => 1
     23});
     24
     25AddMock(playerEnt1, IID_Player, {
     26    "GetName": () => "Player 1",
     27    "GetState": () => "active",
     28});
     29
     30let cmpPlayerManager = ConstructComponent(SYSTEM_ENTITY, "PlayerManager");
     31
     32TS_ASSERT_EQUALS(cmpEndGameManager.skipAlliedVictoryCheck, true);
     33cmpEndGameManager.SetAlliedVictory(true);
     34TS_ASSERT_EQUALS(cmpEndGameManager.GetAlliedVictory(), true);
     35cmpEndGameManager.SetGameType("wonder", gameTypeSettings);
     36TS_ASSERT_EQUALS(cmpEndGameManager.CheckGameType("regicide"), false);
     37TS_ASSERT_EQUALS(cmpEndGameManager.skipAlliedVictoryCheck, false);
     38TS_ASSERT(cmpEndGameManager.GetGameType() == "wonder");
     39TS_ASSERT_EQUALS(cmpEndGameManager.GetGameTypeSettings().wonderDuration, 60000);
     40cmpEndGameManager.AlliedVictoryCheck();
  • binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js

    Property changes on: binaries/data/mods/public/simulation/components/tests/test_EndGameManager.js
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
    4747});
    4848
    4949AddMock(SYSTEM_ENTITY, IID_EndGameManager, {
    50     GetGameType: function() { return "conquest"; }
     50    GetGameType: function() { return "conquest"; },
     51    GetAlliedVictory: function() { return false; }
    5152});
    5253
    5354AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
     
    331332    circularMap: false,
    332333    timeElapsed: 0,
    333334    gameType: "conquest",
     335    alliedVictory: false,
    334336    barterPrices: {buy: {food: 150}, sell: {food: 25}}
    335337});
    336338
     
    450452    circularMap: false,
    451453    timeElapsed: 0,
    452454    gameType: "conquest",
     455    alliedVictory: false,
    453456    barterPrices: {buy: {food: 150}, sell: {food: 25}}
    454457});
    455458