Ticket #1089: AIFix.patch

File AIFix.patch, 8.5 KB (added by wraitii, 6 years ago)
  • binaries/data/mods/public/simulation/ai/aegis/aegis.js

     
    227227    }
    228228};
    229229
    230 // TODO: Remove override when the whole AI state is serialised
    231 // TODO: this currently is very much equivalent to "rungamestateinit" with a few hacks. Should deserialize/serialize properly someday.
    232 AegisBot.prototype.Deserialize = function(data, sharedScript)
     230/*AegisBot.prototype.Deserialize = function(data, sharedScript)
    233231{
    234     BaseAI.prototype.Deserialize.call(this, data);
    235    
    236     var ents = sharedScript.entities.filter(Filters.byOwner(PlayerID));
    237     var myKeyEntities = ents.filter(function(ent) {
    238         return ent.hasClass("CivCentre");
    239     });
    240    
    241     if (myKeyEntities.length == 0){
    242         myKeyEntities = sharedScript.entities.filter(Filters.byOwner(PlayerID));
    243     }
    244    
    245     var filter = Filters.byClass("CivCentre");
    246     var enemyKeyEntities = sharedScript.entities.filter(Filters.not(Filters.byOwner(PlayerID))).filter(filter);
    247    
    248     if (enemyKeyEntities.length == 0){
    249         enemyKeyEntities = sharedScript.entities.filter(Filters.not(Filters.byOwner(PlayerID)));
    250     }
    251    
    252     this.terrainAnalyzer = sharedScript.terrainAnalyzer;
    253     this.passabilityMap = sharedScript.passabilityMap;
    254 
    255     var fakeState = { "ai" : this, "sharedScript" : sharedScript };
    256     this.pathFinder = new aStarPath(fakeState, false, true);
    257     this.pathsToMe = [];
    258     this.pathInfo = { "angle" : 0, "needboat" : true, "mkeyPos" : myKeyEntities.toEntityArray()[0].position(), "ekeyPos" : enemyKeyEntities.toEntityArray()[0].position() };
    259    
    260     // First path has a sampling of 3, which ensures we'll get at least one path even on Acropolis. The others are 6 so might fail.
    261     var pos = [this.pathInfo.mkeyPos[0] + 150*Math.cos(this.pathInfo.angle),this.pathInfo.mkeyPos[1] + 150*Math.sin(this.pathInfo.angle)];
    262     var path = this.pathFinder.getPath(this.pathInfo.ekeyPos, pos, 2, 2);
    263    
    264     if (path !== undefined && path[1] !== undefined && path[1] == false) {
    265         // path is viable and doesn't require boating.
    266         // blackzone the last two waypoints.
    267         this.pathFinder.markImpassableArea(path[0][0][0],path[0][0][1],20);
    268         this.pathsToMe.push(path[0][0][0]);
    269         this.pathInfo.needboat = false;
    270     }
    271     this.pathInfo.angle += Math.PI/3.0;
    272232};
    273233
    274234// Override the default serializer
    275235AegisBot.prototype.Serialize = function()
    276236{
    277     //var ret = BaseAI.prototype.Serialize.call(this);
    278237    return {};
    279 };
     238};*/
    280239
    281240function debug(output){
    282241    if (Config.debug){
  • binaries/data/mods/public/simulation/ai/common-api-v3/baseAI.js

     
    2626{
    2727    // TODO: ought to get the AI script subclass to deserialize its own state
    2828    // TODO: actually this is part of a larger reflection on wether AIs should or not.
     29    this.isDeserialized = true;
    2930};
    3031
    3132BaseAI.prototype.Init = function(state, sharedAI)
     
    5960{
    6061    this.events = sharedAI.events;
    6162   
     63    if (this.isDeserialized && this.turn !== 0)
     64    {
     65        this.isDeserialized = false;
     66        this.Init(state, sharedAI);
     67    } else if (this.isDeserialized)
     68        return;
    6269    this.OnUpdate(sharedAI);
    6370};
    6471
  • binaries/data/mods/public/simulation/ai/common-api-v3/shared.js

     
    3737//Return a simple object (using no classes etc) that will be serialized
    3838//into saved games
    3939//TODO: that
    40 // note: we'll need to serialize much more than that before this can work.
    4140SharedScript.prototype.Serialize = function()
    4241{
    43     // serializing entities without using the class.
    44     var entities = [];
    45     for (var id in this._entities)
    46     {
    47         var ent = this._entities[id];
    48         entities.push( [ent._template, ent._entity, ent._templateName]);
    49     }
    50    
    51     // serialiazing metadata will be done by each AI on a AI basis and they shall update the shared script with that info on deserialization (using DeserializeMetadata() ).
    52     // TODO: this may not be the most clever method.
    53     return { "entities" : entities, "techModifs" : this._techModifications, "passabClasses" : this.passabilityClasses, "passabMap" : this.passabilityMap,
    54         "timeElapsed" : this.timeElapsed, "techTemplates" : this._techTemplates, "players": this._players};
     42    return { "players" : this._players, "templates" : this._templates, "techTp" : this._techTemplates };
    5543};
    5644
    5745// Called after the constructor when loading a saved game, with 'data' being
    5846// whatever Serialize() returned
    59 // todo: very not-finished. Mostly hacky, and ugly too.
    6047SharedScript.prototype.Deserialize = function(data)
    6148{
    62     this._entities = {};
    63 
    6449    this._players = data.players;
    65     this._entityMetadata = {};
    66     for (var i in this._players)
    67         this._entityMetadata[this._players[i]] = {};
    68 
    69     this._techModifications = data.techModifs;
    70     this.techModifications = data.techModifs;   // needed for entities
    71    
    72     this.passabilityClasses = data.passabClasses;
    73     this.passabilityMap = data.passabMap;
    74     var dataArray = [];
    75     for (var i in this.passabilityMap.data)
    76         dataArray.push(this.passabilityMap.data[i]);
    77 
    78     this.passabilityMap.data = dataArray;
    79 
    80     // TODO: this is needlessly slow (not to mention a hack)
    81     // Should probably call a "init" function rather to avoid this and serialize the terrainanalyzer state.
    82     var fakeState = { "passabilityClasses" : this.passabilityClasses, "passabilityMap":this.passabilityMap };
    83     this.terrainAnalyzer = new TerrainAnalysis (this, fakeState);
    84     this.accessibility = new Accessibility(fakeState, this.terrainAnalyzer);
    85    
    86     this._techTemplates = data.techTemplates;
    87     this.timeElapsed = data.timeElapsed;
    88 
    89     // deserializing entities;
    90     for (var i in data.entities)
    91     {
    92         var entData = data.entities[i];
    93         entData[1].template = entData[2];
    94         this._entities[entData[1].id] = new Entity(this, entData[1]);
    95     }
    96     // entity collection updated on create/destroy event.
    97     this.entities = new EntityCollection(this, this._entities);
    98    
    99     //deserializing game states.
    100     fakeState["timeElapsed"] = this.timeElapsed;
    101     fakeState["players"] = this._players;
    102    
    103     this.gameState = {};
    104     for (var i in this._players)
    105         this.gameState[this._players[i]] = new GameState(this, fakeState, this._players[i]);
     50    this._templates = data.templates;
     51    this._techTemplates = data.techTp;
     52    this.isDeserialized = true;
    10653};
    10754
    10855// Components that will be disabled in foundation entity templates.
     
    207154// applies entity deltas, and each gamestate.
    208155SharedScript.prototype.onUpdate = function(state)
    209156{
     157    if (this.isDeserialized && this.turn !== 0)
     158    {
     159        this.isDeserialized = false;
     160        this.init(state);
     161    } else if (this.isDeserialized)
     162        return;
    210163    // deals with updating based on create and destroy messages.
    211164    this.ApplyEntitiesDelta(state);
    212165
  • source/simulation2/components/CCmpAIManager.cpp

     
    892892    virtual void Init(const CParamNode& UNUSED(paramNode))
    893893    {
    894894        m_TerritoriesDirtyID = 0;
     895        m_JustDeserialized = false;
    895896
    896897        StartLoadEntityTemplates();
    897898    }
     
    917918        ForceLoadEntityTemplates();
    918919
    919920        m_Worker.Deserialize(deserialize.GetStream());
     921       
     922        m_JustDeserialized = true;
    920923    }
    921924
    922925    virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     
    10161019        ENSURE(cmpAIInterface);
    10171020
    10181021        // Get the game state from AIInterface
    1019         CScriptVal state = cmpAIInterface->GetRepresentation();
     1022        CScriptVal state;
     1023        if (m_JustDeserialized)
     1024            state = cmpAIInterface->GetFullRepresentation(true);
     1025        else
     1026            state = cmpAIInterface->GetRepresentation();
    10201027
    10211028        // Get the passability data
    10221029        Grid<u16> dummyGrid;
     
    10401047        LoadPathfinderClasses(state);
    10411048
    10421049        m_Worker.StartComputation(scriptInterface.WriteStructuredClone(state.get()), *passabilityMap, *territoryMap, territoryMapDirty);
     1050       
     1051        m_JustDeserialized = false;
    10431052    }
    10441053
    10451054    virtual void PushCommands()
     
    10691078    std::vector<std::pair<std::string, const CParamNode*> > m_Templates;
    10701079    size_t m_TerritoriesDirtyID;
    10711080
     1081    bool m_JustDeserialized;
     1082
    10721083    void StartLoadEntityTemplates()
    10731084    {
    10741085        CmpPtr<ICmpTemplateManager> cmpTemplateManager(GetSystemEntity());