Ticket #2322: AI_in_one_global_WIP_v0.4.diff

File AI_in_one_global_WIP_v0.4.diff, 308.7 KB (added by Yves, 10 years ago)

This version also moves Aegis to its own module

  • binaries/data/mods/public/simulation/ai/aegis/base-manager.js

     
     1var AEGIS = function(m)
     2{
    13/* Base Manager
    24 * Handles lower level economic stuffs.
    35 * Some tasks:
     
    1012    -updating whatever needs updating, keeping track of stuffs (rebuilding needs…)
    1113 */
    1214
    13 var BaseManager = function() {
     15m.BaseManager = function(Config) {
     16    this.Config = Config;
    1417    this.farmingFields = false;
    15     this.ID = uniqueIDBases++;
     18    this.ID = m.playerGlobals[PlayerID].uniqueIDBases++;
    1619   
    1720    // anchor building: seen as the main building of the base. Needs to have territorial influence
    1821    this.anchor = undefined;
     
    3134    this.territoryIndices = [];
    3235};
    3336
    34 BaseManager.prototype.init = function(gameState, events, unconstructed){
     37m.BaseManager.prototype.init = function(gameState, events, unconstructed){
    3538    this.constructing = unconstructed;
    3639    // entitycollections
    37     this.units = gameState.getOwnEntities().filter(Filters.and(Filters.byClass("Unit"),Filters.byMetadata(PlayerID, "base", this.ID)));
    38     this.buildings = gameState.getOwnEntities().filter(Filters.and(Filters.byClass("Structure"),Filters.byMetadata(PlayerID, "base", this.ID)));
     40    this.units = gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byClass("Unit"),API3.Filters.byMetadata(PlayerID, "base", this.ID)));
     41    this.buildings = gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byClass("Structure"),API3.Filters.byMetadata(PlayerID, "base", this.ID)));
    3942   
    40     this.workers = this.units.filter(Filters.byMetadata(PlayerID,"role","worker"));
     43    this.workers = this.units.filter(API3.Filters.byMetadata(PlayerID,"role","worker"));
    4144
    4245    this.workers.allowQuickIter();
    4346    this.buildings.allowQuickIter();
     
    6265    this.bigRadius = { 'food':70*70,'wood':200*200,'stone':200*200,'metal':200*200 };
    6366};
    6467
    65 BaseManager.prototype.assignEntity = function(unit){
     68m.BaseManager.prototype.assignEntity = function(unit){
    6669    unit.setMetadata(PlayerID, "base", this.ID);
    6770    this.units.updateEnt(unit);
    6871    this.workers.updateEnt(unit);
     
    7376        this.territoryBuildings.push(unit.id());
    7477};
    7578
    76 BaseManager.prototype.setAnchor = function(anchorEntity) {
     79m.BaseManager.prototype.setAnchor = function(anchorEntity) {
    7780    if (!anchorEntity.hasClass("Structure") || !anchorEntity.hasTerritoryInfluence())
    7881    {
    7982        warn("Error: Aegis' base " + this.ID + " has been assigned an anchor building that has no territorial influence. Please report this on the forum.")
     
    9093}
    9194
    9295// affects the HQ map.
    93 BaseManager.prototype.initTerritory = function(HQ, gameState) {
     96m.BaseManager.prototype.initTerritory = function(HQ, gameState) {
    9497    if (!this.anchor)
    9598        warn ("Error: Aegis tried to initialize the territory of base " + this.ID + " without assigning it an anchor building first");
    9699    var radius = Math.round((this.anchor.territoryInfluenceRadius() / 4.0) * 1.25);
     
    122125            }
    123126}
    124127
    125 BaseManager.prototype.initGatheringFunctions = function(HQ, gameState, specTypes) {
     128m.BaseManager.prototype.initGatheringFunctions = function(HQ, gameState, specTypes) {
    126129    // init our gathering functions.
    127130    var types = ["food","wood","stone","metal"];
    128131    if (specTypes !== undefined)
     
    136139        var type = types[i];
    137140        // TODO: set us as "X" gatherer
    138141       
    139         this.buildings.filter(Filters.isDropsite(type)).forEach(function(ent) { self.initializeDropsite(gameState, ent,type) });
     142        this.buildings.filter(API3.Filters.isDropsite(type)).forEach(function(ent) { self.initializeDropsite(gameState, ent,type) });
    140143
    141144        if (this.getResourceLevel(gameState, type, "all") > 1000)
    142145            this.willGather[type] = 1;
     
    151154        if (needFarm)
    152155            this.willGather["food"] = 1;
    153156    }
    154     debug ("food" + this.willGather["food"]);
    155     debug (this.willGather["wood"]);
    156     debug (this.willGather["stone"]);
    157     debug (this.willGather["metal"]);
     157    m.debug ("food" + this.willGather["food"]);
     158    m.debug (this.willGather["wood"]);
     159    m.debug (this.willGather["stone"]);
     160    m.debug (this.willGather["metal"]);
    158161}
    159162
    160 BaseManager.prototype.checkEvents = function (gameState, events, queues) {
     163m.BaseManager.prototype.checkEvents = function (gameState, events, queues) {
    161164    for (i in events)
    162165    {
    163166        if (events[i].type == "Destroy")
     
    185188                    if (ent.hasClass("CivCentre"))
    186189                    {
    187190                        // TODO: might want to tell the queue manager to pause other stuffs if we are the only base.
    188                         queues.civilCentre.addItem(new ConstructionPlan(gameState, "structures/{civ}_civil_centre", { "base" : this.ID, "baseAnchor" : true }, 0 , -1,ent.position()));
     191                        queues.civilCentre.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_civil_centre", { "base" : this.ID, "baseAnchor" : true }, 0 , -1,ent.position()));
    189192                    } else {
    190193                        // TODO
    191                         queues.civilCentre.addItem(new ConstructionPlan(gameState, "structures/{civ}_civil_centre", { "base" : this.ID, "baseAnchor" : true },0,-1,ent.position()));
     194                        queues.civilCentre.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_civil_centre", { "base" : this.ID, "baseAnchor" : true },0,-1,ent.position()));
    192195                    }
    193196                }
    194197            }
     
    238241};
    239242
    240243// If no specific dropsite, it'll assign to the closest
    241 BaseManager.prototype.assignResourceToDP = function (gameState, supply, specificDP) {
     244m.BaseManager.prototype.assignResourceToDP = function (gameState, supply, specificDP) {
    242245    var type = supply.resourceSupplyType()["generic"];
    243246    if (type == "treasure")
    244247        type = supply.resourceSupplyType()["specific"];
     
    249252        for (i in this.dropsites)
    250253        {
    251254            var dp = gameState.getEntityById(i);
    252             var distance = SquareVectorDistance(supply.position(), dp.position());
     255            var distance = API3.SquareVectorDistance(supply.position(), dp.position());
    253256            if (distance < dist && distance < this.bigRadius[type])
    254257            {
    255258                closest = dp.id();
     
    267270    // TODO: ought to recount immediatly.
    268271}
    269272
    270 BaseManager.prototype.initializeDropsite = function (gameState, ent, type) {
     273m.BaseManager.prototype.initializeDropsite = function (gameState, ent, type) {
    271274    var count = 0, farCount = 0;
    272275    var self = this;
    273276
     
    278281        resources.filter( function (supply) { //}){
    279282            if (!supply.position() || !ent.position())
    280283                return;
    281             var distance = SquareVectorDistance(supply.position(), ent.position());
     284            var distance = API3.SquareVectorDistance(supply.position(), ent.position());
    282285           
    283286            if (supply.getMetadata(PlayerID, "linked-dropsite") == undefined || supply.getMetadata(PlayerID, "linked-dropsite-dist") > distance) {
    284287                if (distance < self.bigRadius[type]) {
     
    294297            }
    295298        });
    296299        // This one is both for the nearby and the linked
    297         var filter = Filters.byMetadata(PlayerID, "linked-dropsite", ent.id());
     300        var filter = API3.Filters.byMetadata(PlayerID, "linked-dropsite", ent.id());
    298301        var collection = resources.filter(filter);
    299302        collection.registerUpdates();
    300303       
    301         filter = Filters.byMetadata(PlayerID, "linked-dropsite-close",true);
     304        filter = API3.Filters.byMetadata(PlayerID, "linked-dropsite-close",true);
    302305        var collection2 = collection.filter(filter);
    303306        collection2.registerUpdates();
    304307
    305         filter = Filters.byMetadata(PlayerID, "linked-dropsite-nearby",true);
     308        filter = API3.Filters.byMetadata(PlayerID, "linked-dropsite-nearby",true);
    306309        var collection3 = collection.filter(filter);
    307310        collection3.registerUpdates();
    308311
    309         filter = Filters.byMetadata(PlayerID, "linked-to-dropsite", ent.id());
     312        filter = API3.Filters.byMetadata(PlayerID, "linked-to-dropsite", ent.id());
    310313        var WkCollection = this.workers.filter(filter);
    311314        WkCollection.registerUpdates();
    312315       
     
    318321        // TODO: get workers on those resources and do something with them.
    319322    }
    320323   
    321     if (Config.debug)
     324    if (this.Config.debug)
    322325    {
    323326        // Make resources glow wildly
    324327        if (type == "food") {
    325328            self.dropsites[ent.id()][type][2].forEach(function(ent){
    326                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0.5,0,0]});
     329                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0.5,0,0]});
    327330            });
    328331            self.dropsites[ent.id()][type][1].forEach(function(ent){
    329                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [2,0,0]});
     332                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [2,0,0]});
    330333            });
    331334            self.dropsites[ent.id()][type][0].forEach(function(ent){
    332                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,0,0]});
     335                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,0,0]});
    333336            });
    334337        }
    335338        if (type == "wood") {
    336339            self.dropsites[ent.id()][type][2].forEach(function(ent){
    337                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0.5,0]});
     340                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0.5,0]});
    338341            });
    339342            self.dropsites[ent.id()][type][1].forEach(function(ent){
    340                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,2,0]});
     343                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,2,0]});
    341344            });
    342345            self.dropsites[ent.id()][type][0].forEach(function(ent){
    343                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,0]});
     346                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,0]});
    344347            });
    345348        }
    346349        if (type == "stone") {
    347350            self.dropsites[ent.id()][type][2].forEach(function(ent){
    348                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0.5,0.5,0]});
     351                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0.5,0.5,0]});
    349352            });
    350353            self.dropsites[ent.id()][type][1].forEach(function(ent){
    351                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [2,2,0]});
     354                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [2,2,0]});
    352355            });
    353356            self.dropsites[ent.id()][type][0].forEach(function(ent){
    354                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,10,0]});
     357                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,10,0]});
    355358            });
    356359        }
    357360        if (type == "metal") {
    358361            self.dropsites[ent.id()][type][2].forEach(function(ent){
    359                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0.5,0.5]});
     362                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0.5,0.5]});
    360363            });
    361364            self.dropsites[ent.id()][type][1].forEach(function(ent){
    362                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,2,2]});
     365                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,2,2]});
    363366            });
    364367            self.dropsites[ent.id()][type][0].forEach(function(ent){
    365                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,10]});
     368                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,10]});
    366369            });
    367370        }
    368371    }
     
    371374// completely and "safely" remove a dropsite from our list.
    372375// this also removes any linked resource and so on.
    373376// TODO: should re-add the resources to another dropsite.
    374 BaseManager.prototype.scrapDropsite = function (gameState, ent) {
     377m.BaseManager.prototype.scrapDropsite = function (gameState, ent) {
    375378    if (this.dropsites[ent.id()] === undefined)
    376379        return true;
    377380   
     
    398401};
    399402
    400403// Returns the position of the best place to build a new dropsite for the specified resource
    401 BaseManager.prototype.findBestDropsiteLocation = function(gameState, resource){
     404m.BaseManager.prototype.findBestDropsiteLocation = function(gameState, resource){
    402405   
    403406    var storeHousePlate = gameState.getTemplate(gameState.applyCiv("structures/{civ}_storehouse"));
    404407
     
    407410    // Then checks for a good spot in the territory. If none, and town/city phase, checks outside
    408411    // The AI will currently not build a CC if it wouldn't connect with an existing CC.
    409412   
    410     var territory = Map.createTerritoryMap(gameState);
     413    var territory = m.createTerritoryMap(gameState);
    411414   
    412     var obstructions = Map.createObstructionMap(gameState,this.accessIndex,storeHousePlate);
     415    var obstructions = m.createObstructionMap(gameState,this.accessIndex,storeHousePlate);
    413416    obstructions.expandInfluences();
    414417   
    415418    // copy the resource map as initialization.
    416     var friendlyTiles = new Map(gameState.sharedScript, gameState.sharedScript.resourceMaps[resource].map, true);
     419    var friendlyTiles = new API3.Map(gameState.sharedScript, gameState.sharedScript.resourceMaps[resource].map, true);
    417420
    418     var DPFoundations = gameState.getOwnFoundations().filter(Filters.byType(gameState.applyCiv("foundation|structures/{civ}_storehouse")));
     421    var DPFoundations = gameState.getOwnFoundations().filter(API3.Filters.byType(gameState.applyCiv("foundation|structures/{civ}_storehouse")));
    419422   
    420423    // TODO: might be better to check dropsites someplace else.
    421424    // loop over this in this.terrytoryindices. It's usually a little too much, but it's always enough.
     
    434437        {
    435438            var pos = [j%friendlyTiles.width, Math.floor(j/friendlyTiles.width)];
    436439            var dpPos = gameState.getEntityById(i).position();
    437             if (dpPos && SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 250)
     440            if (dpPos && API3.SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 250)
    438441            {
    439442                friendlyTiles.map[j] = 0;
    440443                continue;
    441             } else if (dpPos && SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 450)
     444            } else if (dpPos && API3.SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 450)
    442445                friendlyTiles.map[j] /= 2;
    443446        }
    444447        for (var i in DPFoundations._entities)
    445448        {
    446449            var pos = [j%friendlyTiles.width, Math.floor(j/friendlyTiles.width)];
    447450            var dpPos = gameState.getEntityById(i).position();
    448             if (dpPos && SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 250)
     451            if (dpPos && API3.SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 250)
    449452                friendlyTiles.map[j] = 0;
    450             else if (dpPos && SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 450)
     453            else if (dpPos && API3.SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 450)
    451454                friendlyTiles.map[j] /= 2;
    452455        }
    453456    }
    454457   
    455     if (Config.debug)
     458    if (this.Config.debug)
    456459        friendlyTiles.dumpIm("DP_" + resource + "_" + gameState.getTimeElapsed() + ".png");
    457460   
    458461    var best = friendlyTiles.findBestTile(2, obstructions); // try to find a spot to place a DP.
     
    469472};
    470473
    471474// update the resource level of a dropsite.
    472 BaseManager.prototype.updateDropsite = function (gameState, ent, type) {
     475m.BaseManager.prototype.updateDropsite = function (gameState, ent, type) {
    473476    if (this.dropsites[ent.id()] === undefined || this.dropsites[ent.id()][type] === undefined)
    474477        return undefined;   // should initialize it first.
    475478
     
    490493};
    491494
    492495// Updates dropsites.
    493 BaseManager.prototype.updateDropsites = function (gameState) {
     496m.BaseManager.prototype.updateDropsites = function (gameState) {
    494497    // for each dropsite, recalculate
    495498    for (i in this.dropsites)
    496499    {
     
    507510// we're assuming Max - 3 for metal/stone mines, and 20 for any dropsite that has wood.
    508511// TODO: for wood might want to count the trees too.
    509512// TODO: this returns "future" worker capacity, might want to have a current one.
    510 BaseManager.prototype.getWorkerCapacity = function (gameState, type) {
     513m.BaseManager.prototype.getWorkerCapacity = function (gameState, type) {
    511514    var count = 0;
    512515    if (type == "food")
    513516        return 1000000; // TODO: perhaps return something sensible here.
     
    530533
    531534// TODO: ought to be cached or something probably
    532535// Returns the amount of resource left
    533 BaseManager.prototype.getResourceLevel = function (gameState, type, searchType, threshold) {
     536m.BaseManager.prototype.getResourceLevel = function (gameState, type, searchType, threshold) {
    534537    var count = 0;
    535538    if (searchType == "all")
    536539    {
    537540        // return all resources in the base area.
    538         gameState.getResourceSupplies(type).filter(Filters.byTerritory(gameState.ai.HQ.basesMap, this.ID)).forEach( function (ent) { //}){
     541        gameState.getResourceSupplies(type).filter(API3.Filters.byTerritory(gameState.ai.HQ.basesMap, this.ID)).forEach( function (ent) { //}){
    539542            count += ent.resourceSupplyAmount();
    540543        });
    541544        return count;
     
    574577};
    575578
    576579// check our resource levels and react accordingly
    577 BaseManager.prototype.checkResourceLevels = function (gameState,queues) {
     580m.BaseManager.prototype.checkResourceLevels = function (gameState,queues) {
    578581    for (type in this.willGather)
    579582    {
    580583        if (this.willGather[type] === 0)
     
    589592            if (!this.isFarming && count < 1600 && queues.field.length === 0)
    590593            {
    591594                // tell the queue manager we'll be trying to build fields shortly.
    592                 for (var  i = 0; i < Config.Economy.initialFields;++i)
     595                for (var  i = 0; i < this.Config.Economy.initialFields;++i)
    593596                {
    594                     var plan = new ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID });
     597                    var plan = new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID });
    595598                    plan.isGo = function() { return false; };   // don't start right away.
    596599                    queues.field.addItem(plan);
    597600                }
     
    604607            if (this.isFarming)
    605608            {
    606609                var numFarms = 0;
    607                 this.buildings.filter(Filters.byClass("Field")).forEach(function (field) {
     610                this.buildings.filter(API3.Filters.byClass("Field")).forEach(function (field) {
    608611                    if (field.resourceSupplyAmount() > 400)
    609612                        numFarms++;
    610613                });
     
    615618                // let's see if we need to push new farms.
    616619                if (numFd < 2)
    617620                    if (numFarms < Math.round(this.gatherersByType(gameState, "food").length / 4.6) || numFarms < Math.round(this.workers.length / 15.0))
    618                         queues.field.addItem(new ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID }));
     621                        queues.field.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID }));
    619622                // TODO: refine count to only count my base.
    620623            }
    621624        } else if (queues.dropsites.length() === 0 && gameState.countFoundationsWithType(gameState.applyCiv("structures/{civ}_storehouse")) === 0) {
     
    626629                var pos = this.findBestDropsiteLocation(gameState, type);
    627630                if (!pos)
    628631                {
    629                     debug ("Found no right position for a " + type + " dropsite, going into \"noSpot\" mode");
     632                    m.debug ("Found no right position for a " + type + " dropsite, going into \"noSpot\" mode");
    630633                    this.willGather[type] = 2;  // won't build
    631634                    // TODO: tell the HQ we'll be needing a new base for this resource, or tell it we've ran out of resource Z.
    632635                } else {
    633                     debug ("planning new dropsite for " + type);
    634                     queues.dropsites.addItem(new ConstructionPlan(gameState, "structures/{civ}_storehouse",{ "base" : this.ID }, 0, -1, pos));
     636                    m.debug ("planning new dropsite for " + type);
     637                    queues.dropsites.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_storehouse",{ "base" : this.ID }, 0, -1, pos));
    635638                }
    636639            }
    637640        }
     
    640643};
    641644
    642645// let's return the estimated gather rates.
    643 BaseManager.prototype.getGatherRates = function(gameState, currentRates) {
     646m.BaseManager.prototype.getGatherRates = function(gameState, currentRates) {
    644647
    645648};
    646649
    647 BaseManager.prototype.assignRolelessUnits = function(gameState) {
     650m.BaseManager.prototype.assignRolelessUnits = function(gameState) {
    648651    // TODO: make this cleverer.
    649     var roleless = this.units.filter(Filters.not(Filters.byHasMetadata(PlayerID, "role")));
     652    var roleless = this.units.filter(API3.Filters.not(API3.Filters.byHasMetadata(PlayerID, "role")));
    650653    var self = this;
    651654    roleless.forEach(function(ent) {
    652655        if (ent.hasClass("Worker") || ent.hasClass("CitizenSoldier")) {
     
    660663// If the numbers of workers on the resources is unbalanced then set some of workers to idle so
    661664// they can be reassigned by reassignIdleWorkers.
    662665// TODO: actually this probably should be in the HQ.
    663 BaseManager.prototype.setWorkersIdleByPriority = function(gameState){
     666m.BaseManager.prototype.setWorkersIdleByPriority = function(gameState){
    664667    var self = this;
    665668    if (gameState.currentPhase() < 2 && gameState.getTimeElapsed() < 360000)
    666669        return; // not in the first phase or the first 6 minutes.
     
    685688                this.gatherersByType(gameState,types.types[i]).forEach( function (ent) { //}){
    686689                    if (nb > 0)
    687690                    {
    688                         //debug ("Moving " +ent.id() + " from " + types.types[i]);
     691                        //m.debug ("Moving " +ent.id() + " from " + types.types[i]);
    689692                        nb--;
    690693                        // TODO: might want to direct assign.
    691694                        ent.stopMoving();
     
    693696                    }
    694697                });
    695698            }
    696     //debug (currentRates);
     699    //m.debug (currentRates);
    697700};
    698701
    699702// TODO: work on this.
    700 BaseManager.prototype.reassignIdleWorkers = function(gameState) {
     703m.BaseManager.prototype.reassignIdleWorkers = function(gameState) {
    701704   
    702705    var self = this;
    703706
    704707    // Search for idle workers, and tell them to gather resources based on demand
    705     var filter = Filters.or(Filters.byMetadata(PlayerID,"subrole","idle"), Filters.not(Filters.byHasMetadata(PlayerID,"subrole")));
     708    var filter = API3.Filters.or(API3.Filters.byMetadata(PlayerID,"subrole","idle"), API3.Filters.not(API3.Filters.byHasMetadata(PlayerID,"subrole")));
    706709    var idleWorkers = gameState.updatingCollection("idle-workers-base-" + this.ID, filter, this.workers);
    707710
    708711    if (idleWorkers.length) {
     
    713716            }
    714717            if (ent.hasClass("Worker")) {
    715718                var types = gameState.ai.HQ.pickMostNeededResources(gameState);
    716                 //debug ("assigning " +ent.id() + " to " + types[0]);
     719                //m.debug ("assigning " +ent.id() + " to " + types[0]);
    717720                ent.setMetadata(PlayerID, "subrole", "gatherer");
    718721                ent.setMetadata(PlayerID, "gather-type", types[0]);
    719722               
     
    734737    }
    735738};
    736739
    737 BaseManager.prototype.workersBySubrole = function(gameState, subrole) {
    738     return gameState.updatingCollection("subrole-" + subrole +"-base-" + this.ID, Filters.byMetadata(PlayerID, "subrole", subrole), this.workers, true);
     740m.BaseManager.prototype.workersBySubrole = function(gameState, subrole) {
     741    return gameState.updatingCollection("subrole-" + subrole +"-base-" + this.ID, API3.Filters.byMetadata(PlayerID, "subrole", subrole), this.workers, true);
    739742};
    740743
    741 BaseManager.prototype.gatherersByType = function(gameState, type) {
    742     return gameState.updatingCollection("workers-gathering-" + type +"-base-" + this.ID, Filters.byMetadata(PlayerID, "gather-type", type), this.workersBySubrole(gameState, "gatherer"));
     744m.BaseManager.prototype.gatherersByType = function(gameState, type) {
     745    return gameState.updatingCollection("workers-gathering-" + type +"-base-" + this.ID, API3.Filters.byMetadata(PlayerID, "gather-type", type), this.workersBySubrole(gameState, "gatherer"));
    743746};
    744747
    745748
    746749// returns an entity collection of workers.
    747750// They are idled immediatly and their subrole set to idle.
    748 BaseManager.prototype.pickBuilders = function(gameState, number) {
    749     var collec = new EntityCollection(gameState.sharedScript);
     751m.BaseManager.prototype.pickBuilders = function(gameState, number) {
     752    var collec = new API3.EntityCollection(gameState.sharedScript);
    750753    // TODO: choose better.
    751     var workers = this.workers.filter(Filters.not(Filters.byClass("Cavalry"))).toEntityArray();
     754    var workers = this.workers.filter(API3.Filters.not(API3.Filters.byClass("Cavalry"))).toEntityArray();
    752755    workers.sort(function (a,b) {
    753756        var vala = 0, valb = 0;
    754757        if (a.getMetadata(PlayerID,"subrole") == "builder")
     
    770773    return collec;
    771774}
    772775
    773 BaseManager.prototype.assignToFoundations = function(gameState, noRepair) {
     776m.BaseManager.prototype.assignToFoundations = function(gameState, noRepair) {
     777
    774778    // If we have some foundations, and we don't have enough builder-workers,
    775779    // try reassigning some other workers who are nearby
    776780   
     
    778782   
    779783    var self = this;
    780784   
    781     var foundations = this.buildings.filter(Filters.and(Filters.isFoundation(),Filters.not(Filters.byClass("Field")))).toEntityArray();
     785    var foundations = this.buildings.filter(API3.Filters.and(API3.Filters.isFoundation(),API3.Filters.not(API3.Filters.byClass("Field")))).toEntityArray();
    782786    var damagedBuildings = this.buildings.filter(function (ent) { if (ent.needsRepair() && ent.getMetadata(PlayerID, "plan") == undefined) { return true; } return false; }).toEntityArray();
    783787   
    784788    // Check if nothing to build
    785789    if (!foundations.length && !damagedBuildings.length){
    786790        return;
    787791    }
    788     var workers = this.workers.filter(Filters.not(Filters.byClass("Cavalry")));
     792    var workers = this.workers.filter(API3.Filters.not(API3.Filters.byClass("Cavalry")));
    789793    var builderWorkers = this.workersBySubrole(gameState, "builder");
    790     var idleBuilderWorkers = this.workersBySubrole(gameState, "builder").filter(Filters.isIdle());
     794    var idleBuilderWorkers = this.workersBySubrole(gameState, "builder").filter(API3.Filters.isIdle());
    791795
    792796    // if we're constructing and we have the foundations to our base anchor, only try building that.
    793     if (this.constructing == true && this.buildings.filter(Filters.and(Filters.isFoundation(), Filters.byMetadata(PlayerID, "baseAnchor", true))).length !== 0)
     797    if (this.constructing == true && this.buildings.filter(API3.Filters.and(API3.Filters.isFoundation(), API3.Filters.byMetadata(PlayerID, "baseAnchor", true))).length !== 0)
    794798    {
    795         foundations = this.buildings.filter(Filters.byMetadata(PlayerID, "baseAnchor", true)).toEntityArray();
     799        foundations = this.buildings.filter(API3.Filters.byMetadata(PlayerID, "baseAnchor", true)).toEntityArray();
    796800        var tID = foundations[0].id();
    797801        workers.forEach(function (ent) { //}){
    798802            var target = ent.getMetadata(PlayerID, "target-foundation");
     
    832836       
    833837        var assigned = gameState.getOwnEntitiesByMetadata("target-foundation", target.id()).length;
    834838
    835         var targetNB = Config.Economy.targetNumBuilders;    // TODO: dynamic that.
     839        var targetNB = this.Config.Economy.targetNumBuilders;   // TODO: dynamic that.
    836840        if (target.hasClass("CivCentre") || target.buildTime() > 150 || target.hasClass("House"))
    837841            targetNB *= 2;
    838842        if (target.getMetadata(PlayerID, "baseAnchor") == true)
     
    844848                var addedToThis = 0;
    845849               
    846850                idleBuilderWorkers.forEach(function(ent) {
    847                     if (ent.position() && SquareVectorDistance(ent.position(), target.position()) < 10000 && assigned + addedToThis < targetNB)
     851                    if (ent.position() && API3.SquareVectorDistance(ent.position(), target.position()) < 10000 && assigned + addedToThis < targetNB)
    848852                    {
    849853                        addedWorkers++;
    850854                        addedToThis++;
     
    876880        } else if (noRepair && !target.hasClass("CivCentre"))
    877881            continue;
    878882       
    879         var territory = Map.createTerritoryMap(gameState);
     883        var territory = m.createTerritoryMap(gameState);
    880884        if (territory.getOwner(target.position()) !== PlayerID || territory.getOwner([target.position()[0] + 5, target.position()[1]]) !== PlayerID)
    881885            continue;
    882886       
     
    900904    }
    901905};
    902906
    903 BaseManager.prototype.update = function(gameState, queues, events) {
     907m.BaseManager.prototype.update = function(gameState, queues, events) {
    904908    Engine.ProfileStart("Base update - base " + this.ID);
    905909    var self = this;
    906910   
     
    957961    Engine.ProfileStart("Run Workers");
    958962    this.workers.forEach(function(ent) {
    959963        if (!ent.getMetadata(PlayerID, "worker-object"))
    960             ent.setMetadata(PlayerID, "worker-object", new Worker(ent));
     964            ent.setMetadata(PlayerID, "worker-object", new m.Worker(ent));
    961965        ent.getMetadata(PlayerID, "worker-object").update(self, gameState);
    962966    });
    963967    Engine.ProfileStop();
    964968       
    965969    Engine.ProfileStop();
    966970};
     971
     972return m;
     973
     974}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/utils-extend.js

     
    1 function AssocArraytoArray(assocArray) {
     1var AEGIS = function(m)
     2{
     3
     4m.AssocArraytoArray = function(assocArray) {
    25    var endArray = [];
    36    for (var i in assocArray)
    47        endArray.push(assocArray[i]);
     
    710
    811// A is the reference, B must be in "range" of A
    912// this supposes the range is already squared
    10 function inRange(a, b, range)// checks for X distance
     13m.inRange = function(a, b, range)// checks for X distance
    1114{
    1215    // will avoid unnecessary checking for position in some rare cases... I'm lazy
    1316    if (a === undefined || b === undefined || range === undefined)
     
    1821    return ((dx*dx + dz*dz ) < range);
    1922}
    2023// slower than SquareVectorDistance, faster than VectorDistance but not exactly accurate.
    21 function ManhattanDistance(a, b)
     24m.ManhattanDistance = function(a, b)
    2225{
    2326    var dx = a[0] - b[0];
    2427    var dz = a[1] - b[1];
    2528    return Math.abs(dx) + Math.abs(dz);
    2629}
     30
     31return m;
     32}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/defence.js

     
     1var AEGIS = function(m)
     2{
     3
    14// directly imported from Marilyn, with slight modifications to work with qBot.
    25
    3 function Defence(){
     6m.Defence = function(Config){
    47    this.defenceRatio = Config.Defence.defenceRatio;// How many defenders we want per attacker.  Need to balance fewer losses vs. lost economy
    58                            // note: the choice should be a no-brainer most of the time: better deflect the attack.
    69                            // This is also sometimes forcebly overcome by the defense manager.
     
    4851// 1: Huge army in the base, outnumbering us.
    4952
    5053
    51 Defence.prototype.update = function(gameState, events, HQ){
     54m.Defence.prototype.update = function(gameState, events, HQ){
    5255   
    5356    Engine.ProfileStart("Defence Manager");
    5457   
    5558    // a litlle cache-ing
    5659    if (!this.idleDefs) {
    57         var filter = Filters.and(Filters.byMetadata(PlayerID, "role", "defence"), Filters.isIdle());
     60        var filter = API3.Filters.and(API3.Filters.byMetadata(PlayerID, "role", "defence"), API3.Filters.isIdle());
    5861        this.idleDefs = gameState.getOwnEntities().filter(filter);
    5962        this.idleDefs.registerUpdates();
    6063    }
    6164    if (!this.defenders) {
    62         var filter = Filters.byMetadata(PlayerID, "role", "defence");
     65        var filter = API3.Filters.byMetadata(PlayerID, "role", "defence");
    6366        this.defenders = gameState.getOwnEntities().filter(filter);
    6467        this.defenders.registerUpdates();
    6568    }
    6669    /*if (!this.listedEnemyCollection) {
    67         var filter = Filters.byMetadata(PlayerID, "listed-enemy", true);
     70        var filter = API3.Filters.byMetadata(PlayerID, "listed-enemy", true);
    6871        this.listedEnemyCollection = gameState.getEnemyEntities().filter(filter);
    6972        this.listedEnemyCollection.registerUpdates();
    7073    }
    71     this.myBuildings = gameState.getOwnEntities().filter(Filters.byClass("Structure")).toEntityArray();
    72     this.myUnits = gameState.getOwnEntities().filter(Filters.byClass("Unit"));
     74    this.myBuildings = gameState.getOwnEntities().filter(API3.Filters.byClass("Structure")).toEntityArray();
     75    this.myUnits = gameState.getOwnEntities().filter(API3.Filters.byClass("Unit"));
    7376    */
    74     var filter = Filters.and(Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), Filters.byOwner(PlayerID));
     77    var filter = API3.Filters.and(API3.Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), API3.Filters.byOwner(PlayerID));
    7578    this.myUnits = gameState.updatingGlobalCollection("player-" +PlayerID + "-soldiers", filter);
    7679   
    77     filter = Filters.and(Filters.byClass("Structure"), Filters.byOwner(PlayerID));
     80    filter = API3.Filters.and(API3.Filters.byClass("Structure"), API3.Filters.byOwner(PlayerID));
    7881    this.myBuildings = gameState.updatingGlobalCollection("player-" +PlayerID + "-structures", filter);
    7982
    80     this.territoryMap = Map.createTerritoryMap(gameState);  // used by many func
     83    this.territoryMap = m.createTerritoryMap(gameState);    // used by many func
    8184
    8285    // First step: we deal with enemy armies, those are the highest priority.
    8386    this.defendFromEnemies(gameState, events, HQ);
     
    118121        }
    119122        for (var o in this.myBuildings) {
    120123            // if the armies out of my buildings LOS (with a little more, because we're cheating right now and big armies could go undetected)
    121             if (inRange(pos, this.myBuildings[o].position(),this.myBuildings[o].visionRange()*this.myBuildings[o].visionRange() + 2500)) {
     124            if (m.inRange(pos, this.myBuildings[o].position(),this.myBuildings[o].visionRange()*this.myBuildings[o].visionRange() + 2500)) {
    122125                stillDangerousArmies[i] = armies[i];
    123126                break;
    124127            }
     
    138141}*/
    139142// Incorporates an entity in an army. If no army fits, it creates a new one around this one.
    140143// an army is basically an entity collection.
    141 Defence.prototype.armify = function(gameState, entity, HQ, minNBForArmy) {
     144m.Defence.prototype.armify = function(gameState, entity, HQ, minNBForArmy) {
    142145    if (entity.position() === undefined)
    143146        return;
    144147    if (this.enemyArmy[entity.owner()] === undefined)
     
    151154            if (army.getCentrePosition() === undefined)
    152155            {
    153156            } else {
    154                 if (SquareVectorDistance(army.getCentrePosition(), entity.position()) < this.armyCompactSize)
     157                if (API3.SquareVectorDistance(army.getCentrePosition(), entity.position()) < this.armyCompactSize)
    155158                {
    156159                    entity.setMetadata(PlayerID, "inArmy", armyIndex);
    157160                    army.addEnt(entity);
     
    163166    if (HQ)
    164167    {
    165168        var self = this;
    166         var close = HQ.enemyWatchers[entity.owner()].enemySoldiers.filter(Filters.byDistance(entity.position(), self.armyCompactSize));
     169        var close = HQ.enemyWatchers[entity.owner()].enemySoldiers.filter(API3.Filters.byDistance(entity.position(), self.armyCompactSize));
    167170        if (!minNBForArmy || close.length >= minNBForArmy)
    168171        {
    169172            // if we're here, we need to create an army for it, and freeze it to make sure no unit will be added automatically
    170             var newArmy = new EntityCollection(gameState.sharedScript, {}, [Filters.byOwner(entity.owner())]);
     173            var newArmy = new API3.EntityCollection(gameState.sharedScript, {}, [API3.Filters.byOwner(entity.owner())]);
    171174            newArmy.addEnt(entity);
    172175            newArmy.freeze();
    173176            newArmy.registerUpdates();
     
    184187        }
    185188    } else {
    186189        // if we're here, we need to create an army for it, and freeze it to make sure no unit will be added automatically
    187         var newArmy = new EntityCollection(gameState.sharedScript, {}, [Filters.byOwner(entity.owner())]);
     190        var newArmy = new API3.EntityCollection(gameState.sharedScript, {}, [API3.Filters.byOwner(entity.owner())]);
    188191        newArmy.addEnt(entity);
    189192        newArmy.freeze();
    190193        newArmy.registerUpdates();
     
    195198    return;
    196199}
    197200// Returns if a unit should be seen as dangerous or not.
    198 Defence.prototype.evaluateRawEntity = function(gameState, entity) {
     201m.Defence.prototype.evaluateRawEntity = function(gameState, entity) {
    199202    if (entity.position && +this.territoryMap.point(entity.position) - 64 === +PlayerID && entity._template.Attack !== undefined)
    200203        return true;
    201204    return false;
    202205}
    203 Defence.prototype.evaluateEntity = function(gameState, entity) {
     206m.Defence.prototype.evaluateEntity = function(gameState, entity) {
    204207    if (!entity.position())
    205208        return false;
    206209    if (this.territoryMap.point(entity.position()) - 64 === entity.owner() || entity.attackTypes() === undefined)
     
    210213    {
    211214        if (!this.myBuildings._entities[i].hasClass("ConquestCritical"))
    212215            continue;
    213         if (SquareVectorDistance(this.myBuildings._entities[i].position(), entity.position()) < 6000)
     216        if (API3.SquareVectorDistance(this.myBuildings._entities[i].position(), entity.position()) < 6000)
    214217            return true;
    215218    }
    216219    return false;
    217220}
    218221// returns false if the unit is in its territory
    219 Defence.prototype.reevaluateEntity = function(gameState, entity) {
     222m.Defence.prototype.reevaluateEntity = function(gameState, entity) {
    220223    if ( (entity.position() && +this.territoryMap.point(entity.position()) - 64 === +entity.owner()) || entity.attackTypes() === undefined)
    221224        return false;
    222225    return true;
    223226}
    224227// This deals with incoming enemy armies, setting the defcon if needed. It will take new soldiers, and assign them to attack
    225228// TODO: still is still pretty dumb, it could use improvements.
    226 Defence.prototype.defendFromEnemies = function(gameState, events, HQ) {
     229m.Defence.prototype.defendFromEnemies = function(gameState, events, HQ) {
    227230    var self = this;
    228231   
    229232    // New, faster system will loop for enemy soldiers, and also females on occasions ( TODO )
     
    313316            } else {
    314317                army.forEach(function (ent) { //}){
    315318                    // check if the unit is a breakaway
    316                     if (ent.position() && SquareVectorDistance(position, ent.position()) > self.armyBreakawaySize)
     319                    if (ent.position() && API3.SquareVectorDistance(position, ent.position()) > self.armyBreakawaySize)
    317320                    {
    318321                        ent.setMetadata(PlayerID, "inArmy", undefined);
    319322                        army.removeEnt(ent);
     
    322325                    } else {
    323326                        // check if we have registered that unit already.
    324327                        if (self.listOfEnemies[ent.id()] === undefined) {
    325                             self.listOfEnemies[ent.id()] = new EntityCollection(gameState.sharedScript, {}, [Filters.byOwner(ent.owner())]);
     328                            self.listOfEnemies[ent.id()] = new API3.EntityCollection(gameState.sharedScript, {}, [API3.Filters.byOwner(ent.owner())]);
    326329                            self.listOfEnemies[ent.id()].freeze();
    327330                            self.listOfEnemies[ent.id()].addEnt(ent);
    328331                            self.listOfEnemies[ent.id()].registerUpdates();
    329332                           
    330                             self.attackerCache[ent.id()] = self.myUnits.filter(Filters.byTargetedEntity(ent.id()));
     333                            self.attackerCache[ent.id()] = self.myUnits.filter(API3.Filters.byTargetedEntity(ent.id()));
    331334                            self.attackerCache[ent.id()].registerUpdates();
    332335                            nbOfAttackers++;
    333336                            self.nbAttackers++;
     
    373376   
    374377    if (this.nbAttackers === 0 && this.nbDefenders === 0) {
    375378        // Release all our units
    376         this.myUnits.filter(Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
     379        this.myUnits.filter(API3.Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
    377380            defender.stopMoving();
    378381            if (defender.getMetadata(PlayerID, "formerrole"))
    379382                defender.setMetadata(PlayerID, "role", defender.getMetadata(PlayerID, "formerrole") );
     
    387390        return;
    388391    } else if (this.nbAttackers === 0 && this.nbDefenders !== 0) {
    389392        // Release all our units
    390         this.myUnits.filter(Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
     393        this.myUnits.filter(API3.Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
    391394            defender.stopMoving();
    392395            if (defender.getMetadata(PlayerID, "formerrole"))
    393396                defender.setMetadata(PlayerID, "role", defender.getMetadata(PlayerID, "formerrole") );
     
    404407        HQ.ungarrisonAll(gameState);
    405408    }
    406409   
    407     //debug ("total number of attackers:"+ this.nbAttackers);
    408     //debug ("total number of defenders:"+ this.nbDefenders);
     410    //m.debug ("total number of attackers:"+ this.nbAttackers);
     411    //m.debug ("total number of defenders:"+ this.nbDefenders);
    409412
    410413    // If I'm here, I have a list of enemy units, and a list of my units attacking it (in absolute terms, I could use a list of any unit attacking it).
    411414    // now I'll list my idle defenders, then my idle soldiers that could defend.
     
    419422    }
    420423   
    421424    // we're having too many. Release those that attack units already dealt with, or idle ones.
    422     if (this.myUnits.filter(Filters.byMetadata(PlayerID, "role","defence")).length > nbOfAttackers*this.defenceRatio*1.2) {
    423         this.myUnits.filter(Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
     425    if (this.myUnits.filter(API3.Filters.byMetadata(PlayerID, "role","defence")).length > nbOfAttackers*this.defenceRatio*1.2) {
     426        this.myUnits.filter(API3.Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
    424427            if ( defender.isIdle() || (defender.unitAIOrderData() && defender.unitAIOrderData()["target"])) {
    425428                if ( defender.isIdle() || (self.attackerCache[defender.unitAIOrderData()["target"]] && self.attackerCache[defender.unitAIOrderData()["target"]].length > 3)) {
    426429                    // okay release me.
     
    437440    }
    438441   
    439442
    440     var nonDefenders = this.myUnits.filter(Filters.or(Filters.not(Filters.byMetadata(PlayerID, "role","defence")),Filters.isIdle()));
    441     nonDefenders = nonDefenders.filter(Filters.not(Filters.byClass("Female")));
    442     nonDefenders = nonDefenders.filter(Filters.not(Filters.byMetadata(PlayerID, "subrole","attacking")));
     443    var nonDefenders = this.myUnits.filter(API3.Filters.or(API3.Filters.not(API3.Filters.byMetadata(PlayerID, "role","defence")),API3.Filters.isIdle()));
     444    nonDefenders = nonDefenders.filter(API3.Filters.not(API3.Filters.byClass("Female")));
     445    nonDefenders = nonDefenders.filter(API3.Filters.not(API3.Filters.byMetadata(PlayerID, "subrole","attacking")));
    443446    var defenceRatio = this.defenceRatio;
    444447   
    445448    if (newEnemies.length + this.nbAttackers > (this.nbDefenders + nonDefenders.length) * 0.8 && this.nbAttackers > 9)
     
    448451    if (newEnemies.length + this.nbAttackers > (this.nbDefenders + nonDefenders.length) * 1.5 && this.nbAttackers > 5)
    449452        gameState.setDefcon(1);
    450453
    451     //debug ("newEnemies.length "+ newEnemies.length);
    452     //debug ("nonDefenders.length "+ nonDefenders.length);
     454    //m.debug ("newEnemies.length "+ newEnemies.length);
     455    //m.debug ("nonDefenders.length "+ nonDefenders.length);
    453456       
    454457    if (gameState.defcon() > 3)
    455458        HQ.unpauseAllPlans(gameState);
     
    457460    if ( (nonDefenders.length + this.nbDefenders > newEnemies.length + this.nbAttackers)
    458461        || this.nbDefenders + nonDefenders.length < 4)
    459462    {
    460         var buildings = gameState.getOwnEntities().filter(Filters.byCanGarrison()).toEntityArray();
     463        var buildings = gameState.getOwnEntities().filter(API3.Filters.byCanGarrison()).toEntityArray();
    461464        buildings.forEach( function (struct) {
    462465            if (struct.garrisoned() && struct.garrisoned().length)
    463466                struct.unloadAll();
     
    513516        {
    514517            var ent = nonDefenders._entities[id];
    515518            if (ent.position())
    516                 data.push([id, ent, SquareVectorDistance(enemy.position(), ent.position())]);
     519                data.push([id, ent, API3.SquareVectorDistance(enemy.position(), ent.position())]);
    517520        }
    518521        // refine the defenders we want. Since it's the distance squared, it has the effect
    519522        // of tending to always prefer closer units, though this refinement should change it slighty.
     
    547550        for each (var val in data.slice(0, Math.min(nonDefenders._length, defRatio - assigned)))
    548551            ret[val[0]] = val[1];
    549552       
    550         var defs = new EntityCollection(nonDefenders._ai, ret);
     553        var defs = new API3.EntityCollection(nonDefenders._ai, ret);
    551554
    552555        // successfully sorted
    553556        defs.forEach(function (defender) { //}){
    554557            if (defender.getMetadata(PlayerID, "plan") != undefined && (gameState.defcon() < 4 || defender.getMetadata(PlayerID,"subrole") == "walking"))
    555558                HQ.pausePlan(gameState, defender.getMetadata(PlayerID, "plan"));
    556             //debug ("Against " +enemy.id() + " Assigning " + defender.id());
     559            //m.debug ("Against " +enemy.id() + " Assigning " + defender.id());
    557560            if (defender.getMetadata(PlayerID, "role") == "worker" || defender.getMetadata(PlayerID, "role") == "attack")
    558561                defender.setMetadata(PlayerID, "formerrole", defender.getMetadata(PlayerID, "role"));
    559562            defender.setMetadata(PlayerID, "role","defence");
     
    571574        /*if (gameState.defcon() <= 3)
    572575        {
    573576            // let's try to garrison neighboring females.
    574             var buildings = gameState.getOwnEntities().filter(Filters.byCanGarrison()).toEntityArray();
    575             var females = gameState.getOwnEntities().filter(Filters.byClass("Support"));
     577            var buildings = gameState.getOwnEntities().filter(API3.Filters.byCanGarrison()).toEntityArray();
     578            var females = gameState.getOwnEntities().filter(API3.Filters.byClass("Support"));
    576579               
    577580            var cache = {};
    578581            var garrisoned = false;
     
    580583                garrisoned = false;
    581584                if (ent.position())
    582585                {
    583                     if (SquareVectorDistance(ent.position(), enemy.position()) < 3500)
     586                    if (API3.SquareVectorDistance(ent.position(), enemy.position()) < 3500)
    584587                    {
    585588                        for (var i in buildings)
    586589                        {
     
    611614// this processes the attackmessages
    612615// So that a unit that gets attacked will not be completely dumb.
    613616// warning: huge levels of indentation coming.
    614 Defence.prototype.MessageProcess = function(gameState,events, HQ) {
     617m.Defence.prototype.MessageProcess = function(gameState,events, HQ) {
    615618    var self = this;
    616619   
    617620    for (var key in events){
     
    646649                        if (territory === PlayerID)
    647650                        {
    648651                            // anyway we'll register the animal as dangerous, and attack it (note: only on our territory. Don't care otherwise).
    649                             this.listOfWantedUnits[attacker.id()] = new EntityCollection(gameState.sharedScript);
     652                            this.listOfWantedUnits[attacker.id()] = new API3.EntityCollection(gameState.sharedScript);
    650653                            this.listOfWantedUnits[attacker.id()].addEnt(attacker);
    651654                            this.listOfWantedUnits[attacker.id()].freeze();
    652655                            this.listOfWantedUnits[attacker.id()].registerUpdates();
    653656
    654                             var filter = Filters.byTargetedEntity(attacker.id());
     657                            var filter = API3.Filters.byTargetedEntity(attacker.id());
    655658                            this.WantedUnitsAttacker[attacker.id()] = this.myUnits.filter(filter);
    656659                            this.WantedUnitsAttacker[attacker.id()].registerUpdates();
    657660                        }
     
    666669                           
    667670                            // Right now, to make the AI less gameable, we'll mark any surrounding resource as inaccessible.
    668671                            // usual tower range is 80. Be on the safe side.
    669                             var close = gameState.getResourceSupplies("wood").filter(Filters.byDistance(attacker.position(), 90));
     672                            var close = gameState.getResourceSupplies("wood").filter(API3.Filters.byDistance(attacker.position(), 90));
    670673                            close.forEach(function (supply) { //}){
    671674                                supply.setMetadata(PlayerID, "inaccessible", true);
    672675                            });
     
    683686                                    if (this.reevaluateEntity(gameState, attacker))
    684687                                    {
    685688                                        var position = attacker.position();
    686                                         var close = HQ.enemyWatchers[attacker.owner()].enemySoldiers.filter(Filters.byDistance(position, self.armyCompactSize));
     689                                        var close = HQ.enemyWatchers[attacker.owner()].enemySoldiers.filter(API3.Filters.byDistance(position, self.armyCompactSize));
    687690                                       
    688691                                        if (close.length > 2 || ourUnit.hasClass("Support") || attacker.hasClass("Siege"))
    689692                                        {
     
    692695                                            armyID = attacker.getMetadata(PlayerID, "inArmy");
    693696                                           
    694697                                            close.forEach(function (ent) { //}){
    695                                                 if (SquareVectorDistance(position, ent.position()) < self.armyCompactSize)
     698                                                if (API3.SquareVectorDistance(position, ent.position()) < self.armyCompactSize)
    696699                                                {
    697700                                                    ent.setMetadata(PlayerID, "inArmy", armyID);
    698701                                                          self.enemyArmy[ent.owner()][armyID].addEnt(ent);
     
    708711                                        // let's try to garrison this support unit.
    709712                                        if (ourUnit.position())
    710713                                        {
    711                                             var buildings = gameState.getOwnEntities().filter(Filters.byCanGarrison()).filterNearest(ourUnit.position(),4).toEntityArray();
     714                                            var buildings = gameState.getOwnEntities().filter(API3.Filters.byCanGarrison()).filterNearest(ourUnit.position(),4).toEntityArray();
    712715                                            var garrisoned = false;
    713716                                            for (var i in buildings)
    714717                                            {
     
    742745}; // nice sets of closing brackets, isn't it?
    743746
    744747// At most, this will put defcon to 4
    745 Defence.prototype.DealWithWantedUnits = function(gameState, events, HQ) {
     748m.Defence.prototype.DealWithWantedUnits = function(gameState, events, HQ) {
    746749    //if (gameState.defcon() < 3)
    747750    //  return;
    748751   
     
    841844    }
    842845    return;
    843846}
     847
     848return m;
     849}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/worker.js

     
     1var AEGIS = function(m)
     2{
     3
    14/**
    25 * This class makes a worker do as instructed by the economy manager
    36 */
     
    25
    3 var Worker = function(ent) {
     6m.Worker = function(ent) {
    47    this.ent = ent;
     
    912    this.baseID = 0;
    1013};
    1114
    12 Worker.prototype.update = function(baseManager, gameState) {
     15m.Worker.prototype.update = function(baseManager, gameState) {
    1316    this.baseID = baseManager.ID;
    1417    var subrole = this.ent.getMetadata(PlayerID, "subrole");
    1518
     
    6467                }
    6568                Engine.ProfileStop();
    6669            }
    67             // debug: show the resource we're gathering from
     70            // m.debug: show the resource we're gathering from
    6871            //Engine.PostCommand({"type": "set-shading-color", "entities": [this.ent.id()], "rgb": [10,0,0]});
    6972        } else if (this.ent.unitAIState().split(".")[1] === "GATHER") {
    7073           
     
    9396                    && this.ent.unitAIOrderData()[0]["target"])
    9497                {
    9598                    var ent = gameState.getEntityById(this.ent.unitAIOrderData()[0]["target"]);
    96                     debug ("here " + this.startApproachingResourceAmount + "," + ent.resourceSupplyAmount());
     99                    m.debug ("here " + this.startApproachingResourceAmount + "," + ent.resourceSupplyAmount());
    97100                    if (ent && this.startApproachingResourceAmount == ent.resourceSupplyAmount() && this.startEnt == ent.id()) {
    98                         debug (ent.toString() + " is inaccessible");
     101                        m.debug (ent.toString() + " is inaccessible");
    99102                        ent.setMetadata(PlayerID, "inaccessible", true);
    100103                        this.ent.flee(ent);
    101104                        this.ent.setMetadata(PlayerID, "subrole", "idle");
     
    116119                    var ent = gameState.getEntityById(this.gatheringFrom);
    117120                    if ((ent && ent.resourceSupplyAmount() == ent.resourceSupplyMax())) {
    118121                        // if someone gathers from it, it's only that the pathfinder sucks.
    119                         debug (ent.toString() + " is inaccessible");
     122                        m.debug (ent.toString() + " is inaccessible");
    120123                        ent.setMetadata(PlayerID, "inaccessible", true);
    121124                        this.ent.flee(ent);
    122125                        this.ent.setMetadata(PlayerID, "subrole", "idle");
     
    129132                var ent = gameState.getEntityById(this.ent.unitAIOrderData()[0].target);
    130133                if (ent && !ent.isHurt()) {
    131134                    // if someone gathers from it, it's only that the pathfinder sucks.
    132                     debug (ent.toString() + " is inaccessible from Combat");
     135                    m.debug (ent.toString() + " is inaccessible from Combat");
    133136                    ent.setMetadata(PlayerID, "inaccessible", true);
    134137                    this.ent.flee(ent);
    135138                    this.ent.setMetadata(PlayerID, "subrole", "idle");
     
    186189// this can happen in two ways:
    187190//      -either we were on an unsatisfactory resource last time we started gathering (this.unsatisfactoryResource)
    188191//      -Or we auto-moved to a bad resource thanks to the great UnitAI.
    189 Worker.prototype.checkUnsatisfactoryResource = function(gameState) {
     192m.Worker.prototype.checkUnsatisfactoryResource = function(gameState) {
    190193    if (this.unsatisfactoryResource)
    191194        return true;
    192195    if (this.ent.unitAIOrderData().length && this.ent.unitAIState().split(".")[1] === "GATHER" && this.ent.unitAIState().split(".")[2] === "GATHERING" && this.ent.unitAIOrderData()[0]["target"])
     
    198201    return false;
    199202};
    200203
    201 Worker.prototype.startGathering = function(baseManager, gameState) {
     204m.Worker.prototype.startGathering = function(baseManager, gameState) {
     205
    202206    var resource = this.ent.getMetadata(PlayerID, "gather-type");
    203207    var ent = this.ent;
    204208    var self = this;
     
    219223    // TODO: this is a huge part of multi-base support. Count only those in the same base as the worker.
    220224    var number = 0;
    221225   
    222     var ourDropsites = EntityCollectionFromIds(gameState,Object.keys(baseManager.dropsites));
     226    var ourDropsites = m.EntityCollectionFromIds(gameState,Object.keys(baseManager.dropsites));
    223227    if (ourDropsites.length === 0)
    224228    {
    225         debug ("We do not have a dropsite for " + resource + ", aborting");
     229        m.debug ("We do not have a dropsite for " + resource + ", aborting");
    226230        return;
    227231    }
    228232   
     
    245249                return;
    246250            if (dropsite.position() && (baseManager.dropsites[dropsite.id()][resource][4] > 1000 || (number === 1 && baseManager.dropsites[dropsite.id()][resource][4] > 200) )
    247251                && baseManager.dropsites[dropsite.id()][resource][5].length < maxPerDP) {
    248                 var dist = SquareVectorDistance(ent.position(), dropsite.position());
     252                var dist = API3.SquareVectorDistance(ent.position(), dropsite.position());
    249253                if (dist < minDropsiteDist){
    250254                    minDropsiteDist = dist;
    251255                    nearestResources = baseManager.dropsites[dropsite.id()][resource][1];
     
    254258            }
    255259        });
    256260    }
     261   
    257262    // we've found no fitting dropsites close enough from us.
    258263    // So'll try with far away.
    259264    if (!nearestResources || nearestResources.length === 0) {
     
    262267                return;
    263268            if (dropsite.position() && baseManager.dropsites[dropsite.id()][resource][4] > 400
    264269                && baseManager.dropsites[dropsite.id()][resource][5].length < maxPerDP) {
    265                 var dist = SquareVectorDistance(ent.position(), dropsite.position());
     270                var dist = API3.SquareVectorDistance(ent.position(), dropsite.position());
    266271                if (dist < minDropsiteDist){
    267272                    minDropsiteDist = dist;
    268273                    nearestResources = baseManager.dropsites[dropsite.id()][resource][1];
     
    271276            }
    272277        });
    273278    }
    274 
     279   
    275280    if (!nearestResources || nearestResources.length === 0){
    276281        if (resource === "food")
    277282            if (this.buildAnyField(gameState))
     
    283288        if (gameState.ai.HQ.switchWorkerBase(gameState, this.ent, resource))
    284289            return;
    285290
    286         //debug ("No fitting dropsite for " + resource + " found, iterating the map.");
     291        //m.debug ("No fitting dropsite for " + resource + " found, iterating the map.");
    287292        nearestResources = gameState.getResourceSupplies(resource);
    288293        this.unsatisfactoryResource = true;
    289294        // TODO: should try setting up dropsites.
     
    298303                return;
    299304            if (gameState.ai.HQ.switchWorkerBase(gameState, this.ent, resource))
    300305                return;
    301             debug("No " + resource + " found! (1)");
     306            m.debug("No " + resource + " found! (1)");
    302307        }
    303308        else
    304309        {
    305310            if (gameState.ai.HQ.switchWorkerBase(gameState, this.ent, resource))
    306311                return;
    307             debug("No " + resource + " found! (1)");
     312            m.debug("No " + resource + " found! (1)");
    308313        }
    309314        return;
    310315    }
    311     //debug("Found " + nearestResources.length + "spots for " + resource);
     316    //m.debug("Found " + nearestResources.length + "spots for " + resource);
    312317   
    313318    /*if (!nearestDropsite) {
    314         debug ("No dropsite for " +resource);
     319        m.debug ("No dropsite for " +resource);
    315320        return;
    316321    }*/
    317322   
     
    324329    nearestResources.forEach(function(supply) { //}){
    325330        // sanity check, perhaps sheep could be garrisoned?
    326331        if (!supply.position()) {
    327             //debug ("noposition");
     332            //m.debug ("noposition");
    328333            return;
    329334        }
    330335       
    331336        if (supply.getMetadata(PlayerID, "inaccessible") === true) {
    332             //debug ("inaccessible");
     337            //m.debug ("inaccessible");
    333338            return;
    334339        }
    335340
     
    341346                             
    342347        // Don't gather enemy farms or farms from another base
    343348        if ((!supply.isOwn(PlayerID) && supply.owner() !== 0) || (supply.isOwn(PlayerID) && supply.getMetadata(PlayerID,"base") !== self.baseID)) {
    344             //debug ("enemy");
     349            //m.debug ("enemy");
    345350            return;
    346351        }
    347352       
    348353        // quickscope accessbility check.
    349354        if (!gameState.ai.accessibility.pathAvailable(gameState, ent.position(), supply.position())) {
    350             //debug ("nopath");
     355            //m.debug ("nopath");
    351356            return;
    352357        }
    353358        // some simple check for chickens: if they're in a square that's inaccessible, we won't gather from them.
    354359        if (supply.footprintRadius() < 1)
    355360        {
    356             var fakeMap = new Map(gameState.sharedScript,gameState.getMap().data);
     361            var fakeMap = new API3.Map(gameState.sharedScript,gameState.getMap().data);
    357362            var id = fakeMap.gamePosToMapPos(supply.position())[0] + fakeMap.width*fakeMap.gamePosToMapPos(supply.position())[1];
    358363            if ( (gameState.sharedScript.passabilityClasses["pathfinderObstruction"] & gameState.getMap().data[id]) )
    359364            {
     
    363368        }
    364369
    365370        // measure the distance to the resource (largely irrelevant)
    366          var dist = SquareVectorDistance(supply.position(), ent.position());
     371         var dist = API3.SquareVectorDistance(supply.position(), ent.position());
    367372                             
    368373        if (dist > 4900 && supply.hasClass("Animal"))
    369374        return;
    370375
    371376        // Add on a factor for the nearest dropsite if one exists
    372377        if (nearestDropsite !== undefined ){
    373             dist += 4*SquareVectorDistance(supply.position(), nearestDropsite.position());
     378            dist += 4*API3.SquareVectorDistance(supply.position(), nearestDropsite.position());
    374379            dist /= 5.0;
    375380        }
    376381                   
    377         var territoryOwner = Map.createTerritoryMap(gameState).getOwner(supply.position());
     382        var territoryOwner = m.createTerritoryMap(gameState).getOwner(supply.position());
    378383        if (territoryOwner != PlayerID && territoryOwner != 0) {
    379384            dist *= 5.0;
    380385            //return;
     
    395400        if (!nearestDropsite) {
    396401            ourDropsites.forEach(function (dropsite){ //}){
    397402                if (dropsite.position()){
    398                     var dist = SquareVectorDistance(pos, dropsite.position());
     403                    var dist = API3.SquareVectorDistance(pos, dropsite.position());
    399404                    if (dist < minDropsiteDist){
    400405                        minDropsiteDist = dist;
    401406                        nearestDropsite = dropsite;
     
    404409            });
    405410            if (!nearestDropsite)
    406411            {
    407                 debug ("No dropsite for " +resource);
     412                m.debug ("No dropsite for " +resource);
    408413                return;
    409414            }
    410415        }
    411416
    412417        // if the resource is far away, try to build a farm instead.
    413418        var tried = false;
    414         if (resource === "food" && SquareVectorDistance(pos,this.ent.position()) > 22500)
     419        if (resource === "food" && API3.SquareVectorDistance(pos,this.ent.position()) > 22500)
    415420        {
    416421            tried = this.buildAnyField(gameState);
    417             if (!tried && SquareVectorDistance(pos,this.ent.position()) > 62500) {
     422            if (!tried && API3.SquareVectorDistance(pos,this.ent.position()) > 62500) {
    418423                // TODO: ought to change behavior here.
    419424                return; // wait. a farm should appear.
    420425            }
     
    429434            else
    430435                gameState.turnCache["ressGathererNB"][nearestSupply.id()]++;
    431436           
    432             this.maxApproachTime = Math.max(30000, VectorDistance(pos,this.ent.position()) * 5000);
     437            this.maxApproachTime = Math.max(30000, API3.VectorDistance(pos,this.ent.position()) * 5000);
    433438            this.startApproachingResourceAmount = ent.resourceSupplyAmount();
    434439            this.startEnt = ent.id();
    435440            ent.gather(nearestSupply);
     
    443448            return;
    444449       
    445450        if (resource !== "food")
    446             debug("No " + resource + " found! (2)");
     451            m.debug("No " + resource + " found! (2)");
    447452        // If we had a fitting closest dropsite with a lot of resources, mark it as not good. It means it's probably full. Then retry.
    448453        // it'll be resetted next time it's counted anyway.
    449454        if (nearestDropsite && nearestDropsite.getMetadata(PlayerID, "resource-quantity-" +resource)+nearestDropsite.getMetadata(PlayerID, "resource-quantity-far-" +resource) > 400)
     
    456461};
    457462
    458463// Makes the worker deposit the currently carried resources at the closest dropsite
    459 Worker.prototype.returnResources = function(gameState){
     464m.Worker.prototype.returnResources = function(gameState){
    460465    if (!this.ent.resourceCarrying() || this.ent.resourceCarrying().length === 0){
    461466        return true;    // assume we're OK.
    462467    }
     
    472477    var dist = Math.min();
    473478    gameState.getOwnDropsites(resource).forEach(function(dropsite){
    474479        if (dropsite.position()){
    475             var d = SquareVectorDistance(self.ent.position(), dropsite.position());
     480            var d = API3.SquareVectorDistance(self.ent.position(), dropsite.position());
    476481            if (d < dist){
    477482                dist = d;
    478483                closestDropsite = dropsite;
     
    481486    });
    482487   
    483488    if (!closestDropsite){
    484         debug("No dropsite found to deposit " + resource);
     489        m.debug("No dropsite found to deposit " + resource);
    485490        return false;
    486491    }
    487492   
     
    489494    return true;
    490495};
    491496
    492 Worker.prototype.startHunting = function(gameState, baseManager){
     497m.Worker.prototype.startHunting = function(gameState, baseManager){
    493498    var ent = this.ent;
    494499   
    495500    if (!ent.position() || !baseManager.isHunting)
     
    500505    var resources = gameState.getResourceSupplies("food");
    501506   
    502507    if (resources.length === 0){
    503         debug("No food found to hunt!");
     508        m.debug("No food found to hunt!");
    504509        return;
    505510    }
    506511   
     
    522527            return;
    523528                     
    524529        // measure the distance to the resource
    525         var dist = SquareVectorDistance(supply.position(), ent.position());
     530        var dist = API3.SquareVectorDistance(supply.position(), ent.position());
    526531
    527         var territoryOwner = Map.createTerritoryMap(gameState).getOwner(supply.position());
     532        var territoryOwner = m.createTerritoryMap(gameState).getOwner(supply.position());
    528533        if (territoryOwner != PlayerID && territoryOwner != 0) {
    529534            dist *= 3.0;
    530535        }
     
    547552        // find a fitting dropsites in case we haven't already.
    548553        gameState.getOwnDropsites("food").forEach(function (dropsite){ //}){
    549554            if (dropsite.position()){
    550                 var dist = SquareVectorDistance(pos, dropsite.position());
     555                var dist = API3.SquareVectorDistance(pos, dropsite.position());
    551556                if (dist < minDropsiteDist){
    552557                    minDropsiteDist = dist;
    553558                    nearestDropsite = dropsite;
     
    558563        {
    559564            baseManager.isHunting = false;
    560565            ent.setMetadata(PlayerID, "role", undefined);
    561             debug ("No dropsite for hunting food");
     566            m.debug ("No dropsite for hunting food");
    562567            return;
    563568        }
    564569        if (minDropsiteDist > 35000) {
     
    571576    } else {
    572577        baseManager.isHunting = false;
    573578        ent.setMetadata(PlayerID, "role", undefined);
    574         debug("No food found for hunting! (2)");
     579        m.debug("No food found for hunting! (2)");
    575580    }
    576581};
    577582
    578 Worker.prototype.getResourceType = function(type){
     583m.Worker.prototype.getResourceType = function(type){
    579584    if (!type || !type.generic){
    580585        return undefined;
    581586    }
     
    587592    }
    588593};
    589594
    590 Worker.prototype.getGatherRate = function(gameState) {
     595m.Worker.prototype.getGatherRate = function(gameState) {
    591596    if (this.ent.getMetadata(PlayerID,"subrole") !== "gatherer")
    592597        return 0;
    593598    var rates = this.ent.resourceGatherRates();
     
    601606        if (type.generic == "treasure")
    602607            return 1000;
    603608        var tstring = type.generic + "." + type.specific;
    604         //debug (+rates[tstring] + " for " + tstring + " for " + this.ent._templateName);
     609        //m.debug (+rates[tstring] + " for " + tstring + " for " + this.ent._templateName);
    605610        if (rates[tstring])
    606611            return rates[tstring];
    607612        return 0;
     
    609614    return 0;
    610615};
    611616
    612 Worker.prototype.buildAnyField = function(gameState){
     617m.Worker.prototype.buildAnyField = function(gameState){
    613618    var self = this;
    614619    var okay = false;
    615     var foundations = gameState.getOwnFoundations().filter(Filters.byMetadata(PlayerID,"base",this.baseID));
     620    var foundations = gameState.getOwnFoundations().filter(API3.Filters.byMetadata(PlayerID,"base",this.baseID));
    616621    foundations.filterNearest(this.ent.position(), foundations.length);
    617622    foundations.forEach(function (found) {
    618623        if (found._template.BuildRestrictions.Category === "Field" && !okay) {
     
    636641    }
    637642    return okay;
    638643};
     644
     645return m;
     646}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/attack_plan.js

     
     1var AEGIS = function(m)
     2{
     3
    14/* This is an attack plan (despite the name, it's a relic of older times).
    25 * It deals with everything in an attack, from picking a target to picking a path to it
    36 * To making sure units rae built, and pushing elements to the queue manager otherwise
     
    69 * There is a basic support for naval expeditions here.
    710 */
    811
    9 function CityAttack(gameState, HQ, uniqueID, targetEnemy, type , targetFinder) {
     12m.CityAttack = function CityAttack(gameState, HQ, Config, uniqueID, targetEnemy, type , targetFinder) {
    1013   
     14    this.Config = Config;
    1115    //This is the list of IDs of the units in the plan
    1216    this.idList=[];
    1317   
     
    3337        return false;
    3438    }
    3539   
    36     var CCs = gameState.getOwnEntities().filter(Filters.byClass("CivCentre"));
     40    var CCs = gameState.getOwnEntities().filter(API3.Filters.byClass("CivCentre"));
    3741    if (CCs.length === 0)
    3842    {
    3943        this.failed = true;
    4044        return false;
    4145    }
    4246
    43     debug ("Target (" + PlayerID +") = " +this.targetPlayer);
     47    m.debug ("Target (" + PlayerID +") = " +this.targetPlayer);
    4448    this.targetFinder = targetFinder || this.defaultTargetFinder;
    4549    this.type = type || "normal";
    4650    this.name = uniqueID;
     
    5054   
    5155    this.maxPreparationTime = 210*1000;
    5256    // in this case we want to have the attack ready by the 13th minute. Countdown. Minimum 2 minutes.
    53     if (type !== "superSized" && Config.difficulty >= 1)
     57    if (type !== "superSized" && this.Config.difficulty >= 1)
    5458        this.maxPreparationTime = 780000 - gameState.getTimeElapsed() < 120000 ? 120000 : 780000 - gameState.getTimeElapsed();
    5559   
    5660    this.pausingStart = 0;
     
    120124        return (strength[0] > 15 || strength[1] > 15);
    121125    };*/
    122126
    123     var filter = Filters.and(Filters.byMetadata(PlayerID, "plan",this.name),Filters.byOwner(PlayerID));
     127    var filter = API3.Filters.and(API3.Filters.byMetadata(PlayerID, "plan",this.name),API3.Filters.byOwner(PlayerID));
    124128    this.unitCollection = gameState.getOwnEntities().filter(filter);
    125129    this.unitCollection.registerUpdates();
    126130    this.unitCollection.length;
     
    136140        var cat = unitCat;
    137141        var Unit = this.unitStat[cat];
    138142
    139         filter = Filters.and(Filters.byClassesAnd(Unit["classes"]),Filters.and(Filters.byMetadata(PlayerID, "plan",this.name),Filters.byOwner(PlayerID)));
     143        filter = API3.Filters.and(API3.Filters.byClassesAnd(Unit["classes"]),API3.Filters.and(API3.Filters.byMetadata(PlayerID, "plan",this.name),API3.Filters.byOwner(PlayerID)));
    140144        this.unit[cat] = gameState.getOwnEntities().filter(filter);
    141145        this.unit[cat].registerUpdates();
    142146        this.unit[cat].length;
     
    186190    this.anyNotMinimal = true;  // used for support plans
    187191
    188192
    189     var myFortresses = gameState.getOwnTrainingFacilities().filter(Filters.byClass("GarrisonFortress"));
     193    var myFortresses = gameState.getOwnTrainingFacilities().filter(API3.Filters.byClass("GarrisonFortress"));
    190194    if (myFortresses.length !== 0)
    191195    {
    192196        // make this our rallypoint
     
    237241   
    238242    this.assignUnits(gameState);
    239243   
    240     //debug ("Before");
     244    //m.debug ("Before");
    241245    //Engine.DumpHeap();
    242246   
    243247    // get a good path to an estimated target.
    244     this.pathFinder = new aStarPath(gameState,false,false, this.targetPlayer);
     248    this.pathFinder = new API3.aStarPath(gameState,false,false, this.targetPlayer);
    245249    //Engine.DumpImage("widthmap.png", this.pathFinder.widthMap, this.pathFinder.width,this.pathFinder.height,255);
    246250
    247251    this.pathWidth = 6; // prefer a path far from entities. This will avoid units getting stuck in trees and also results in less straight paths.
     
    249253    this.onBoat = false;    // tells us if our units are loaded on boats.
    250254    this.needsShip = false;
    251255   
    252     //debug ("after");
     256    //m.debug ("after");
    253257    //Engine.DumpHeap();
    254258    return true;
    255259};
    256260
    257 CityAttack.prototype.getName = function(){
     261m.CityAttack.prototype.getName = function(){
    258262    return this.name;
    259263};
    260 CityAttack.prototype.getType = function(){
     264m.CityAttack.prototype.getType = function(){
    261265    return this.type;
    262266};
    263267// Returns true if the attack can be executed at the current time
    264268// Basically his checks we have enough units.
    265269// We run a count of our units.
    266 CityAttack.prototype.canStart = function(gameState){   
     270m.CityAttack.prototype.canStart = function(gameState){ 
    267271    for (var unitCat in this.unitStat) {
    268272        var Unit = this.unitStat[unitCat];
    269273        if (this.unit[unitCat].length < Unit["minSize"])
     
    273277
    274278    // TODO: check if our target is valid and a few other stuffs (good moment to attack?)
    275279};
    276 CityAttack.prototype.isStarted = function(){
     280m.CityAttack.prototype.isStarted = function(){
    277281    if ((this.state !== "unexecuted"))
    278         debug ("Attack plan already started");
     282        m.debug ("Attack plan already started");
    279283    return !(this.state == "unexecuted");
    280284};
    281285
    282 CityAttack.prototype.isPaused = function(){
     286m.CityAttack.prototype.isPaused = function(){
    283287    return this.paused;
    284288};
    285 CityAttack.prototype.setPaused = function(gameState, boolValue){
     289m.CityAttack.prototype.setPaused = function(gameState, boolValue){
    286290    if (!this.paused && boolValue === true) {
    287291        this.pausingStart = gameState.getTimeElapsed();
    288292        this.paused = true;
    289         debug ("Pausing attack plan " +this.name);
     293        m.debug ("Pausing attack plan " +this.name);
    290294    } else if (this.paused && boolValue === false) {
    291295        this.totalPausingTime += gameState.getTimeElapsed() - this.pausingStart;
    292296        this.paused = false;
    293         debug ("Unpausing attack plan " +this.name);
     297        m.debug ("Unpausing attack plan " +this.name);
    294298    }
    295299};
    296 CityAttack.prototype.mustStart = function(gameState){
     300m.CityAttack.prototype.mustStart = function(gameState){
    297301    if (this.isPaused() || this.path === undefined)
    298302        return false;
    299303    var MaxReachedEverywhere = true;
     
    309313};
    310314
    311315// Adds a build order. If resetQueue is true, this will reset the queue.
    312 CityAttack.prototype.addBuildOrder = function(gameState, name, unitStats, resetQueue) {
     316m.CityAttack.prototype.addBuildOrder = function(gameState, name, unitStats, resetQueue) {
    313317    if (!this.isStarted())
    314318    {
    315         debug ("Adding a build order for " + name);
     319        m.debug ("Adding a build order for " + name);
    316320        // no minsize as we don't want the plan to fail at the last minute though.
    317321        this.unitStat[name] = unitStats;
    318322        var Unit = this.unitStat[name];
    319         var filter = Filters.and(Filters.byClassesAnd(Unit["classes"]),Filters.and(Filters.byMetadata(PlayerID, "plan",this.name),Filters.byOwner(PlayerID)));
     323        var filter = API3.Filters.and(API3.Filters.byClassesAnd(Unit["classes"]),API3.Filters.and(API3.Filters.byMetadata(PlayerID, "plan",this.name),API3.Filters.byOwner(PlayerID)));
    320324        this.unit[name] = gameState.getOwnEntities().filter(filter);
    321325        this.unit[name].registerUpdates();
    322326        this.buildOrder.push([0, Unit["classes"], this.unit[name], Unit, name]);
     
    330334
    331335// Three returns possible: 1 is "keep going", 0 is "failed plan", 2 is "start"
    332336// 3 is a special case: no valid path returned. Right now I stop attacking alltogether.
    333 CityAttack.prototype.updatePreparation = function(gameState, HQ,events) {
     337m.CityAttack.prototype.updatePreparation = function(gameState, HQ,events) {
    334338    var self = this;
    335339   
    336340    if (this.path == undefined || this.target == undefined || this.path === "toBeContinued") {
     
    342346                targets = this.defaultTargetFinder(gameState, HQ);
    343347               
    344348            if (targets.length !== 0) {
    345                 debug ("Aiming for " + targets);
     349                m.debug ("Aiming for " + targets);
    346350                // picking a target
    347351                var maxDist = -1;
    348352                var index = 0;
    349353                for (var i in targets._entities)
    350354                {
    351355                    // we're sure it has a position has TargetFinder already checks that.
    352                     var dist = SquareVectorDistance(targets._entities[i].position(), this.rallyPoint);
     356                    var dist = API3.SquareVectorDistance(targets._entities[i].position(), this.rallyPoint);
    353357                    if (dist < maxDist || maxDist === -1)
    354358                    {
    355359                        maxDist = dist;
     
    385389            // Basically we'll add it as a new class to train compulsorily, and we'll recompute our path.
    386390            if (!gameState.ai.HQ.waterMap)
    387391            {
    388                 debug ("This is actually a water map.");
     392                m.debug ("This is actually a water map.");
    389393                gameState.ai.HQ.waterMap = true;
    390394                return 0;
    391395            }
    392             debug ("We need a ship.");
     396            m.debug ("We need a ship.");
    393397            this.needsShip = true;
    394398            this.pathWidth = 3;
    395399            this.pathSampling = 3;
     
    400404            {
    401405                // my pathfinder returns arrays in arrays in arrays.
    402406                var waypointPos = this.path[i][0];
    403                 var territory = Map.createTerritoryMap(gameState);
     407                var territory = m.createTerritoryMap(gameState);
    404408                if (territory.getOwner(waypointPos) !== PlayerID || this.path[i][1] === true)
    405409                {
    406410                    // if we're suddenly out of our territory or this is the point where we change transportation method.
     
    426430            {
    427431                // my pathfinder returns arrays in arrays in arrays.
    428432                var waypointPos = this.path[i][0];
    429                 var territory = Map.createTerritoryMap(gameState);
     433                var territory = m.createTerritoryMap(gameState);
    430434                if (territory.getOwner(waypointPos) !== PlayerID || this.path[i][1] === true)
    431435                {
    432436                    // if we're suddenly out of our territory or this is the point where we change transportation method.
     
    511515           
    512516            if (this.buildOrder[0][0] < 1 && queue.length() <= 5) {
    513517                var template = HQ.findBestTrainableSoldier(gameState, this.buildOrder[0][1], this.buildOrder[0][3]["interests"] );
    514                 //debug ("tried " + uneval(this.buildOrder[0][1]) +", and " + template);
     518                //m.debug ("tried " + uneval(this.buildOrder[0][1]) +", and " + template);
    515519                // HACK (TODO replace) : if we have no trainable template... Then we'll simply remove the buildOrder, effectively removing the unit from the plan.
    516520                if (template === undefined) {
    517521                    // TODO: this is a complete hack.
     
    523527                    if (gameState.getTimeElapsed() > 1800000)
    524528                        max *= 2;
    525529                    if (gameState.getTemplate(template).hasClass("CitizenSoldier"))
    526                         queue.addItem( new TrainingPlan(gameState,template, { "role" : "worker", "plan" : this.name, "special" : specialData, "base" : 1 }, this.buildOrder[0][3]["batchSize"],max ) );
     530                        queue.addItem( new m.TrainingPlan(gameState,template, { "role" : "worker", "plan" : this.name, "special" : specialData, "base" : 1 }, this.buildOrder[0][3]["batchSize"],max ) );
    527531                    else
    528                         queue.addItem( new TrainingPlan(gameState,template, { "role" : "attack", "plan" : this.name, "special" : specialData, "base" : 1 }, this.buildOrder[0][3]["batchSize"],max ) );
     532                        queue.addItem( new m.TrainingPlan(gameState,template, { "role" : "attack", "plan" : this.name, "special" : specialData, "base" : 1 }, this.buildOrder[0][3]["batchSize"],max ) );
    529533                }
    530534            }
    531535        }
     
    546550                    this.targetPos = target.position();
    547551                    count++;
    548552                    if (count > 1000){
    549                         debug("No target with a valid position found");
     553                        m.debug("No target with a valid position found");
    550554                        return false;
    551555                    }
    552556                }
     
    559563            if (path !== "toBeContinued") {
    560564                this.startedPathing = false;
    561565                this.path = path;
    562                 debug("Pathing ended");
     566                m.debug("Pathing ended");
    563567            }
    564568        }
    565569        */
     
    567571        Engine.ProfileStop();
    568572        // can happen for now
    569573        if (this.buildOrder.length === 0) {
    570             debug ("Ending plan: no build orders");
     574            m.debug ("Ending plan: no build orders");
    571575            return 0;   // will abort the plan, should return something else
    572576        }
    573577        return 1;
     
    583587        return 0;
    584588    return 0;
    585589};
    586 CityAttack.prototype.assignUnits = function(gameState){
     590m.CityAttack.prototype.assignUnits = function(gameState){
    587591    var self = this;
    588592
    589593    // TODO: assign myself units that fit only, right now I'm getting anything.
     
    604608
    605609};
    606610// this sends a unit by ID back to the "rally point"
    607 CityAttack.prototype.ToRallyPoint = function(gameState,id)
     611m.CityAttack.prototype.ToRallyPoint = function(gameState,id)
    608612{   
    609613    // Move back to nearest rallypoint
    610614    gameState.getEntityById(id).move(this.rallyPoint[0],this.rallyPoint[1]);
    611615}
    612616// this sends all units back to the "rally point" by entity collections.
    613617// It doesn't disturb ones that could be currently defending, even if the plan is not (yet) paused.
    614 CityAttack.prototype.AllToRallyPoint = function(gameState, evenWorkers) {
     618m.CityAttack.prototype.AllToRallyPoint = function(gameState, evenWorkers) {
    615619    var self = this;
    616620    if (evenWorkers) {
    617621        for (var unitCat in this.unit) {
     
    634638}
    635639
    636640// Default target finder aims for conquest critical targets
    637 CityAttack.prototype.defaultTargetFinder = function(gameState, HQ){
     641m.CityAttack.prototype.defaultTargetFinder = function(gameState, HQ){
    638642    var targets = undefined;
    639643   
    640644    targets = HQ.enemyWatchers[this.targetPlayer].getEnemyBuildings(gameState, "CivCentre",true);
     
    650654    }
    651655    // no buildings, attack anything conquest critical, even units (it's assuming it won't move).
    652656    if (targets.length == 0) {
    653         targets = gameState.getEnemyEntities().filter(Filters.and( Filters.byOwner(this.targetPlayer),Filters.byClass("ConquestCritical")));
     657        targets = gameState.getEnemyEntities().filter(API3.Filters.and( API3.Filters.byOwner(this.targetPlayer),API3.Filters.byClass("ConquestCritical")));
    654658    }
    655659    return targets;
    656660};
    657661
    658662// tupdate
    659 CityAttack.prototype.raidingTargetFinder = function(gameState, HQ, Target){
     663m.CityAttack.prototype.raidingTargetFinder = function(gameState, HQ, Target){
    660664    var targets = undefined;
    661665    if (Target == "villager")
    662666    {
     
    684688// Executes the attack plan, after this is executed the update function will be run every turn
    685689// If we're here, it's because we have in our IDlist enough units.
    686690// now the IDlist units are treated turn by turn
    687 CityAttack.prototype.StartAttack = function(gameState, HQ){
     691m.CityAttack.prototype.StartAttack = function(gameState, HQ){
    688692   
    689693    // check we have a target and a path.
    690694    if (this.targetPos && this.path !== undefined) {
     
    701705       
    702706        this.unitCollection.move(this.path[0][0][0], this.path[0][0][1]);
    703707        this.unitCollection.setStance("aggressive");
    704         this.unitCollection.filter(Filters.byClass("Siege")).setStance("defensive");
     708        this.unitCollection.filter(API3.Filters.byClass("Siege")).setStance("defensive");
    705709
    706710        this.state = "walking";
    707711    } else {
    708712        gameState.ai.gameFinished = true;
    709         debug ("I do not have any target. So I'll just assume I won the game.");
     713        m.debug ("I do not have any target. So I'll just assume I won the game.");
    710714        return false;
    711715    }
    712716    return true;
    713717};
    714718
    715719// Runs every turn after the attack is executed
    716 CityAttack.prototype.update = function(gameState, HQ, events){
     720m.CityAttack.prototype.update = function(gameState, HQ, events){
    717721    var self = this;
    718722       
    719723    Engine.ProfileStart("Update Attack");
     
    750754
    751755                    if (attacker && attacker.position() && attacker.hasClass("Unit") && attacker.owner() != 0 && attacker.owner() != PlayerID) {
    752756                       
    753                         var territoryMap = Map.createTerritoryMap(gameState);
     757                        var territoryMap = m.createTerritoryMap(gameState);
    754758                        if ( +territoryMap.point(attacker.position()) - 64 === +this.targetPlayer)
    755759                        {
    756760                            attackedNB++;
     
    769773            }
    770774        }
    771775        if (attackedNB > 4) {
    772             debug ("Attack Plan " +this.type +" " +this.name +" has arrived to destination.");
     776            m.debug ("Attack Plan " +this.type +" " +this.name +" has arrived to destination.");
    773777            // we must assume we've arrived at the end of the trail.
    774778            this.state = "arrived";
    775779        }
     
    799803                                var enemy = enemySoldiers[j];
    800804                                if (enemy.position() === undefined) // likely garrisoned
    801805                                    continue;
    802                                 if (inRange(enemy.position(), attacker.position(), 1000) && this.threatList.indexOf(enemy.id()) === -1)
     806                                if (m.inRange(enemy.position(), attacker.position(), 1000) && this.threatList.indexOf(enemy.id()) === -1)
    803807                                    this.threatList.push(enemy.id());
    804808                            }
    805809                            this.threatList.push(e.msg.attacker);
     
    844848        }
    845849
    846850        // basically haven't moved an inch: very likely stuck)
    847         if (SquareVectorDistance(this.position, this.position5TurnsAgo) < 10 && this.path.length > 0 && gameState.ai.playedTurn % 5 === 0) {
     851        if (API3.SquareVectorDistance(this.position, this.position5TurnsAgo) < 10 && this.path.length > 0 && gameState.ai.playedTurn % 5 === 0) {
    848852            // check for stuck siege units
    849853           
    850             var sieges = this.unitCollection.filter(Filters.byClass("Siege"));
     854            var sieges = this.unitCollection.filter(API3.Filters.byClass("Siege"));
    851855            var farthest = 0;
    852856            var farthestEnt = -1;
    853857            sieges.forEach (function (ent) {
    854                 if (SquareVectorDistance(ent.position(),self.position) > farthest)
     858                if (API3.SquareVectorDistance(ent.position(),self.position) > farthest)
    855859                {
    856                     farthest = SquareVectorDistance(ent.position(),self.position);
     860                    farthest = API3.SquareVectorDistance(ent.position(),self.position);
    857861                    farthestEnt = ent;
    858862                }
    859863            });
     
    863867        if (gameState.ai.playedTurn % 5 === 0)
    864868            this.position5TurnsAgo = this.position;
    865869       
    866         if (this.lastPosition && SquareVectorDistance(this.position, this.lastPosition) < 20 && this.path.length > 0) {
     870        if (this.lastPosition && API3.SquareVectorDistance(this.position, this.lastPosition) < 20 && this.path.length > 0) {
    867871            this.unitCollection.moveIndiv(this.path[0][0][0], this.path[0][0][1]);
    868872            // We're stuck, presumably. Check if there are no walls just close to us. If so, we're arrived, and we're gonna tear down some serious stone.
    869             var walls = gameState.getEnemyEntities().filter(Filters.and(Filters.byOwner(this.targetPlayer), Filters.byClass("StoneWall")));
     873            var walls = gameState.getEnemyEntities().filter(API3.Filters.and(API3.Filters.byOwner(this.targetPlayer), API3.Filters.byClass("StoneWall")));
    870874            var nexttoWalls = false;
    871875            walls.forEach( function (ent) {
    872                 if (!nexttoWalls && SquareVectorDistance(self.position, ent.position()) < 800)
     876                if (!nexttoWalls && API3.SquareVectorDistance(self.position, ent.position()) < 800)
    873877                    nexttoWalls = true;
    874878            });
    875879            // there are walls but we can attack
    876             if (nexttoWalls && this.unitCollection.filter(Filters.byCanAttack("StoneWall")).length !== 0)
     880            if (nexttoWalls && this.unitCollection.filter(API3.Filters.byCanAttack("StoneWall")).length !== 0)
    877881            {
    878                 debug ("Attack Plan " +this.type +" " +this.name +" has met walls and is not happy.");
     882                m.debug ("Attack Plan " +this.type +" " +this.name +" has met walls and is not happy.");
    879883                this.state = "arrived";
    880884            } else if (nexttoWalls) {
    881885                // abort plan.
    882                 debug ("Attack Plan " +this.type +" " +this.name +" has met walls and gives up.");
     886                m.debug ("Attack Plan " +this.type +" " +this.name +" has met walls and gives up.");
    883887                Engine.ProfileStop();
    884888                return 0;
    885889            }
    886890        }
    887891       
    888892        // check if our land units are close enough from the next waypoint.
    889         if (SquareVectorDistance(this.unitCollection.getCentrePosition(), this.targetPos) < 7500 ||
    890             SquareVectorDistance(this.unitCollection.getCentrePosition(), this.path[0][0]) < 650) {
    891             if (this.unitCollection.filter(Filters.byClass("Siege")).length !== 0
    892                 && SquareVectorDistance(this.unitCollection.getCentrePosition(), this.targetPos) >= 7500
    893                 && SquareVectorDistance(this.unitCollection.filter(Filters.byClass("Siege")).getCentrePosition(), this.path[0][0]) >= 650)
     893        if (API3.SquareVectorDistance(this.unitCollection.getCentrePosition(), this.targetPos) < 7500 ||
     894            API3.SquareVectorDistance(this.unitCollection.getCentrePosition(), this.path[0][0]) < 650) {
     895            if (this.unitCollection.filter(API3.Filters.byClass("Siege")).length !== 0
     896                && API3.SquareVectorDistance(this.unitCollection.getCentrePosition(), this.targetPos) >= 7500
     897                && API3.SquareVectorDistance(this.unitCollection.filter(API3.Filters.byClass("Siege")).getCentrePosition(), this.path[0][0]) >= 650)
    894898            {
    895899            } else {
    896900
    897901                for (var i = 0; i < this.path.length; ++i)
    898902                {
    899                     debug ("path waypoint " + i + "," + this.path[i][1] + " at " + uneval(this.path[i][0]));
     903                    m.debug ("path waypoint " + i + "," + this.path[i][1] + " at " + uneval(this.path[i][0]));
    900904                }
    901                 debug ("position is " + this.unitCollection.getCentrePosition());
     905                m.debug ("position is " + this.unitCollection.getCentrePosition());
    902906
    903907                // okay so here basically two cases. The first one is "we need a boat at this point".
    904908                // the second one is "we need to unload at this point". The third is "normal".
     
    908912                    if (this.path.length > 0){
    909913                        this.unitCollection.move(this.path[0][0][0], this.path[0][0][1]);
    910914                    } else {
    911                         debug ("Attack Plan " +this.type +" " +this.name +" has arrived to destination.");
     915                        m.debug ("Attack Plan " +this.type +" " +this.name +" has arrived to destination.");
    912916                        // we must assume we've arrived at the end of the trail.
    913917                        this.state = "arrived";
    914918                    }
     
    917921                    // TODO: make this require an escort later on.
    918922                    this.path.shift();
    919923                    if (this.path.length === 0) {
    920                         debug ("Attack Plan " +this.type +" " +this.name +" has arrived to destination.");
     924                        m.debug ("Attack Plan " +this.type +" " +this.name +" has arrived to destination.");
    921925                        // we must assume we've arrived at the end of the trail.
    922926                        this.state = "arrived";
    923927                    } else {
     
    925929                        var plan = new TransportPlan(gameState, this.unitCollection.toIdArray(), this.path[0][0], false);
    926930                        this.tpPlanID = plan.ID;
    927931                        HQ.navalManager.transportPlans.push(plan);
    928                         debug ("Transporting over sea");
     932                        m.debug ("Transporting over sea");
    929933                        this.state = "transporting";
    930934                    */
    931935                        // TODO: fix this above
     
    962966                });
    963967            var targetList = [];
    964968            enemyCitizens.forEach( function (enemy) {
    965                 if (inRange(enemy.position(), units.getCentrePosition(), 2500) && targetList.indexOf(enemy.id()) === -1)
     969                if (m.inRange(enemy.position(), units.getCentrePosition(), 2500) && targetList.indexOf(enemy.id()) === -1)
    966970                    targetList.push(enemy.id());
    967971            });
    968972            if (targetList.length > 0)
     
    989993                    if (attacker && attacker.position() && attacker.hasClass("Unit") && attacker.owner() != 0 && attacker.owner() != PlayerID) {
    990994                        if (ourUnit.hasClass("Siege"))
    991995                        {
    992                             var collec = this.unitCollection.filterNearest(ourUnit.position(), 8).filter(Filters.not(Filters.byClass("Siege"))).toEntityArray();
     996                            var collec = this.unitCollection.filterNearest(ourUnit.position(), 8).filter(API3.Filters.not(API3.Filters.byClass("Siege"))).toEntityArray();
    993997                            if (collec.length !== 0)
    994998                            {
    995999                                collec[0].attack(attacker.id());
     
    10181022            this.unitCollUpdateArray = this.unitCollection.toIdArray();
    10191023        } else {
    10201024            // some stuffs for locality and speed
    1021             var territoryMap = Map.createTerritoryMap(gameState);
     1025            var territoryMap = m.createTerritoryMap(gameState);
    10221026            var timeElapsed = gameState.getTimeElapsed();
    10231027           
    10241028            // Let's check a few units each time we update. Currently 10
     
    10571061                        if (!enemy.position() || (enemy.hasClass("StoneWall") && ent.canAttackClass("StoneWall"))) {
    10581062                            return false;
    10591063                        }
    1060                         if (SquareVectorDistance(enemy.position(),ent.position()) > 3000) {
     1064                        if (API3.SquareVectorDistance(enemy.position(),ent.position()) > 3000) {
    10611065                            return false;
    10621066                        }
    10631067                        return true;
     
    10701074                            }
    10711075                            if (!enemy.hasClass("Support"))
    10721076                                return false;
    1073                             if (SquareVectorDistance(enemy.position(),ent.position()) > 10000) {
     1077                            if (API3.SquareVectorDistance(enemy.position(),ent.position()) > 10000) {
    10741078                                return false;
    10751079                            }
    10761080                            return true;
     
    10811085                            if (!enemy.position()) {
    10821086                                return false;
    10831087                            }
    1084                             if (SquareVectorDistance(enemy.position(),ent.position()) > 10000) {
     1088                            if (API3.SquareVectorDistance(enemy.position(),ent.position()) > 10000) {
    10851089                                return false;
    10861090                            }
    10871091                            return true;
     
    11181122                            {
    11191123                                var rand = Math.floor(Math.random() * mStruct.length*0.1);
    11201124                                ent.attack(mStruct[+rand].id());
    1121                                 //debug ("Siege units attacking a structure from " +mStruct[+rand].owner() + " , " +mStruct[+rand].templateName());
     1125                                //m.debug ("Siege units attacking a structure from " +mStruct[+rand].owner() + " , " +mStruct[+rand].templateName());
    11221126                            }
    1123                         } else if (SquareVectorDistance(self.targetPos, ent.position()) > 900 ){
    1124                             //debug ("Siege units moving to " + uneval(self.targetPos));
     1127                        } else if (API3.SquareVectorDistance(self.targetPos, ent.position()) > 900 ){
     1128                            //m.debug ("Siege units moving to " + uneval(self.targetPos));
    11251129                            ent.move(self.targetPos[0],self.targetPos[1]);
    11261130                        }
    11271131                    } else {
    11281132                        if (mUnit.length !== 0) {
    11291133                            var rand = Math.floor(Math.random() * mUnit.length*0.99);
    11301134                            ent.attack(mUnit[(+rand)].id());
    1131                             //debug ("Units attacking a unit from " +mUnit[+rand].owner() + " , " +mUnit[+rand].templateName());
    1132                         } else if (SquareVectorDistance(self.targetPos, ent.position()) > 900 ){
    1133                             //debug ("Units moving to " + uneval(self.targetPos));
     1135                            //m.debug ("Units attacking a unit from " +mUnit[+rand].owner() + " , " +mUnit[+rand].templateName());
     1136                        } else if (API3.SquareVectorDistance(self.targetPos, ent.position()) > 900 ){
     1137                            //m.debug ("Units moving to " + uneval(self.targetPos));
    11341138                            ent.move(self.targetPos[0],self.targetPos[1]);
    11351139                        } else if (mStruct.length !== 0) {
    11361140                            mStruct.sort(function (structa,structb) { //}){
     
    11561160                            {
    11571161                                var rand = Math.floor(Math.random() * mStruct.length*0.1);
    11581162                                ent.attack(mStruct[+rand].id());
    1159                                 //debug ("Units attacking a structure from " +mStruct[+rand].owner() + " , " +mStruct[+rand].templateName());
     1163                                //m.debug ("Units attacking a structure from " +mStruct[+rand].owner() + " , " +mStruct[+rand].templateName());
    11601164                            }
    11611165                        }
    11621166                    }
     
    11721176                targets = this.defaultTargetFinder(gameState, HQ);
    11731177            }
    11741178            if (targets.length) {
    1175                 debug ("Seems like our target has been destroyed. Switching.");
    1176                 debug ("Aiming for " + targets);
     1179                m.debug ("Seems like our target has been destroyed. Switching.");
     1180                m.debug ("Aiming for " + targets);
    11771181                // picking a target
    11781182                this.targetPos = undefined;
    11791183                var count = 0;
     
    11831187                    this.targetPos = this.target.position();
    11841188                    count++;
    11851189                    if (count > 1000){
    1186                         debug("No target with a valid position found");
     1190                        m.debug("No target with a valid position found");
    11871191                        Engine.ProfileStop();
    11881192                        return false;
    11891193                    }
     
    12151219   
    12161220    return this.unitCollection.length;
    12171221};
    1218 CityAttack.prototype.totalCountUnits = function(gameState){
     1222m.CityAttack.prototype.totalCountUnits = function(gameState){
    12191223    var totalcount = 0;
    12201224    for (var i in this.idList)
    12211225    {
     
    12241228    return totalcount;
    12251229};
    12261230// reset any units
    1227 CityAttack.prototype.Abort = function(gameState){   
     1231m.CityAttack.prototype.Abort = function(gameState){
    12281232    this.unitCollection.forEach(function(ent) {
    12291233        ent.setMetadata(PlayerID, "role",undefined);
    12301234        ent.setMetadata(PlayerID, "subrole",undefined);
     
    12381242    gameState.ai.queueManager.removeQueue("plan_" + this.name);
    12391243    gameState.ai.queueManager.removeQueue("plan_" + this.name + "_champ");
    12401244};
     1245
     1246return m;
     1247}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/plan-transport.js

     
     1var AEGIS = function(m)
     2{
     3
    14/*
    25 Describes a transport plan
    36 Constructor assign units (units is an ID array, or an ID), a destionation (position, ingame), and a wanted escort size.
     
    1518// TODO: finish the support of multiple accessibility indexes.
    1619// TODO: this doesn't check we can actually reach in the init, which we might want?
    1720
    18 var TransportPlan = function(gameState, units, destination, allAtOnce, escortSize, onlyIfOK) {
     21m.TransportPlan = function(gameState, units, destination, allAtOnce, escortSize, onlyIfOK) {
    1922    var self = this;
    2023
    21     this.ID = uniqueIDTPlans++;
     24    this.ID = m.playerGlobals[PlayerID].uniqueIDTPlans++;
    2225   
    2326    var unitsID = [];
    2427    if (units.length !== undefined)
     
    2629    else
    2730        unitsID = [units];
    2831   
    29     this.units = EntityCollectionFromIds(gameState, unitsID);
     32    this.units = m.EntityCollectionFromIds(gameState, unitsID);
    3033    this.units.forEach(function (ent) { //}){
    3134        ent.setMetadata(PlayerID, "tpplan", self.ID);
    3235        ent.setMetadata(PlayerID, "formerRole", ent.getMetadata(PlayerID, "role"));
     
    3639    this.units.freeze();
    3740    this.units.registerUpdates();
    3841
    39     debug ("Starting a new plan with ID " +  this.ID + " to " + destination);
    40     debug ("units are " + uneval (units));
     42    m.debug ("Starting a new plan with ID " +  this.ID + " to " + destination);
     43    m.debug ("units are " + uneval (units));
    4144   
    4245    this.destination = destination;
    4346    this.destinationIndex = gameState.ai.accessibility.getAccessValue(destination);
     
    7073};
    7174
    7275// count available slots
    73 TransportPlan.prototype.countFreeSlots = function(onlyTrulyFree)
     76m.TransportPlan.prototype.countFreeSlots = function(onlyTrulyFree)
    7477{
    7578    var slots = 0;
    7679    this.transportShips.forEach(function (ent) { //}){
     
    8083    });
    8184}
    8285
    83 TransportPlan.prototype.assignShip = function(gameState, ship)
     86m.TransportPlan.prototype.assignShip = function(gameState, ship)
    8487{
    8588    ship.setMetadata(PlayerID,"tpplan", this.ID);
    8689}
    8790
    88 TransportPlan.prototype.releaseAll = function(gameState)
     91m.TransportPlan.prototype.releaseAll = function(gameState)
    8992{
    9093    this.ships.forEach(function (ent) { ent.setMetadata(PlayerID,"tpplan", undefined) });
    9194    this.units.forEach(function (ent) {
     
    9699    });
    97100}
    98101
    99 TransportPlan.prototype.releaseAllShips = function(gameState)
     102m.TransportPlan.prototype.releaseAllShips = function(gameState)
    100103{
    101104    this.ships.forEach(function (ent) { ent.setMetadata(PlayerID,"tpplan", undefined) });
    102105}
    103106
    104 TransportPlan.prototype.needTpShips = function()
     107m.TransportPlan.prototype.needTpShips = function()
    105108{
    106109    if ((this.allAtOnce && this.countFreeSlots() >= this.units.length) || this.transportShips.length > 0)
    107110        return false;
    108111    return true;
    109112}
    110113
    111 TransportPlan.prototype.needEscortShips = function()
     114m.TransportPlan.prototype.needEscortShips = function()
    112115{
    113116    return !((this.onlyIfOK && this.escortShips.length < this.escortSize) || !this.onlyIfOK);
    114117}
    115118
    116119// returns the zone for which we are needing our ships
    117 TransportPlan.prototype.neededShipsZone = function()
     120m.TransportPlan.prototype.neededShipsZone = function()
    118121{
    119122    if (!this.seaZone)
    120123        return false;
     
    134137    > there is the possibility that we'll be moving units on land, but that's basically a restart too, with more clearing.
    135138 Grouping Path is basically the same with "grouping" and we never unboard (unless there is a need to)
    136139 */
    137 TransportPlan.prototype.carryOn = function(gameState, navalManager)
     140m.TransportPlan.prototype.carryOn = function(gameState, navalManager)
    138141{
    139142    if (this.state === "unstarted")
    140143    {
     
    171174        // let's get our index this turn.
    172175        this.startIndex = unitIndexes[0];
    173176
    174         debug ("plan " +  this.ID + " from " + this.startIndex);
     177        m.debug ("plan " +  this.ID + " from " + this.startIndex);
    175178
    176179        return true;
    177180    }
     
    190193            }
    191194            // we have a path, register the first sea zone.
    192195            this.seaZone = this.path[1];
    193             debug ("Plan " + this.ID + " over seazone " + this.seaZone);
     196            m.debug ("Plan " + this.ID + " over seazone " + this.seaZone);
    194197        }
    195198        // if we currently have no baoarding spot, try and find one.
    196199        if (!this.boardingSpot)
     
    206209            var passabilityMap = gameState.getMap();
    207210            var territoryMap = gameState.ai.territoryMap;
    208211            var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction") | gameState.getPassabilityClassMask("building-shore");
    209             var obstructions = new Map(gameState.sharedScript);
     212            var obstructions = new API3.Map(gameState.sharedScript);
    210213           
    211214            // wanted map.
    212             var friendlyTiles = new Map(gameState.sharedScript);
     215            var friendlyTiles = new API3.Map(gameState.sharedScript);
    213216           
    214217            for (var j = 0; j < friendlyTiles.length; ++j)
    215218            {
     
    248251           
    249252            // we have the spot we want to board at.
    250253            this.boardingSpot = [x,z];
    251             debug ("Plan " + this.ID + " new boarding spot is  " + this.boardingSpot);
     254            m.debug ("Plan " + this.ID + " new boarding spot is  " + this.boardingSpot);
    252255        }
    253256
    254257        // if all at once we need to be full, else we just need enough escort ships.
     
    262265           
    263266            this.garrisonShipID = -1;
    264267           
    265             debug ("Boarding");
     268            m.debug ("Boarding");
    266269            this.state = "boarding";
    267270        }
    268271        return true;
     
    300303
    301304        // check if we need to move our units and ships closer together
    302305        var stillMoving = false;
    303         if (SquareVectorDistance(this.ships.getCentrePosition(),this.boardingSpot) > 1600)
     306        if (API3.SquareVectorDistance(this.ships.getCentrePosition(),this.boardingSpot) > 1600)
    304307        {
    305308            this.ships.move(this.boardingSpot[0],this.boardingSpot[1]);
    306309            stillMoving = true; // wait till ships are in position
    307310        }
    308         if (SquareVectorDistance(this.units.getCentrePosition(),this.boardingSpot) > 1600)
     311        if (API3.SquareVectorDistance(this.units.getCentrePosition(),this.boardingSpot) > 1600)
    309312        {
    310313            this.units.move(this.boardingSpot[0],this.boardingSpot[1]);
    311314            stillMoving = true; // wait till units are in position
     
    365368            var passabilityMap = gameState.getMap();
    366369            var territoryMap = gameState.ai.territoryMap;
    367370            var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction") | gameState.getPassabilityClassMask("building-shore");
    368             var obstructions = new Map(gameState.sharedScript);
     371            var obstructions = new API3.Map(gameState.sharedScript);
    369372           
    370373            // wanted map.
    371             var friendlyTiles = new Map(gameState.sharedScript);
     374            var friendlyTiles = new API3.Map(gameState.sharedScript);
    372375           
    373376            var wantedIndex = -1;
    374377           
     
    377380                this.path.splice(0,2);
    378381                wantedIndex = this.path[0];
    379382            } else {
    380                 debug ("too short at " +uneval(this.path));
     383                m.debug ("too short at " +uneval(this.path));
    381384                return false; // Incomputable
    382385            }
    383386           
     
    431434            return false;
    432435       
    433436        // check if we need to move ships
    434         if (SquareVectorDistance(this.ships.getCentrePosition(),this.unboardingSpot) > 400)
     437        if (API3.SquareVectorDistance(this.ships.getCentrePosition(),this.unboardingSpot) > 400)
    435438        {
    436439            this.ships.move(this.unboardingSpot[0],this.unboardingSpot[1]);
    437440        } else {
     
    447450            return false;
    448451       
    449452        // check if we need to move ships
    450         if (SquareVectorDistance(this.ships.getCentrePosition(),this.unboardingSpot) > 400)
     453        if (API3.SquareVectorDistance(this.ships.getCentrePosition(),this.unboardingSpot) > 400)
    451454        {
    452455            this.ships.move(this.unboardingSpot[0],this.unboardingSpot[1]);
    453456        } else {
     
    455458            // TODO: improve on this.
    456459            if (this.path.length > 1)
    457460            {
    458                 debug ("plan " +  this.ID + " going back for more");
     461                m.debug ("plan " +  this.ID + " going back for more");
    459462                // basically reset.
    460463                delete this.boardingSpot;
    461464                delete this.unboardingSpot;
     
    463466                this.releaseAllShips();
    464467                return true;
    465468            }
    466             debug ("plan " +  this.ID + " is finished");
     469            m.m.debug ("plan " +  this.ID + " is finished");
    467470            return false;
    468471        }
    469472    }
    470473
    471474    return true;
    472475}
     476
     477return m;
     478}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/aegis.js

     
     1
     2var AEGIS = (function() {
     3var m = {};
     4
    15// "local" global variables for stuffs that will need a unique ID
    26// Note that since order of loading is alphabetic, this means this file must go before any other file using them.
    3 var uniqueIDBOPlans = 0;    // training/building/research plans
    4 var uniqueIDBases = 1;  // base manager ID. Starts at one because "0" means "no base" on the map
    5 var uniqueIDTPlans = 1; // transport plans. starts at 1 because 0 might be used as none.
     7m.playerGlobals = [];
     8m.g_debugEnabled = false;
    69
    7 function AegisBot(settings) {
    8     BaseAI.call(this, settings);
     10m.AegisBot = function AegisBot(settings) {
     11    API3.BaseAI.call(this, settings);
    912
    10     Config.updateDifficulty(settings.difficulty);
     13    this.Config = new m.Config();
     14
     15    this.Config.updateDifficulty(settings.difficulty);
    1116   
    1217    this.turn = 0;
    1318
    1419    this.playedTurn = 0;
    15        
    16     this.priorities = Config.priorities;
     20   
     21    this.priorities = this.Config.priorities;
    1722
    1823    // this.queues can only be modified by the queue manager or things will go awry.
    1924    this.queues = {};
    2025    for (i in this.priorities)
    21         this.queues[i] = new Queue();
     26        this.queues[i] = new m.Queue();
    2227
    23     this.queueManager = new QueueManager(this.queues, this.priorities);
     28    this.queueManager = new m.QueueManager(this.Config, this.queues, this.priorities);
    2429
    25     this.HQ = new HQ();
     30    this.HQ = new m.HQ(this.Config);
    2631
    2732    this.firstTime = true;
    2833
     
    3035   
    3136    this.defcon = 5;
    3237    this.defconChangeTime = -10000000;
    33 }
     38};
    3439
    35 AegisBot.prototype = new BaseAI();
     40m.AegisBot.prototype = new API3.BaseAI();
    3641
    37 AegisBot.prototype.CustomInit = function(gameState, sharedScript) {
    38    
     42m.AegisBot.prototype.CustomInit = function(gameState, sharedScript) {
     43
     44    m.playerGlobals[PlayerID] = {};
     45    m.playerGlobals[PlayerID].uniqueIDBOPlans = 0;  // training/building/research plans
     46    m.playerGlobals[PlayerID].uniqueIDBases = 1;    // base manager ID. Starts at one because "0" means "no base" on the map
     47    m.playerGlobals[PlayerID].uniqueIDTPlans = 1;   // transport plans. starts at 1 because 0 might be used as none.   
     48
    3949    this.HQ.init(gameState,sharedScript.events,this.queues);
    40     debug ("Initialized with the difficulty " + Config.difficulty);
     50    m.debug ("Initialized with the difficulty " + this.Config.difficulty);
    4151
    42     var ents = gameState.getEntities().filter(Filters.byOwner(PlayerID));
     52    var ents = gameState.getEntities().filter(API3.Filters.byOwner(this.player));
    4353    var myKeyEntities = ents.filter(function(ent) {
    4454            return ent.hasClass("CivCentre");
    4555    });
    4656
    4757    if (myKeyEntities.length == 0){
    48         myKeyEntities = gameState.getEntities().filter(Filters.byOwner(PlayerID));
     58        myKeyEntities = gameState.getEntities().filter(API3.Filters.byOwner(this.player));
    4959    }
    5060   
    51     var filter = Filters.byClass("CivCentre");
    52     var enemyKeyEntities = gameState.getEntities().filter(Filters.not(Filters.byOwner(PlayerID))).filter(filter);
     61    var filter = API3.Filters.byClass("CivCentre");
     62    var enemyKeyEntities = gameState.getEntities().filter(API3.Filters.not(API3.Filters.byOwner(this.player))).filter(filter);
    5363   
    5464    if (enemyKeyEntities.length == 0){
    55         enemyKeyEntities = gameState.getEntities().filter(Filters.not(Filters.byOwner(PlayerID)));
     65        enemyKeyEntities = gameState.getEntities().filter(API3.Filters.not(API3.Filters.byOwner(this.player)));
    5666    }
    5767
    5868    this.myIndex = this.accessibility.getAccessValue(myKeyEntities.toEntityArray()[0].position());
    5969   
    60     this.pathFinder = new aStarPath(gameState, false, true);
     70    this.pathFinder = new API3.aStarPath(gameState, false, true);
    6171    this.pathsToMe = [];
    6272    this.pathInfo = { "angle" : 0, "needboat" : true, "mkeyPos" : myKeyEntities.toEntityArray()[0].position(), "ekeyPos" : enemyKeyEntities.toEntityArray()[0].position() };
    6373   
     
    6575    var pos = [this.pathInfo.mkeyPos[0] + 150*Math.cos(this.pathInfo.angle),this.pathInfo.mkeyPos[1] + 150*Math.sin(this.pathInfo.angle)];
    6676    var path = this.pathFinder.getPath(this.pathInfo.ekeyPos, pos, 2, 2);// uncomment for debug:*/, 300000, gameState);
    6777
    68     //Engine.DumpImage("initialPath" + PlayerID + ".png", this.pathFinder.TotorMap.map, this.pathFinder.TotorMap.width,this.pathFinder.TotorMap.height,255);
     78    //Engine.DumpImage("initialPath" + this.player + ".png", this.pathFinder.TotorMap.map, this.pathFinder.TotorMap.width,this.pathFinder.TotorMap.height,255);
    6979   
    7080    if (path !== undefined && path[1] !== undefined && path[1] == false) {
    7181        // path is viable and doesn't require boating.
     
    8090    this.chooseRandomStrategy();
    8191}
    8292
    83 AegisBot.prototype.OnUpdate = function(sharedScript) {
     93m.AegisBot.prototype.OnUpdate = function(sharedScript) {
     94
    8495    if (this.gameFinished){
    8596        return;
    8697    }
     
    120131            {
    121132                if (this.pathInfo.needboat)
    122133                {
    123                     debug ("Assuming this is a water map");
     134                    m.debug ("Assuming this is a water map");
    124135                    this.HQ.waterMap = true;
    125136                }
    126137                delete this.pathFinder;
     
    132143        var cityPhase = this.gameState.cityPhase();
    133144        // try going up phases.
    134145        // TODO: softcode this.
    135         if (this.gameState.canResearch(townPhase,true) && this.gameState.getTimeElapsed() > (Config.Economy.townPhase*1000) && this.gameState.getPopulation() > 40
     146        if (this.gameState.canResearch(townPhase,true) && this.gameState.getTimeElapsed() > (this.Config.Economy.townPhase*1000) && this.gameState.getPopulation() > 40
    136147            && this.gameState.findResearchers(townPhase,true).length != 0 && this.queues.majorTech.length() === 0
    137             && this.gameState.getOwnEntities().filter(Filters.byClass("Village")).length > 5)
     148            && this.gameState.getOwnEntities().filter(API3.Filters.byClass("Village")).length > 5)
    138149        {
    139150            this.queueManager.pauseQueue("villager", true);
    140151            this.queueManager.pauseQueue("citizenSoldier", true);
    141152            this.queueManager.pauseQueue("house", true);
    142             this.queues.majorTech.addItem(new ResearchPlan(this.gameState, townPhase,0,-1,true));   // we rush the town phase.
    143             debug ("Trying to reach town phase");
     153            this.queues.majorTech.addItem(new m.ResearchPlan(this.gameState, townPhase,0,-1,true)); // we rush the town phase.
     154            m.debug ("Trying to reach town phase");
    144155        }
    145         else if (this.gameState.canResearch(cityPhase,true) && this.gameState.getTimeElapsed() > (Config.Economy.cityPhase*1000)
     156        else if (this.gameState.canResearch(cityPhase,true) && this.gameState.getTimeElapsed() > (this.Config.Economy.cityPhase*1000)
    146157                && this.gameState.getOwnEntitiesByRole("worker").length > 85
    147158                && this.gameState.findResearchers(cityPhase, true).length != 0 && this.queues.majorTech.length() === 0) {
    148             debug ("Trying to reach city phase");
    149             this.queues.majorTech.addItem(new ResearchPlan(this.gameState, cityPhase));
     159            m.debug ("Trying to reach city phase");
     160            this.queues.majorTech.addItem(new m.ResearchPlan(this.gameState, cityPhase));
    150161        }
    151162        // defcon cooldown
    152163        if (this.defcon < 5 && this.gameState.timeSinceDefconChange() > 20000)
    153164        {
    154165            this.defcon++;
    155             debug ("updefconing to " +this.defcon);
     166            m.debug ("updefconing to " +this.defcon);
    156167            if (this.defcon >= 4 && this.HQ.hasGarrisonedFemales)
    157168                this.HQ.ungarrisonAll(this.gameState);
    158169        }
     
    210221    this.turn++;
    211222};
    212223
    213 AegisBot.prototype.chooseRandomStrategy = function()
     224m.AegisBot.prototype.chooseRandomStrategy = function()
    214225{
    215226    // deactivated for now.
    216227    this.strategy = "normal";
    217228    // rarely and if we can assume it's not a water map.
    218     if (!this.pathInfo.needboat && 0)//Math.random() < 0.2 && Config.difficulty == 2)
     229    if (!this.pathInfo.needboat && 0)//Math.random() < 0.2 && this.Config.difficulty == 2)
    219230    {
    220231        this.strategy = "rush";
    221232        // going to rush.
    222233        this.HQ.targetNumWorkers = 0;
    223         Config.Economy.townPhase = 480;
    224         Config.Economy.cityPhase = 900;
    225         Config.Economy.farmsteadStartTime = 600;
    226         Config.Economy.femaleRatio = 0; // raise it since we'll want to rush age 2.
     234        this.Config.Economy.townPhase = 480;
     235        this.Config.Economy.cityPhase = 900;
     236        this.Config.Economy.farmsteadStartTime = 600;
     237        this.Config.Economy.femaleRatio = 0;    // raise it since we'll want to rush age 2.
    227238    }
    228239};
    229240
    230 /*AegisBot.prototype.Deserialize = function(data, sharedScript)
     241/*m.AegisBot.prototype.Deserialize = function(data, sharedScript)
    231242{
    232243};
    233244
     
    237248    return {};
    238249};*/
    239250
    240 function debug(output){
    241     if (Config.debug){
     251m.debug = function(output){
     252    if (m.g_debugEnabled){
    242253        if (typeof output === "string"){
    243254            warn(output);
    244255        }else{
    245256            warn(uneval(output));
    246257        }
    247258    }
    248 }
     259};
    249260
    250 function copyPrototype(descendant, parent) {
     261m.copyPrototype = function(descendant, parent) {
    251262    var sConstructor = parent.toString();
    252263    var aMatch = sConstructor.match( /\s*function (.*)\(/ );
    253264    if ( aMatch != null ) { descendant.prototype[aMatch[1]] = parent; }
    254265    for (var m in parent.prototype) {
    255266        descendant.prototype[m] = parent.prototype[m];
    256267    }
    257 }
     268};
     269
     270return m;
     271}());
  • binaries/data/mods/public/simulation/ai/aegis/queueplan-building.js

     
    1 var ConstructionPlan = function(gameState, type, metadata, startTime, expectedTime, position) {
     1var AEGIS = function(m)
     2{
     3
     4m.ConstructionPlan = function(gameState, type, metadata, startTime, expectedTime, position) {
    25    this.type = gameState.applyCiv(type);
    36    this.position = position;
    47
    58    this.metadata = metadata;
    69
    7     this.ID = uniqueIDBOPlans++;
     10    this.ID = m.playerGlobals[PlayerID].uniqueIDBOPlans++;
    811
    912    this.template = gameState.getTemplate(this.type);
    1013    if (!this.template) {
     
    1215    }
    1316   
    1417    this.category = "building";
    15     this.cost = new Resources(this.template.cost());
     18    this.cost = new API3.Resources(this.template.cost());
    1619    this.number = 1; // The number of buildings to build
    1720   
    1821    if (!startTime)
     
    2831};
    2932
    3033// return true if we willstart amassing resource for this plan
    31 ConstructionPlan.prototype.isGo = function(gameState) {
     34m.ConstructionPlan.prototype.isGo = function(gameState) {
    3235    return (gameState.getTimeElapsed() > this.startTime);
    3336};
    3437
    3538// checks other than resource ones.
    3639// TODO: change this.
    37 ConstructionPlan.prototype.canStart = function(gameState) {
     40m.ConstructionPlan.prototype.canStart = function(gameState) {
    3841    if (gameState.buildingsBuilt > 0)
    3942        return false;
    4043   
     
    5154    return (builders.length != 0);
    5255};
    5356
    54 ConstructionPlan.prototype.start = function(gameState) {
     57m.ConstructionPlan.prototype.start = function(gameState) {
    5558   
    5659    var builders = gameState.findBuilders(this.type).toEntityArray();
    5760
     
    6366    if (!pos){
    6467        if (this.template.hasClass("Naval"))
    6568            gameState.ai.HQ.dockFailed = true;
    66         debug("No room to place " + this.type);
     69        m.debug("No room to place " + this.type);
    6770        return;
    6871    }
    6972    if (this.template.hasClass("Naval"))
    70         debug (pos);
     73        m.debug (pos);
    7174    gameState.buildingsBuilt++;
    7275
    7376    if (gameState.getTemplate(this.type).buildCategory() === "Dock")
     
    8083        builders[0].construct(this.type, pos.x, pos.z, pos.angle, this.metadata);
    8184};
    8285
    83 ConstructionPlan.prototype.getCost = function() {
    84     var costs = new Resources();
     86m.ConstructionPlan.prototype.getCost = function() {
     87    var costs = new API3.Resources();
    8588    costs.add(this.cost);
    8689    return costs;
    8790};
    8891
    89 ConstructionPlan.prototype.findGoodPosition = function(gameState) {
     92m.ConstructionPlan.prototype.findGoodPosition = function(gameState) {
    9093    var template = gameState.getTemplate(this.type);
    9194
    9295    var cellSize = gameState.cellSize; // size of each tile
    9396
    9497    // First, find all tiles that are far enough away from obstructions:
    9598
    96     var obstructionMap = Map.createObstructionMap(gameState,0, template);
     99    var obstructionMap = m.createObstructionMap(gameState,0, template);
    97100   
    98101    //obstructionMap.dumpIm(template.buildCategory() + "_obstructions_pre.png");
    99102
     
    104107
    105108    // Compute each tile's closeness to friendly structures:
    106109
    107     var friendlyTiles = new Map(gameState.sharedScript);
     110    var friendlyTiles = new API3.Map(gameState.sharedScript);
    108111   
    109112    var alreadyHasHouses = false;
    110113
     
    229232        "angle" : angle
    230233    };
    231234};
     235
     236
     237return m;
     238}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/entity-extend.js

     
     1var AEGIS = function(m)
     2{
     3
    14// returns some sort of DPS * health factor. If you specify a class, it'll use the modifiers against that class too.
    2 function getMaxStrength(ent, againstClass)
     5m.getMaxStrength = function(ent, againstClass)
    36{
    47    var strength = 0.0;
    58    var attackTypes = ent.attackTypes();
     
    6164    }
    6265    return strength * hp;
    6366};
     67
     68return m;
     69}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/config.js

     
    1 // Baseconfig is the highest difficulty.
    2 var baseConfig = {
    3     "Military" : {
     1var AEGIS = function(m)
     2{
     3
     4m.Config = function() {
     5    this.debug = false; // 0 is sandbox, 1 is easy, 2 is medium, 3 is hard, 4 is very hard.
     6    this.difficulty = 2;    // overriden by the GUI
     7
     8    this.Military = {
    49        "fortressLapseTime" : 540, // Time to wait between building 2 fortresses
    510        "defenceBuildingTime" : 600, // Time to wait before building towers or fortresses
    611        "attackPlansStartTime" : 0, // time to wait before attacking. Start as soon as possible (first barracks)
     
    813        "popForBarracks1" : 15,
    914        "popForBarracks2" : 95,
    1015        "timeForBlacksmith" : 900,
    11     },
    12     "Economy" : {
     16    };
     17    this.Economy = {
    1318        "townPhase" : 180,  // time to start trying to reach town phase (might be a while after. Still need the requirements + ress )
    1419        "cityPhase" : 840,  // time to start trying to reach city phase
    1520        "popForMarket" : 80,
     
    1924        "targetNumBuilders" : 1.5, // Base number of builders per foundation.
    2025        "femaleRatio" : 0.4, // percent of females among the workforce.
    2126        "initialFields" : 2
    22     },
     27    };
    2328   
    2429    // Note: attack settings are set directly in attack_plan.js
    2530   
    2631    // defence
    27     "Defence" : {
     32    this.Defence =
     33    {
    2834        "defenceRatio" : 5, // see defence.js for more info.
    2935        "armyCompactSize" : 700,    // squared. Half-diameter of an army.
    3036        "armyBreakawaySize" : 900  // squared.
    31     },
     37    };
    3238   
    3339    // military
    34     "buildings" : {
     40    this.buildings =
     41    {
    3542        "moderate" : {
    3643            "default" : [ "structures/{civ}_barracks" ]
    3744        },
     
    5158            "default" : [ "structures/{civ}_fortress" ],
    5259            "celt" : [ "structures/{civ}_fortress_b", "structures/{civ}_fortress_g" ]
    5360        }
    54     },
     61    };
    5562
    5663    // qbot
    57     "priorities" : {  // Note these are dynamic, you are only setting the initial values
     64    this.priorities =
     65    {  // Note these are dynamic, you are only setting the initial values
    5866        "house" : 350,
    5967        "villager" : 40,
    6068        "citizenSoldier" : 60,
     
    6775        "majorTech" : 700,
    6876        "minorTech" : 50,
    6977        "civilCentre" : 400
    70     },
    71     "difficulty" : 2,   // 0 is sandbox, 1 is easy, 2 is medium, 3 is hard, 4 is very hard.
    72     "debug" : false
     78    };
    7379};
    7480
    75 var Config = {
    76     "debug": false,
    77     "difficulty" : 2,   // overriden by the GUI
    78     updateDifficulty: function(difficulty)
     81//Config.prototype = new BaseConfig();
     82
     83m.Config.prototype.updateDifficulty = function(difficulty)
     84{
     85    this.difficulty = difficulty;
     86    // changing settings based on difficulty.
     87    if (this.difficulty === 1)
    7988    {
    80         Config.difficulty = difficulty;
    81         // changing settings based on difficulty.
    82         if (Config.difficulty === 1)
    83         {
    84             Config.Military.defenceBuildingTime = 1200;
    85             Config.Military.attackPlansStartTime = 960;
    86             Config.Military.popForBarracks1 = 35;
    87             Config.Military.popForBarracks2 = 150;  // shouldn't reach it
    88             Config.Military.popForBlacksmith = 150; // shouldn't reach it
     89        this.Military.defenceBuildingTime = 1200;
     90        this.Military.attackPlansStartTime = 960;
     91        this.Military.popForBarracks1 = 35;
     92        this.Military.popForBarracks2 = 150;    // shouldn't reach it
     93        this.Military.popForBlacksmith = 150;   // shouldn't reach it
    8994
    90             Config.Economy.cityPhase = 1800;
    91             Config.Economy.popForMarket = 80;
    92             Config.Economy.techStartTime = 600;
    93             Config.Economy.femaleRatio = 0.6;
    94             Config.Economy.initialFields = 1;
    95             // Config.Economy.targetNumWorkers will be set by AI scripts.
    96         }
    97         else if (Config.difficulty === 0)
    98         {
    99             Config.Military.defenceBuildingTime = 450;
    100             Config.Military.attackPlansStartTime = 9600000; // never
    101             Config.Military.popForBarracks1 = 60;
    102             Config.Military.popForBarracks2 = 150;  // shouldn't reach it
    103             Config.Military.popForBlacksmith = 150; // shouldn't reach it
     95        this.Economy.cityPhase = 1800;
     96        this.Economy.popForMarket = 80;
     97        this.Economy.techStartTime = 600;
     98        this.Economy.femaleRatio = 0.6;
     99        this.Economy.initialFields = 1;
     100        // Config.Economy.targetNumWorkers will be set by AI scripts.
     101    }
     102    else if (this.difficulty === 0)
     103    {
     104        this.Military.defenceBuildingTime = 450;
     105        this.Military.attackPlansStartTime = 9600000;   // never
     106        this.Military.popForBarracks1 = 60;
     107        this.Military.popForBarracks2 = 150;    // shouldn't reach it
     108        this.Military.popForBlacksmith = 150;   // shouldn't reach it
    104109
    105             Config.Economy.cityPhase = 240000;
    106             Config.Economy.popForMarket = 200;
    107             Config.Economy.techStartTime = 1800;
    108             Config.Economy.femaleRatio = 0.2;
    109             Config.Economy.initialFields = 1;
    110             // Config.Economy.targetNumWorkers will be set by AI scripts.
    111         }
     110        this.Economy.cityPhase = 240000;
     111        this.Economy.popForMarket = 200;
     112        this.Economy.techStartTime = 1800;
     113        this.Economy.femaleRatio = 0.2;
     114        this.Economy.initialFields = 1;
     115        // Config.Economy.targetNumWorkers will be set by AI scripts.
    112116    }
    113117};
    114118
    115 Config.__proto__ = baseConfig;
     119return m;
     120}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/queueplan-training.js

     
    1 var TrainingPlan = function(gameState, type, metadata, number, startTime, expectedTime, maxMerge) {
     1var AEGIS = function(m)
     2{
     3
     4m.TrainingPlan = function(gameState, type, metadata, number, startTime, expectedTime, maxMerge) {
    25    this.type = gameState.applyCiv(type);
    36    this.metadata = metadata;
    47
    5     this.ID = uniqueIDBOPlans++;
     8    this.ID = m.playerGlobals[PlayerID].uniqueIDBOPlans++;
    69   
    710    this.template = gameState.getTemplate(this.type);
    811    if (!this.template)
    912        return false;
    1013
    1114    this.category = "unit";
    12     this.cost = new Resources(this.template.cost(), this.template._template.Cost.Population);
     15    this.cost = new API3.Resources(this.template.cost(), this.template._template.Cost.Population);
    1316    if (!number)
    1417        this.number = 1;
    1518    else
     
    3336};
    3437
    3538// return true if we willstart amassing resource for this plan
    36 TrainingPlan.prototype.isGo = function(gameState) {
     39m.TrainingPlan.prototype.isGo = function(gameState) {
    3740    return (gameState.getTimeElapsed() > this.startTime);
    3841};
    3942
    40 TrainingPlan.prototype.canStart = function(gameState) {
     43m.TrainingPlan.prototype.canStart = function(gameState) {
    4144    if (this.invalidTemplate)
    4245        return false;
    4346
     
    4851    return (trainers.length != 0);
    4952};
    5053
    51 TrainingPlan.prototype.start = function(gameState) {
     54m.TrainingPlan.prototype.start = function(gameState) {
    5255    //warn("Executing TrainingPlan " + uneval(this));
    5356    var self = this;
    5457    var trainers = gameState.findTrainers(this.type).toEntityArray();
     
    7275    }
    7376};
    7477
    75 TrainingPlan.prototype.getCost = function(){
    76     var multCost = new Resources();
     78m.TrainingPlan.prototype.getCost = function(){
     79    var multCost = new API3.Resources();
    7780    multCost.add(this.cost);
    7881    multCost.multiply(this.number);
    7982    return multCost;
    8083};
    8184
    82 TrainingPlan.prototype.addItem = function(amount){
     85m.TrainingPlan.prototype.addItem = function(amount){
    8386    if (amount === undefined)
    8487        amount = 1;
    8588    this.number += amount;
    8689};
     90
     91
     92return m;
     93}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/enemy-watcher.js

     
     1var AEGIS = function(m)
     2{
     3
    14/*
    25 * A class that keeps track of enemy buildings, units, and pretty much anything I can think of (still a LOT TODO here)
    36 * Only watches one enemy, you'll need one per enemy.
     
    47 * Note: pretty much unused in the current version.
    58 */
    69
    7 var enemyWatcher = function(gameState, playerToWatch) {
     10m.enemyWatcher = function(gameState, playerToWatch) {
    811   
    912    this.watched = playerToWatch;
    1013   
    1114    // using global entity collections, shared by any AI that knows the name of this.
    1215   
    13     var filter = Filters.and(Filters.byClass("Structure"), Filters.byOwner(this.watched));
     16    var filter = API3.Filters.and(API3.Filters.byClass("Structure"), API3.Filters.byOwner(this.watched));
    1417    this.enemyBuildings = gameState.updatingGlobalCollection("player-" +this.watched + "-structures", filter);
    1518
    16     filter = Filters.and(Filters.byClass("Unit"), Filters.byOwner(this.watched));
     19    filter = API3.Filters.and(API3.Filters.byClass("Unit"), API3.Filters.byOwner(this.watched));
    1720    this.enemyUnits = gameState.updatingGlobalCollection("player-" +this.watched + "-units", filter);
    1821
    19     filter = Filters.and(Filters.byClass("Worker"), Filters.byOwner(this.watched));
     22    filter = API3.Filters.and(API3.Filters.byClass("Worker"), API3.Filters.byOwner(this.watched));
    2023    this.enemyCivilians = gameState.updatingGlobalCollection("player-" +this.watched + "-civilians", filter);
    2124                             
    22     filter = Filters.and(Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), Filters.byOwner(this.watched));
     25    filter = API3.Filters.and(API3.Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), API3.Filters.byOwner(this.watched));
    2326    this.enemySoldiers = gameState.updatingGlobalCollection("player-" +this.watched + "-soldiers", filter);
    2427   
    25     filter = Filters.and(Filters.byClass("Worker"), Filters.byOwner(this.watched));
     28    filter = API3.Filters.and(API3.Filters.byClass("Worker"), API3.Filters.byOwner(this.watched));
    2629    this.enemyCivilians = gameState.getEnemyEntities().filter(filter);
    2730    this.enemyCivilians.registerUpdates();
    2831
    29     filter = Filters.and(Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), Filters.byOwner(this.watched));
     32    filter = API3.Filters.and(API3.Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), API3.Filters.byOwner(this.watched));
    3033    this.enemySoldiers = gameState.getEnemyEntities().filter(filter);
    3134    this.enemySoldiers.registerUpdates();
    3235
     
    4043    this.dangerousArmies = [];
    4144   
    4245};
    43 enemyWatcher.prototype.getAllEnemySoldiers = function() {
     46m.enemyWatcher.prototype.getAllEnemySoldiers = function() {
    4447    return this.enemySoldiers;
    4548};
    46 enemyWatcher.prototype.getAllEnemyBuildings = function() {
     49m.enemyWatcher.prototype.getAllEnemyBuildings = function() {
    4750    return this.enemyBuildings;
    4851};
    4952
    50 enemyWatcher.prototype.getEnemyBuildings = function(gameState, specialClass, OneTime) {
    51     var filter = Filters.byClass(specialClass);
     53m.enemyWatcher.prototype.getEnemyBuildings = function(gameState, specialClass, OneTime) {
     54    var filter = API3.Filters.byClass(specialClass);
    5255   
    5356    if (OneTime && gameState.getGEC("player-" +this.watched + "-structures-" +specialClass))
    5457        return gameState.getGEC("player-" +this.watched + "-structures-" +specialClass);
     
    5760   
    5861    return gameState.updatingGlobalCollection("player-" +this.watched + "-structures-" +specialClass, filter, gameState.getGEC("player-" +this.watched + "-structures"));
    5962};
    60 enemyWatcher.prototype.getDangerousArmies = function() {
     63m.enemyWatcher.prototype.getDangerousArmies = function() {
    6164    var toreturn = {};
    6265    for (var i in this.dangerousArmies)
    6366        toreturn[this.dangerousArmies[i]] = this.armies[this.dangerousArmies[i]];
    6467    return toreturn;
    6568};
    66 enemyWatcher.prototype.getSafeArmies = function() {
     69m.enemyWatcher.prototype.getSafeArmies = function() {
    6770    var toreturn = {};
    6871    for (var i in this.armies)
    6972        if (this.dangerousArmies.indexOf(i) == -1)
    7073            toreturn[i] = this.armies[i];
    7174    return toreturn;
    7275};
    73 enemyWatcher.prototype.resetDangerousArmies = function() {
     76m.enemyWatcher.prototype.resetDangerousArmies = function() {
    7477    this.dangerousArmies = [];
    7578};
    76 enemyWatcher.prototype.setAsDangerous = function(armyID) {
     79m.enemyWatcher.prototype.setAsDangerous = function(armyID) {
    7780    if (this.dangerousArmies.indexOf(armyID) === -1)
    7881        this.dangerousArmies.push(armyID);
    7982};
    80 enemyWatcher.prototype.isDangerous = function(armyID) {
     83m.enemyWatcher.prototype.isDangerous = function(armyID) {
    8184    if (this.dangerousArmies.indexOf(armyID) === -1)
    8285        return false;
    8386    return true;
    8487};
    8588// returns [id, army]
    86 enemyWatcher.prototype.getArmyFromMember = function(memberID) {
     89m.enemyWatcher.prototype.getArmyFromMember = function(memberID) {
    8790    for (var i in this.armies) {
    8891        if (this.armies[i].toIdArray().indexOf(memberID) !== -1)
    8992            return [i,this.armies[i]];
    9093    }
    9194    return undefined;
    9295};
    93 enemyWatcher.prototype.isPartOfDangerousArmy = function(memberID) {
     96m.enemyWatcher.prototype.isPartOfDangerousArmy = function(memberID) {
    9497    var armyID = this.getArmyFromMember(memberID)[0];
    9598    if (this.isDangerous(armyID))
    9699        return true;
    97100    return false;
    98101};
    99 enemyWatcher.prototype.cleanDebug = function() {
     102m.enemyWatcher.prototype.cleanDebug = function() {
    100103    for (var armyID in this.armies) {
    101104        var army = this.armies[armyID];
    102         debug ("Army " +armyID);
    103         debug (army.length +" members, centered around " +army.getCentrePosition());
     105        m.debug ("Army " +armyID);
     106        m.debug (army.length +" members, centered around " +army.getCentrePosition());
    104107    }
    105108}
    106109
    107110// this will monitor any unmonitored soldier.
    108 enemyWatcher.prototype.detectArmies = function(gameState){
     111m.enemyWatcher.prototype.detectArmies = function(gameState){
    109112    //this.cleanDebug();
    110113   
    111114    var self = this;
     
    121124            var armyID = gameState.player + "" + self.totalNBofArmies;
    122125            self.totalNBofArmies++,
    123126            enemy.setMetadata(PlayerID, "EnemyWatcherArmy",armyID);
    124             var filter = Filters.byMetadata(PlayerID, "EnemyWatcherArmy",armyID);
     127            var filter = API3.Filters.byMetadata(PlayerID, "EnemyWatcherArmy",armyID);
    125128            var army = self.enemySoldiers.filter(filter);
    126129            self.armies[armyID] = army;
    127130            self.armies[armyID].registerUpdates();
     
    140143};
    141144// this will merge any two army who are too close together. The distance for "army" is fairly big.
    142145// note: this doesn't actually merge two entity collections... It simply changes the unit metadatas, and will clear the empty entity collection
    143 enemyWatcher.prototype.mergeArmies = function(){
     146m.enemyWatcher.prototype.mergeArmies = function(){
    144147    for (var army in this.armies) {
    145148        var firstArmy = this.armies[army];
    146149        if (firstArmy.length !== 0) {
     
    149152                if (otherArmy !== army && this.armies[otherArmy].length !== 0) {
    150153                    var secondArmy = this.armies[otherArmy];
    151154                    // we're not self merging, so we check if the two armies are close together
    152                     if (inRange(firstAPos,secondArmy.getApproximatePosition(4), 4000 ) ) {
     155                    if (m.inRange(firstAPos,secondArmy.getApproximatePosition(4), 4000 ) ) {
    153156                        // okay so we merge the two together
    154157                       
    155158                        // if the other one was dangerous and we weren't, we're now.
     
    166169    }
    167170    this.ScrapEmptyArmies();
    168171};
    169 enemyWatcher.prototype.ScrapEmptyArmies = function(){
     172m.enemyWatcher.prototype.ScrapEmptyArmies = function(){
    170173    var removelist = [];
    171174    for (var army in this.armies) {
    172175        if (this.armies[army].length === 0) {
     
    181184    }
    182185};
    183186// splits any unit too far from the centerposition
    184 enemyWatcher.prototype.splitArmies = function(gameState){
     187m.enemyWatcher.prototype.splitArmies = function(gameState){
    185188    var self = this;
    186189   
    187     var map = Map.createTerritoryMap(gameState);
     190    var map = m.createTerritoryMap(gameState);
    188191   
    189192    for (var armyID in this.armies) {
    190193        var army = this.armies[armyID];
     
    197200            if (enemy.position() === undefined)
    198201                return;
    199202                     
    200             if (!inRange(enemy.position(),centre, 3500) ) {
     203            if (!m.inRange(enemy.position(),centre, 3500) ) {
    201204                var newArmyID = gameState.player + "" + self.totalNBofArmies;
    202205                if (self.dangerousArmies.indexOf(armyID) !== -1)
    203206                     self.dangerousArmies.push(newArmyID);
    204207               
    205208                self.totalNBofArmies++,
    206209                enemy.setMetadata(PlayerID, "EnemyWatcherArmy",newArmyID);
    207                 var filter = Filters.byMetadata(PlayerID, "EnemyWatcherArmy",newArmyID);
     210                var filter = API3.Filters.byMetadata(PlayerID, "EnemyWatcherArmy",newArmyID);
    208211                var newArmy = self.enemySoldiers.filter(filter);
    209212                self.armies[newArmyID] = newArmy;
    210213                self.armies[newArmyID].registerUpdates();
     
    213216        });
    214217    }
    215218};
     219
     220
     221return m;
     222}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/entitycollection-extend.js

     
    1 function EntityCollectionFromIds(gameState, idList){
     1var AEGIS = function(m)
     2{
     3
     4m.EntityCollectionFromIds = function(gameState, idList){
    25    var ents = {};
    36    for (var i in idList){
    47        var id = idList[i];
     
    69            ents[id] = gameState.entities._entities[id];
    710        }
    811    }
    9     return new EntityCollection(gameState.sharedScript, ents);
     12    return new API3.EntityCollection(gameState.sharedScript, ents);
    1013}
     14
     15return m;
     16}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/timer.js

     
     1var AEGIS = function(m)
     2{
     3
    14//The Timer class // The instance of this class is created in the qBot object under the name 'timer'
    25//The methods that are available to call from this instance are:
    36//timer.setTimer           : Creates a new timer with the given interval (miliseconds).
     
    1114
    1215
    1316//-EmjeR-// Timer class //
    14 var Timer = function() {
     17m.Timer = function() {
    1518    ///Private array.
    1619    var alarmList = [];
    1720   
     
    9497
    9598
    9699//-EmjeR-// Alarm class //
    97 function alarm(gameState, id, interval, delay, repeat) {
     100m.alarm = function(gameState, id, interval, delay, repeat) {
    98101    this.id = id;
    99102    this.interval = interval;
    100103    this.delay = delay;
     
    104107    this.active = true;
    105108    this.counter = 0;
    106109};
     110
     111return m;
     112}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/template-manager.js

     
     1var AEGIS = function(m)
     2{
     3
    14/*
    25 * Used to know which templates I have, which templates I know I can train, things like that.
    36 * Mostly unused.
     
    36 */
    47
    5 var TemplateManager = function(gameState) {
     8m.TemplateManager = function(gameState) {
    69    var self = this;
    710   
     
    2326    this.getTemplateCounters(gameState);
    2427   
    2528};
    26 TemplateManager.prototype.AcknowledgeTemplates = function(gameState)
     29m.TemplateManager.prototype.AcknowledgeTemplates = function(gameState)
    2730{
    2831    var self = this;
    2932    var myEntities = gameState.getOwnEntities();
     
    3942
    4043    });
    4144}
    42 TemplateManager.prototype.getBuildableSubtemplates = function(gameState)
     45m.TemplateManager.prototype.getBuildableSubtemplates = function(gameState)
    4346{
    4447    for each (var templateName in this.knownTemplatesList) {
    4548        var template = gameState.getTemplate(templateName);
     
    5962        }
    6063    }
    6164}
    62 TemplateManager.prototype.getTrainableSubtemplates = function(gameState)
     65m.TemplateManager.prototype.getTrainableSubtemplates = function(gameState)
    6366{
    6467    for each (var templateName in this.knownTemplatesList) {
    6568        var template = gameState.getTemplate(templateName);
     
    7982        }
    8083    }
    8184}
    82 TemplateManager.prototype.getTemplateCounters = function(gameState)
     85m.TemplateManager.prototype.getTemplateCounters = function(gameState)
    8386{
    8487    for (var i in this.unitTemplates)
    8588    {
     
    8992    }
    9093}
    9194// features auto-caching
    92 TemplateManager.prototype.getCountersToClasses = function(gameState,classes,templateName)
     95m.TemplateManager.prototype.getCountersToClasses = function(gameState,classes,templateName)
    9396{
    9497    if (templateName !== undefined && this.templateCounteredBy[templateName])
    9598        return this.templateCounteredBy[templateName];
     
    114117    return templates;
    115118}
    116119
     120
     121return m;
     122}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/queue.js

     
     1var AEGIS = function(m)
     2{
     3
    14/*
    25 * Holds a list of wanted items to train or construct
    36 */
     
    25
    3 var Queue = function() {
     6m.Queue = function() {
    47    this.queue = [];
    58    this.paused = false;
    69};
    710
    8 Queue.prototype.empty = function() {
     11m.Queue.prototype.empty = function() {
    912    this.queue = [];
    1013};
    1114
    12 Queue.prototype.addItem = function(plan) {
     15m.Queue.prototype.addItem = function(plan) {
    1316    for (var i in this.queue)
     
    2326    this.queue.push(plan);
    2427};
    2528
    26 Queue.prototype.getNext = function() {
     29m.Queue.prototype.getNext = function() {
    2730    if (this.queue.length > 0) {
    2831        return this.queue[0];
    2932    } else {
     
    3134    }
    3235};
    3336
    34 Queue.prototype.startNext = function(gameState) {
     37m.Queue.prototype.startNext = function(gameState) {
    3538    if (this.queue.length > 0) {
    3639        this.queue.shift().start(gameState);
    3740        return true;
     
    4245
    4346// returns the maximal account we'll accept for this queue.
    4447// Currently 100% of the cost of the first element and 80% of that of the second
    45 Queue.prototype.maxAccountWanted = function(gameState) {
    46     var cost = new Resources();
     48m.Queue.prototype.maxAccountWanted = function(gameState) {
     49    var cost = new API3.Resources();
    4750    if (this.queue.length > 0 && this.queue[0].isGo(gameState))
    4851        cost.add(this.queue[0].getCost());
    4952    if (this.queue.length > 1 && this.queue[1].isGo(gameState))
     
    5558    return cost;
    5659};
    5760
    58 Queue.prototype.queueCost = function(){
    59     var cost = new Resources();
     61m.Queue.prototype.queueCost = function(){
     62    var cost = new API3.Resources();
    6063    for (var key in this.queue){
    6164        cost.add(this.queue[key].getCost());
    6265    }
    6366    return cost;
    6467};
    6568
    66 Queue.prototype.length = function() {
     69m.Queue.prototype.length = function() {
    6770    return this.queue.length;
    6871};
    6972
    70 Queue.prototype.countQueuedUnits = function(){
     73m.Queue.prototype.countQueuedUnits = function(){
    7174    var count = 0;
    7275    for (var i in this.queue){
    7376        count += this.queue[i].number;
     
    7578    return count;
    7679};
    7780
    78 Queue.prototype.countQueuedUnitsWithClass = function(classe){
     81m.Queue.prototype.countQueuedUnitsWithClass = function(classe){
    7982    var count = 0;
    8083    for (var i in this.queue){
    8184        if (this.queue[i].template && this.queue[i].template.hasClass(classe))
     
    8386    }
    8487    return count;
    8588};
    86 Queue.prototype.countQueuedUnitsWithMetadata = function(data,value){
     89m.Queue.prototype.countQueuedUnitsWithMetadata = function(data,value){
    8790    var count = 0;
    8891    for (var i in this.queue){
    8992        if (this.queue[i].metadata[data] && this.queue[i].metadata[data] == value)
     
    9295    return count;
    9396};
    9497
    95 Queue.prototype.countAllByType = function(t){
     98m.Queue.prototype.countAllByType = function(t){
    9699    var count = 0;
    97100   
    98101    for (var i = 0; i < this.queue.length; i++){
     
    102105    }
    103106    return count;
    104107};
     108
     109return m;
     110}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/headquarters.js

     
     1var AEGIS = function(m)
     2{
    13/* Headquarters
    24 * Deal with high level logic for the AI. Most of the interesting stuff gets done here.
    35 * Some tasks:
     
    1214    -picking new CC locations.
    1315 */
    1416
    15 var HQ = function() {
    16     this.targetNumBuilders = Config.Economy.targetNumBuilders; // number of workers we want building stuff
     17m.HQ = function(Config) {
    1718   
    18     this.dockStartTime =  Config.Economy.dockStartTime * 1000;
    19     this.techStartTime = Config.Economy.techStartTime * 1000;
     19    this.Config = Config;
     20    this.targetNumBuilders = this.Config.Economy.targetNumBuilders; // number of workers we want building stuff
    2021   
     22    this.dockStartTime =  this.Config.Economy.dockStartTime * 1000;
     23    this.techStartTime = this.Config.Economy.techStartTime * 1000;
     24   
    2125    this.dockFailed = false;    // sanity check
    2226    this.waterMap = false;  // set by the aegis.js file.
    2327   
     
    2731    this.baseManagers = {};
    2832   
    2933    // this means we'll have about a big third of women, and thus we can maximize resource gathering rates.
    30     this.femaleRatio = Config.Economy.femaleRatio;
     34    this.femaleRatio = this.Config.Economy.femaleRatio;
    3135   
    3236    this.fortressStartTime = 0;
    33     this.fortressLapseTime = Config.Military.fortressLapseTime * 1000;
    34     this.defenceBuildingTime = Config.Military.defenceBuildingTime * 1000;
    35     this.attackPlansStartTime = Config.Military.attackPlansStartTime * 1000;
    36     this.defenceManager = new Defence();
     37    this.fortressLapseTime = this.Config.Military.fortressLapseTime * 1000;
     38    this.defenceBuildingTime = this.Config.Military.defenceBuildingTime * 1000;
     39    this.attackPlansStartTime = this.Config.Military.attackPlansStartTime * 1000;
     40    this.defenceManager = new m.Defence(this.Config);
    3741   
    38     this.navalManager = new NavalManager();
     42    this.navalManager = new m.NavalManager();
    3943   
    4044    this.TotalAttackNumber = 0;
    4145    this.upcomingAttacks = { "CityAttack" : [] };
     
    4347};
    4448
    4549// More initialisation for stuff that needs the gameState
    46 HQ.prototype.init = function(gameState, events, queues){
     50m.HQ.prototype.init = function(gameState, events, queues){
    4751    // initialize base map. Each pixel is a base ID, or 0 if none
    48     this.basesMap = new Map(gameState.sharedScript, new Uint8Array(gameState.getMap().data.length));
     52    this.basesMap = new API3.Map(gameState.sharedScript, new Uint8Array(gameState.getMap().data.length));
    4953    this.basesMap.setMaxVal(255);
    5054
    51     if (Config.Economy.targetNumWorkers)
    52         this.targetNumWorkers = Config.Economy.targetNumWorkers;
     55    if (this.Config.Economy.targetNumWorkers)
     56        this.targetNumWorkers = this.Config.Economy.targetNumWorkers;
    5357    else if (this.targetNumWorkers === undefined)
    54         this.targetNumWorkers = Math.max(Math.floor(gameState.getPopulationMax()*(0.2 + Math.min(+(Config.difficulty)*0.125,0.3))), 1);
     58        this.targetNumWorkers = Math.max(Math.floor(gameState.getPopulationMax()*(0.2 + Math.min(+(this.Config.difficulty)*0.125,0.3))), 1);
    5559
    5660
    5761    // Let's get our initial situation here.
    5862    // TODO: improve on this.
    5963    // TODO: aknowledge bases, assign workers already.
    60     var ents = gameState.getEntities().filter(Filters.byOwner(PlayerID));
     64    var ents = gameState.getEntities().filter(API3.Filters.byOwner(PlayerID));
    6165   
    6266    var workersNB = 0;
    6367    var hasScout = false;
    6468    var treasureAmount = { 'food': 0, 'wood': 0, 'stone': 0, 'metal': 0 };
    6569    var hasCC = false;
    6670   
    67     if (ents.filter(Filters.byClass("CivCentre")).length > 0)
     71    if (ents.filter(API3.Filters.byClass("CivCentre")).length > 0)
    6872        hasCC = true;
    69     workersNB = ents.filter(Filters.byClass("Worker")).length;
    70     if (ents.filter(Filters.byClass("Cavalry")).length > 0)
     73    workersNB = ents.filter(API3.Filters.byClass("Worker")).length;
     74    if (ents.filter(API3.Filters.byClass("Cavalry")).length > 0)
    7175        hasScout = true;
    7276   
    7377    // tODO: take multiple CCs into account.
    7478    if (hasCC)
    7579    {
    76         var CC = ents.filter(Filters.byClass("CivCentre")).toEntityArray()[0];
     80        var CC = ents.filter(API3.Filters.byClass("CivCentre")).toEntityArray()[0];
    7781        for (i in treasureAmount)
    7882            gameState.getResourceSupplies(i).forEach( function (ent) {
    79                 if (ent.resourceSupplyType().generic === "treasure" && SquareVectorDistance(ent.position(), CC.position()) < 5000)
     83                if (ent.resourceSupplyType().generic === "treasure" && API3.SquareVectorDistance(ent.position(), CC.position()) < 5000)
    8084                    treasureAmount[i] += ent.resourceSupplyMax();
    8185            });
    82         this.baseManagers[1] = new BaseManager();
     86        this.baseManagers[1] = new m.BaseManager(this.Config);
    8387        this.baseManagers[1].init(gameState, events);
    8488        this.baseManagers[1].setAnchor(CC);
    8589        this.baseManagers[1].initTerritory(this, gameState);
    8690        this.baseManagers[1].initGatheringFunctions(this, gameState);
    8791       
    88         if (Config.debug)
     92        if (this.Config.debug)
    8993            this.basesMap.dumpIm("basesMap.png");
    9094        var self = this;
    9195
     
    105109            var pos = this.baseManagers[1].findBestDropsiteLocation(gameState, "wood");
    106110            if (pos)
    107111            {
    108                 queues.dropsites.addItem(new ConstructionPlan(gameState, "structures/{civ}_storehouse",{ "base" : 1 }, 0, -1, pos));
    109                 queues.minorTech.addItem(new ResearchPlan(gameState, "gather_capacity_wheelbarrow"));
     112                queues.dropsites.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_storehouse",{ "base" : 1 }, 0, -1, pos));
     113                queues.minorTech.addItem(new m.ResearchPlan(gameState, "gather_capacity_wheelbarrow"));
    110114            }
    111115        }
    112116    }
    113117   
    114     var map = new Map(gameState.sharedScript, gameState.sharedScript.CCResourceMaps["wood"].map);
    115     if (Config.debug)
     118    var map = new API3.Map(gameState.sharedScript, gameState.sharedScript.CCResourceMaps["wood"].map);
     119    if (this.Config.debug)
    116120        map.dumpIm("map_CC_Wood.png");
    117121   
    118122    //this.reassignIdleWorkers(gameState);
     
    125129   
    126130    // load units and buildings from the config files
    127131   
    128     if (civ in Config.buildings.moderate){
    129         this.bModerate = Config.buildings.moderate[civ];
     132    if (civ in this.Config.buildings.moderate){
     133        this.bModerate = this.Config.buildings.moderate[civ];
    130134    }else{
    131         this.bModerate = Config.buildings.moderate['default'];
     135        this.bModerate = this.Config.buildings.moderate['default'];
    132136    }
    133137   
    134     if (civ in Config.buildings.advanced){
    135         this.bAdvanced = Config.buildings.advanced[civ];
     138    if (civ in this.Config.buildings.advanced){
     139        this.bAdvanced = this.Config.buildings.advanced[civ];
    136140    }else{
    137         this.bAdvanced = Config.buildings.advanced['default'];
     141        this.bAdvanced = this.Config.buildings.advanced['default'];
    138142    }
    139143   
    140     if (civ in Config.buildings.fort){
    141         this.bFort = Config.buildings.fort[civ];
     144    if (civ in this.Config.buildings.fort){
     145        this.bFort = this.Config.buildings.fort[civ];
    142146    }else{
    143         this.bFort = Config.buildings.fort['default'];
     147        this.bFort = this.Config.buildings.fort['default'];
    144148    }
    145149   
    146150    for (var i in this.bAdvanced){
     
    156160    }
    157161   
    158162    var enemies = gameState.getEnemyEntities();
    159     var filter = Filters.byClassesOr(["CitizenSoldier", "Champion", "Hero", "Siege"]);
     163    var filter = API3.Filters.byClassesOr(["CitizenSoldier", "Champion", "Hero", "Siege"]);
    160164    this.enemySoldiers = enemies.filter(filter); // TODO: cope with diplomacy changes
    161165    this.enemySoldiers.registerUpdates();
    162166   
     
    167171    this.ennWatcherIndex = [];
    168172    for (var i = 1; i <= 8; i++)
    169173        if (PlayerID != i && gameState.isPlayerEnemy(i)) {
    170             this.enemyWatchers[i] = new enemyWatcher(gameState, i);
     174            this.enemyWatchers[i] = new m.enemyWatcher(gameState, i);
    171175            this.ennWatcherIndex.push(i);
    172176            this.defenceManager.enemyArmy[i] = [];
    173177        }
    174178};
    175179
    176 HQ.prototype.checkEvents = function (gameState, events, queues) {
     180m.HQ.prototype.checkEvents = function (gameState, events, queues) {
    177181    for (i in events)
    178182    {
    179183        if (events[i].type == "Destroy")
     
    193197                if (ent.isOwn(PlayerID) && ent.getMetadata(PlayerID, "base") === -1)
    194198                {
    195199                    // Okay so let's try to create a new base around this.
    196                     var bID = uniqueIDBases;
    197                     this.baseManagers[bID] = new BaseManager();
     200                    var bID = m.playerGlobals[PlayerID].uniqueIDBases;
     201                    this.baseManagers[bID] = new m.BaseManager(this.Config);
    198202                    this.baseManagers[bID].init(gameState, events, true);
    199203                    this.baseManagers[bID].setAnchor(ent);
    200204                    this.baseManagers[bID].initTerritory(this, gameState);
     
    243247// TODO: This should probably be changed to favor a more mixed approach for better defense.
    244248//      (or even to adapt based on estimated enemy strategy).
    245249// TODO: this should probably set which base it wants them in.
    246 HQ.prototype.trainMoreWorkers = function(gameState, queues) {
     250m.HQ.prototype.trainMoreWorkers = function(gameState, queues) {
    247251    // Count the workers in the world and in progress
    248252    var numFemales = gameState.countEntitiesAndQueuedByType(gameState.applyCiv("units/{civ}_support_female_citizen"));
    249253    numFemales += queues.villager.countQueuedUnitsWithClass("Support");
     
    293297       
    294298        // base "0" means "auto"
    295299        if (template === gameState.applyCiv("units/{civ}_support_female_citizen"))
    296             queues.villager.addItem(new TrainingPlan(gameState, template, { "role" : "worker", "base" : 0 }, size, 0, -1, size ));
     300            queues.villager.addItem(new m.TrainingPlan(gameState, template, { "role" : "worker", "base" : 0 }, size, 0, -1, size ));
    297301        else
    298             queues.citizenSoldier.addItem(new TrainingPlan(gameState, template, { "role" : "worker", "base" : 0 }, size, 0, -1, size));
     302            queues.citizenSoldier.addItem(new m.TrainingPlan(gameState, template, { "role" : "worker", "base" : 0 }, size, 0, -1, size));
    299303    }
    300304};
    301305
    302306// picks the best template based on parameters and classes
    303 HQ.prototype.findBestTrainableUnit = function(gameState, classes, parameters) {
     307m.HQ.prototype.findBestTrainableUnit = function(gameState, classes, parameters) {
    304308    var units = gameState.findTrainableUnits(classes);
    305309   
    306310    if (units.length === 0)
     
    317321                bTopParam = param[1];
    318322            }
    319323            if (param[0] == "strength") {
    320                 aTopParam += getMaxStrength(a[1]) * param[1];
    321                 bTopParam += getMaxStrength(b[1]) * param[1];
     324                aTopParam += m.getMaxStrength(a[1]) * param[1];
     325                bTopParam += m.getMaxStrength(b[1]) * param[1];
    322326            }
    323327            if (param[0] == "speed") {
    324328                aTopParam += a[1].walkSpeed() * param[1];
     
    343347};
    344348
    345349// picks the best template based on parameters and classes
    346 HQ.prototype.findBestTrainableSoldier = function(gameState, classes, parameters) {
     350m.HQ.prototype.findBestTrainableSoldier = function(gameState, classes, parameters) {
    347351    var units = gameState.findTrainableUnits(classes);
    348352   
    349353    if (units.length === 0)
     
    361365                bTopParam = param[1];
    362366            }
    363367            if (param[0] == "strength") {
    364                 aTopParam += getMaxStrength(a[1]) * param[1];
    365                 bTopParam += getMaxStrength(b[1]) * param[1];
     368                aTopParam += m.getMaxStrength(a[1]) * param[1];
     369                bTopParam += m.getMaxStrength(b[1]) * param[1];
    366370            }
    367371            if (param[0] == "siegeStrength") {
    368                 aTopParam += getMaxStrength(a[1], "Structure") * param[1];
    369                 bTopParam += getMaxStrength(b[1], "Structure") * param[1];
     372                aTopParam += m.getMaxStrength(a[1], "Structure") * param[1];
     373                bTopParam += m.getMaxStrength(b[1], "Structure") * param[1];
    370374            }
    371375            if (param[0] == "speed") {
    372376                aTopParam += a[1].walkSpeed() * param[1];
     
    394398// Tries to research any available tech
    395399// Only one at once. Also does military tech (selection is completely random atm)
    396400// TODO: Lots, lots, lots here.
    397 HQ.prototype.tryResearchTechs = function(gameState, queues) {
     401m.HQ.prototype.tryResearchTechs = function(gameState, queues) {
    398402    if (queues.minorTech.length() === 0)
    399403    {
    400404        var possibilities = gameState.findAvailableTech();
     
    402406            return;
    403407        // randomly pick one. No worries about pairs in that case.
    404408        var p = Math.floor((Math.random()*possibilities.length));
    405         queues.minorTech.addItem(new ResearchPlan(gameState, possibilities[p][0]));
     409        queues.minorTech.addItem(new m.ResearchPlan(gameState, possibilities[p][0]));
    406410    }
    407411}
    408412
    409413// We're given a worker and a resource type
    410414// We'll assign the worker for the best base for that resource type.
    411415// TODO: improve choice alogrithm
    412 HQ.prototype.switchWorkerBase = function(gameState, worker, type) {
     416m.HQ.prototype.switchWorkerBase = function(gameState, worker, type) {
    413417    var bestBase = 0;
     418
    414419    for (var i in this.baseManagers)
    415420    {
    416421        if (this.baseManagers[i].willGather[type] >= 1)
     
    435440// returns an entity collection of workers through BaseManager.pickBuilders
    436441// TODO: better the choice algo.
    437442// TODO: also can't get over multiple bases right now.
    438 HQ.prototype.bulkPickWorkers = function(gameState, newBaseID, number) {
     443m.HQ.prototype.bulkPickWorkers = function(gameState, newBaseID, number) {
    439444    var accessIndex = this.baseManagers[newBaseID].accessIndex;
    440445    if (!accessIndex)
    441446        return false;
    442447    // sorting bases by whether they are on the same accessindex or not.
    443     var baseBest = AssocArraytoArray(this.baseManagers).sort(function (a,b) {
     448    var baseBest = m.AssocArraytoArray(this.baseManagers).sort(function (a,b) {
    444449        if (a.accessIndex === accessIndex && b.accessIndex !== accessIndex)
    445450            return -1;
    446451        else if (b.accessIndex === accessIndex && a.accessIndex !== accessIndex)
     
    459464
    460465// returns the current gather rate
    461466// This is not per-se exact, it performs a few adjustments ad-hoc to account for travel distance, stuffs like that.
    462 HQ.prototype.GetCurrentGatherRates = function(gameState) {
     467m.HQ.prototype.GetCurrentGatherRates = function(gameState) {
    463468    var self = this;
    464469
    465470    var currentRates = {};
     
    474479
    475480
    476481// Pick the resource which most needs another worker
    477 HQ.prototype.pickMostNeededResources = function(gameState) {
     482m.HQ.prototype.pickMostNeededResources = function(gameState) {
    478483    var self = this;
    479484   
    480485    this.wantedRates = gameState.ai.queueManager.wantedGatherRates(gameState);
     
    517522
    518523// If all the CC's are destroyed then build a new one
    519524// TODO: rehabilitate.
    520 HQ.prototype.buildNewCC= function(gameState, queues) {
     525m.HQ.prototype.buildNewCC= function(gameState, queues) {
    521526    var numCCs = gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_civil_centre"));
    522527    numCCs += queues.civilCentre.length();
    523528
     
    529534            this.baseNeed["wood"] = 50;
    530535            this.baseNeed["stone"] = 50;
    531536            this.baseNeed["metal"] = 50;
    532             queues.civilCentre.addItem(new ConstructionPlan(gameState, "structures/{civ}_civil_centre"));
     537            queues.civilCentre.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_civil_centre"));
    533538        }
    534539    return (gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_civil_centre"), true) == 0 && gameState.currentPhase() > 1);
    535540};
    536541
    537542// Returns the best position to build a new Civil Centre
    538543// Whose primary function would be to reach new resources of type "resource".
    539 HQ.prototype.findBestEcoCCLocation = function(gameState, resource){
     544m.HQ.prototype.findBestEcoCCLocation = function(gameState, resource){
    540545   
    541546    var CCPlate = gameState.getTemplate("structures/{civ}_civil_centre");
    542547
     
    545550    // Then checks for a good spot in the territory. If none, and town/city phase, checks outside
    546551    // The AI will currently not build a CC if it wouldn't connect with an existing CC.
    547552   
    548     var territory = Map.createTerritoryMap(gameState);
     553    var territory = m.createTerritoryMap(gameState);
    549554   
    550     var obstructions = Map.createObstructionMap(gameState, 0);
     555    var obstructions = m.createObstructionMap(gameState, 0);
    551556    obstructions.expandInfluences();
    552557
    553558    // copy the resource map as initialization.
    554     var friendlyTiles = new Map(gameState.sharedScript, gameState.sharedScript.CCResourceMaps[resource].map, true);
     559    var friendlyTiles = new API3.Map(gameState.sharedScript, gameState.sharedScript.CCResourceMaps[resource].map, true);
    555560    friendlyTiles.setMaxVal(255);
    556     var ents = gameState.getOwnEntities().filter(Filters.byClass("CivCentre")).toEntityArray();
    557     var eEnts = gameState.getEnemyEntities().filter(Filters.byClass("CivCentre")).toEntityArray();
     561    var ents = gameState.getOwnEntities().filter(API3.Filters.byClass("CivCentre")).toEntityArray();
     562    var eEnts = gameState.getEnemyEntities().filter(API3.Filters.byClass("CivCentre")).toEntityArray();
    558563
    559564    var dps = gameState.getOwnDropsites().toEntityArray();
    560565
     
    576581            var entPos = ents[i].position();
    577582            entPos = [entPos[0]/4.0,entPos[1]/4.0];
    578583           
    579             var dist = SquareVectorDistance(entPos, pos);
     584            var dist = API3.SquareVectorDistance(entPos, pos);
    580585            if (dist < 2120)
    581586            {
    582587                canBuild = false;
     
    598603                var entPos = eEnts[i].position();
    599604                entPos = [entPos[0]/4.0,entPos[1]/4.0];
    600605                // 7100 works well as a limit.
    601                 if (SquareVectorDistance(entPos, pos) < 2500)
     606                if (API3.SquareVectorDistance(entPos, pos) < 2500)
    602607                {
    603608                    canBuild = false;
    604609                    continue;
     
    620625                continue;
    621626            }
    622627            dpPos = [dpPos[0]/4.0,dpPos[1]/4.0];
    623             if (SquareVectorDistance(dpPos, pos) < 100)
     628            if (API3.SquareVectorDistance(dpPos, pos) < 100)
    624629            {
    625630                friendlyTiles.map[j] = 0;
    626631                continue;
    627             } else if (SquareVectorDistance(dpPos, pos) < 400)
     632            } else if (API3.SquareVectorDistance(dpPos, pos) < 400)
    628633                friendlyTiles.map[j] /= 2;
    629634        }
    630635
     
    645650    var best = friendlyTiles.findBestTile(6, obstructions);
    646651    var bestIdx = best[0];
    647652
    648     if (Config.debug)
     653    if (this.Config.debug)
    649654    {
    650655        friendlyTiles.map[bestIdx] = 270;
    651656        friendlyTiles.dumpIm("cc_placement_base_" + gameState.getTimeElapsed() + "_" + resource + "_" + best[1] + ".png",301);
     
    659664    var x = ((bestIdx % friendlyTiles.width) + 0.5) * gameState.cellSize;
    660665    var z = (Math.floor(bestIdx / friendlyTiles.width) + 0.5) * gameState.cellSize;
    661666
    662     debug ("Best for value " + best[1] + " at " + uneval([x,z]));
     667    m.debug ("Best for value " + best[1] + " at " + uneval([x,z]));
    663668
    664669    return [x,z];
    665670};
    666671
    667 HQ.prototype.buildTemple = function(gameState, queues){
     672m.HQ.prototype.buildTemple = function(gameState, queues){
    668673    if (gameState.currentPhase() >= 2 ) {
    669674        if (queues.economicBuilding.countQueuedUnits() === 0 &&
    670675            gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_temple")) === 0){
    671             queues.economicBuilding.addItem(new ConstructionPlan(gameState, "structures/{civ}_temple", { "base" : 1 }));
     676            queues.economicBuilding.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_temple", { "base" : 1 }));
    672677        }
    673678    }
    674679};
    675680
    676 HQ.prototype.buildMarket = function(gameState, queues){
    677     if (gameState.getPopulation() > Config.Economy.popForMarket && gameState.currentPhase() >= 2 ) {
     681m.HQ.prototype.buildMarket = function(gameState, queues){
     682    if (gameState.getPopulation() > this.Config.Economy.popForMarket && gameState.currentPhase() >= 2 ) {
    678683        if (queues.economicBuilding.countQueuedUnitsWithClass("BarterMarket") === 0 &&
    679684            gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_market")) === 0){
    680685            //only ever build one storehouse/CC/market at a time
    681             queues.economicBuilding.addItem(new ConstructionPlan(gameState, "structures/{civ}_market", { "base" : 1 }));
     686            queues.economicBuilding.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_market", { "base" : 1 }));
    682687        }
    683688    }
    684689};
    685690
    686691// Build a farmstead to go to town phase faster and prepare for research. Only really active on higher diff mode.
    687 HQ.prototype.buildFarmstead = function(gameState, queues){
    688     if (gameState.getPopulation() > Config.Economy.popForFarmstead) {
     692m.HQ.prototype.buildFarmstead = function(gameState, queues){
     693    if (gameState.getPopulation() > this.Config.Economy.popForFarmstead) {
    689694        // achtung: "DropsiteFood" does not refer to CCs.
    690695        if (queues.economicBuilding.countQueuedUnitsWithClass("DropsiteFood") === 0 &&
    691696            gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_farmstead")) === 0){
    692697            //only ever build one storehouse/CC/market at a time
    693             queues.economicBuilding.addItem(new ConstructionPlan(gameState, "structures/{civ}_farmstead", { "base" : 1 }));
     698            queues.economicBuilding.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_farmstead", { "base" : 1 }));
    694699        }
    695700    }
    696701};
    697702
    698703// TODO: generic this, probably per-base
    699 HQ.prototype.buildDock = function(gameState, queues){
     704m.HQ.prototype.buildDock = function(gameState, queues){
    700705    if (!this.waterMap || this.dockFailed)
    701706        return;
    702707    if (gameState.getTimeElapsed() > this.dockStartTime) {
     
    710715            if (tp !== "")
    711716            {
    712717                var remaining = this.navalManager.getUnconnectedSeas(gameState, this.baseManagers[1].accessIndex);
    713                 queues.economicBuilding.addItem(new ConstructionPlan(gameState, tp, { "base" : 1, "sea" : remaining[0] }));
     718                queues.economicBuilding.addItem(new m.ConstructionPlan(gameState, tp, { "base" : 1, "sea" : remaining[0] }));
    714719            }
    715720        }
    716721    }
     
    719724// if Aegis has resources it doesn't need, it'll try to barter it for resources it needs
    720725// once per turn because the info doesn't update between a turn and I don't want to fix it.
    721726// Not sure how efficient it is but it seems to be sane, at least.
    722 HQ.prototype.tryBartering = function(gameState){
     727m.HQ.prototype.tryBartering = function(gameState){
    723728    var done = false;
    724729    if (gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_market"), true) >= 1) {
    725730       
     
    732737                    if ( (ress[buy] < 400) || needs[buy] > 0) { // if we need that other resource/ have too little of it
    733738                        var markets = gameState.getOwnEntitiesByType(gameState.applyCiv("structures/{civ}_market"), true).toEntityArray();
    734739                        markets[0].barter(buy,sell,100);
    735                         //debug ("bartered " +sell +" for " + buy + ", value 100");
     740                        //m.debug ("bartered " +sell +" for " + buy + ", value 100");
    736741                        done = true;
    737742                    }
    738743                }
     
    743748
    744749// build more houses if needed.
    745750// kinda ugly, lots of special cases to both build enough houses but not tooo many…
    746 HQ.prototype.buildMoreHouses = function(gameState,queues) {
     751m.HQ.prototype.buildMoreHouses = function(gameState,queues) {
    747752
    748753    if (gameState.getPopulationLimit() < gameState.getPopulationMax()) {
    749754
     
    751756
    752757        if (numPlanned < 3 || (numPlanned < 5 && gameState.getPopulation() > 80))
    753758        {
    754             var plan = new ConstructionPlan(gameState, "structures/{civ}_house", { "base" : 1 });
     759            var plan = new m.ConstructionPlan(gameState, "structures/{civ}_house", { "base" : 1 });
     760            // make the difficulty available to the isGo function without having to pass it as argument
     761            var difficulty = this.Config.difficulty;
    755762            // change the starting condition to "less than 15 slots left".
    756763            plan.isGo = function (gameState) {
    757764                var HouseNb = gameState.countEntitiesByType(gameState.applyCiv("foundation|structures/{civ}_house"), true);
     
    761768                    freeSlots = gameState.getPopulationLimit() + HouseNb*5 - gameState.getPopulation();
    762769                else
    763770                    freeSlots = gameState.getPopulationLimit() + HouseNb*10 - gameState.getPopulation();
    764                 if (gameState.getPopulation() > 55 && Config.difficulty > 1)
     771                if (gameState.getPopulation() > 55 && difficulty > 1)
    765772                    return (freeSlots <= 21);
    766                 else if (gameState.getPopulation() >= 20 && Config.difficulty !== 0)
     773                else if (gameState.getPopulation() >= 20 && difficulty !== 0)
    767774                    return (freeSlots <= 16);
    768775                else
    769776                    return (freeSlots <= 10);
     
    774781};
    775782
    776783// checks if we have bases for all resource types (bar food for now) or if we need to expand.
    777 HQ.prototype.checkBasesRessLevel = function(gameState,queues) {
     784m.HQ.prototype.checkBasesRessLevel = function(gameState,queues) {
    778785    if (gameState.currentPhase() === 1 && !gameState.isResearching(gameState.townPhase()))
    779786        return;
    780787    var count = { "wood" : 0, "stone" : 0, "metal" : 0 }
    781788    var capacity = { "wood" : 0, "stone" : 0, "metal" : 0 }
    782789    var need = { "wood" : true, "stone" : true, "metal" : true };
    783790    var posss = [];
     791
    784792    for (i in this.baseManagers)
    785793    {
    786794        var base = this.baseManagers[i];
    787795        for (type in count)
    788796        {
    789             if (base.getResourceLevel(gameState, type, "all") > 1500*Math.max(Config.difficulty,2))
     797            if (base.getResourceLevel(gameState, type, "all") > 1500*Math.max(this.Config.difficulty,2))
    790798                count[type]++;
    791799            capacity[type] += base.getWorkerCapacity(gameState, type);
    792800            if (base.willGather[type] !== 2)
     
    796804    for (type in count)
    797805    {
    798806        if (count[type] === 0 || need[type]
    799             || capacity[type] < gameState.getOwnEntities().filter(Filters.and(Filters.byMetadata(PlayerID, "subrole", "gatherer"), Filters.byMetadata(PlayerID, "gather-type", type))).length * 1.05)
     807            || capacity[type] < gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byMetadata(PlayerID, "subrole", "gatherer"), API3.Filters.byMetadata(PlayerID, "gather-type", type))).length * 1.05)
    800808        {
    801809            // plan a new base.
    802810            if (gameState.countFoundationsWithType(gameState.applyCiv("structures/{civ}_civil_centre")) === 0 && queues.civilCentre.length() === 0) {
     
    809817                    this.outOf[type] = true;
    810818                } else {
    811819                    // base "-1" means new base.
    812                     queues.civilCentre.addItem(new ConstructionPlan(gameState, "structures/{civ}_civil_centre",{ "base" : -1 }, 0, -1, pos));
     820                    queues.civilCentre.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_civil_centre",{ "base" : -1 }, 0, -1, pos));
    813821                }
    814822            }
    815823        }
     
    819827// Deals with building fortresses and towers.
    820828// Currently build towers next to every useful dropsites.
    821829// TODO: Fortresses are placed randomly atm.
    822 HQ.prototype.buildDefences = function(gameState, queues){
     830m.HQ.prototype.buildDefences = function(gameState, queues){
    823831   
    824     var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(Filters.not(Filters.byHasMetadata(PlayerID,"plan"))).length;
     832    var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(API3.Filters.not(API3.Filters.byHasMetadata(PlayerID,"plan"))).length;
    825833   
    826834    if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv('structures/{civ}_defense_tower'))
    827835        + queues.defenceBuilding.length() < gameState.getEntityLimits()["DefenseTower"] && queues.defenceBuilding.length() < 4 && gameState.currentPhase() > 1) {
     
    836844                    {
    837845                        var position = dpEnt.position();
    838846                        if (position) {
    839                             queues.defenceBuilding.addItem(new ConstructionPlan(gameState, 'structures/{civ}_defense_tower', { "base" : i }, 0 , -1, position));
     847                            queues.defenceBuilding.addItem(new m.ConstructionPlan(gameState, 'structures/{civ}_defense_tower', { "base" : i }, 0 , -1, position));
    840848                        }
    841849                        dpEnt.setMetadata(PlayerID, "defenseTower", true);
    842850                    }
     
    855863        {
    856864            if (!this.fortressStartTime)
    857865                this.fortressStartTime = gameState.getTimeElapsed();
    858             queues.defenceBuilding.addItem(new ConstructionPlan(gameState, this.bFort[0], { "base" : 1 }));
    859             debug ("Building a fortress");
     866            queues.defenceBuilding.addItem(new m.ConstructionPlan(gameState, this.bFort[0], { "base" : 1 }));
     867            m.debug ("Building a fortress");
    860868        }
    861869    }
    862870    if (gameState.countEntitiesByType(gameState.applyCiv(this.bFort[i]), true) >= 1) {
     
    877885    }
    878886};
    879887
    880 HQ.prototype.buildBlacksmith = function(gameState, queues){
    881     if (gameState.getTimeElapsed() > Config.Military.timeForBlacksmith*1000) {
     888m.HQ.prototype.buildBlacksmith = function(gameState, queues){
     889    if (gameState.getTimeElapsed() > this.Config.Military.timeForBlacksmith*1000) {
    882890        if (queues.militaryBuilding.length() === 0 &&
    883891            gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_blacksmith")) === 0) {
    884892            var tp = gameState.getTemplate(gameState.applyCiv("structures/{civ}_blacksmith"));
    885893            if (tp.available(gameState))
    886                 queues.militaryBuilding.addItem(new ConstructionPlan(gameState, "structures/{civ}_blacksmith", { "base" : 1 }));
     894                queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_blacksmith", { "base" : 1 }));
    887895        }
    888896    }
    889897};
     
    892900// They are mostly defined by Config.js. This is unreliable since changes could be done easily.
    893901// TODO: We need to determine these dynamically. Also doesn't build fortresses since the above function does that.
    894902// TODO: building placement is bad. Choice of buildings is also fairly dumb.
    895 HQ.prototype.constructTrainingBuildings = function(gameState, queues) {
     903m.HQ.prototype.constructTrainingBuildings = function(gameState, queues) {
    896904    Engine.ProfileStart("Build buildings");
    897     var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(Filters.not(Filters.byHasMetadata(PlayerID, "plan"))).length;
     905    var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(API3.Filters.not(API3.Filters.byHasMetadata(PlayerID, "plan"))).length;
    898906
    899     if (workersNumber > Config.Military.popForBarracks1) {
     907    if (workersNumber > this.Config.Military.popForBarracks1) {
    900908        if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) + queues.militaryBuilding.length() < 1) {
    901             debug ("Trying to build barracks");
    902             queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
     909            m.debug ("Trying to build barracks");
     910            queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
    903911        }
    904912    }
    905913   
    906     if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 2 && workersNumber > Config.Military.popForBarracks2)
     914    if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 2 && workersNumber > this.Config.Military.popForBarracks2)
    907915        if (queues.militaryBuilding.length() < 1)
    908             queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
     916            queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
    909917   
    910918    if (gameState.countEntitiesByType(gameState.applyCiv(this.bModerate[0]), true) === 2 && gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 3 && workersNumber > 125)
    911919        if (queues.militaryBuilding.length() < 1)
    912920        {
    913             queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
     921            queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
    914922            if (gameState.civ() == "gaul" || gameState.civ() == "brit" || gameState.civ() == "iber") {
    915                 queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
    916                 queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
     923                queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
     924                queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
    917925            }
    918926        }
    919927    //build advanced military buildings
    920     if (workersNumber >= Config.Military.popForBarracks2 - 15 && gameState.currentPhase() > 2){
     928    if (workersNumber >= this.Config.Military.popForBarracks2 - 15 && gameState.currentPhase() > 2){
    921929        if (queues.militaryBuilding.length() === 0){
    922930            var inConst = 0;
    923931            for (var i in this.bAdvanced)
     
    925933            if (inConst == 0 && this.bAdvanced && this.bAdvanced.length !== 0) {
    926934                var i = Math.floor(Math.random() * this.bAdvanced.length);
    927935                if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bAdvanced[i])) < 1){
    928                     queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bAdvanced[i], { "base" : 1 }));
     936                    queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, this.bAdvanced[i], { "base" : 1 }));
    929937                }
    930938            }
    931939        }
     
    939947        if (inConst == 1) {
    940948            var i = Math.floor(Math.random() * this.bAdvanced.length);
    941949            if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bAdvanced[i])) < 1){
    942                 queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bAdvanced[i], { "base" : 1 }));
    943                 queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bAdvanced[i], { "base" : 1 }));
     950                queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, this.bAdvanced[i], { "base" : 1 }));
     951                queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, this.bAdvanced[i], { "base" : 1 }));
    944952            }
    945953        }
    946954    }
     
    949957};
    950958
    951959// TODO: use pop(). Currently unused as this is too gameable.
    952 HQ.prototype.garrisonAllFemales = function(gameState) {
    953     var buildings = gameState.getOwnEntities().filter(Filters.byCanGarrison()).toEntityArray();
    954     var females = gameState.getOwnEntities().filter(Filters.byClass("Support"));
     960m.HQ.prototype.garrisonAllFemales = function(gameState) {
     961    var buildings = gameState.getOwnEntities().filter(API3.Filters.byCanGarrison()).toEntityArray();
     962    var females = gameState.getOwnEntities().filter(API3.Filters.byClass("Support"));
    955963   
    956964    var cache = {};
    957965   
     
    974982    });
    975983    this.hasGarrisonedFemales = true;
    976984};
    977 HQ.prototype.ungarrisonAll = function(gameState) {
     985m.HQ.prototype.ungarrisonAll = function(gameState) {
    978986    this.hasGarrisonedFemales = false;
    979     var buildings = gameState.getOwnEntities().filter(Filters.and(Filters.byClass("Structure"),Filters.byCanGarrison())).toEntityArray();
     987    var buildings = gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byClass("Structure"),API3.Filters.byCanGarrison())).toEntityArray();
    980988    buildings.forEach( function (struct) {
    981989        if (struct.garrisoned() && struct.garrisoned().length)
    982990            struct.unloadAll();
    983991        });
    984992};
    985993
    986 HQ.prototype.pausePlan = function(gameState, planName) {
     994m.HQ.prototype.pausePlan = function(gameState, planName) {
    987995    for (var attackType in this.upcomingAttacks) {
    988996        for (var i in this.upcomingAttacks[attackType]) {
    989997            var attack = this.upcomingAttacks[attackType][i];
     
    9991007        }
    10001008    }
    10011009}
    1002 HQ.prototype.unpausePlan = function(gameState, planName) {
     1010m.HQ.prototype.unpausePlan = function(gameState, planName) {
    10031011    for (var attackType in this.upcomingAttacks) {
    10041012        for (var i in this.upcomingAttacks[attackType]) {
    10051013            var attack = this.upcomingAttacks[attackType][i];
     
    10151023        }
    10161024    }
    10171025}
    1018 HQ.prototype.pauseAllPlans = function(gameState) {
     1026m.HQ.prototype.pauseAllPlans = function(gameState) {
    10191027    for (var attackType in this.upcomingAttacks) {
    10201028        for (var i in this.upcomingAttacks[attackType]) {
    10211029            var attack = this.upcomingAttacks[attackType][i];
     
    10291037        }
    10301038    }
    10311039}
    1032 HQ.prototype.unpauseAllPlans = function(gameState) {
     1040m.HQ.prototype.unpauseAllPlans = function(gameState) {
    10331041    for (var attackType in this.upcomingAttacks) {
    10341042        for (var i in this.upcomingAttacks[attackType]) {
    10351043            var attack = this.upcomingAttacks[attackType][i];
     
    10471055
    10481056// Some functions are run every turn
    10491057// Others once in a while
    1050 HQ.prototype.update = function(gameState, queues, events) {
     1058m.HQ.prototype.update = function(gameState, queues, events) {   
    10511059    Engine.ProfileStart("Headquarters update");
    10521060   
    10531061    this.checkEvents(gameState,events,queues);
     
    10571065    this.trainMoreWorkers(gameState, queues);
    10581066   
    10591067    // sandbox doesn't expand.
    1060     if (Config.difficulty !== 0)
     1068    if (this.Config.difficulty !== 0)
    10611069        this.checkBasesRessLevel(gameState, queues);
    10621070
    10631071    this.buildMoreHouses(gameState,queues);
     
    10651073    if (gameState.getTimeElapsed() > this.techStartTime && gameState.currentPhase() > 2)
    10661074        this.tryResearchTechs(gameState,queues);
    10671075   
    1068     if (Config.difficulty > 1)
     1076    if (this.Config.difficulty > 1)
    10691077        this.tryBartering(gameState);
    10701078   
    10711079    this.buildFarmstead(gameState, queues);
     
    10871095    for (i in this.baseManagers)
    10881096    {
    10891097        this.baseManagers[i].checkEvents(gameState, events, queues)
    1090         if ( ( (+i + gameState.ai.playedTurn) % (uniqueIDBases - 1)) === 0)
     1098        if ( ( (+i + gameState.ai.playedTurn) % (m.playerGlobals[PlayerID].uniqueIDBases - 1)) === 0)
    10911099            this.baseManagers[i].update(gameState, queues, events);
    10921100    }
    10931101
     
    11131121                    if (updateStep === 1 || attack.isPaused() ) {
    11141122                        // just chillin'
    11151123                    } else if (updateStep === 0 || updateStep === 3) {
    1116                         debug ("Military Manager: " +attack.getType() +" plan " +attack.getName() +" aborted.");
     1124                        m.debug ("Military Manager: " +attack.getType() +" plan " +attack.getName() +" aborted.");
    11171125                        if (updateStep === 3) {
    11181126                            this.attackPlansEncounteredWater = true;
    1119                             debug("No attack path found. Aborting.");
     1127                            m.debug("No attack path found. Aborting.");
    11201128                        }
    11211129                        attack.Abort(gameState, this);
    11221130                        this.upcomingAttacks[attackType].splice(i--,1);
     
    11301138                            chatText = "I'm starting an attack against " + gameState.sharedScript.playersData[attack.targetPlayer].name + ".";
    11311139                        gameState.ai.chatTeam(chatText);
    11321140                       
    1133                         debug ("Military Manager: Starting " +attack.getType() +" plan " +attack.getName());
     1141                        m.debug ("Military Manager: Starting " +attack.getType() +" plan " +attack.getName());
    11341142                        attack.StartAttack(gameState,this);
    11351143                        this.startedAttacks[attackType].push(attack);
    11361144                        this.upcomingAttacks[attackType].splice(i--,1);
     
    11451153                        chatText = "I'm starting an attack against " + gameState.sharedScript.playersData[attack.targetPlayer].name + ".";
    11461154                    gameState.ai.chatTeam(chatText);
    11471155                   
    1148                     debug ("Military Manager: Starting " +attack.getType() +" plan " +attack.getName());
     1156                    m.debug ("Military Manager: Starting " +attack.getType() +" plan " +attack.getName());
    11491157                    this.startedAttacks[attackType].push(attack);
    11501158                    this.upcomingAttacks[attackType].splice(i--,1);
    11511159                }
     
    11601168            {
    11611169                var remaining = attack.update(gameState,this,events);
    11621170                if (remaining == 0 || remaining == undefined) {
    1163                     debug ("Military Manager: " +attack.getType() +" plan " +attack.getName() +" is now finished.");
     1171                    m.debug ("Military Manager: " +attack.getType() +" plan " +attack.getName() +" is now finished.");
    11641172                    attack.Abort(gameState);
    11651173                    this.startedAttacks[attackType].splice(i--,1);
    11661174                }
     
    11741182    if (gameState.ai.strategy === "rush" && this.startedAttacks["CityAttack"].length !== 0) {
    11751183        // and then we revert.
    11761184        gameState.ai.strategy = "normal";
    1177         Config.Economy.femaleRatio = 0.4;
     1185        this.Config.Economy.femaleRatio = 0.4;
    11781186        gameState.ai.modules.economy.targetNumWorkers = Math.max(Math.floor(gameState.getPopulationMax()*0.55), 1);
    11791187    } else if (gameState.ai.strategy === "rush" && this.upcomingAttacks["CityAttack"].length === 0)
    11801188    {
    1181         Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1, "rush")
     1189        Lalala = new m.CityAttack(gameState, this, this.Config, this.TotalAttackNumber, -1, "rush")
    11821190        this.TotalAttackNumber++;
    11831191        this.upcomingAttacks["CityAttack"].push(Lalala);
    1184         debug ("Starting a little something");
     1192        m.debug ("Starting a little something");
    11851193    } else if (gameState.ai.strategy !== "rush" && !this.waterMap)
    11861194    {
    11871195        // creating plans after updating because an aborted plan might be reused in that case.
     
    11931201            } else {
    11941202                // basically only the first plan, really.
    11951203                if (this.upcomingAttacks["CityAttack"].length == 0 && gameState.getTimeElapsed() < 12*60000) {
    1196                     var Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1);
     1204                    var Lalala = new m.CityAttack(gameState, this, this.Config, this.TotalAttackNumber, -1);
    11971205                    if (Lalala.failed)
    11981206                    {
    11991207                        this.attackPlansEncounteredWater = true; // hack
    12001208                    } else {
    1201                         debug ("Military Manager: Creating the plan " +this.TotalAttackNumber);
     1209                        m.debug ("Military Manager: Creating the plan " +this.TotalAttackNumber);
    12021210                        this.TotalAttackNumber++;
    12031211                        this.upcomingAttacks["CityAttack"].push(Lalala);
    12041212                    }
    1205                 } else if (this.upcomingAttacks["CityAttack"].length == 0 && Config.difficulty !== 0) {
    1206                     var Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1, "superSized");
     1213                } else if (this.upcomingAttacks["CityAttack"].length == 0 && this.Config.difficulty !== 0) {
     1214                    var Lalala = new m.CityAttack(gameState, this, this.Config, this.TotalAttackNumber, -1, "superSized");
    12071215                    if (Lalala.failed)
    12081216                    {
    12091217                        this.attackPlansEncounteredWater = true; // hack
    12101218                    } else {
    1211                         debug ("Military Manager: Creating the super sized plan " +this.TotalAttackNumber);
     1219                        m.debug ("Military Manager: Creating the super sized plan " +this.TotalAttackNumber);
    12121220                        this.TotalAttackNumber++;
    12131221                        this.upcomingAttacks["CityAttack"].push(Lalala);
    12141222                    }
     
    12211229     // very old relic. This should be reimplemented someday so the code stays here.
    12221230     
    12231231     if (this.HarassRaiding && this.preparingRaidNumber + this.startedRaidNumber < 1 && gameState.getTimeElapsed() < 780000) {
    1224      var Lalala = new CityAttack(gameState, this,this.totalStartedAttackNumber, -1, "harass_raid");
     1232     var Lalala = new m.CityAttack(gameState, this,this.totalStartedAttackNumber, -1, "harass_raid");
    12251233     if (!Lalala.createSupportPlans(gameState, this, )) {
    1226      debug ("Military Manager: harrassing plan not a valid option");
     1234     m.debug ("Military Manager: harrassing plan not a valid option");
    12271235     this.HarassRaiding = false;
    12281236     } else {
    1229      debug ("Military Manager: Creating the harass raid plan " +this.totalStartedAttackNumber);
     1237     m.debug ("Military Manager: Creating the harass raid plan " +this.totalStartedAttackNumber);
    12301238     
    12311239     this.totalStartedAttackNumber++;
    12321240     this.preparingRaidNumber++;
     
    12431251    this.buildDropsites(gameState, queues);
    12441252    Engine.ProfileStop();
    12451253
    1246     if (Config.difficulty !== 0)
     1254    if (this.Config.difficulty !== 0)
    12471255        this.tryBartering(gameState);
    12481256       
    12491257    this.buildFarmstead(gameState, queues);
     
    12551263*/
    12561264    Engine.ProfileStop();   // Heaquarters update
    12571265};
     1266
     1267return m;
     1268
     1269}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/queueplan-research.js

     
    1 var ResearchPlan = function(gameState, type, startTime, expectedTime, rush) {
     1var AEGIS = function(m)
     2{
     3
     4m.ResearchPlan = function(gameState, type, startTime, expectedTime, rush) {
    25    this.type = type;
    36
    4     this.ID = uniqueIDBOPlans++;
     7    this.ID = m.playerGlobals[PlayerID].uniqueIDBOPlans++;
    58
    69    this.template = gameState.getTemplate(this.type);
    710    if (!this.template || this.template.researchTime === undefined) {
    811        return false;
    912    }
    1013    this.category = "technology";
    11     this.cost = new Resources(this.template.cost(),0);
     14    this.cost = new API3.Resources(this.template.cost(),0);
    1215    this.number = 1; // Obligatory for compatibility
    1316   
    1417    if (!startTime)
     
    3033};
    3134
    3235// return true if we willstart amassing resource for this plan
    33 ResearchPlan.prototype.isGo = function(gameState) {
     36m.ResearchPlan.prototype.isGo = function(gameState) {
    3437    return (gameState.getTimeElapsed() > this.startTime);
    3538};
    3639
    37 ResearchPlan.prototype.canStart = function(gameState) {
     40m.ResearchPlan.prototype.canStart = function(gameState) {
    3841    // also checks canResearch
    3942    return (gameState.findResearchers(this.type).length !== 0);
    4043};
    4144
    42 ResearchPlan.prototype.start = function(gameState) {
     45m.ResearchPlan.prototype.start = function(gameState) {
    4346    var self = this;
    4447   
    4548    // TODO: this is special cased for "rush" technologies, ie the town phase
    4649    // which currently is a 100% focus.
    4750    gameState.ai.queueManager.unpauseAll();
    4851   
    49     //debug ("Starting the research plan for " + this.type);
     52    //m.debug ("Starting the research plan for " + this.type);
    5053    var trainers = gameState.findResearchers(this.type).toEntityArray();
    5154
    5255    //for (var i in trainers)
     
    6669    }
    6770};
    6871
    69 ResearchPlan.prototype.getCost = function(){
    70     var costs = new Resources();
     72m.ResearchPlan.prototype.getCost = function(){
     73    var costs = new API3.Resources();
    7174    costs.add(this.cost);
    7275    return costs;
    7376};
    7477
     78
     79return m;
     80}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/queue-manager.js

     
     1var AEGIS = function(m)
     2{
     3
    14// This takes the input queues and picks which items to fund with resources until no more resources are left to distribute.
    25//
    36// Currently this manager keeps accounts for each queue, split between the 4 main resources
     
    1720//
    1821// This system should be improved. It's probably not flexible enough.
    1922
    20 var QueueManager = function(queues, priorities) {
     23m.QueueManager = function(Config, queues, priorities) {
     24    this.Config = Config;
    2125    this.queues = queues;
    2226    this.priorities = priorities;
    2327    this.account = {};
     
    2832    this.queueArrays = [];
    2933    for (var p in this.queues) {
    3034        this.account[p] = 0;
    31         this.accounts[p] = new Resources();
     35        this.accounts[p] = new API3.Resources();
    3236        this.queueArrays.push([p,this.queues[p]]);
    3337    }
    3438    this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
     
    3640    this.curItemQueue = [];
    3741};
    3842
    39 QueueManager.prototype.getAvailableResources = function(gameState, noAccounts) {
     43m.QueueManager.prototype.getAvailableResources = function(gameState, noAccounts) {
    4044    var resources = gameState.getResources();
    4145    if (noAccounts)
    4246        return resources;
     
    4650    return resources;
    4751};
    4852
    49 QueueManager.prototype.getTotalAccountedResources = function(gameState) {
    50     var resources = new Resources();
     53m.QueueManager.prototype.getTotalAccountedResources = function(gameState) {
     54    var resources = new API3.Resources();
    5155    for (var key in this.queues) {
    5256        resources.add(this.accounts[key]);
    5357    }
    5458    return resources;
    5559};
    5660
    57 QueueManager.prototype.currentNeeds = function(gameState) {
    58     var needs = new Resources();
     61m.QueueManager.prototype.currentNeeds = function(gameState) {
     62    var needs = new API3.Resources();
    5963    // get out current resources, not removing accounts.
    6064    var current = this.getAvailableResources(gameState, true);
    6165    //queueArrays because it's faster.
     
    8286    };
    8387};
    8488
    85 QueueManager.prototype.futureNeeds = function(gameState) {
    86     var needs = new Resources();
     89m.QueueManager.prototype.futureNeeds = function(gameState) {
     90    var needs = new API3.Resources();
    8791    // get out current resources, not removing accounts.
    8892    var current = this.getAvailableResources(gameState, true);
    8993    //queueArrays because it's faster.
     
    108112};
    109113
    110114// calculate the gather rates we'd want to be able to use all elements in our queues
    111 QueueManager.prototype.wantedGatherRates = function(gameState) {
     115m.QueueManager.prototype.wantedGatherRates = function(gameState) {
    112116    var rates = { "food" : 0, "wood" : 0, "stone" : 0, "metal" : 0 };
    113117    var qTime = gameState.getTimeElapsed();
    114118    var qCosts = { "food" : 0, "wood" : 0, "stone" : 0, "metal" : 0 };
     
    143147                // estimate time based on priority + cost + nb
    144148                // TODO: work on this.
    145149                for (type in qCosts)
     150                {
    146151                    qCosts[type] += (cost[type] + Math.min(cost[type],this.priorities[name]));
     152                }
    147153                qTime += 30000;
    148154            } else {
    149155                // TODO: work on this.
     
    165171    return rates;
    166172};
    167173
    168 /*QueueManager.prototype.logNeeds = function(gameState) {
     174/*m.QueueManager.prototype.logNeeds = function(gameState) {
    169175 if (!this.totor)
    170176 {
    171177 this.totor = [];
     
    255261};
    256262*/
    257263
    258 QueueManager.prototype.printQueues = function(gameState){
    259     debug("QUEUES");
     264m.QueueManager.prototype.printQueues = function(gameState){
     265    m.debug("QUEUES");
    260266    for (var i in this.queues){
    261267        var qStr = "";
    262268        var q = this.queues[i];
    263269        if (q.queue.length > 0)
    264             debug((i + ":"));
     270            m.debug((i + ":"));
    265271        for (var j in q.queue){
    266272            qStr = "     " + q.queue[j].type + " ";
    267273            if (q.queue[j].number)
    268274                qStr += "x" + q.queue[j].number;
    269             debug (qStr);
     275            m.debug (qStr);
    270276        }
    271277    }
    272     debug ("Accounts");
     278    m.debug ("Accounts");
    273279    for (var p in this.accounts)
    274280    {
    275         debug(p + ": " + uneval(this.accounts[p]));
     281        m.debug(p + ": " + uneval(this.accounts[p]));
    276282    }
    277     debug("Needed Resources:" + uneval(this.futureNeeds(gameState,false)));
    278     debug ("Wanted Gather Rates:" + uneval(this.wantedGatherRates(gameState)));
    279     debug ("Current Resources:" + uneval(gameState.getResources()));
    280     debug ("Available Resources:" + uneval(this.getAvailableResources(gameState)));
     283    m.debug("Needed Resources:" + uneval(this.futureNeeds(gameState,false)));
     284    m.debug ("Wanted Gather Rates:" + uneval(this.wantedGatherRates(gameState)));
     285    m.debug ("Current Resources:" + uneval(gameState.getResources()));
     286    m.debug ("Available Resources:" + uneval(this.getAvailableResources(gameState)));
    281287};
    282288
    283289// nice readable HTML version.
    284 QueueManager.prototype.HTMLprintQueues = function(gameState){
    285     if (!Config.debug)
     290m.QueueManager.prototype.HTMLprintQueues = function(gameState){
     291    if (!this.Config.debug)
    286292        return;
    287293    log("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"> <html> <head> <title>Aegis Queue Manager</title> <link rel=\"stylesheet\" href=\"table.css\">  </head> <body> <table> <caption>Aegis Build Order</caption> ");
    288294    for (var i in this.queues){
     
    325331    log("</body></html>");
    326332};
    327333
    328 QueueManager.prototype.clear = function(){
     334m.QueueManager.prototype.clear = function(){
    329335    this.curItemQueue = [];
    330336    for (var i in this.queues)
    331337        this.queues[i].empty();
    332338};
    333339
    334 QueueManager.prototype.update = function(gameState) {
     340m.QueueManager.prototype.update = function(gameState) {
    335341    var self = this;
    336342   
    337343    for (var i in this.priorities){
     
    430436                            this.accounts[queues[under]] -= amnt;
    431437                            this.accounts[queues[over]] += amnt;
    432438                            --over;
    433                             debug ("Shifting " + amnt + " from " + queues[under] + " to " +queues[over]);
     439                            m.debug ("Shifting " + amnt + " from " + queues[under] + " to " +queues[over]);
    434440                            continue;
    435441                        } else {
    436442                            ++under;
     
    447453   
    448454    Engine.ProfileStart("Pick items from queues");
    449455
    450     //debug ("start");
    451     //debug (uneval(this.accounts));
     456    //m.debug ("start");
     457    //m.debug (uneval(this.accounts));
    452458    // Start the next item in the queue if we can afford it.
    453459    for (var i in this.queueArrays)
    454460    {
     
    457463        if (queue.length() > 0 && !queue.paused)
    458464        {
    459465            var item = queue.getNext();
    460             var total = new Resources();
     466            var total = new API3.Resources();
    461467            total.add(this.accounts[name]);
    462468            if (total.canAfford(item.getCost()))
    463469            {
     
    471477            this.accounts[name].reset();
    472478        }
    473479    }
    474     //debug (uneval(this.accounts));
     480    //m.debug (uneval(this.accounts));
    475481   
    476482    Engine.ProfileStop();
    477483   
     
    481487    Engine.ProfileStop();
    482488};
    483489
    484 QueueManager.prototype.pauseQueue = function(queue, scrapAccounts) {
     490m.QueueManager.prototype.pauseQueue = function(queue, scrapAccounts) {
    485491    if (this.queues[queue])
    486492    {
    487493        this.queues[queue].paused = true;
     
    490496    }
    491497}
    492498
    493 QueueManager.prototype.unpauseQueue = function(queue) {
     499m.QueueManager.prototype.unpauseQueue = function(queue) {
    494500    if (this.queues[queue])
    495501        this.queues[queue].paused = false;
    496502}
    497503
    498 QueueManager.prototype.pauseAll = function(scrapAccounts, but) {
     504m.QueueManager.prototype.pauseAll = function(scrapAccounts, but) {
    499505    for (var p in this.queues)
    500506        if (p != but)
    501507        {
     
    505511        }
    506512}
    507513
    508 QueueManager.prototype.unpauseAll = function(but) {
     514m.QueueManager.prototype.unpauseAll = function(but) {
    509515    for (var p in this.queues)
    510516        if (p != but)
    511517            this.queues[p].paused = false;
    512518}
    513519
    514520
    515 QueueManager.prototype.addQueue = function(queueName, priority) {
     521m.QueueManager.prototype.addQueue = function(queueName, priority) {
    516522    if (this.queues[queueName] == undefined) {
    517         this.queues[queueName] = new Queue();
     523        this.queues[queueName] = new m.Queue();
    518524        this.priorities[queueName] = priority;
    519525        this.account[queueName] = 0;
    520         this.accounts[queueName] = new Resources();
     526        this.accounts[queueName] = new API3.Resources();
    521527
    522528        var self = this;
    523529        this.queueArrays = [];
    524530        for (var p in this.queues)
     531        {
    525532            this.queueArrays.push([p,this.queues[p]]);
     533        }
    526534        this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
    527535    }
    528536}
    529 QueueManager.prototype.removeQueue = function(queueName) {
     537m.QueueManager.prototype.removeQueue = function(queueName) {
    530538    if (this.queues[queueName] !== undefined) {
    531539        if ( this.curItemQueue.indexOf(queueName) !== -1) {
    532540            this.curItemQueue.splice(this.curItemQueue.indexOf(queueName),1);
     
    539547        var self = this;
    540548        this.queueArrays = [];
    541549        for (var p in this.queues)
     550        {
    542551            this.queueArrays.push([p,this.queues[p]]);
     552        }
    543553        this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
    544554    }
    545555}
    546 QueueManager.prototype.changePriority = function(queueName, newPriority) {
     556m.QueueManager.prototype.changePriority = function(queueName, newPriority) {
    547557    var self = this;
    548558    if (this.queues[queueName] !== undefined)
    549559        this.priorities[queueName] = newPriority;
    550560    this.queueArrays = [];
    551     for (var p in this.queues) {
     561    for (var p in this.queues)
     562    {
    552563        this.queueArrays.push([p,this.queues[p]]);
    553564    }
    554565    this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
    555566}
    556567
     568return m;
     569}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/map-module.js

     
     1var AEGIS = function(m)
     2{
     3
    14// other map functions
    25
    3 Map.createObstructionMap = function(gameState, accessIndex, template){
     6m.createObstructionMap = function(gameState, accessIndex, template){
    47    var passabilityMap = gameState.getMap();
    58    var territoryMap = gameState.ai.territoryMap;
    69   
     
    3134            for (var y = 0; y < passabilityMap.height; ++y)
    3235            {
    3336                var i = x + y*passabilityMap.width;
    34                 var tilePlayer = (territoryMap.data[i] & TERRITORY_PLAYER_MASK);
     37                var tilePlayer = (territoryMap.data[i] & 0x3F);
    3538               
    3639                if (gameState.ai.myIndex !== gameState.ai.accessibility.landPassMap[i])
    3740                {
     
    8891        var obstructionTiles = new Uint8Array(passabilityMap.data.length);
    8992        for (var i = 0; i < passabilityMap.data.length; ++i)
    9093        {
    91             var tilePlayer = (territoryMap.data[i] & TERRITORY_PLAYER_MASK);
     94            var tilePlayer = (territoryMap.data[i] & 0x3F);
    9295            var invalidTerritory = (
    9396                                    (!buildOwn && tilePlayer == playerID) ||
    9497                                    (!buildAlly && gameState.isPlayerAlly(tilePlayer) && tilePlayer != playerID) ||
     
    105108        }
    106109    }
    107110   
    108     var map = new Map(gameState.sharedScript, obstructionTiles);
     111    var map = new API3.Map(gameState.sharedScript, obstructionTiles);
    109112    map.setMaxVal(255);
    110113   
    111114    if (template && template.buildDistance()){
     
    126129};
    127130
    128131
    129 
    130 Map.createTerritoryMap = function(gameState) {
     132m.createTerritoryMap = function(gameState) {
    131133    var map = gameState.ai.territoryMap;
    132134   
    133     var ret = new Map(gameState.sharedScript, map.data);
     135    var ret = new API3.Map(gameState.sharedScript, map.data);
    134136   
    135137    ret.getOwner = function(p) {
    136         return this.point(p) & TERRITORY_PLAYER_MASK;
     138        return this.point(p) & 0x3F;
    137139    }
    138140    ret.getOwnerIndex = function(p) {
    139         return this.map[p] & TERRITORY_PLAYER_MASK;
     141        return this.map[p] & 0x3F;
    140142    }
    141143    return ret;
    142144};
     145
     146return m;
     147}(AEGIS);
  • binaries/data/mods/public/simulation/ai/aegis/data.json

     
    11{
    22  "name": "Aegis Bot",
    33  "description": "Wraitii's improvement of qBot. It is more reliable and generally a better player. Note that it doesn't support saved games yet, and there may be other bugs. Please report issues to Wildfire Games (see the link in the main menu).",
     4  "moduleName" : "AEGIS",
    45  "constructor": "AegisBot",
    56  "useShared": true
    67}
  • binaries/data/mods/public/simulation/ai/aegis/naval-manager.js

     
     1var AEGIS = function(m)
     2{
     3
    14/* Naval Manager
    25 Will deal with anything ships.
    36 -Basically trade over water (with fleets and goals commissioned by the economy manager)
     
    912 Does not build them though, that's for the base manager to handle.
    1013 */
    1114
    12 var NavalManager = function() {
     15m.NavalManager = function() {
    1316    // accessibility zones for which we have a dock.
    1417    // Connexion is described as [landindex] = [seaIndexes];
    1518    // technically they also exist for sea zones but I don't care.
     
    3235};
    3336
    3437// More initialisation for stuff that needs the gameState
    35 NavalManager.prototype.init = function(gameState, events, queues) {
     38m.NavalManager.prototype.init = function(gameState, events, queues) {
    3639    // finished docks
    37     this.docks = gameState.getOwnEntities().filter(Filters.and(Filters.byClass("Dock"), Filters.not(Filters.isFoundation())));
     40    this.docks = gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byClass("Dock"), API3.Filters.not(API3.Filters.isFoundation())));
    3841    this.docks.allowQuickIter();
    3942    this.docks.registerUpdates();
    4043   
    41     this.ships = gameState.getOwnEntities().filter(Filters.byClass("Ship"));
     44    this.ships = gameState.getOwnEntities().filter(API3.Filters.byClass("Ship"));
    4245    // note: those two can overlap (some transport ships are warships too and vice-versa).
    43     this.tpShips = this.ships.filter(Filters.byCanGarrison());
    44     this.warships = this.ships.filter(Filters.byClass("Warship"));
     46    this.tpShips = this.ships.filter(API3.Filters.byCanGarrison());
     47    this.warships = this.ships.filter(API3.Filters.byClass("Warship"));
    4548
    4649    this.ships.registerUpdates();
    4750    this.tpShips.registerUpdates();
     
    5255        if (gameState.ai.accessibility.regionType[i] !== "water")
    5356        {
    5457            // push dummies
    55             this.seaShips.push(new EntityCollection(gameState.sharedScript));
    56             this.seaTpShips.push(new EntityCollection(gameState.sharedScript));
    57             this.seaWarships.push(new EntityCollection(gameState.sharedScript));
     58            this.seaShips.push(new API3.EntityCollection(gameState.sharedScript));
     59            this.seaTpShips.push(new API3.EntityCollection(gameState.sharedScript));
     60            this.seaWarships.push(new API3.EntityCollection(gameState.sharedScript));
    5861            this.wantedTpShips.push(0);
    5962            this.wantedWarships.push(0);
    6063        } else {
    61             var collec = this.ships.filter(Filters.byStaticMetadata(PlayerID, "sea", i));
     64            var collec = this.ships.filter(API3.Filters.byStaticMetadata(PlayerID, "sea", i));
    6265            collec.registerUpdates();
    6366            this.seaShips.push(collec);
    64             collec = this.tpShips.filter(Filters.byStaticMetadata(PlayerID, "sea", i));
     67            collec = this.tpShips.filter(API3.Filters.byStaticMetadata(PlayerID, "sea", i));
    6568            collec.registerUpdates();
    6669            this.seaTpShips.push(collec);
    67             var collec = this.warships.filter(Filters.byStaticMetadata(PlayerID, "sea", i));
     70            var collec = this.warships.filter(API3.Filters.byStaticMetadata(PlayerID, "sea", i));
    6871            collec.registerUpdates();
    6972            this.seaWarships.push(collec);
    7073           
     
    7679    }
    7780};
    7881
    79 NavalManager.prototype.getUnconnectedSeas = function (gameState, region) {
     82m.NavalManager.prototype.getUnconnectedSeas = function (gameState, region) {
    8083    var seas = gameState.ai.accessibility.regionLinks[region]
    8184    if (seas.length === 0)
    8285        return [];
     
    8992};
    9093
    9194// returns true if there is a path from A to B and we have docks.
    92 NavalManager.prototype.canReach = function (gameState, regionA, regionB) {
     95m.NavalManager.prototype.canReach = function (gameState, regionA, regionB) {
    9396    var path = gameState.ai.accessibility.getTrajectToIndex(regionA, regionB);
    9497    if (!path)
    9598    {
     
    100103        if (gameState.ai.accessibility.regionType[path[i]] == "land")
    101104            if (this.accessibleSeas.indexOf(path[i+1]) === -1)
    102105            {
    103                 debug ("cannot reach because of " + path[i+1]);
     106                m.debug ("cannot reach because of " + path[i+1]);
    104107                return false;   // we wn't be able to board on that sea
    105108            }
    106109    }
     
    108111};
    109112
    110113
    111 NavalManager.prototype.checkEvents = function (gameState, queues, events) {
     114m.NavalManager.prototype.checkEvents = function (gameState, queues, events) {
    112115    for (i in events)
    113116    {
    114117        if (events[i].type == "Destroy")
     
    137140    }
    138141};
    139142
    140 NavalManager.prototype.addPlan = function(plan) {
     143m.NavalManager.prototype.addPlan = function(plan) {
    141144    this.transportPlans.push(plan);
    142145};
    143146
    144147// will create a plan at the end of the turn.
    145148// many units can call this separately and end up in the same plan
    146149// which can be useful.
    147 NavalManager.prototype.askForTransport = function(entity, startPos, endPos) {
     150m.NavalManager.prototype.askForTransport = function(entity, startPos, endPos) {
    148151    this.askedPlans.push([entity, startPos, endPos]);
    149152};
    150153
    151154// creates aforementionned plans
    152 NavalManager.prototype.createPlans = function(gameState) {
     155m.NavalManager.prototype.createPlans = function(gameState) {
    153156    var startID = {};
    154157
    155158    for (i in this.askedPlans)
     
    178181};
    179182
    180183// TODO: work on this.
    181 NavalManager.prototype.maintainFleet = function(gameState, queues, events) {
     184m.NavalManager.prototype.maintainFleet = function(gameState, queues, events) {
    182185    // check if we have enough transport ships.
    183186    // check per region.
    184187    for (var i = 0; i < this.seaShips.length; ++i)
     
    188191            && tpNb + queues.ships.length() === 0 && gameState.getTemplate(gameState.applyCiv("units/{civ}_ship_bireme")).available(gameState))
    189192        {
    190193            // TODO: check our dock can build the wanted ship types, for Carthage.
    191             queues.ships.addItem(new TrainingPlan(gameState, "units/{civ}_ship_bireme", { "sea" : i }, 1, 0, -1, 1 ));
     194            queues.ships.addItem(new m.TrainingPlan(gameState, "units/{civ}_ship_bireme", { "sea" : i }, 1, 0, -1, 1 ));
    192195        }
    193196    }
    194197};
    195198
    196199// bumps up the number of ships we want if we need more.
    197 NavalManager.prototype.checkLevels = function(gameState, queues) {
     200m.NavalManager.prototype.checkLevels = function(gameState, queues) {
    198201    if (queues.ships.length() !== 0)
    199202        return;
    200203    for (var i = 0; i < this.transportPlans.length; ++i)
     
    214217};
    215218
    216219// assigns free ships to plans that need some
    217 NavalManager.prototype.assignToPlans = function(gameState, queues, events) {
     220m.NavalManager.prototype.assignToPlans = function(gameState, queues, events) {
    218221    for (var i = 0; i < this.transportPlans.length; ++i)
    219222    {
    220223        var plan = this.transportPlans[i];
     
    228231                {
    229232                    if (!ship.getMetadata(PlayerID, "tpplan"))
    230233                    {
    231                         debug ("Assigning ship " + ship.id() + " to plan" + plan.ID);
     234                        m.debug ("Assigning ship " + ship.id() + " to plan" + plan.ID);
    232235                        plan.assignShip(gameState, ship);
    233236                        return true;
    234237                    }
     
    239242    return false;
    240243};
    241244
    242 NavalManager.prototype.checkActivePlan = function(ID) {
     245m.NavalManager.prototype.checkActivePlan = function(ID) {
    243246    for (var i = 0; i < this.transportPlans.length; ++i)
    244247        if (this.transportPlans[i].ID === ID)
    245248            return true;
     
    249252
    250253// Some functions are run every turn
    251254// Others once in a while
    252 NavalManager.prototype.update = function(gameState, queues, events) {
     255m.NavalManager.prototype.update = function(gameState, queues, events) {
    253256    Engine.ProfileStart("Naval Manager update");
    254257   
    255258    this.checkEvents(gameState, queues, events);
     
    286289    }
    287290    Engine.ProfileStop();
    288291};
     292
     293return m;
     294}(AEGIS);
  • binaries/data/mods/public/simulation/ai/qbot/attackMoveToLocation.js

     
    1 function AttackMoveToLocation(gameState, militaryManager, minAttackSize, maxAttackSize, targetFinder){
     1function AttackMoveToLocation(gameState, Config, militaryManager, minAttackSize, maxAttackSize, targetFinder){
     2   
     3    this.Config = Config;   
    24    this.minAttackSize = minAttackSize || Config.attack.minAttackSize;
    35    this.maxAttackSize = maxAttackSize || Config.attack.maxAttackSize;
    46    this.idList=[];
     
    1719    var enemyCount = militaryManager.measureEnemyCount(gameState);
    1820   
    1921    // We require our army to be >= this strength
    20     var targetStrength = enemyStrength * Config.attack.enemyRatio;
     22    var targetStrength = enemyStrength * this.Config.attack.enemyRatio;
    2123   
    2224    var availableCount = militaryManager.countAvailableUnits();
    2325    var availableStrength = militaryManager.measureAvailableStrength();
  • binaries/data/mods/public/simulation/ai/qbot/worker.js

     
    3434           
    3535            this.startApproachingResourceTime = gameState.getTimeElapsed();
    3636           
    37             //Engine.PostCommand({"type": "set-shading-color", "entities": [this.ent.id()], "rgb": [10,0,0]});
     37            //Engine.PostCommand(PlayerID, {"type": "set-shading-color", "entities": [this.ent.id()], "rgb": [10,0,0]});
    3838        }else{
    3939            // If we haven't reached the resource in 2 minutes twice in a row and none of the resource has been
    4040            // gathered then mark it as inaccessible.
     
    6161            this.ent.repair(target);
    6262        }
    6363       
    64         //Engine.PostCommand({"type": "set-shading-color", "entities": [this.ent.id()], "rgb": [0,10,0]});
     64        //Engine.PostCommand(PlayerID, {"type": "set-shading-color", "entities": [this.ent.id()], "rgb": [0,10,0]});
    6565    }
    6666   
    6767    Engine.ProfileStart("Update Gatherer Counts");
     
    248248    }else{
    249249        return type.generic;
    250250    }
    251 };
    252  Kein Zeilenumbruch am Ende der Datei
     251};
  • binaries/data/mods/public/simulation/ai/qbot/defence.js

     
    1 function Defence(){
     1function Defence(Config){
    22    this.ACQUIRE_DIST = Config.defence.acquireDistance;
    33    this.RELEASE_DIST = Config.defence.releaseDistance;
    44   
  • binaries/data/mods/public/simulation/ai/qbot/military.js

     
    66 *
    77 */
    88
    9 var MilitaryAttackManager = function() {
     9var MilitaryAttackManager = function(Config) {
     10
     11    this.Config = Config
    1012    // these use the structure soldiers[unitId] = true|false to register the units
    1113    this.attackManagers = [AttackMoveToLocation];
    1214    this.availableAttacks = [];
     
    1618    this.attackCount = 0;
    1719    this.lastAttackTime = 0;
    1820   
    19     this.defenceManager = new Defence();
     21    this.defenceManager = new Defence(Config);
    2022};
    2123
    2224MilitaryAttackManager.prototype.init = function(gameState) {
     
    2426   
    2527    // load units and buildings from the config files
    2628   
    27     if (civ in Config.buildings.moderate){
    28         this.bModerate = Config.buildings.moderate[civ];
     29    if (civ in this.Config.buildings.moderate){
     30        this.bModerate = this.Config.buildings.moderate[civ];
    2931    }else{
    30         this.bModerate = Config.buildings.moderate['default'];
     32        this.bModerate = this.Config.buildings.moderate['default'];
    3133    }
    3234   
    33     if (civ in Config.buildings.advanced){
    34         this.bAdvanced = Config.buildings.advanced[civ];
     35    if (civ in this.Config.buildings.advanced){
     36        this.bAdvanced = this.Config.buildings.advanced[civ];
    3537    }else{
    36         this.bAdvanced = Config.buildings.advanced['default'];
     38        this.bAdvanced = this.Config.buildings.advanced['default'];
    3739    }
    3840   
    39     if (civ in Config.buildings.fort){
    40         this.bFort = Config.buildings.fort[civ];
     41    if (civ in this.Config.buildings.fort){
     42        this.bFort = this.Config.buildings.fort[civ];
    4143    }else{
    42         this.bFort = Config.buildings.fort['default'];
     44        this.bFort = this.Config.buildings.fort['default'];
    4345    }
    4446
    4547    for (var i in this.bAdvanced){
     
    5456    };
    5557    // TODO: figure out how to make this generic
    5658    for (var i in this.attackManagers){
    57         this.availableAttacks[i] = new this.attackManagers[i](gameState, this);
     59        this.availableAttacks[i] = new this.attackManagers[i](gameState, this.Config, this);
    5860    }
    5961   
    6062    var enemies = gameState.getEnemyEntities();
     
    435437            this.currentAttacks.push(this.availableAttacks[i]);
    436438            //debug("Attacking!");
    437439        }
    438         this.availableAttacks.splice(i, 1, new this.attackManagers[i](gameState, this));
     440        this.availableAttacks.splice(i, 1, new this.attackManagers[i](gameState, this.Config, this));
    439441    }
    440442    Engine.ProfileStop();
    441443   
  • binaries/data/mods/public/simulation/ai/qbot/entity-extend.js

     
    33};
    44
    55Entity.prototype.garrison = function(target) {
    6     Engine.PostCommand({"type": "garrison", "entities": [this.id()], "target": target.id(),"queued": false});
     6    Engine.PostCommand(PlayerID, {"type": "garrison", "entities": [this.id()], "target": target.id(),"queued": false});
    77    return this;
    88};
    99
    1010Entity.prototype.attack = function(unitId)
    1111{
    12     Engine.PostCommand({"type": "attack", "entities": [this.id()], "target": unitId, "queued": false});
     12    Engine.PostCommand(PlayerID, {"type": "attack", "entities": [this.id()], "target": unitId, "queued": false});
    1313    return this;
    14 };
    15  Kein Zeilenumbruch am Ende der Datei
     14};
  • binaries/data/mods/public/simulation/ai/qbot/config.js

     
    1 var baseConfig = {
    2     "attack" : {
     1function Config() {
     2    this.debug = false
     3
     4    this.attack = {
    35        "minAttackSize" : 20, // attackMoveToLocation
    46        "maxAttackSize" : 60, // attackMoveToLocation
    57        "enemyRatio" : 1.5, // attackMoveToLocation
    68        "groupSize" : 10 // military
    7     },
     9    };
    810   
    911    // defence
    10     "defence" : {
     12    this.defence = {
    1113        "acquireDistance" : 220,
    1214        "releaseDistance" : 250,
    1315        "groupRadius" : 20,
    1416        "groupBreakRadius" : 40,
    1517        "groupMergeRadius" : 10,
    1618        "defenderRatio" : 2
    17     },
     19    };
    1820   
    1921    // military
    20     "buildings" : {
     22    this.buildings = {
    2123        "moderate" : {
    2224            "default" : [ "structures/{civ}_barracks" ]
    2325        },
     
    3739            "default" : [ "structures/{civ}_fortress" ],
    3840            "celt" : [ "structures/{civ}_fortress_b", "structures/{civ}_fortress_g" ]
    3941        }
    40     },
     42    };
    4143
    4244    // qbot
    43     "priorities" : {  // Note these are dynamic, you are only setting the initial values
     45    this.priorities = {  // Note these are dynamic, you are only setting the initial values
    4446        "house" : 500,
    4547        "citizenSoldier" : 100,
    4648        "villager" : 100,
     
    5153        "militaryBuilding" : 50,
    5254        "defenceBuilding" : 17,
    5355        "civilCentre" : 1000
    54     },
    55    
    56     "debug" : false
     56    };
    5757};
    5858
    59 var Config = {
    60         "debug": false
    61 };
    62 
    63 Config.__proto__ = baseConfig;
    64  Kein Zeilenumbruch am Ende der Datei
  • binaries/data/mods/public/simulation/ai/qbot/qbot.js

     
     1var g_debugEnabled = false;
    12
    23function QBotAI(settings) {
    34    BaseAI.call(this, settings);
     
    45
    56    this.turn = 0;
    67
     8    this.Config = new Config();
     9
    710    this.modules = {
    811            "economy": new EconomyManager(),
    9             "military": new MilitaryAttackManager(),
     12            "military": new MilitaryAttackManager(this.Config),
    1013            "housing": new HousingManager()
    1114    };
    1215
     16
    1317    // this.queues cannot be modified past initialisation or queue-manager will break
    1418    this.queues = {
    1519        house : new Queue(),
     
    2630
    2731    this.productionQueues = [];
    2832   
    29     this.priorities = Config.priorities;
     33    this.priorities = this.Config.priorities;
    3034   
    3135    this.queueManager = new QueueManager(this.queues, this.priorities);
    3236   
     
    161165};
    162166
    163167function debug(output){
    164     if (Config.debug){
     168    if (g_debugEnabled){
    165169        if (typeof output === "string"){
    166170            warn(output);
    167171        }else{
  • binaries/data/mods/public/simulation/ai/qbot/economy.js

     
    357357            // Make resources glow wildly
    358358            if (resource == "food"){
    359359                ent.getMetadata("nearby-resources-" + resource).forEach(function(ent){
    360                     Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,0,0]});
     360                    Engine.PostCommand(PlayerID, {"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,0,0]});
    361361                });
    362362            }
    363363            if (resource == "wood"){
    364364                ent.getMetadata("nearby-resources-" + resource).forEach(function(ent){
    365                     Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,0]});
     365                    Engine.PostCommand(PlayerID, {"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,0]});
    366366                });
    367367            }
    368368            if (resource == "metal"){
    369369                ent.getMetadata("nearby-resources-" + resource).forEach(function(ent){
    370                     Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0,10]});
     370                    Engine.PostCommand(PlayerID, {"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0,10]});
    371371                });
    372372            }*/
    373373        });
  • binaries/data/mods/public/simulation/ai/qbot/entitycollection-extend.js

     
    77        unitId = unit;
    88    }
    99   
    10     Engine.PostCommand({"type": "attack", "entities": this.toIdArray(), "target": unitId, "queued": false});
     10    Engine.PostCommand(PlayerID, {"type": "attack", "entities": this.toIdArray(), "target": unitId, "queued": false});
    1111    return this;
    1212};
    1313
     
    3737    }else{
    3838        return [sumPos[0]/count, sumPos[1]/count];
    3939    }
    40 };
    41  Kein Zeilenumbruch am Ende der Datei
     40};
  • binaries/data/mods/public/simulation/ai/common-api-v2/entitycollection.js

     
    109109EntityCollection.prototype.move = function(x, z, queued)
    110110{
    111111    queued = queued || false;
    112     Engine.PostCommand({"type": "walk", "entities": this.toIdArray(), "x": x, "z": z, "queued": queued});
     112    Engine.PostCommand(PlayerID, {"type": "walk", "entities": this.toIdArray(), "x": x, "z": z, "queued": queued});
    113113    return this;
    114114};
    115115
    116116EntityCollection.prototype.destroy = function()
    117117{
    118     Engine.PostCommand({"type": "delete-entities", "entities": this.toIdArray()});
     118    Engine.PostCommand(PlayerID, {"type": "delete-entities", "entities": this.toIdArray()});
    119119    return this;
    120120};
    121121
  • binaries/data/mods/public/simulation/ai/common-api-v2/base.js

     
     1var PlayerID = -1;
     2
    13function BaseAI(settings)
    24{
    35    if (!settings)
     
    112114    return null;
    113115};
    114116
    115 BaseAI.prototype.HandleMessage = function(state)
     117BaseAI.prototype.HandleMessage = function(state, playerID)
    116118{
     119    PlayerID = playerID;
    117120    if (!this._entities)
    118121    {
    119122        // Do a (shallow) clone of all the initial entity properties (in order
     
    237240
    238241BaseAI.prototype.chat = function(message)
    239242{
    240     Engine.PostCommand({"type": "chat", "message": message});
     243    Engine.PostCommand(PlayerID, {"type": "chat", "message": message});
    241244};
    242245
    243246BaseAI.prototype.registerUpdatingEntityCollection = function(entCollection)
  • binaries/data/mods/public/simulation/ai/common-api-v2/entity.js

     
    372372
    373373    move: function(x, z, queued) {
    374374        queued = queued || false;
    375         Engine.PostCommand({"type": "walk", "entities": [this.id()], "x": x, "z": z, "queued": queued});
     375        Engine.PostCommand(PlayerID, {"type": "walk", "entities": [this.id()], "x": x, "z": z, "queued": queued});
    376376        return this;
    377377    },
    378378
    379379    garrison: function(target) {
    380         Engine.PostCommand({"type": "garrison", "entities": [this.id()], "target": target.id(),"queued": false});
     380        Engine.PostCommand(PlayerID, {"type": "garrison", "entities": [this.id()], "target": target.id(),"queued": false});
    381381        return this;
    382382    },
    383383
    384384    attack: function(unitId) {
    385         Engine.PostCommand({"type": "attack", "entities": [this.id()], "target": unitId, "queued": false});
     385        Engine.PostCommand(PlayerID, {"type": "attack", "entities": [this.id()], "target": unitId, "queued": false});
    386386        return this;
    387387    },
    388388
    389389    gather: function(target, queued) {
    390390        queued = queued || false;
    391         Engine.PostCommand({"type": "gather", "entities": [this.id()], "target": target.id(), "queued": queued});
     391        Engine.PostCommand(PlayerID, {"type": "gather", "entities": [this.id()], "target": target.id(), "queued": queued});
    392392        return this;
    393393    },
    394394
    395395    repair: function(target, queued) {
    396396        queued = queued || false;
    397         Engine.PostCommand({"type": "repair", "entities": [this.id()], "target": target.id(), "autocontinue": false, "queued": queued});
     397        Engine.PostCommand(PlayerID, {"type": "repair", "entities": [this.id()], "target": target.id(), "autocontinue": false, "queued": queued});
    398398        return this;
    399399    },
    400400   
    401401    returnResources: function(target, queued) {
    402402        queued = queued || false;
    403         Engine.PostCommand({"type": "returnresource", "entities": [this.id()], "target": target.id(), "queued": queued});
     403        Engine.PostCommand(PlayerID, {"type": "returnresource", "entities": [this.id()], "target": target.id(), "queued": queued});
    404404        return this;
    405405    },
    406406
    407407    destroy: function() {
    408         Engine.PostCommand({"type": "delete-entities", "entities": [this.id()]});
     408        Engine.PostCommand(PlayerID, {"type": "delete-entities", "entities": [this.id()]});
    409409        return this;
    410410    },
    411411
     
    423423            return this;
    424424        }
    425425
    426         Engine.PostCommand({
     426        Engine.PostCommand(PlayerID, {
    427427            "type": "train",
    428428            "entities": [this.id()],
    429429            "template": type,
     
    437437        // TODO: verify this unit can construct this, just for internal
    438438        // sanity-checking and error reporting
    439439
    440         Engine.PostCommand({
     440        Engine.PostCommand(PlayerID, {
    441441            "type": "construct",
    442442            "entities": [this.id()],
    443443            "template": template,
  • binaries/data/mods/public/simulation/ai/common-api-v3/terrain-analysis-pathfinder.js

     
     1var API3 = function(m)
     2{
     3
    14// An implementation of A* as a pathfinder.
    25// It's oversamplable, and has a specific "distance from block"
    36// variable to avoid narrow passages if wanted.
     
    1114
    1215// The initializer creates an expanded influence map for checking.
    1316// It's not extraordinarily slow, but it might be.
    14 function aStarPath(gameState, onWater, disregardEntities, targetTerritory) {
     17m.aStarPath = function(gameState, onWater, disregardEntities, targetTerritory) {
    1518    var self = this;
    1619   
    1720    // get the terrain analyzer map as a reference.
     
    5255    }
    5356    this.expandInfluences(255,this.widthMap);
    5457}
    55 copyPrototype(aStarPath, Map);
     58m.copyPrototype(m.aStarPath, m.Map);
    5659
    5760// marks some points of the map as impassable. This can be used to create different paths, or to avoid going through some areas.
    58 aStarPath.prototype.markImpassableArea = function(cx, cy, Distance) {
     61m.aStarPath.prototype.markImpassableArea = function(cx, cy, Distance) {
    5962    [cx,cy] = this.gamePosToMapPos([cx,cy]);
    6063    var x0 = Math.max(0, cx - Distance);
    6164    var y0 = Math.max(0, cy - Distance);
     
    7881
    7982// sending gamestate creates a map
    8083// (you run the risk of "jumping" over obstacles or weird behavior.
    81 aStarPath.prototype.getPath = function(start, end, Sampling, preferredWidth, iterationLimit, gamestate)
     84m.aStarPath.prototype.getPath = function(start, end, Sampling, preferredWidth, iterationLimit, gamestate)
    8285{
    8386    this.Sampling = Sampling >= 1 ? Sampling : 1;
    8487    this.minWidth = 1;
     
    97100    }
    98101    if (gamestate !== undefined)
    99102    {
    100         this.TotorMap = new Map(gamestate);
     103        this.TotorMap = new m.Map(gamestate);
    101104        this.TotorMap.addInfluence(s[0],s[1],1,200,'constant');
    102105        this.TotorMap.addInfluence(e[0],e[1],1,200,'constant');
    103106    }
     
    135138   
    136139    this.isOpened[this.s] = true;
    137140    this.openList.push(this.s);
    138     this.fCostArray[this.s] = SquareVectorDistance([this.s%w, Math.floor(this.s/w)], [this.e%w, Math.floor(this.e/w)]);
     141    this.fCostArray[this.s] = m.SquareVectorDistance([this.s%w, Math.floor(this.s/w)], [this.e%w, Math.floor(this.e/w)]);
    139142    this.gCostArray[this.s] = 0;
    140143    this.parentSquare[this.s] = this.s;
    141144   
     
    143146   
    144147}
    145148// in case it's not over yet, this can carry on the calculation of a path over multiple turn until it's over
    146 aStarPath.prototype.continuePath = function(gamestate)
     149m.aStarPath.prototype.continuePath = function(gamestate)
    147150{
    148151    var w = this.width;
    149152    var h = this.height;
     
    208211                {
    209212                    this.parentSquare[index] = this.currentSquare;
    210213                   
    211                     this.fCostArray[index] = SquareVectorDistance([index%w, Math.floor(index/w)], target);// * cost[i];
     214                    this.fCostArray[index] = m.SquareVectorDistance([index%w, Math.floor(index/w)], target);// * cost[i];
    212215                    this.gCostArray[index] = this.gCostArray[this.currentSquare] + cost[i] * this.Sampling;// - this.map[index];
    213216                   
    214217                    if (!this.onWater && this.map[index] === 200) {
     
    231234                        this.openList.push(index);
    232235                    }
    233236                    this.isOpened[index] = true;
    234                     if (SquareVectorDistance( [index%w, Math.floor(index/w)] , target) <= this.Sampling*this.Sampling-1) {
     237                    if (m.SquareVectorDistance( [index%w, Math.floor(index/w)] , target) <= this.Sampling*this.Sampling-1) {
    235238                        if (this.e != index)
    236239                            this.parentSquare[this.e] = index;
    237240                        found = true;
     
    294297            if (gamestate !== undefined)
    295298                this.TotorMap.addInfluence(this.currentSquare % w, Math.floor(this.currentSquare / w),1,50,'constant');
    296299           
    297             if (SquareVectorDistance([lastPosx,lastPosy],[this.currentSquare % w, Math.floor(this.currentSquare / w)]) > 300 || changes[this.currentSquare])
     300            if (m.SquareVectorDistance([lastPosx,lastPosy],[this.currentSquare % w, Math.floor(this.currentSquare / w)]) > 300 || changes[this.currentSquare])
    298301            {
    299302                lastPosx = (this.currentSquare % w);
    300303                lastPosy = Math.floor(this.currentSquare / w);
     
    325328    }
    326329   
    327330}
     331
     332return m;
     333
     334}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/gamestate.js

     
     1var API3 = function(m)
     2{
     3
     4
    15/**
    26 * Provides an API for the rest of the AI scripts to query the world state at a
    37 * higher level than the raw data.
     
    26 */
    3 var GameState = function() {
     7m.GameState = function() {
    48    this.ai = null; // must be updated by the AIs.
     
    1014    this.turnCache = {};
    1115};
    1216
    13 GameState.prototype.init = function(SharedScript, state, player) {
     17m.GameState.prototype.init = function(SharedScript, state, player) {
    1418    this.sharedScript = SharedScript;
    1519    this.EntCollecNames = SharedScript._entityCollectionsName;
    1620    this.EntCollec = SharedScript._entityCollections;
     
    2327    this.techModifications = SharedScript._techModifications[this.player];
    2428};
    2529
    26 GameState.prototype.update = function(SharedScript, state) {
     30m.GameState.prototype.update = function(SharedScript, state) {
    2731    this.sharedScript = SharedScript;
    2832    this.EntCollecNames = SharedScript._entityCollectionsName;
    2933    this.EntCollec = SharedScript._entityCollections;
     
    3943    this.turnCache = {};
    4044};
    4145
    42 GameState.prototype.updatingCollection = function(id, filter, collection, allowQuick){
     46m.GameState.prototype.updatingCollection = function(id, filter, collection, allowQuick){
    4347    // automatically add the player ID
    4448    id = this.player + "-" + id;
    4549    if (!this.EntCollecNames[id]){
     
    5660   
    5761    return this.EntCollecNames[id];
    5862};
    59 GameState.prototype.destroyCollection = function(id){
     63m.GameState.prototype.destroyCollection = function(id){
    6064    // automatically add the player ID
    6165    id = this.player + "-" + id;
    6266   
     
    6569        delete this.EntCollecNames[id];
    6670    }
    6771};
    68 GameState.prototype.getEC = function(id){
     72m.GameState.prototype.getEC = function(id){
    6973    // automatically add the player ID
    7074    id = this.player + "-" + id;
    7175
     
    7478    return undefined;
    7579};
    7680
    77 GameState.prototype.updatingGlobalCollection = function(id, filter, collection, allowQuick) {
     81m.GameState.prototype.updatingGlobalCollection = function(id, filter, collection, allowQuick) {
    7882    if (!this.EntCollecNames[id]){
    7983        if (collection !== undefined)
    8084            this.EntCollecNames[id] = collection.filter(filter);
     
    8892   
    8993    return this.EntCollecNames[id];
    9094};
    91 GameState.prototype.destroyGlobalCollection = function(id)
     95m.GameState.prototype.destroyGlobalCollection = function(id)
    9296{
    9397    if (this.EntCollecNames[id] !== undefined){
    9498        this.sharedScript.removeUpdatingEntityCollection(this.EntCollecNames[id]);
    9599        delete this.EntCollecNames[id];
    96100    }
    97101};
    98 GameState.prototype.getGEC = function(id)
     102m.GameState.prototype.getGEC = function(id)
    99103{
    100104    if (this.EntCollecNames[id] !== undefined)
    101105        return this.EntCollecNames[id];
    102106    return undefined;
    103107};
    104108
    105 GameState.prototype.currentPhase = function()
     109m.GameState.prototype.currentPhase = function()
    106110{
    107111    if (this.isResearched("phase_city"))
    108112        return 3;
     
    113117    return 0;
    114118};
    115119
    116 GameState.prototype.townPhase = function()
     120m.GameState.prototype.townPhase = function()
    117121{
    118122    if (this.playerData.civ == "athen")
    119123        return "phase_town_athen";
    120124    return "phase_town_generic";
    121125};
    122126
    123 GameState.prototype.cityPhase = function()
     127m.GameState.prototype.cityPhase = function()
    124128{
    125129    return "phase_city_generic";
    126130};
    127131
    128 GameState.prototype.isResearched = function(template)
     132m.GameState.prototype.isResearched = function(template)
    129133{
    130134    return this.playerData.researchedTechs[template] !== undefined;
    131135};
    132136// true if started or queued
    133 GameState.prototype.isResearching = function(template)
     137m.GameState.prototype.isResearching = function(template)
    134138{
    135139    return (this.playerData.researchStarted[template] !== undefined || this.playerData.researchQueued[template] !== undefined);
    136140};
    137141
    138142// this is an absolute check that doesn't check if we have a building to research from.
    139 GameState.prototype.canResearch = function(techTemplateName, noRequirementCheck)
     143m.GameState.prototype.canResearch = function(techTemplateName, noRequirementCheck)
    140144{
    141145    var template = this.getTemplate(techTemplateName);
    142146    if (!template)
     
    170174
    171175// Private function for checking a set of requirements is met
    172176// basically copies TechnologyManager's
    173 GameState.prototype.checkTechRequirements = function (reqs)
     177m.GameState.prototype.checkTechRequirements = function (reqs)
    174178{
    175179    // If there are no requirements then all requirements are met
    176180    if (!reqs)
     
    229233};
    230234
    231235
    232 GameState.prototype.getTimeElapsed = function()
     236m.GameState.prototype.getTimeElapsed = function()
    233237{
    234238    return this.timeElapsed;
    235239};
    236240
    237 GameState.prototype.getTemplate = function(type)
     241m.GameState.prototype.getTemplate = function(type)
    238242{
    239243    if (this.techTemplates[type] !== undefined)
    240         return new Technology(this.techTemplates, type);
     244        return new m.Technology(this.techTemplates, type);
    241245   
    242246    if (!this.templates[type])
    243247        return null;
    244248   
    245     return new EntityTemplate(this.templates[type], this.techModifications);
     249    return new m.EntityTemplate(this.templates[type], this.techModifications);
    246250};
    247251
    248 GameState.prototype.applyCiv = function(str) {
     252m.GameState.prototype.applyCiv = function(str) {
    249253    return str.replace(/\{civ\}/g, this.playerData.civ);
    250254};
    251255
    252 GameState.prototype.civ = function() {
     256m.GameState.prototype.civ = function() {
    253257    return this.playerData.civ;
    254258};
    255259
    256260/**
    257261 * @returns {Resources}
    258262 */
    259 GameState.prototype.getResources = function() {
    260     return new Resources(this.playerData.resourceCounts);
     263m.GameState.prototype.getResources = function() {
     264    return new m.Resources(this.playerData.resourceCounts);
    261265};
    262266
    263 GameState.prototype.getMap = function() {
     267m.GameState.prototype.getMap = function() {
    264268    return this.sharedScript.passabilityMap;
    265269};
    266270
    267 GameState.prototype.getPopulation = function() {
     271m.GameState.prototype.getPopulation = function() {
    268272    return this.playerData.popCount;
    269273};
    270274
    271 GameState.prototype.getPopulationLimit = function() {
     275m.GameState.prototype.getPopulationLimit = function() {
    272276    return this.playerData.popLimit;
    273277};
    274278
    275 GameState.prototype.getPopulationMax = function() {
     279m.GameState.prototype.getPopulationMax = function() {
    276280    return this.playerData.popMax;
    277281};
    278282
    279 GameState.prototype.getPassabilityClassMask = function(name) {
     283m.GameState.prototype.getPassabilityClassMask = function(name) {
    280284    if (!(name in this.sharedScript.passabilityClasses)){
    281285        error("Tried to use invalid passability class name '" + name + "'");
    282286    }
    283287    return this.sharedScript.passabilityClasses[name];
    284288};
    285289
    286 GameState.prototype.getPlayerID = function() {
     290m.GameState.prototype.getPlayerID = function() {
    287291    return this.player;
    288292};
    289293
    290 GameState.prototype.isPlayerAlly = function(id) {
     294m.GameState.prototype.isPlayerAlly = function(id) {
    291295    return this.playerData.isAlly[id];
    292296};
    293297
    294 GameState.prototype.isPlayerEnemy = function(id) {
     298m.GameState.prototype.isPlayerEnemy = function(id) {
    295299    return this.playerData.isEnemy[id];
    296300};
    297301
    298 GameState.prototype.getEnemies = function(){
     302m.GameState.prototype.getEnemies = function(){
    299303    var ret = [];
    300304    for (var i in this.playerData.isEnemy){
    301305        if (this.playerData.isEnemy[i]){
     
    305309    return ret;
    306310};
    307311
    308 GameState.prototype.isEntityAlly = function(ent) {
     312m.GameState.prototype.isEntityAlly = function(ent) {
    309313    if (ent && ent.owner && (typeof ent.owner) === "function"){
    310314        return this.playerData.isAlly[ent.owner()];
    311315    } else if (ent && ent.owner){
     
    314318    return false;
    315319};
    316320
    317 GameState.prototype.isEntityEnemy = function(ent) {
     321m.GameState.prototype.isEntityEnemy = function(ent) {
    318322    if (ent && ent.owner && (typeof ent.owner) === "function"){
    319323        return this.playerData.isEnemy[ent.owner()];
    320324    } else if (ent && ent.owner){
     
    323327    return false;
    324328};
    325329 
    326 GameState.prototype.isEntityOwn = function(ent) {
     330m.GameState.prototype.isEntityOwn = function(ent) {
    327331    if (ent && ent.owner && (typeof ent.owner) === "function"){
    328332        return ent.owner() == this.player;
    329333    } else if (ent && ent.owner){
     
    332336    return false;
    333337};
    334338
    335 GameState.prototype.getOwnEntities = function() {
    336     return this.updatingCollection("own-entities", Filters.byOwner(this.player));
     339m.GameState.prototype.getOwnEntities = function() {
     340    return this.updatingCollection("own-entities", m.Filters.byOwner(this.player));
    337341};
    338342
    339 GameState.prototype.getEnemyEntities = function() {
     343m.GameState.prototype.getEnemyEntities = function() {
    340344    var diplomacyChange = false;
    341345    var enemies = this.getEnemies();
    342346    if (this.enemies){
     
    351355        }
    352356    }
    353357    if (diplomacyChange || !this.enemies){
    354         return this.updatingCollection("enemy-entities", Filters.byOwners(enemies));
     358        return this.updatingCollection("enemy-entities", m.Filters.byOwners(enemies));
    355359        this.enemies = enemies;
    356360    }
    357361    return this.getEC("enemy-entities");
    358362};
    359363
    360 GameState.prototype.getEntities = function() {
     364m.GameState.prototype.getEntities = function() {
    361365    return this.entities;
    362366};
    363367
    364 GameState.prototype.getEntityById = function(id){
     368m.GameState.prototype.getEntityById = function(id){
    365369    if (this.entities._entities[id]) {
    366370        return this.entities._entities[id];
    367371    }else{
     
    370374    return undefined;
    371375};
    372376
    373 GameState.prototype.getOwnEntitiesByMetadata = function(key, value, maintain){
     377m.GameState.prototype.getOwnEntitiesByMetadata = function(key, value, maintain){
    374378    if (maintain === true)
    375         return this.updatingCollection(key + "-" + value, Filters.byMetadata(this.player, key, value),this.getOwnEntities());
    376     return this.getOwnEntities().filter(Filters.byMetadata(this.player, key, value));
     379        return this.updatingCollection(key + "-" + value, m.Filters.byMetadata(this.player, key, value),this.getOwnEntities());
     380    return this.getOwnEntities().filter(m.Filters.byMetadata(this.player, key, value));
    377381};
    378382
    379 GameState.prototype.getOwnEntitiesByRole = function(role){
     383m.GameState.prototype.getOwnEntitiesByRole = function(role){
    380384    return this.getOwnEntitiesByMetadata("role", role, true);
    381385};
    382386
    383 GameState.prototype.getOwnTrainingFacilities = function(){
    384     return this.updatingCollection("own-training-facilities", Filters.byTrainingQueue(), this.getOwnEntities(), true);
     387m.GameState.prototype.getOwnTrainingFacilities = function(){
     388    return this.updatingCollection("own-training-facilities", m.Filters.byTrainingQueue(), this.getOwnEntities(), true);
    385389};
    386390
    387 GameState.prototype.getOwnResearchFacilities = function(){
    388     return this.updatingCollection("own-research-facilities", Filters.byResearchAvailable(), this.getOwnEntities(), true);
     391m.GameState.prototype.getOwnResearchFacilities = function(){
     392    return this.updatingCollection("own-research-facilities", m.Filters.byResearchAvailable(), this.getOwnEntities(), true);
    389393};
    390394
    391 GameState.prototype.getOwnEntitiesByType = function(type, maintain){
    392     var filter = Filters.byType(type);
     395m.GameState.prototype.getOwnEntitiesByType = function(type, maintain){
     396    var filter = m.Filters.byType(type);
    393397    if (maintain === true)
    394398        return this.updatingCollection("own-by-type-" + type, filter, this.getOwnEntities());
    395399    return this.getOwnEntities().filter(filter);
    396400
    397401};
    398402
    399 GameState.prototype.countEntitiesByType = function(type, maintain) {
     403m.GameState.prototype.countEntitiesByType = function(type, maintain) {
    400404    return this.getOwnEntitiesByType(type, maintain).length;
    401405};
    402406
    403 GameState.prototype.countEntitiesAndQueuedByType = function(type) {
     407m.GameState.prototype.countEntitiesAndQueuedByType = function(type) {
    404408    var count = this.countEntitiesByType(type, true);
    405409   
    406410    // Count building foundations
     
    424428    return count;
    425429};
    426430
    427 GameState.prototype.countFoundationsWithType = function(type) {
     431m.GameState.prototype.countFoundationsWithType = function(type) {
    428432    var foundationType = "foundation|" + type;
    429433    var count = 0;
    430434    this.getOwnEntities().forEach(function(ent) {
     
    435439    return count;
    436440};
    437441
    438 GameState.prototype.countOwnEntitiesByRole = function(role) {
     442m.GameState.prototype.countOwnEntitiesByRole = function(role) {
    439443    return this.getOwnEntitiesByRole(role).length;
    440444};
    441445
    442 GameState.prototype.countOwnEntitiesAndQueuedWithRole = function(role) {
     446m.GameState.prototype.countOwnEntitiesAndQueuedWithRole = function(role) {
    443447    var count = this.countOwnEntitiesByRole(role);
    444448   
    445449    // Count entities in building production queues
     
    452456    return count;
    453457};
    454458
    455 GameState.prototype.countOwnQueuedEntitiesWithMetadata = function(data, value) {
     459m.GameState.prototype.countOwnQueuedEntitiesWithMetadata = function(data, value) {
    456460    // Count entities in building production queues
    457461    var count = 0;
    458462    this.getOwnTrainingFacilities().forEach(function(ent) {
     
    468472 * Find buildings that are capable of training the given unit type, and aren't
    469473 * already too busy.
    470474 */
    471 GameState.prototype.findTrainers = function(template) {
     475m.GameState.prototype.findTrainers = function(template) {
    472476    var maxQueueLength = 3; // avoid tying up resources in giant training queues
    473477   
    474478    return this.getOwnTrainingFacilities().filter(function(ent) {
     
    490494/**
    491495 * Find units that are capable of constructing the given building type.
    492496 */
    493 GameState.prototype.findBuilders = function(template) {
     497m.GameState.prototype.findBuilders = function(template) {
    494498    return this.getOwnEntities().filter(function(ent) {
    495499
    496500        var buildable = ent.buildableEntities();
     
    505509 * Find buildings that are capable of researching the given tech, and aren't
    506510 * already too busy.
    507511 */
    508 GameState.prototype.findResearchers = function(templateName, noRequirementCheck) {
     512m.GameState.prototype.findResearchers = function(templateName, noRequirementCheck) {
    509513    // let's check we can research the tech.
    510514    if (!this.canResearch(templateName, noRequirementCheck))
    511515        return [];
     
    532536    });
    533537};
    534538
    535 GameState.prototype.getOwnFoundations = function() {
    536     return this.updatingCollection("ownFoundations", Filters.isFoundation(), this.getOwnEntities());
     539m.GameState.prototype.getOwnFoundations = function() {
     540    return this.updatingCollection("ownFoundations", m.Filters.isFoundation(), this.getOwnEntities());
    537541};
    538542
    539 GameState.prototype.getOwnDropsites = function(resource){
     543m.GameState.prototype.getOwnDropsites = function(resource){
    540544    if (resource !== undefined)
    541         return this.updatingCollection("dropsite-own-" + resource, Filters.isDropsite(resource), this.getOwnEntities(), true);
    542     return this.updatingCollection("dropsite-own", Filters.isDropsite(), this.getOwnEntities(), true);
     545        return this.updatingCollection("dropsite-own-" + resource, m.Filters.isDropsite(resource), this.getOwnEntities(), true);
     546    return this.updatingCollection("dropsite-own", m.Filters.isDropsite(), this.getOwnEntities(), true);
    543547};
    544548
    545 GameState.prototype.getResourceSupplies = function(resource){
    546     return this.updatingGlobalCollection("resource-" + resource, Filters.byResource(resource), this.getEntities(), true);
     549m.GameState.prototype.getResourceSupplies = function(resource){
     550    return this.updatingGlobalCollection("resource-" + resource, m.Filters.byResource(resource), this.getEntities(), true);
    547551};
    548552
    549 GameState.prototype.getEntityLimits = function() {
     553m.GameState.prototype.getEntityLimits = function() {
    550554    return this.playerData.entityLimits;
    551555};
    552556
    553 GameState.prototype.getEntityCounts = function() {
     557m.GameState.prototype.getEntityCounts = function() {
    554558    return this.playerData.entityCounts;
    555559};
    556560
    557561// Checks whether the maximum number of buildings have been cnstructed for a certain catergory
    558 GameState.prototype.isEntityLimitReached = function(category) {
     562m.GameState.prototype.isEntityLimitReached = function(category) {
    559563    if(this.playerData.entityLimits[category] === undefined || this.playerData.entityCounts[category] === undefined)
    560564        return false;
    561565    return (this.playerData.entityCounts[category] >= this.playerData.entityLimits[category]);
    562566};
    563567
    564 GameState.prototype.findTrainableUnits = function(classes){
     568m.GameState.prototype.findTrainableUnits = function(classes){
    565569    var allTrainable = [];
    566570    this.getOwnEntities().forEach(function(ent) {
    567571        var trainable = ent.trainableEntities();
     
    593597// Return all techs which can currently be researched
    594598// Does not factor cost.
    595599// If there are pairs, both techs are returned.
    596 GameState.prototype.findAvailableTech = function() {
     600m.GameState.prototype.findAvailableTech = function() {
    597601   
    598602    var allResearchable = [];
    599603    this.getOwnEntities().forEach(function(ent) {
     
    625629};
    626630
    627631// defcon utilities
    628 GameState.prototype.timeSinceDefconChange = function() {
     632m.GameState.prototype.timeSinceDefconChange = function() {
    629633    return this.getTimeElapsed()-this.ai.defconChangeTime;
    630634};
    631 GameState.prototype.setDefcon = function(level,force) {
     635m.GameState.prototype.setDefcon = function(level,force) {
    632636    if (this.ai.defcon >= level || force) {
    633637        this.ai.defcon = level;
    634638        this.ai.defconChangeTime = this.getTimeElapsed();
    635639    }
    636640};
    637 GameState.prototype.defcon = function() {
     641m.GameState.prototype.defcon = function() {
    638642    return this.ai.defcon;
    639643};
    640644
     645return m;
     646
     647}(API3);
     648
  • binaries/data/mods/public/simulation/ai/common-api-v3/resources.js

     
    1 function Resources(amounts, population) {
     1var API3 = function(m)
     2{
     3
     4m.Resources = function(amounts, population) {
    25    if (amounts === undefined) {
    36        amounts = {
    47            food : 0,
     
    1922    }
    2023}
    2124
    22 Resources.prototype.types = [ "food", "wood", "stone", "metal" ];
     25m.Resources.prototype.types = [ "food", "wood", "stone", "metal" ];
    2326
    24 Resources.prototype.reset = function() {
     27m.Resources.prototype.reset = function() {
    2528    for ( var tKey in this.types) {
    2629        var t = this.types[tKey];
    2730        this[t] = 0;
     
    2932    this.population = 0;
    3033};
    3134
    32 Resources.prototype.canAfford = function(that) {
     35m.Resources.prototype.canAfford = function(that) {
    3336    for ( var tKey in this.types) {
    3437        var t = this.types[tKey];
    3538        if (this[t] < that[t]) {
     
    3942    return true;
    4043};
    4144
    42 Resources.prototype.add = function(that) {
     45m.Resources.prototype.add = function(that) {
    4346    for ( var tKey in this.types) {
    4447        var t = this.types[tKey];
    4548        this[t] += that[t];
     
    4750    this.population += that.population;
    4851};
    4952
    50 Resources.prototype.subtract = function(that) {
     53m.Resources.prototype.subtract = function(that) {
    5154    for ( var tKey in this.types) {
    5255        var t = this.types[tKey];
    5356        this[t] -= that[t];
     
    5558    this.population += that.population;
    5659};
    5760
    58 Resources.prototype.multiply = function(n) {
     61m.Resources.prototype.multiply = function(n) {
    5962    for ( var tKey in this.types) {
    6063        var t = this.types[tKey];
    6164        this[t] *= n;
     
    6366    this.population *= n;
    6467};
    6568
    66 Resources.prototype.toInt = function() {
     69m.Resources.prototype.toInt = function() {
    6770    var sum = 0;
    6871    for ( var tKey in this.types) {
    6972        var t = this.types[tKey];
     
    7275    sum += this.population * 50; // based on typical unit costs
    7376    return sum;
    7477};
     78
     79return m;
     80
     81}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/technology.js

     
     1var API3 = function(m)
     2{
     3
    14// Wrapper around a technology template
    25
    3 function Technology(allTemplates, templateName)
     6m.Technology = function(allTemplates, templateName)
    47{
    58    this._templateName = templateName;
    69    var template = allTemplates[templateName];
     
    2023    this._techTemplates = allTemplates;
    2124}
    2225// returns generic, or specific if civ provided.
    23 Technology.prototype.name = function(civ)
     26m.Technology.prototype.name = function(civ)
    2427{
    2528    if (civ === undefined)
    2629    {
     
    3437    }
    3538};
    3639
    37 Technology.prototype.pairDef = function()
     40m.Technology.prototype.pairDef = function()
    3841{
    3942    return this._definesPair;
    4043};
    4144// in case this defines a pair only, returns the two paired technologies.
    42 Technology.prototype.getPairedTechs = function()
     45m.Technology.prototype.getPairedTechs = function()
    4346{
    4447    if (!this._definesPair)
    4548        return undefined;
    4649   
    47     var techOne = new Technology(this._techTemplates, this._template.top);
    48     var techTwo = new Technology(this._techTemplates, this._template.bottom);
     50    var techOne = new m.Technology(this._techTemplates, this._template.top);
     51    var techTwo = new m.Technology(this._techTemplates, this._template.bottom);
    4952   
    5053    return [techOne,techTwo];
    5154};
    5255
    53 Technology.prototype.pair = function()
     56m.Technology.prototype.pair = function()
    5457{
    5558    if (!this._isPair)
    5659        return undefined;
    5760    return this._template.pair;
    5861};
    5962
    60 Technology.prototype.pairedWith = function()
     63m.Technology.prototype.pairedWith = function()
    6164{
    6265    if (!this._isPair)
    6366        return undefined;
    6467    return this._pairedWith;
    6568};
    6669
    67 Technology.prototype.cost = function()
     70m.Technology.prototype.cost = function()
    6871{
    6972    if (!this._template.cost)
    7073        return undefined;
     
    7275};
    7376
    7477// seconds
    75 Technology.prototype.researchTime = function()
     78m.Technology.prototype.researchTime = function()
    7679{
    7780    if (!this._template.researchTime)
    7881        return undefined;
    7982    return this._template.researchTime;
    8083};
    8184
    82 Technology.prototype.requirements = function()
     85m.Technology.prototype.requirements = function()
    8386{
    8487    if (!this._template.requirements)
    8588        return undefined;
    8689    return this._template.requirements;
    8790};
    8891
    89 Technology.prototype.autoResearch = function()
     92m.Technology.prototype.autoResearch = function()
    9093{
    9194    if (!this._template.autoResearch)
    9295        return undefined;
    9396    return this._template.autoResearch;
    9497};
    9598
    96 Technology.prototype.supersedes = function()
     99m.Technology.prototype.supersedes = function()
    97100{
    98101    if (!this._template.supersedes)
    99102        return undefined;
    100103    return this._template.supersedes;
    101104};
    102105
    103 Technology.prototype.modifications = function()
     106m.Technology.prototype.modifications = function()
    104107{
    105108    if (!this._template.modifications)
    106109        return undefined;
    107110    return this._template.modifications;
    108111};
    109112
    110 Technology.prototype.affects = function()
     113m.Technology.prototype.affects = function()
    111114{
    112115    if (!this._template.affects)
    113116        return undefined;
    114117    return this._template.affects;
    115118};
    116119
    117 Technology.prototype.isAffected = function(classes)
     120m.Technology.prototype.isAffected = function(classes)
    118121{
    119122    if (!this._template.affects)
    120123        return false;
     
    136139    }
    137140    return false;
    138141};
     142
     143return m;
     144
     145}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/baseAI.js

     
    11var PlayerID = -1;
    22
    3 function BaseAI(settings)
     3var API3 = (function() {
     4
     5var m = {};
     6
     7m.BaseAI = function(settings)
    48{
    59    if (!settings)
    610        return;
    711
    812    this.player = settings.player;
    9     PlayerID = this.player;
    1013
    1114    // played turn, in case you don't want the AI to play every turn.
    1215    this.turn = 0;
    13 }
     16};
    1417
    1518//Return a simple object (using no classes etc) that will be serialized into saved games
    16 BaseAI.prototype.Serialize = function()
     19m.BaseAI.prototype.Serialize = function()
    1720{
    1821    // TODO: ought to get the AI script subclass to serialize its own state
    1922    // TODO: actually this is part of a larger reflection on wether AIs should or not.
     
    2225
    2326//Called after the constructor when loading a saved game, with 'data' being
    2427//whatever Serialize() returned
    25 BaseAI.prototype.Deserialize = function(data, sharedScript)
     28m.BaseAI.prototype.Deserialize = function(data, sharedScript)
    2629{
    2730    // TODO: ought to get the AI script subclass to deserialize its own state
    2831    // TODO: actually this is part of a larger reflection on wether AIs should or not.
    2932    this.isDeserialized = true;
    3033};
    3134
    32 BaseAI.prototype.Init = function(state, sharedAI)
     35m.BaseAI.prototype.Init = function(state, playerID, sharedAI)
    3336{
     37    PlayerID = playerID;
    3438    // define some references
    3539    this.entities = sharedAI.entities;
    3640    this.templates = sharedAI.templates;
     
    4347    this.techModifications = sharedAI._techModifications[this.player];
    4448    this.playerData = sharedAI.playersData[this.player];
    4549   
    46     this.gameState = sharedAI.gameState[PlayerID];
     50    this.gameState = sharedAI.gameState[this.player];
    4751    this.gameState.ai = this;
    4852    this.sharedScript = sharedAI;
    4953   
     
    5256    this.CustomInit(this.gameState, this.sharedScript);
    5357}
    5458
    55 BaseAI.prototype.CustomInit = function()
     59m.BaseAI.prototype.CustomInit = function()
    5660{   // AIs override this function
    5761};
    5862
    59 BaseAI.prototype.HandleMessage = function(state, sharedAI)
     63m.BaseAI.prototype.HandleMessage = function(state, playerID, sharedAI)
    6064{
    6165    this.events = sharedAI.events;
     66    PlayerID = playerID;
    6267   
    6368    if (this.isDeserialized && this.turn !== 0)
    6469    {
     
    7075    this.OnUpdate(sharedAI);
    7176};
    7277
    73 BaseAI.prototype.OnUpdate = function()
     78m.BaseAI.prototype.OnUpdate = function()
    7479{   // AIs override this function
    7580};
    7681
    77 BaseAI.prototype.chat = function(message)
     82m.BaseAI.prototype.chat = function(message)
    7883{
    79     Engine.PostCommand({"type": "chat", "message": message});
     84    Engine.PostCommand(PlayerID,{"type": "chat", "message": message});
    8085};
    81 BaseAI.prototype.chatTeam = function(message)
     86m.BaseAI.prototype.chatTeam = function(message)
    8287{
    83     Engine.PostCommand({"type": "chat", "message": "/team " +message});
     88    Engine.PostCommand(PlayerID,{"type": "chat", "message": "/team " +message});
    8489};
    85 BaseAI.prototype.chatEnemies = function(message)
     90m.BaseAI.prototype.chatEnemies = function(message)
    8691{
    87     Engine.PostCommand({"type": "chat", "message": "/enemy " +message});
     92    Engine.PostCommand(PlayerID,{"type": "chat", "message": "/enemy " +message});
    8893};
    8994
     95return m;
     96
     97}());
     98
  • binaries/data/mods/public/simulation/ai/common-api-v3/map-module.js

     
     1var API3 = function(m)
     2{
     3
    14/* The map module.
    25 * Copied with changes from QuantumState's original for qBot, it's a component for storing 8 bit values.
    36 */
     
    25
    3 const TERRITORY_PLAYER_MASK = 0x3F;
    4 
    5 function Map(sharedScript, originalMap, actualCopy){
     6// The function needs to be named too because of the copyConstructor functionality
     7m.Map = function Map(sharedScript, originalMap, actualCopy){
    68    // get the map to find out the correct dimensions
     
    2527    this.cellSize = 4;
    2628}
    2729
    28 Map.prototype.setMaxVal = function(val){
     30m.Map.prototype.setMaxVal = function(val){
    2931    this.maxVal = val;
    3032};
    3133
    32 Map.prototype.gamePosToMapPos = function(p){
     34m.Map.prototype.gamePosToMapPos = function(p){
    3335    return [Math.floor(p[0]/this.cellSize), Math.floor(p[1]/this.cellSize)];
    3436};
    3537
    36 Map.prototype.point = function(p){
     38m.Map.prototype.point = function(p){
    3739    var q = this.gamePosToMapPos(p);
    3840    return this.map[q[0] + this.width * q[1]];
    3941};
    40 Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type) {
     42m.Map.prototype.addInfluence = function(cx, cy, maxDist, strength, type) {
    4143    strength = strength ? +strength : +maxDist;
    4244    type = type ? type : 'linear';
    4345   
     
    9092    }
    9193};
    9294
    93 Map.prototype.multiplyInfluence = function(cx, cy, maxDist, strength, type) {
     95m.Map.prototype.multiplyInfluence = function(cx, cy, maxDist, strength, type) {
    9496    strength = strength ? +strength : +maxDist;
    9597    type = type ? type : 'constant';
    9698   
     
    145147};
    146148
    147149// doesn't check for overflow.
    148 Map.prototype.setInfluence = function(cx, cy, maxDist, value) {
     150m.Map.prototype.setInfluence = function(cx, cy, maxDist, value) {
    149151    value = value ? value : 0;
    150152   
    151153    var x0 = Math.max(0, cx - maxDist);
     
    166168    }
    167169};
    168170
    169 Map.prototype.sumInfluence = function(cx, cy, radius){
     171m.Map.prototype.sumInfluence = function(cx, cy, radius){
    170172    var x0 = Math.max(0, cx - radius);
    171173    var y0 = Math.max(0, cy - radius);
    172174    var x1 = Math.min(this.width, cx + radius);
     
    192194 * neighbours' values. (If the grid is initialised with 0s and 65535s or 255s, the
    193195 * result of each cell is its Manhattan distance to the nearest 0.)
    194196 */
    195 Map.prototype.expandInfluences = function(maximum, map) {
     197m.Map.prototype.expandInfluences = function(maximum, map) {
    196198    var grid = this.map;
    197199    if (map !== undefined)
    198200        grid = map;
     
    252254    }
    253255};
    254256
    255 Map.prototype.findBestTile = function(radius, obstructionTiles){
     257m.Map.prototype.findBestTile = function(radius, obstructionTiles){
    256258    // Find the best non-obstructed tile
    257259    var bestIdx = 0;
    258260    var bestVal = -1;
     
    269271    return [bestIdx, bestVal];
    270272};
    271273// Multiplies current map by the parameter map pixelwise
    272 Map.prototype.multiply = function(map, onlyBetter, divider, maxMultiplier){
     274m.Map.prototype.multiply = function(map, onlyBetter, divider, maxMultiplier){
    273275    for (var i = 0; i < this.length; ++i){
    274276        if (map.map[i]/divider > 1)
    275277            this.map[i] = Math.min(maxMultiplier*this.map[i], this.map[i] * (map.map[i]/divider));
    276278    }
    277279};
    278280// add to current map by the parameter map pixelwise
    279 Map.prototype.add = function(map){
     281m.Map.prototype.add = function(map){
    280282    for (var i = 0; i < this.length; ++i) {
    281283        if (this.map[i] + map.map[i] < 0)
    282284            this.map[i] = 0;
     
    287289    }
    288290};
    289291
    290 Map.prototype.dumpIm = function(name, threshold){
     292m.Map.prototype.dumpIm = function(name, threshold){
    291293    name = name ? name : "default.png";
    292294    threshold = threshold ? threshold : this.maxVal;
    293295    Engine.DumpImage(name, this.map, this.width, this.height, threshold);
    294296};
     297
     298return m;
     299
     300}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/class.js

     
     1var API3 = function(m)
     2{
    13/**
    24 * Provides a nicer syntax for defining classes,
    35 * with support for OO-style inheritance.
     
    24 */
    3 function Class(data)
     5m.Class = function(data)
    46{
     
    3436print((new B).foo+" "+(new B).bar+"\n");
    3537print((new C).foo+" "+(new C).bar+"\n");
    3638//*/
     39
     40return m;
     41
     42}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/filters.js

     
    1 var Filters = {
     1var API3 = function(m)
     2{
     3
     4m.Filters = {
    25    byType: function(type){
    36        return {"func" : function(ent){
    47            return ent.templateName() === type;
     
    169172            if (ent.position() === undefined){
    170173                return false;
    171174            }else{
    172                 return (SquareVectorDistance(startPoint, ent.position()) < dist*dist);
     175                return (m.SquareVectorDistance(startPoint, ent.position()) < dist*dist);
    173176            }
    174177        },
    175178        "dynamicProperties": ['position']};
     
    181184            if (!ent.position()){
    182185                return false;
    183186            }else{
    184                 return (SquareVectorDistance(startPoint, ent.position()) < dist*dist);
     187                return (m.SquareVectorDistance(startPoint, ent.position()) < dist*dist);
    185188            }
    186189        },
    187190        "dynamicProperties": []};
     
    238241        "dynamicProperties": []};
    239242    }
    240243};
     244
     245return m;
     246
     247}(API3);
     248
  • binaries/data/mods/public/simulation/ai/common-api-v3/entity.js

     
    1 var EntityTemplate = Class({
     1var API3 = function(m)
     2{
    23
     4m.EntityTemplate = m.Class({
     5
    36    // techModifications should be the tech modifications of only one player.
    47    // gamestates handle "GetTemplate" and should push the player's
    58    // while entities should push the owner's
     
    447450
    448451
    449452
    450 var Entity = Class({
    451     _super: EntityTemplate,
     453m.Entity = m.Class({
     454    _super: m.EntityTemplate,
    452455
    453456    _init: function(sharedAI, entity)
    454457    {
     
    576579        return this._entity.resourceCarrying;
    577580    },
    578581
    579     garrisoned: function() { return new EntityCollection(this._ai, this._entity.garrisoned); },
     582    garrisoned: function() { return new m.EntityCollection(this._ai, this._entity.garrisoned); },
    580583   
    581584    canGarrisonInside: function() { return this._entity.garrisoned.length < this.garrisonMax(); },
    582585
     
    584587
    585588    move: function(x, z, queued) {
    586589        queued = queued || false;
    587         Engine.PostCommand({"type": "walk", "entities": [this.id()], "x": x, "z": z, "queued": queued });
     590        Engine.PostCommand(PlayerID,{"type": "walk", "entities": [this.id()], "x": x, "z": z, "queued": queued });
    588591        return this;
    589592    },
    590593   
    591594    attackMove: function(x, z, queued) {
    592595        queued = queued || false;
    593         Engine.PostCommand({"type": "attack-walk", "entities": [this.id()], "x": x, "z": z, "queued": queued });
     596        Engine.PostCommand(PlayerID,{"type": "attack-walk", "entities": [this.id()], "x": x, "z": z, "queued": queued });
    594597        return this;
    595598    },
    596599
    597600    // violent, aggressive, defensive, passive, standground
    598601    setStance: function(stance,queued){
    599         Engine.PostCommand({"type": "stance", "entities": [this.id()], "name" : stance, "queued": queued });
     602        Engine.PostCommand(PlayerID,{"type": "stance", "entities": [this.id()], "name" : stance, "queued": queued });
    600603        return this;
    601604    },
    602605
    603606    // TODO: replace this with the proper "STOP" command
    604607    stopMoving: function() {
    605608        if (this.position() !== undefined)
    606             Engine.PostCommand({"type": "walk", "entities": [this.id()], "x": this.position()[0], "z": this.position()[1], "queued": false});
     609            Engine.PostCommand(PlayerID,{"type": "walk", "entities": [this.id()], "x": this.position()[0], "z": this.position()[1], "queued": false});
    607610    },
    608611
    609612    unload: function(id) {
    610613        if (!this._template.GarrisonHolder)
    611614            return undefined;
    612         Engine.PostCommand({"type": "unload", "garrisonHolder": this.id(), "entities": [id]});
     615        Engine.PostCommand(PlayerID,{"type": "unload", "garrisonHolder": this.id(), "entities": [id]});
    613616        return this;
    614617    },
    615618
     
    617620    unloadAll: function() {
    618621        if (!this._template.GarrisonHolder)
    619622            return undefined;
    620         Engine.PostCommand({"type": "unload-all-own", "garrisonHolders": [this.id()]});
     623        Engine.PostCommand(PlayerID,{"type": "unload-all-own", "garrisonHolders": [this.id()]});
    621624        return this;
    622625    },
    623626
    624627    garrison: function(target) {
    625         Engine.PostCommand({"type": "garrison", "entities": [this.id()], "target": target.id(),"queued": false});
     628        Engine.PostCommand(PlayerID,{"type": "garrison", "entities": [this.id()], "target": target.id(),"queued": false});
    626629        return this;
    627630    },
    628631
    629632    attack: function(unitId) {
    630         Engine.PostCommand({"type": "attack", "entities": [this.id()], "target": unitId, "queued": false});
     633        Engine.PostCommand(PlayerID,{"type": "attack", "entities": [this.id()], "target": unitId, "queued": false});
    631634        return this;
    632635    },
    633636   
     
    635638    flee: function(unitToFleeFrom) {
    636639        if (this.position() !== undefined && unitToFleeFrom.position() !== undefined) {
    637640            var FleeDirection = [this.position()[0] - unitToFleeFrom.position()[0],this.position()[1] - unitToFleeFrom.position()[1]];
    638             var dist = VectorDistance(unitToFleeFrom.position(), this.position() );
     641            var dist = m.VectorDistance(unitToFleeFrom.position(), this.position() );
    639642            FleeDirection[0] = (FleeDirection[0]/dist) * 8;
    640643            FleeDirection[1] = (FleeDirection[1]/dist) * 8;
    641644           
    642             Engine.PostCommand({"type": "walk", "entities": [this.id()], "x": this.position()[0] + FleeDirection[0]*5, "z": this.position()[1] + FleeDirection[1]*5, "queued": false});
     645            Engine.PostCommand(PlayerID,{"type": "walk", "entities": [this.id()], "x": this.position()[0] + FleeDirection[0]*5, "z": this.position()[1] + FleeDirection[1]*5, "queued": false});
    643646        }
    644647        return this;
    645648    },
    646649
    647650    gather: function(target, queued) {
    648651        queued = queued || false;
    649         Engine.PostCommand({"type": "gather", "entities": [this.id()], "target": target.id(), "queued": queued});
     652        Engine.PostCommand(PlayerID,{"type": "gather", "entities": [this.id()], "target": target.id(), "queued": queued});
    650653        return this;
    651654    },
    652655
    653656    repair: function(target, queued) {
    654657        queued = queued || false;
    655         Engine.PostCommand({"type": "repair", "entities": [this.id()], "target": target.id(), "autocontinue": false, "queued": queued});
     658        Engine.PostCommand(PlayerID,{"type": "repair", "entities": [this.id()], "target": target.id(), "autocontinue": false, "queued": queued});
    656659        return this;
    657660    },
    658661   
    659662    returnResources: function(target, queued) {
    660663        queued = queued || false;
    661         Engine.PostCommand({"type": "returnresource", "entities": [this.id()], "target": target.id(), "queued": queued});
     664        Engine.PostCommand(PlayerID,{"type": "returnresource", "entities": [this.id()], "target": target.id(), "queued": queued});
    662665        return this;
    663666    },
    664667
    665668    destroy: function() {
    666         Engine.PostCommand({"type": "delete-entities", "entities": [this.id()] });
     669        Engine.PostCommand(PlayerID,{"type": "delete-entities", "entities": [this.id()] });
    667670        return this;
    668671    },
    669672   
    670673    barter: function(buyType, sellType, amount) {
    671         Engine.PostCommand({"type": "barter", "sell" : sellType, "buy" : buyType, "amount" : amount });
     674        Engine.PostCommand(PlayerID,{"type": "barter", "sell" : sellType, "buy" : buyType, "amount" : amount });
    672675        return this;
    673676    },
    674677   
     
    686689            return this;
    687690        }
    688691
    689         Engine.PostCommand({
     692        Engine.PostCommand(PlayerID,{
    690693            "type": "train",
    691694            "entities": [this.id()],
    692695            "template": type,
     
    699702    construct: function(template, x, z, angle, metadata) {
    700703        // TODO: verify this unit can construct this, just for internal
    701704        // sanity-checking and error reporting
    702 
    703         Engine.PostCommand({
     705        Engine.PostCommand(PlayerID,{
    704706            "type": "construct",
    705707            "entities": [this.id()],
    706708            "template": template,
     
    716718    },
    717719                   
    718720     research: function(template) {
    719         Engine.PostCommand({ "type": "research", "entity": this.id(), "template": template });
     721        Engine.PostCommand(PlayerID,{ "type": "research", "entity": this.id(), "template": template });
    720722        return this;
    721723    },
    722724
    723725    stopProduction: function(id) {
    724         Engine.PostCommand({ "type": "stop-production", "entity": this.id(), "id": id });
     726        Engine.PostCommand(PlayerID,{ "type": "stop-production", "entity": this.id(), "id": id });
    725727        return this;
    726728    },
    727729   
     
    732734        for (var i in queue)
    733735        {
    734736            if (queue[i].progress < percentToStopAt)
    735                 Engine.PostCommand({ "type": "stop-production", "entity": this.id(), "id": queue[i].id });
     737                Engine.PostCommand(PlayerID,{ "type": "stop-production", "entity": this.id(), "id": queue[i].id });
    736738        }
    737739        return this;
    738740    }
    739741});
    740742
     743return m;
     744
     745}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/terrain-analysis.js

     
     1var API3 = function(m)
     2{
     3
    14/*
    25 * TerrainAnalysis, inheriting from the Map Component.
    36 *
     
    1215 * But truly separating optimizes.
    1316 */
    1417
    15 function TerrainAnalysis() {
     18m.TerrainAnalysis = function() {
    1619    this.cellSize = 4;
    1720}
    1821
    19 copyPrototype(TerrainAnalysis, Map);
     22m.copyPrototype(m.TerrainAnalysis, m.Map);
    2023
    21 TerrainAnalysis.prototype.init = function(sharedScript,rawState) {
     24m.TerrainAnalysis.prototype.init = function(sharedScript,rawState) {
    2225    var self = this;
    2326
    2427    var passabilityMap = rawState.passabilityMap;
     
    108111};
    109112
    110113// Returns the (approximately) closest point which is passable by searching in a spiral pattern
    111 TerrainAnalysis.prototype.findClosestPassablePoint = function(startPoint, onLand, limitDistance, quickscope){
     114m.TerrainAnalysis.prototype.findClosestPassablePoint = function(startPoint, onLand, limitDistance, quickscope){
    112115    var w = this.width;
    113116    var p = startPoint;
    114117    var direction = 1;
     
    150153
    151154// Returns an estimate of a tile accessibility. It checks neighboring cells over two levels.
    152155// returns a count. It's not integer. About 2 should be fairly accessible already.
    153 TerrainAnalysis.prototype.countConnected = function(startIndex, byLand){
     156m.TerrainAnalysis.prototype.countConnected = function(startIndex, byLand){
    154157    var count = 0.0;
    155158   
    156159    var w = this.width;
     
    181184};
    182185
    183186// TODO: for now this resets to 255.
    184 TerrainAnalysis.prototype.updateMapWithEvents = function(sharedAI) {
     187m.TerrainAnalysis.prototype.updateMapWithEvents = function(sharedAI) {
    185188    var self = this;
    186189   
    187190    var events = sharedAI.events;
     
    243246 * so this can use the land regions already.
    244247
    245248 */
    246 function Accessibility() {
     249m.Accessibility = function() {
    247250   
    248251}
    249252
    250 copyPrototype(Accessibility, TerrainAnalysis);
     253m.copyPrototype(m.Accessibility, m.TerrainAnalysis);
    251254
    252 Accessibility.prototype.init = function(rawState, terrainAnalyser){
     255m.Accessibility.prototype.init = function(rawState, terrainAnalyser){
    253256    var self = this;
    254257   
    255258    this.Map(rawState, terrainAnalyser.map);
     
    322325    //Engine.DumpImage("NavalPassMap.png", this.navalPassMap, this.width, this.height, 255);
    323326}
    324327
    325 Accessibility.prototype.getAccessValue = function(position, onWater) {
     328m.Accessibility.prototype.getAccessValue = function(position, onWater) {
    326329    var gamePos = this.gamePosToMapPos(position);
    327330    if (onWater === true)
    328331        return this.navalPassMap[gamePos[0] + this.width*gamePos[1]];
     
    343346
    344347// Returns true if a point is deemed currently accessible (is not blocked by surrounding trees...)
    345348// NB: accessible means that you can reach it from one side, not necessariliy that you can go ON it.
    346 Accessibility.prototype.isAccessible = function(gameState, position, onLand){
     349m.Accessibility.prototype.isAccessible = function(gameState, position, onLand){
    347350    var gamePos = this.gamePosToMapPos(position);
    348351   
    349352    // quick check
     
    356359// Return true if you can go from a point to a point without switching means of transport
    357360// Hardcore means is also checks for isAccessible at the end (it checks for either water or land though, beware).
    358361// This is a blind check and not a pathfinder: for all it knows there is a huge block of trees in the middle.
    359 Accessibility.prototype.pathAvailable = function(gameState, start, end, onWater, hardcore){
     362m.Accessibility.prototype.pathAvailable = function(gameState, start, end, onWater, hardcore){
    360363    var pstart = this.gamePosToMapPos(start);
    361364    var istart = pstart[0] + pstart[1]*this.width;
    362365    var pend = this.gamePosToMapPos(end);
     
    382385    return false;
    383386};
    384387
    385 Accessibility.prototype.getTrajectTo = function(start, end, noBound) {
     388m.Accessibility.prototype.getTrajectTo = function(start, end, noBound) {
    386389    var pstart = this.gamePosToMapPos(start);
    387390    var istart = pstart[0] + pstart[1]*this.width;
    388391    var pend = this.gamePosToMapPos(end);
     
    413416// assumes a land unit unless start point is over deep water.
    414417// if the path is more complicated than "land->sea->land" (or "sea->land->sea"), it will run A* to try and figure it out
    415418// Thus it can handle arbitrarily complicated paths (theoretically).
    416 Accessibility.prototype.getTrajectToIndex = function(istart, iend, noBound){
     419m.Accessibility.prototype.getTrajectToIndex = function(istart, iend, noBound){
    417420    var startRegion = istart;
    418421    var currentRegion = istart;
    419422   
     
    530533    return path;
    531534};
    532535
    533 Accessibility.prototype.getRegionSize = function(position, onWater){
     536m.Accessibility.prototype.getRegionSize = function(position, onWater){
    534537    var pos = this.gamePosToMapPos(position);
    535538    var index = pos[0] + pos[1]*this.width;
    536539    var ID = (onWater === true) ? this.navalPassMap[index] : this.landPassMap[index];
     
    539542    return this.regionSize[ID];
    540543};
    541544
    542 Accessibility.prototype.getRegionSizei = function(index, onWater) {
     545m.Accessibility.prototype.getRegionSizei = function(index, onWater) {
    543546    if (this.regionSize[this.landPassMap[index]] === undefined && (!onWater || this.regionSize[this.navalPassMap[index]] === undefined))
    544547        return 0;
    545548    if (onWater && this.regionSize[this.navalPassMap[index]] > this.regionSize[this.landPassMap[index]])
     
    549552
    550553// Implementation of a fast flood fill. Reasonably good performances for JS.
    551554// TODO: take big zones of impassable trees into account?
    552 Accessibility.prototype.floodFill = function(startIndex, value, onWater)
     555m.Accessibility.prototype.floodFill = function(startIndex, value, onWater)
    553556{
    554557    this.s = startIndex;
    555558    if ((!onWater && this.landPassMap[this.s] !== 0) || (onWater && this.navalPassMap[this.s] !== 0) ) {
     
    668671}
    669672
    670673// creates a map of resource density
    671 SharedScript.prototype.createResourceMaps = function(sharedScript) {
     674m.SharedScript.prototype.createResourceMaps = function(sharedScript) {
    672675   
    673676    for (var resource in this.decreaseFactor){
    674677        // if there is no resourceMap create one with an influence for everything with that resource
    675678        if (! this.resourceMaps[resource]){
    676679            // We're creting them 8-bit. Things could go above 255 if there are really tons of resources
    677680            // But at that point the precision is not really important anyway. And it saves memory.
    678             this.resourceMaps[resource] = new Map(sharedScript, new Uint8Array(sharedScript.passabilityMap.data.length));
     681            this.resourceMaps[resource] = new m.Map(sharedScript, new Uint8Array(sharedScript.passabilityMap.data.length));
    679682            this.resourceMaps[resource].setMaxVal(255);
    680             this.CCResourceMaps[resource] = new Map(sharedScript, new Uint8Array(sharedScript.passabilityMap.data.length));
     683            this.CCResourceMaps[resource] = new m.Map(sharedScript, new Uint8Array(sharedScript.passabilityMap.data.length));
    681684            this.CCResourceMaps[resource].setMaxVal(255);
    682685        }
    683686    }
     
    711714// creates and maintains a map of unused resource density
    712715// this also takes dropsites into account.
    713716// resources that are "part" of a dropsite are not counted.
    714 SharedScript.prototype.updateResourceMaps = function(sharedScript, events) {
     717m.SharedScript.prototype.updateResourceMaps = function(sharedScript, events) {
    715718   
    716719    for (var resource in this.decreaseFactor){
    717720        // if there is no resourceMap create one with an influence for everything with that resource
    718721        if (! this.resourceMaps[resource]){
    719722            // We're creting them 8-bit. Things could go above 255 if there are really tons of resources
    720723            // But at that point the precision is not really important anyway. And it saves memory.
    721             this.resourceMaps[resource] = new Map(sharedScript, new Uint8Array(sharedScript.passabilityMap.data.length));
     724            this.resourceMaps[resource] = new m.Map(sharedScript, new Uint8Array(sharedScript.passabilityMap.data.length));
    722725            this.resourceMaps[resource].setMaxVal(255);
    723             this.CCResourceMaps[resource] = new Map(sharedScript, new Uint8Array(sharedScript.passabilityMap.data.length));
     726            this.CCResourceMaps[resource] = new m.Map(sharedScript, new Uint8Array(sharedScript.passabilityMap.data.length));
    724727            this.CCResourceMaps[resource].setMaxVal(255);
    725728        }
    726729    }
     
    780783        }
    781784    }
    782785};
     786
     787return m;
     788
     789}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/entitycollection.js

     
    1 function EntityCollection(sharedAI, entities, filters)
     1var API3 = function(m)
    22{
     3
     4m.EntityCollection = function(sharedAI, entities, filters)
     5{
    36    this._ai = sharedAI;
    47    this._entities = entities || {};
    58    this._filters = filters || [];
     
    2225        }
    2326    });
    2427    this.frozen = false;
    25 }
     28};
    2629
    2730// If an entitycollection is frozen, it will never automatically add a unit.
    2831// But can remove one.
    2932// this makes it easy to create entity collection that will auto-remove dead units
    3033// but never add new ones.
    31 EntityCollection.prototype.freeze = function()
     34m.EntityCollection.prototype.freeze = function()
    3235{
    3336    this.frozen = true;
    3437};
    35 EntityCollection.prototype.defreeze = function()
     38m.EntityCollection.prototype.defreeze = function()
    3639{
    3740    this.frozen = false;
    3841};
    3942
    40 EntityCollection.prototype.allowQuickIter = function()
     43m.EntityCollection.prototype.allowQuickIter = function()
    4144{
    4245    this._quickIter = true;
    4346    this._entitiesArray = [];
     
    4548        this._entitiesArray.push(ent);
    4649};
    4750
    48 EntityCollection.prototype.toIdArray = function()
     51m.EntityCollection.prototype.toIdArray = function()
    4952{
    5053    var ret = [];
    5154    for (var id in this._entities)
     
    5356    return ret;
    5457};
    5558
    56 EntityCollection.prototype.toEntityArray = function()
     59m.EntityCollection.prototype.toEntityArray = function()
    5760{
    5861    if (this._quickIter === true)
    5962        return this._entitiesArray;
     
    6366    return ret;
    6467};
    6568
    66 EntityCollection.prototype.toString = function()
     69m.EntityCollection.prototype.toString = function()
    6770{
    6871    return "[EntityCollection " + this.toEntityArray().join(" ") + "]";
    6972};
     
    7174/**
    7275 * Returns the (at most) n entities nearest to targetPos.
    7376 */
    74 EntityCollection.prototype.filterNearest = function(targetPos, n)
     77m.EntityCollection.prototype.filterNearest = function(targetPos, n)
    7578{
    7679    // Compute the distance of each entity
    7780    var data = []; // [id, ent, distance]
     
    8285        {
    8386            var ent = this._entitiesArray[i];
    8487            if (ent.position() !== -1)
    85                 data.push([ent.id(), ent, SquareVectorDistance(targetPos, ent.position())]);
     88                data.push([ent.id(), ent, m.SquareVectorDistance(targetPos, ent.position())]);
    8689        }
    8790    } else {
    8891        for (var id in this._entities)
    8992        {
    9093            var ent = this._entities[id];
    9194            if (ent.position() !== -1)
    92                 data.push([id, ent, SquareVectorDistance(targetPos, ent.position())]);
     95                data.push([id, ent, m.SquareVectorDistance(targetPos, ent.position())]);
    9396        }
    9497    }
    9598
     
    102105    for (var i = 0; i < length; ++i)
    103106        ret[data[i][0]] = data[i][1];
    104107
    105     return new EntityCollection(this._ai, ret);
     108    return new m.EntityCollection(this._ai, ret);
    106109};
    107110
    108 EntityCollection.prototype.filter = function(filter, thisp)
     111m.EntityCollection.prototype.filter = function(filter, thisp)
    109112{
    110113    if (typeof(filter) == "function")
    111114        filter = {"func": filter, "dynamicProperties": []};
     
    129132        }
    130133    }
    131134   
    132     return new EntityCollection(this._ai, ret, this._filters.concat([filter]));
     135    return new m.EntityCollection(this._ai, ret, this._filters.concat([filter]));
    133136};
    134137
    135 EntityCollection.prototype.filter_raw = function(callback, thisp)
     138m.EntityCollection.prototype.filter_raw = function(callback, thisp)
    136139{
    137140    var ret = {};
    138141    for (var id in this._entities)
     
    142145        if (callback.call(thisp, val, id, this))
    143146            ret[id] = ent;
    144147    }
    145     return new EntityCollection(this._ai, ret);
     148    return new m.EntityCollection(this._ai, ret);
    146149};
    147150
    148 EntityCollection.prototype.forEach = function(callback)
     151m.EntityCollection.prototype.forEach = function(callback)
    149152{
    150153    if (this._quickIter === true)
    151154    {
     
    162165    return this;
    163166};
    164167
    165 EntityCollection.prototype.filterNearest = function(targetPos, n)
     168m.EntityCollection.prototype.filterNearest = function(targetPos, n)
    166169{
    167170    // Compute the distance of each entity
    168171    var data = []; // [ [id, ent, distance], ... ]
     
    170173    {
    171174        var ent = this._entities[id];
    172175        if (ent.position())
    173             data.push([id, ent, SquareVectorDistance(targetPos, ent.position())]);
     176            data.push([id, ent, m.SquareVectorDistance(targetPos, ent.position())]);
    174177    }
    175178   
    176179    // Sort by increasing distance
     
    182185    for each (var val in data.slice(0, n))
    183186        ret[val[0]] = val[1];
    184187   
    185     return new EntityCollection(this._ai, ret);
     188    return new m.EntityCollection(this._ai, ret);
    186189};
    187190
    188 EntityCollection.prototype.move = function(x, z, queued)
     191m.EntityCollection.prototype.move = function(x, z, queued)
    189192{
    190193    queued = queued || false;
    191     Engine.PostCommand({"type": "walk", "entities": this.toIdArray(), "x": x, "z": z, "queued": queued});
     194    Engine.PostCommand(PlayerID,{"type": "walk", "entities": this.toIdArray(), "x": x, "z": z, "queued": queued});
    192195    return this;
    193196};
    194 EntityCollection.prototype.attackMove = function(x, z, queued)
     197m.EntityCollection.prototype.attackMove = function(x, z, queued)
    195198{
    196199    queued = queued || false;
    197200    Engine.PostCommand({"type": "attack-walk", "entities": this.toIdArray(), "x": x, "z": z, "queued": queued});
    198201    return this;
    199202};
    200 EntityCollection.prototype.moveIndiv = function(x, z, queued)
     203m.EntityCollection.prototype.moveIndiv = function(x, z, queued)
    201204{
    202205    queued = queued || false;
    203206    for (var id in this._entities)
     
    206209        // It disables JIT compiling of this loop. Don't remove it unless you are sure that the underlying issue has been resolved!
    207210        // TODO: Check this again after the SpiderMonkey upgrade.
    208211        try {} finally {}
    209         Engine.PostCommand({"type": "walk", "entities": [this._entities[id].id()], "x": x, "z": z, "queued": queued});
     212        Engine.PostCommand(PlayerID,{"type": "walk", "entities": [this._entities[id].id()], "x": x, "z": z, "queued": queued});
    210213    }
    211214    return this;
    212215};
    213 EntityCollection.prototype.destroy = function()
     216m.EntityCollection.prototype.destroy = function()
    214217{
    215     Engine.PostCommand({"type": "delete-entities", "entities": this.toIdArray()});
     218    Engine.PostCommand(PlayerID,{"type": "delete-entities", "entities": this.toIdArray()});
    216219    return this;
    217220};
    218 EntityCollection.prototype.attack = function(unit)
     221m.EntityCollection.prototype.attack = function(unit)
    219222{
    220223    var unitId;
    221224    if (typeof(unit) === "Entity")
     
    226229    {
    227230        unitId = unit;
    228231    }   
    229     Engine.PostCommand({"type": "attack", "entities": this.toIdArray(), "target": unitId, "queued": false});
     232    Engine.PostCommand(PlayerID,{"type": "attack", "entities": this.toIdArray(), "target": unitId, "queued": false});
    230233    return this;
    231234};
    232235// violent, aggressive, defensive, passive, standground
    233 EntityCollection.prototype.setStance = function(stance)
     236m.EntityCollection.prototype.setStance = function(stance)
    234237{
    235     Engine.PostCommand({"type": "stance", "entities": this.toIdArray(), "name" : stance, "queued": false});
     238    Engine.PostCommand(PlayerID,{"type": "stance", "entities": this.toIdArray(), "name" : stance, "queued": false});
    236239    return this;
    237240};
    238241
    239242// Returns the average position of all units
    240 EntityCollection.prototype.getCentrePosition = function()
     243m.EntityCollection.prototype.getCentrePosition = function()
    241244{
    242245    var sumPos = [0, 0];
    243246    var count = 0;
     
    263266// returns the average position from the sample first units.
    264267// This might be faster for huge collections, but there's
    265268// always a risk that it'll be unprecise.
    266 EntityCollection.prototype.getApproximatePosition = function(sample)
     269m.EntityCollection.prototype.getApproximatePosition = function(sample)
    267270{
    268271    var sumPos = [0, 0];
    269272    var i = 0;
     
    291294
    292295
    293296// Removes an entity from the collection, returns true if the entity was a member, false otherwise
    294 EntityCollection.prototype.removeEnt = function(ent)
     297m.EntityCollection.prototype.removeEnt = function(ent)
    295298{
    296299    if (this._entities[ent.id()])
    297300    {
     
    310313};
    311314
    312315// Adds an entity to the collection, returns true if the entity was not member, false otherwise
    313 EntityCollection.prototype.addEnt = function(ent)
     316m.EntityCollection.prototype.addEnt = function(ent)
    314317{
    315318    if (this._entities[ent.id()])
    316319    {
     
    333336// Force can add a unit despite a freezing.
    334337// If an entitycollection is frozen, it will never automatically add a unit.
    335338// But can remove one.
    336 EntityCollection.prototype.updateEnt = function(ent, force)
     339m.EntityCollection.prototype.updateEnt = function(ent, force)
    337340{   
    338341    var passesFilters = true;
    339342    for each (var filter in this._filters)
     
    353356    }
    354357};
    355358
    356 EntityCollection.prototype.registerUpdates = function(noPush)
     359m.EntityCollection.prototype.registerUpdates = function(noPush)
    357360{
    358361    this._ai.registerUpdatingEntityCollection(this,noPush);
    359362};
    360363
    361 EntityCollection.prototype.unregister = function()
     364m.EntityCollection.prototype.unregister = function()
    362365{
    363366    this._ai.removeUpdatingEntityCollection(this);
    364367};
    365368
    366 EntityCollection.prototype.dynamicProperties = function()
     369m.EntityCollection.prototype.dynamicProperties = function()
    367370{
    368371    var ret = [];
    369372    for each (var filter in this._filters)
     
    374377    return ret;
    375378};
    376379
    377 EntityCollection.prototype.setUID = function(id)
     380m.EntityCollection.prototype.setUID = function(id)
    378381{
    379382    this._UID = id;
    380383};
    381384
    382 EntityCollection.prototype.getUID = function()
     385m.EntityCollection.prototype.getUID = function()
    383386{
    384387    return this._UID;
    385388};
     389
     390return m;
     391
     392}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/utils.js

     
    1 function VectorDistance(a, b)
     1var API3 = function(m)
    22{
     3
     4m.VectorDistance = function(a, b)
     5{
    36    var dx = a[0] - b[0];
    47    var dz = a[1] - b[1];
    58    return Math.sqrt(dx*dx + dz*dz);
    69}
    710
    8 function SquareVectorDistance(a, b)
     11m.SquareVectorDistance = function(a, b)
    912{
    1013    var dx = a[0] - b[0];
    1114    var dz = a[1] - b[1];
     
    1316}
    1417// A is the reference, B must be in "range" of A
    1518// this supposes the range is already squared
    16 function inRange(a, b, range)// checks for X distance
     19m.inRange = function(a, b, range)// checks for X distance
    1720{
    1821    // will avoid unnecessary checking for position in some rare cases... I'm lazy
    1922    if (a === undefined || b === undefined || range === undefined)
     
    2427    return ((dx*dx + dz*dz ) < range);
    2528}
    2629// slower than SquareVectorDistance, faster than VectorDistance but not exactly accurate.
    27 function ManhattanDistance(a, b)
     30m.ManhattanDistance = function(a, b)
    2831{
    2932    var dx = a[0] - b[0];
    3033    var dz = a[1] - b[1];
    3134    return Math.abs(dx) + Math.abs(dz);
    3235}
    3336
    34 function AssocArraytoArray(assocArray) {
     37m.AssocArraytoArray = function(assocArray) {
    3538    var endArray = [];
    3639    for (var i in assocArray)
    3740        endArray.push(assocArray[i]);
    3841    return endArray;
    3942};
    4043
    41 function MemoizeInit(obj)
     44m.MemoizeInit = function(obj)
    4245{
    4346    obj._memoizeCache = {};
    4447}
    4548
    46 function Memoize(funcname, func)
     49m.Memoize = function(funcname, func)
    4750{
    4851    return function() {
    4952        var args = funcname + '|' + Array.prototype.join.call(arguments, '|');
     
    5659    };
    5760}
    5861
    59 function ShallowClone(obj)
     62m.ShallowClone = function(obj)
    6063{
    6164    var ret = {};
    6265    for (var k in obj)
     
    6568}
    6669
    6770// Picks a random element from an array
    68 function PickRandom(list){
     71m.PickRandom = function(list){
    6972    if (list.length === 0)
    7073    {
    7174        return undefined;
     
    7578        return list[Math.floor(Math.random()*list.length)];
    7679    }
    7780}
     81
     82return m;
     83
     84}(API3);
  • binaries/data/mods/public/simulation/ai/common-api-v3/shared.js

     
     1var API3 = function(m)
     2{
     3
    14// Shared script handling templates and basic terrain analysis
    2 function SharedScript(settings)
     5m.SharedScript = function(settings)
    36{
    47    if (!settings)
    58        return;
     
    3740//Return a simple object (using no classes etc) that will be serialized
    3841//into saved games
    3942//TODO: that
    40 SharedScript.prototype.Serialize = function()
     43m.SharedScript.prototype.Serialize = function()
    4144{
    4245    return { "players" : this._players, "templates" : this._templates, "techTp" : this._techTemplates };
    4346};
    4447
    4548// Called after the constructor when loading a saved game, with 'data' being
    4649// whatever Serialize() returned
    47 SharedScript.prototype.Deserialize = function(data)
     50m.SharedScript.prototype.Deserialize = function(data)
    4851{
    4952    this._players = data.players;
    5053    this._templates = data.templates;
     
    5659// (This is a bit yucky and fragile since it's the inverse of
    5760// CCmpTemplateManager::CopyFoundationSubset and only includes components
    5861// that our EntityTemplate class currently uses.)
    59 var g_FoundationForbiddenComponents = {
     62m.g_FoundationForbiddenComponents = {
    6063    "ProductionQueue": 1,
    6164    "ResourceSupply": 1,
    6265    "ResourceDropsite": 1,
     
    6568
    6669// Components that will be disabled in resource entity templates.
    6770// Roughly the inverse of CCmpTemplateManager::CopyResourceSubset.
    68 var g_ResourceForbiddenComponents = {
     71m.g_ResourceForbiddenComponents = {
    6972    "Cost": 1,
    7073    "Decay": 1,
    7174    "Health": 1,
     
    7477    "Vision": 1
    7578};
    7679
    77 SharedScript.prototype.GetTemplate = function(name)
     80m.SharedScript.prototype.GetTemplate = function(name)
    7881{   
    7982    if (this._templates[name])
    8083        return this._templates[name];
     
    8992       
    9093        var foundation = {};
    9194        for (var key in base)
    92             if (!g_FoundationForbiddenComponents[key])
     95            if (!m.g_FoundationForbiddenComponents[key])
    9396                foundation[key] = base[key];
    9497       
    9598        this._derivedTemplates[name] = foundation;
     
    101104       
    102105        var resource = {};
    103106        for (var key in base)
    104             if (!g_ResourceForbiddenComponents[key])
     107            if (!m.g_ResourceForbiddenComponents[key])
    105108                resource[key] = base[key];
    106109       
    107110        this._derivedTemplates[name] = resource;
     
    115118// Initialize the shared component.
    116119// We need to now the initial state of the game for this, as we will use it.
    117120// This is called right at the end of the map generation.
    118 SharedScript.prototype.init = function(state) {
     121m.SharedScript.prototype.init = function(state) {
    119122    this.passabilityClasses = state.passabilityClasses;
    120123    this.passabilityMap = state.passabilityMap;
    121124    this.players = this._players;
     
    128131   
    129132    this._entities = {};
    130133    for (var id in state.entities)
    131         this._entities[id] = new Entity(this, state.entities[id]);
     134        this._entities[id] = new m.Entity(this, state.entities[id]);
    132135
    133136    // entity collection updated on create/destroy event.
    134     this.entities = new EntityCollection(this, this._entities);
     137    this.entities = new m.EntityCollection(this, this._entities);
    135138   
    136139    // create the terrain analyzer
    137     this.terrainAnalyzer = new TerrainAnalysis();
     140    this.terrainAnalyzer = new m.TerrainAnalysis();
    138141    this.terrainAnalyzer.init(this, state);
    139     this.accessibility = new Accessibility();
     142    this.accessibility = new m.Accessibility();
    140143    this.accessibility.init(state, this.terrainAnalyzer);
    141144   
    142145    // defined in TerrainAnalysis.js
     
    145148    this.gameState = {};
    146149    for (var i in this._players)
    147150    {
    148         this.gameState[this._players[i]] = new GameState();
     151        this.gameState[this._players[i]] = new m.GameState();
    149152        this.gameState[this._players[i]].init(this,state,this._players[i]);
    150153    }
    151154};
    152155
    153156// General update of the shared script, before each AI's update
    154157// applies entity deltas, and each gamestate.
    155 SharedScript.prototype.onUpdate = function(state)
     158m.SharedScript.prototype.onUpdate = function(state)
    156159{
    157160    if (this.isDeserialized && this.turn !== 0)
    158161    {
     
    188191    Engine.ProfileStop();
    189192};
    190193
    191 SharedScript.prototype.ApplyEntitiesDelta = function(state)
     194m.SharedScript.prototype.ApplyEntitiesDelta = function(state)
    192195{
    193196    Engine.ProfileStart("Shared ApplyEntitiesDelta");
    194197
     
    202205            {
    203206                continue; // Sometimes there are things like foundations which get destroyed too fast
    204207            }
    205             this._entities[evt.msg.entity] = new Entity(this, state.entities[evt.msg.entity]);
     208            this._entities[evt.msg.entity] = new m.Entity(this, state.entities[evt.msg.entity]);
    206209            this.entities.addEnt(this._entities[evt.msg.entity]);
    207210
    208211            // Update all the entity collections since the create operation affects static properties as well as dynamic
     
    302305    Engine.ProfileStop();
    303306};
    304307
    305 SharedScript.prototype.registerUpdatingEntityCollection = function(entCollection, noPush)
     308m.SharedScript.prototype.registerUpdatingEntityCollection = function(entCollection, noPush)
    306309{
    307310    if (!noPush) {
    308311        this._entityCollections.push(entCollection);
     
    316319    this._entityCollectionsUID++;
    317320};
    318321
    319 SharedScript.prototype.removeUpdatingEntityCollection = function(entCollection)
     322m.SharedScript.prototype.removeUpdatingEntityCollection = function(entCollection)
    320323{
    321324    for (var i in this._entityCollections)
    322325    {
     
    338341    }
    339342};
    340343
    341 SharedScript.prototype.updateEntityCollections = function(property, ent)
     344m.SharedScript.prototype.updateEntityCollections = function(property, ent)
    342345{
    343346    if (this._entityCollectionsByDynProp[property] !== undefined)
    344347    {
     
    349352    }
    350353}
    351354
    352 SharedScript.prototype.setMetadata = function(player, ent, key, value)
     355m.SharedScript.prototype.setMetadata = function(player, ent, key, value)
    353356{
    354357    var metadata = this._entityMetadata[player][ent.id()];
    355358    if (!metadata)
     
    359362    this.updateEntityCollections('metadata', ent);
    360363    this.updateEntityCollections('metadata.' + key, ent);
    361364};
    362 SharedScript.prototype.getMetadata = function(player, ent, key)
     365m.SharedScript.prototype.getMetadata = function(player, ent, key)
    363366{
    364367    var metadata = this._entityMetadata[player][ent.id()];
    365368   
     
    367370        return undefined;
    368371    return metadata[key];
    369372};
    370 SharedScript.prototype.deleteMetadata = function(player, ent, key)
     373m.SharedScript.prototype.deleteMetadata = function(player, ent, key)
    371374{
    372375    var metadata = this._entityMetadata[player][ent.id()];
    373376   
     
    378381    return true;
    379382};
    380383
    381 function copyPrototype(descendant, parent) {
     384m.copyPrototype = function(descendant, parent) {
    382385    var sConstructor = parent.toString();
    383386    var aMatch = sConstructor.match( /\s*function (.*)\(/ );
    384387    if ( aMatch != null ) { descendant.prototype[aMatch[1]] = parent; }
     
    387390    }
    388391};
    389392
     393return m;
     394
     395}(API3);
     396
  • source/simulation2/components/CCmpAIManager.cpp

     
    7878        NONCOPYABLE(CAIPlayer);
    7979    public:
    8080        CAIPlayer(CAIWorker& worker, const std::wstring& aiName, player_id_t player, uint8_t difficulty,
    81                 const shared_ptr<ScriptRuntime>& runtime, boost::rand48& rng) :
    82             m_Worker(worker), m_AIName(aiName), m_Player(player), m_Difficulty(difficulty), m_ScriptInterface("Engine", "AI", runtime)
     81                shared_ptr<ScriptInterface> scriptInterface) :
     82            m_Worker(worker), m_AIName(aiName), m_Player(player), m_Difficulty(difficulty), m_ScriptInterface(scriptInterface)
    8383        {
    84             m_ScriptInterface.SetCallbackData(static_cast<void*> (this));
    85 
    86             m_ScriptInterface.ReplaceNondeterministicRNG(rng);
    87             m_ScriptInterface.LoadGlobalScripts();
    88 
    89             m_ScriptInterface.RegisterFunction<void, std::wstring, CAIPlayer::IncludeModule>("IncludeModule");
    90             m_ScriptInterface.RegisterFunction<void, CAIPlayer::DumpHeap>("DumpHeap");
    91             m_ScriptInterface.RegisterFunction<void, CAIPlayer::ForceGC>("ForceGC");
    92             m_ScriptInterface.RegisterFunction<void, CScriptValRooted, CAIPlayer::PostCommand>("PostCommand");
    93 
    94             m_ScriptInterface.RegisterFunction<void, std::wstring, std::vector<u32>, u32, u32, u32, CAIPlayer::DumpImage>("DumpImage");
    95 
    96             m_ScriptInterface.RegisterFunction<void, std::wstring, CScriptVal, CAIPlayer::RegisterSerializablePrototype>("RegisterSerializablePrototype");
    9784        }
    9885
    9986        ~CAIPlayer()
     
    10390            m_Commands.clear();
    10491        }
    10592
    106         static void IncludeModule(void* cbdata, std::wstring name)
    107         {
    108             CAIPlayer* self = static_cast<CAIPlayer*> (cbdata);
    109 
    110             self->LoadScripts(name);
    111         }
    112         static void DumpHeap(void* cbdata)
    113         {
    114             CAIPlayer* self = static_cast<CAIPlayer*> (cbdata);
    115            
    116             //std::cout << JS_GetGCParameter(self->m_ScriptInterface.GetRuntime(), JSGC_BYTES) << std::endl;
    117             self->m_ScriptInterface.DumpHeap();
    118         }
    119         static void ForceGC(void* cbdata)
    120         {
    121             CAIPlayer* self = static_cast<CAIPlayer*> (cbdata);
    122            
    123             JS_GC(self->m_ScriptInterface.GetContext());
    124         }       
    125         static void PostCommand(void* cbdata, CScriptValRooted cmd)
    126         {
    127             CAIPlayer* self = static_cast<CAIPlayer*> (cbdata);
    128 
    129             self->m_Commands.push_back(self->m_ScriptInterface.WriteStructuredClone(cmd.get()));
    130         }
    131 
    132         /**
    133          * Debug function for AI scripts to dump 2D array data (e.g. terrain tile weights).
    134          * TODO: check if this needs to be here too.
    135          */
    136         static void DumpImage(void* UNUSED(cbdata), std::wstring name, std::vector<u32> data, u32 w, u32 h, u32 max)
    137         {
    138             // TODO: this is totally not threadsafe.
    139 
    140             VfsPath filename = L"screenshots/aidump/" + name;
    141 
    142             if (data.size() != w*h)
    143             {
    144                 debug_warn(L"DumpImage: data size doesn't match w*h");
    145                 return;
    146             }
    147 
    148             if (max == 0)
    149             {
    150                 debug_warn(L"DumpImage: max must not be 0");
    151                 return;
    152             }
    153 
    154             const size_t bpp = 8;
    155             int flags = TEX_BOTTOM_UP|TEX_GREY;
    156 
    157             const size_t img_size = w * h * bpp/8;
    158             const size_t hdr_size = tex_hdr_size(filename);
    159             shared_ptr<u8> buf;
    160             AllocateAligned(buf, hdr_size+img_size, maxSectorSize);
    161             Tex t;
    162             if (tex_wrap(w, h, bpp, flags, buf, hdr_size, &t) < 0)
    163                 return;
    164 
    165             u8* img = buf.get() + hdr_size;
    166             for (size_t i = 0; i < data.size(); ++i)
    167                 img[i] = (u8)((data[i] * 255) / max);
    168 
    169             tex_write(&t, filename);
    170             tex_free(&t);
    171         }
    172 
    173         static void RegisterSerializablePrototype(void* cbdata, std::wstring name, CScriptVal proto)
    174         {
    175             CAIPlayer* self = static_cast<CAIPlayer*> (cbdata);
    176             // Add our player number to avoid name conflicts with other prototypes
    177             // TODO: it would be better if serializable prototypes were stored in ScriptInterfaces
    178             //  and then each serializer would access those matching its own context, but that's
    179             //  not possible with AIs sharing data across contexts
    180             std::wstringstream protoID;
    181             protoID << self->m_Player << L"." << name.c_str();
    182             self->m_Worker.RegisterSerializablePrototype(protoID.str(), proto);
    183         }
    184 
    185         bool LoadScripts(const std::wstring& moduleName)
    186         {
    187             // Ignore modules that are already loaded
    188             if (m_LoadedModules.find(moduleName) != m_LoadedModules.end())
    189                 return true;
    190 
    191             // Mark this as loaded, to prevent it recursively loading itself
    192             m_LoadedModules.insert(moduleName);
    193 
    194             // Load and execute *.js
    195             VfsPaths pathnames;
    196             vfs::GetPathnames(g_VFS, L"simulation/ai/" + moduleName + L"/", L"*.js", pathnames);
    197             for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
    198             {
    199                 if (!m_ScriptInterface.LoadGlobalScriptFile(*it))
    200                 {
    201                     LOGERROR(L"Failed to load script %ls", it->string().c_str());
    202                     return false;
    203                 }
    204             }
    205 
    206             return true;
    207         }
    208 
    20993        bool Initialise(bool callConstructor)
    21094        {
    211             if (!LoadScripts(m_AIName))
     95            // LoadScripts will only load each script once even though we call it for each player
     96            if (!m_Worker.LoadScripts(m_AIName))
    21297                return false;
    21398
    21499            OsPath path = L"simulation/ai/" + m_AIName + L"/data.json";
     
    220105            }
    221106
    222107            // Get the constructor name from the metadata
     108            // If the AI doesn't use modules, we look for the constructor in the global object
     109            // TODO: All AIs should use modules. Remove the condition if this requirement is met.
     110            std::string moduleName;
    223111            std::string constructor;
    224             if (!m_ScriptInterface.GetProperty(metadata.get(), "constructor", constructor))
     112            CScriptVal objectWithConstructor; // object that should contain the cosntructor fucntion
     113            CScriptVal ctor;
     114            if (!m_ScriptInterface->GetProperty(metadata.get(), "moduleName", moduleName))
    225115            {
     116                objectWithConstructor = m_ScriptInterface->GetGlobalObject();
     117            }
     118            else
     119            {
     120                if(!m_ScriptInterface->GetProperty(m_ScriptInterface->GetGlobalObject(), moduleName.c_str(), objectWithConstructor) || objectWithConstructor.undefined())
     121                {
     122                    LOGERROR(L"Failed to create AI player: %ls: can't find the module that should contain the constructor: '%hs'", path.string().c_str(), moduleName.c_str());
     123                    return false;
     124                }
     125            }
     126            if (!m_ScriptInterface->GetProperty(metadata.get(), "constructor", constructor))
     127            {
    226128                LOGERROR(L"Failed to create AI player: %ls: missing 'constructor'", path.string().c_str());
    227129                return false;
    228130            }
    229131
    230132            // Get the constructor function from the loaded scripts
    231             CScriptVal ctor;
    232             if (!m_ScriptInterface.GetProperty(m_ScriptInterface.GetGlobalObject(), constructor.c_str(), ctor)
     133            if (!m_ScriptInterface->GetProperty(objectWithConstructor.get(), constructor.c_str(), ctor)
    233134                || ctor.undefined())
    234135            {
    235136                LOGERROR(L"Failed to create AI player: %ls: can't find constructor '%hs'", path.string().c_str(), constructor.c_str());
    236137                return false;
    237138            }
    238139
    239             m_ScriptInterface.GetProperty(metadata.get(), "useShared", m_UseSharedComponent);
     140            m_ScriptInterface->GetProperty(metadata.get(), "useShared", m_UseSharedComponent);
    240141           
    241142            CScriptVal obj;
    242143
     
    244145            {
    245146                // Set up the data to pass as the constructor argument
    246147                CScriptVal settings;
    247                 m_ScriptInterface.Eval(L"({})", settings);
    248                 m_ScriptInterface.SetProperty(settings.get(), "player", m_Player, false);
    249                 m_ScriptInterface.SetProperty(settings.get(), "difficulty", m_Difficulty, false);
     148                m_ScriptInterface->Eval(L"({})", settings);
     149                m_ScriptInterface->SetProperty(settings.get(), "player", m_Player, false);
     150                m_ScriptInterface->SetProperty(settings.get(), "difficulty", m_Difficulty, false);
    250151                ENSURE(m_Worker.m_HasLoadedEntityTemplates);
    251                 m_ScriptInterface.SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false);
     152                m_ScriptInterface->SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false);
    252153
    253                 obj = m_ScriptInterface.CallConstructor(ctor.get(), settings.get());
     154                obj = m_ScriptInterface->CallConstructor(ctor.get(), settings.get());
    254155            }
    255156            else
    256157            {
    257158                // For deserialization, we want to create the object with the correct prototype
    258159                // but don't want to actually run the constructor again
    259160                // XXX: actually we don't currently use this path for deserialization - maybe delete it?
    260                 obj = m_ScriptInterface.NewObjectFromConstructor(ctor.get());
     161                obj = m_ScriptInterface->NewObjectFromConstructor(ctor.get());
    261162            }
    262163
    263164            if (obj.undefined())
     
    266167                return false;
    267168            }
    268169
    269             m_Obj = CScriptValRooted(m_ScriptInterface.GetContext(), obj);
     170            m_Obj = CScriptValRooted(m_ScriptInterface->GetContext(), obj);
    270171            return true;
    271172        }
    272173
    273         void Run(CScriptVal state)
     174        void Run(CScriptVal state, int playerID)
    274175        {
    275176            m_Commands.clear();
    276             m_ScriptInterface.CallFunctionVoid(m_Obj.get(), "HandleMessage", state);
     177            m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "HandleMessage", state, playerID);
    277178        }
    278179        // overloaded with a sharedAI part.
    279180        // javascript can handle both natively on the same function.
    280         void Run(CScriptVal state, CScriptValRooted SharedAI)
     181        void Run(CScriptVal state, int playerID, CScriptValRooted SharedAI)
    281182        {
    282183            m_Commands.clear();
    283             m_ScriptInterface.CallFunctionVoid(m_Obj.get(), "HandleMessage", state, SharedAI);
     184            m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "HandleMessage", state, playerID, SharedAI);
    284185        }
    285186        void InitAI(CScriptVal state, CScriptValRooted SharedAI)
    286187        {
    287188            m_Commands.clear();
    288             m_ScriptInterface.CallFunctionVoid(m_Obj.get(), "Init", state, SharedAI);
     189            m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "Init", state, m_Player, SharedAI);
    289190        }
    290191
    291192        CAIWorker& m_Worker;
     
    294195        uint8_t m_Difficulty;
    295196        bool m_UseSharedComponent;
    296197       
    297         ScriptInterface m_ScriptInterface;
     198        shared_ptr<ScriptInterface> m_ScriptInterface;
    298199        CScriptValRooted m_Obj;
    299200        std::vector<shared_ptr<ScriptInterface::StructuredClone> > m_Commands;
    300         std::set<std::wstring> m_LoadedModules;
    301201    };
    302202
    303203public:
     
    313213        // removed as soon whenever the new pathfinder is committed
    314214        // And the AIs can stop relying on their own little hands.
    315215        m_ScriptRuntime(ScriptInterface::CreateRuntime(33554432)),
    316         m_ScriptInterface("Engine", "AI", m_ScriptRuntime),
     216        m_ScriptInterface(new ScriptInterface("Engine", "AI", m_ScriptRuntime)),
    317217        m_TurnNum(0),
    318218        m_CommandsComputed(true),
    319219        m_HasLoadedEntityTemplates(false),
     
    321221    {
    322222
    323223        // TODO: ought to seed the RNG (in a network-synchronised way) before we use it
    324         m_ScriptInterface.ReplaceNondeterministicRNG(m_RNG);
    325         m_ScriptInterface.LoadGlobalScripts();
     224        m_ScriptInterface->ReplaceNondeterministicRNG(m_RNG);
     225        m_ScriptInterface->LoadGlobalScripts();
    326226
    327         m_ScriptInterface.SetCallbackData(NULL);
     227        m_ScriptInterface->SetCallbackData(static_cast<void*> (this));
    328228
    329         m_ScriptInterface.RegisterFunction<void, CScriptValRooted, CAIWorker::PostCommand>("PostCommand");
    330         m_ScriptInterface.RegisterFunction<void, CAIWorker::DumpHeap>("DumpHeap");
    331         m_ScriptInterface.RegisterFunction<void, CAIWorker::ForceGC>("ForceGC");
     229        m_ScriptInterface->RegisterFunction<void, int, CScriptValRooted, CAIWorker::PostCommand>("PostCommand");
     230        m_ScriptInterface->RegisterFunction<void, std::wstring, CAIWorker::IncludeModule>("IncludeModule");
     231        m_ScriptInterface->RegisterFunction<void, CAIWorker::DumpHeap>("DumpHeap");
     232        m_ScriptInterface->RegisterFunction<void, CAIWorker::ForceGC>("ForceGC");
    332233       
    333         m_ScriptInterface.RegisterFunction<void, std::wstring, std::vector<u32>, u32, u32, u32, CAIWorker::DumpImage>("DumpImage");
     234        m_ScriptInterface->RegisterFunction<void, std::wstring, std::vector<u32>, u32, u32, u32, CAIWorker::DumpImage>("DumpImage");
    334235    }
    335236
    336237    ~CAIWorker()
     
    343244        m_PassabilityMapVal = CScriptValRooted();
    344245        m_TerritoryMapVal = CScriptValRooted();
    345246    }
     247   
     248    bool LoadScripts(const std::wstring& moduleName)
     249    {
     250        // Ignore modules that are already loaded
     251        if (m_LoadedModules.find(moduleName) != m_LoadedModules.end())
     252            return true;
    346253
    347     // This is called by AIs if they use the v3 API.
    348     // If the AIs originate the call, cbdata is not NULL.
    349     // If the shared component does, it is, so it must not be taken into account.
    350     static void PostCommand(void* cbdata, CScriptValRooted cmd)
     254        // Mark this as loaded, to prevent it recursively loading itself
     255        m_LoadedModules.insert(moduleName);
     256
     257        // Load and execute *.js
     258        VfsPaths pathnames;
     259        vfs::GetPathnames(g_VFS, L"simulation/ai/" + moduleName + L"/", L"*.js", pathnames);
     260        for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
     261        {
     262            if (!m_ScriptInterface->LoadGlobalScriptFile(*it))
     263            {
     264                LOGERROR(L"Failed to load script %ls", it->string().c_str());
     265                return false;
     266            }
     267        }
     268
     269        return true;
     270    }
     271   
     272    static void IncludeModule(void* cbdata, std::wstring name)
    351273    {
    352         if (cbdata == NULL) {
    353             debug_warn(L"Warning: the shared component has tried to push an engine command. Ignoring.");
    354             return;
     274        CAIWorker* self = static_cast<CAIWorker*> (cbdata);
     275        self->LoadScripts(name);
     276    }
     277
     278    static void PostCommand(void* cbdata, int playerid, CScriptValRooted cmd)
     279    {
     280        CAIWorker* self = static_cast<CAIWorker*> (cbdata);
     281        self->PostCommand(playerid, cmd);
     282    }
     283   
     284    void PostCommand(int playerid, CScriptValRooted cmd)
     285    {
     286        bool playerFound = false;
     287        for (int i=0; i<m_Players.size(); i++)
     288        {
     289            if (m_Players[i]->m_Player == playerid)
     290            {
     291                m_Players[i]->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(cmd.get()));
     292                playerFound = true;
     293            }
    355294        }
    356         CAIPlayer* self = static_cast<CAIPlayer*> (cbdata);
    357         self->m_Commands.push_back(self->m_ScriptInterface.WriteStructuredClone(cmd.get()));
     295       
     296        if (!playerFound)
     297            LOGERROR(L"Invalid playerid in PostCommand!"); 
    358298    }
    359299    // The next two ought to be implmeneted someday but for now as it returns "null" it can't
    360300    static void DumpHeap(void* cbdata)
     
    364304            return;
    365305        }
    366306        CAIWorker* self = static_cast<CAIWorker*> (cbdata);
    367         self->m_ScriptInterface.DumpHeap();
     307        self->m_ScriptInterface->DumpHeap();
    368308    }
    369309    static void ForceGC(void* cbdata)
    370310    {
     
    374314        }
    375315        CAIWorker* self = static_cast<CAIWorker*> (cbdata);
    376316        PROFILE3("AI compute GC");
    377         JS_GC(self->m_ScriptInterface.GetContext());
     317        JS_GC(self->m_ScriptInterface->GetContext());
    378318    }
    379319   
    380320    /**
     
    424364       
    425365        // reset the value so it can be used to determine if we actually initialized it.
    426366        m_HasSharedComponent = false;
    427                
     367       
     368        if (LoadScripts(L"common-api-v3"))
     369            m_HasSharedComponent = true;
     370        else
     371            return false;
     372        /*     
    428373        VfsPaths sharedPathnames;
    429374        // Check for "shared" module.
    430375        vfs::GetPathnames(g_VFS, L"simulation/ai/common-api-v3/", L"*.js", sharedPathnames);
    431376        for (VfsPaths::iterator it = sharedPathnames.begin(); it != sharedPathnames.end(); ++it)
    432377        {
    433             if (!m_ScriptInterface.LoadGlobalScriptFile(*it))
     378            if (!m_ScriptInterface->LoadGlobalScriptFile(*it))
    434379            {
    435380                LOGERROR(L"Failed to load shared script %ls", it->string().c_str());
    436381                return false;
     
    439384        }
    440385        if (!m_HasSharedComponent)
    441386            return false;
    442        
     387        */
    443388        // mainly here for the error messages
    444389        OsPath path = L"simulation/ai/common-api-v2/";
    445390       
    446         // Constructor name is SharedScript
     391        // Constructor name is SharedScript, it's in the module API3
     392        // TODO: Hardcoding this bad, we need a smarter way.
     393        CScriptVal AIModule;
    447394        CScriptVal ctor;
    448         if (!m_ScriptInterface.GetProperty(m_ScriptInterface.GetGlobalObject(), "SharedScript", ctor)
     395        if (!m_ScriptInterface->GetProperty(m_ScriptInterface->GetGlobalObject(), "API3", AIModule) || AIModule.undefined())
     396        {
     397            LOGERROR(L"Failed to create shared AI component: %ls: can't find module '%hs'", path.string().c_str(), "API3");
     398            return false;
     399        }
     400       
     401        if (!m_ScriptInterface->GetProperty(AIModule.get(), "SharedScript", ctor)
    449402            || ctor.undefined())
    450403        {
    451404            LOGERROR(L"Failed to create shared AI component: %ls: can't find constructor '%hs'", path.string().c_str(), "SharedScript");
     
    454407       
    455408        // Set up the data to pass as the constructor argument
    456409        CScriptVal settings;
    457         m_ScriptInterface.Eval(L"({})", settings);
     410        m_ScriptInterface->Eval(L"({})", settings);
    458411        CScriptVal playersID;
    459         m_ScriptInterface.Eval(L"({})", playersID);
     412        m_ScriptInterface->Eval(L"({})", playersID);
    460413       
    461414        for (size_t i = 0; i < m_Players.size(); ++i)
    462415        {
    463             jsval val = m_ScriptInterface.ToJSVal(m_ScriptInterface.GetContext(), m_Players[i]->m_Player);
    464             m_ScriptInterface.SetPropertyInt(playersID.get(), i, CScriptVal(val), true);
     416            jsval val = m_ScriptInterface->ToJSVal(m_ScriptInterface->GetContext(), m_Players[i]->m_Player);
     417            m_ScriptInterface->SetPropertyInt(playersID.get(), i, CScriptVal(val), true);
    465418        }
    466419       
    467         m_ScriptInterface.SetProperty(settings.get(), "players", playersID);
     420        m_ScriptInterface->SetProperty(settings.get(), "players", playersID);
    468421        ENSURE(m_HasLoadedEntityTemplates);
    469         m_ScriptInterface.SetProperty(settings.get(), "templates", m_EntityTemplates, false);
     422        m_ScriptInterface->SetProperty(settings.get(), "templates", m_EntityTemplates, false);
    470423       
    471424        if (hasTechs)
    472425        {
    473             m_ScriptInterface.SetProperty(settings.get(), "techTemplates", m_TechTemplates, false);
     426            m_ScriptInterface->SetProperty(settings.get(), "techTemplates", m_TechTemplates, false);
    474427        }
    475428        else
    476429        {
    477430            // won't get the tech templates directly.
    478431            CScriptVal fakeTech;
    479             m_ScriptInterface.Eval("({})", fakeTech);
    480             m_ScriptInterface.SetProperty(settings.get(), "techTemplates", fakeTech, false);
     432            m_ScriptInterface->Eval("({})", fakeTech);
     433            m_ScriptInterface->SetProperty(settings.get(), "techTemplates", fakeTech, false);
    481434        }
    482         m_SharedAIObj = CScriptValRooted(m_ScriptInterface.GetContext(),m_ScriptInterface.CallConstructor(ctor.get(), settings.get()));
     435        m_SharedAIObj = CScriptValRooted(m_ScriptInterface->GetContext(),m_ScriptInterface->CallConstructor(ctor.get(), settings.get()));
    483436   
    484437       
    485438        if (m_SharedAIObj.undefined())
     
    493446
    494447    bool AddPlayer(const std::wstring& aiName, player_id_t player, uint8_t difficulty, bool callConstructor)
    495448    {
    496         shared_ptr<CAIPlayer> ai(new CAIPlayer(*this, aiName, player, difficulty, m_ScriptRuntime, m_RNG));
     449        shared_ptr<CAIPlayer> ai(new CAIPlayer(*this, aiName, player, difficulty, m_ScriptInterface));
    497450        if (!ai->Initialise(callConstructor))
    498451            return false;
    499452       
     
    501454        if (!m_HasSharedComponent)
    502455            m_HasSharedComponent = ai->m_UseSharedComponent;
    503456
    504         m_ScriptInterface.MaybeGC();
     457        m_ScriptInterface->MaybeGC();
    505458
    506459        m_Players.push_back(ai);
    507460
     
    513466        // this will be run last by InitGame.Js, passing the full game representation.
    514467        // For now it will run for the shared Component.
    515468        // This is NOT run during deserialization.
    516         CScriptVal state = m_ScriptInterface.ReadStructuredClone(gameState);
    517         JSContext* cx = m_ScriptInterface.GetContext();
     469        CScriptVal state = m_ScriptInterface->ReadStructuredClone(gameState);
     470        JSContext* cx = m_ScriptInterface->GetContext();
    518471
    519472        m_PassabilityMapVal = CScriptValRooted(cx, ScriptInterface::ToJSVal(cx, passabilityMap));
    520473        m_TerritoryMapVal = CScriptValRooted(cx, ScriptInterface::ToJSVal(cx, territoryMap));
    521474        if (m_HasSharedComponent)
    522475        {
    523             m_ScriptInterface.SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
    524             m_ScriptInterface.SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
     476            m_ScriptInterface->SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
     477            m_ScriptInterface->SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
    525478
    526             m_ScriptInterface.CallFunctionVoid(m_SharedAIObj.get(), "init", state);
    527             m_ScriptInterface.MaybeGC();
     479            m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "init", state);
     480            m_ScriptInterface->MaybeGC();
    528481           
    529482            for (size_t i = 0; i < m_Players.size(); ++i)
    530483            {
     
    545498        {
    546499            m_PassabilityMap = passabilityMap;
    547500
    548             JSContext* cx = m_ScriptInterface.GetContext();
     501            JSContext* cx = m_ScriptInterface->GetContext();
    549502            m_PassabilityMapVal = CScriptValRooted(cx, ScriptInterface::ToJSVal(cx, m_PassabilityMap));
    550503        }
    551504
     
    553506        {
    554507            m_TerritoryMap = territoryMap;
    555508
    556             JSContext* cx = m_ScriptInterface.GetContext();
     509            JSContext* cx = m_ScriptInterface->GetContext();
    557510            m_TerritoryMapVal = CScriptValRooted(cx, ScriptInterface::ToJSVal(cx, m_TerritoryMap));
    558511        }
    559512
     
    583536    }
    584537
    585538    void RegisterTechTemplates(const shared_ptr<ScriptInterface::StructuredClone>& techTemplates) {
    586         JSContext* cx = m_ScriptInterface.GetContext();
    587         m_TechTemplates = CScriptValRooted(cx, m_ScriptInterface.ReadStructuredClone(techTemplates));
     539        JSContext* cx = m_ScriptInterface->GetContext();
     540        m_TechTemplates = CScriptValRooted(cx, m_ScriptInterface->ReadStructuredClone(techTemplates));
    588541    }
    589542   
    590543    void LoadEntityTemplates(const std::vector<std::pair<std::string, const CParamNode*> >& templates)
    591544    {
    592545        m_HasLoadedEntityTemplates = true;
    593546
    594         m_ScriptInterface.Eval("({})", m_EntityTemplates);
     547        m_ScriptInterface->Eval("({})", m_EntityTemplates);
    595548
    596549        for (size_t i = 0; i < templates.size(); ++i)
    597550        {
    598             jsval val = templates[i].second->ToJSVal(m_ScriptInterface.GetContext(), false);
    599             m_ScriptInterface.SetProperty(m_EntityTemplates.get(), templates[i].first.c_str(), CScriptVal(val), true);
     551            jsval val = templates[i].second->ToJSVal(m_ScriptInterface->GetContext(), false);
     552            m_ScriptInterface->SetProperty(m_EntityTemplates.get(), templates[i].first.c_str(), CScriptVal(val), true);
    600553        }
    601554
    602555        // Since the template data is shared between AI players, freeze it
    603556        // to stop any of them changing it and confusing the other players
    604         m_ScriptInterface.FreezeObject(m_EntityTemplates.get(), true);
     557        m_ScriptInterface->FreezeObject(m_EntityTemplates.get(), true);
    605558    }
    606559
    607560    void Serialize(std::ostream& stream, bool isDebug)
     
    610563
    611564        if (isDebug)
    612565        {
    613             CDebugSerializer serializer(m_ScriptInterface, stream);
     566            CDebugSerializer serializer(*m_ScriptInterface, stream);
    614567            serializer.Indent(4);
    615568            SerializeState(serializer);
    616569        }
    617570        else
    618571        {
    619             CStdSerializer serializer(m_ScriptInterface, stream);
     572            CStdSerializer serializer(*m_ScriptInterface, stream);
    620573            // TODO: see comment in Deserialize()
    621574            serializer.SetSerializablePrototypes(m_SerializablePrototypes);
    622575            SerializeState(serializer);
     
    637590        if (m_HasSharedComponent)
    638591        {
    639592            CScriptVal sharedData;
    640             if (!m_ScriptInterface.CallFunction(m_SharedAIObj.get(), "Serialize", sharedData))
     593            if (!m_ScriptInterface->CallFunction(m_SharedAIObj.get(), "Serialize", sharedData))
    641594                LOGERROR(L"AI shared script Serialize call failed");
    642595            serializer.ScriptVal("sharedData", sharedData);
    643596        }
     
    650603            serializer.NumberU32_Unbounded("num commands", (u32)m_Players[i]->m_Commands.size());
    651604            for (size_t j = 0; j < m_Players[i]->m_Commands.size(); ++j)
    652605            {
    653                 CScriptVal val = m_ScriptInterface.ReadStructuredClone(m_Players[i]->m_Commands[j]);
     606                CScriptVal val = m_ScriptInterface->ReadStructuredClone(m_Players[i]->m_Commands[j]);
    654607                serializer.ScriptVal("command", val);
    655608            }
    656609
    657             bool hasCustomSerialize = m_ScriptInterface.HasProperty(m_Players[i]->m_Obj.get(), "Serialize");
     610            bool hasCustomSerialize = m_ScriptInterface->HasProperty(m_Players[i]->m_Obj.get(), "Serialize");
    658611            if (hasCustomSerialize)
    659612            {
    660613                CScriptVal scriptData;
    661                 if (!m_ScriptInterface.CallFunction(m_Players[i]->m_Obj.get(), "Serialize", scriptData))
     614                if (!m_ScriptInterface->CallFunction(m_Players[i]->m_Obj.get(), "Serialize", scriptData))
    662615                    LOGERROR(L"AI script Serialize call failed");
    663616                serializer.ScriptVal("data", scriptData);
    664617            }
     
    673626    {
    674627        ENSURE(m_CommandsComputed); // deserializing while we're still actively computing would be bad
    675628
    676         CStdDeserializer deserializer(m_ScriptInterface, stream);
     629        CStdDeserializer deserializer(*m_ScriptInterface, stream);
    677630
    678631        m_PlayerMetadata.clear();
    679632        m_Players.clear();
     
    695648        {
    696649            CScriptVal sharedData;
    697650            deserializer.ScriptVal("sharedData", sharedData);
    698             if (!m_ScriptInterface.CallFunctionVoid(m_SharedAIObj.get(), "Deserialize", sharedData))
     651            if (!m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "Deserialize", sharedData))
    699652                LOGERROR(L"AI shared script Deserialize call failed");
    700653        }
    701654
     
    717670            {
    718671                CScriptVal val;
    719672                deserializer.ScriptVal("command", val);
    720                 m_Players.back()->m_Commands.push_back(m_ScriptInterface.WriteStructuredClone(val.get()));
     673                m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val.get()));
    721674            }
    722675           
    723676            // TODO: this is yucky but necessary while the AIs are sharing data between contexts;
     
    726679            //  prototypes could be stored in their ScriptInterface
    727680            deserializer.SetSerializablePrototypes(m_DeserializablePrototypes);
    728681
    729             bool hasCustomDeserialize = m_ScriptInterface.HasProperty(m_Players.back()->m_Obj.get(), "Deserialize");
     682            bool hasCustomDeserialize = m_ScriptInterface->HasProperty(m_Players.back()->m_Obj.get(), "Deserialize");
    730683            if (hasCustomDeserialize)
    731684            {
    732685                CScriptVal scriptData;
    733686                deserializer.ScriptVal("data", scriptData);
    734687                if (m_Players[i]->m_UseSharedComponent)
    735688                {
    736                     if (!m_ScriptInterface.CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData, m_SharedAIObj))
     689                    if (!m_ScriptInterface->CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData, m_SharedAIObj))
    737690                        LOGERROR(L"AI script Deserialize call failed");
    738691                }
    739                 else if (!m_ScriptInterface.CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData))
     692                else if (!m_ScriptInterface->CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData))
    740693                {
    741694                    LOGERROR(L"AI script deserialize() call failed");
    742695                }
     
    770723        if (m_PlayerMetadata.find(path) == m_PlayerMetadata.end())
    771724        {
    772725            // Load and cache the AI player metadata
    773             m_PlayerMetadata[path] = m_ScriptInterface.ReadJSONFile(path);
     726            m_PlayerMetadata[path] = m_ScriptInterface->ReadJSONFile(path);
    774727        }
    775728
    776729        return m_PlayerMetadata[path];
     
    786739            if (m_TurnNum++ % 50 == 0)
    787740            {
    788741                PROFILE3("AI compute GC");
    789                 m_ScriptInterface.MaybeGC();
     742                m_ScriptInterface->MaybeGC();
    790743            }
    791744            return;
    792745        }
     
    795748        CScriptVal state;
    796749        {
    797750            PROFILE3("AI compute read state");
    798             state = m_ScriptInterface.ReadStructuredClone(m_GameState);
    799             m_ScriptInterface.SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
    800             m_ScriptInterface.SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
     751            state = m_ScriptInterface->ReadStructuredClone(m_GameState);
     752            m_ScriptInterface->SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
     753            m_ScriptInterface->SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
    801754        }
    802755
    803756        // It would be nice to do
    804         //   m_ScriptInterface.FreezeObject(state.get(), true);
     757        //   m_ScriptInterface->FreezeObject(state.get(), true);
    805758        // to prevent AI scripts accidentally modifying the state and
    806759        // affecting other AI scripts they share it with. But the performance
    807760        // cost is far too high, so we won't do that.
     
    810763        if (m_HasSharedComponent)
    811764        {
    812765            PROFILE3("AI run shared component");
    813             m_ScriptInterface.CallFunctionVoid(m_SharedAIObj.get(), "onUpdate", state);
     766            m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "onUpdate", state);
    814767        }
    815768       
    816769        for (size_t i = 0; i < m_Players.size(); ++i)
     
    818771            PROFILE3("AI script");
    819772            PROFILE2_ATTR("player: %d", m_Players[i]->m_Player);
    820773            PROFILE2_ATTR("script: %ls", m_Players[i]->m_AIName.c_str());
     774
    821775            if (m_HasSharedComponent && m_Players[i]->m_UseSharedComponent)
    822                 m_Players[i]->Run(state,m_SharedAIObj);
     776                m_Players[i]->Run(state, m_Players[i]->m_Player, m_SharedAIObj);
    823777            else
    824                 m_Players[i]->Run(state);
     778                m_Players[i]->Run(state, m_Players[i]->m_Player);
    825779        }
    826780
    827781        // Run GC if we are about to overflow
    828         if (JS_GetGCParameter(m_ScriptInterface.GetRuntime(), JSGC_BYTES) > 33000000)
     782        if (JS_GetGCParameter(m_ScriptInterface->GetRuntime(), JSGC_BYTES) > 33000000)
    829783        {
    830784            PROFILE3("AI compute GC");
    831785
    832             JS_GC(m_ScriptInterface.GetContext());
     786            JS_GC(m_ScriptInterface->GetContext());
    833787        }
    834788       
    835789        // Run the GC every so often.
     
    838792        /*if (m_TurnNum++ % 20 == 0)
    839793        {
    840794            PROFILE3("AI compute GC");
    841             m_ScriptInterface.MaybeGC();
     795            m_ScriptInterface->MaybeGC();
    842796        }*/
    843797    }
    844798
    845799    shared_ptr<ScriptRuntime> m_ScriptRuntime;
    846     ScriptInterface m_ScriptInterface;
     800    shared_ptr<ScriptInterface> m_ScriptInterface;
    847801    boost::rand48 m_RNG;
    848802    u32 m_TurnNum;
    849803
     
    858812    CScriptValRooted m_SharedAIObj;
    859813    std::vector<SCommandSets> m_Commands;
    860814   
     815    std::set<std::wstring> m_LoadedModules;
     816   
    861817    shared_ptr<ScriptInterface::StructuredClone> m_GameState;
    862818    Grid<u16> m_PassabilityMap;
    863819    CScriptValRooted m_PassabilityMapVal;