Ticket #2322: AI_in_one_global_WIP_v0.3.diff

File AI_in_one_global_WIP_v0.3.diff, 213.7 KB (added by Yves, 10 years ago)

This version of the patch moves common-api-v3 to a module using the module export pattern with Augmentation described here: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html

  • 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/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/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/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
  • 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/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/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/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/aegis/worker.js

     
    199199};
    200200
    201201Worker.prototype.startGathering = function(baseManager, gameState) {
     202
    202203    var resource = this.ent.getMetadata(PlayerID, "gather-type");
    203204    var ent = this.ent;
    204205    var self = this;
     
    245246                return;
    246247            if (dropsite.position() && (baseManager.dropsites[dropsite.id()][resource][4] > 1000 || (number === 1 && baseManager.dropsites[dropsite.id()][resource][4] > 200) )
    247248                && baseManager.dropsites[dropsite.id()][resource][5].length < maxPerDP) {
    248                 var dist = SquareVectorDistance(ent.position(), dropsite.position());
     249                var dist = API3.SquareVectorDistance(ent.position(), dropsite.position());
    249250                if (dist < minDropsiteDist){
    250251                    minDropsiteDist = dist;
    251252                    nearestResources = baseManager.dropsites[dropsite.id()][resource][1];
     
    254255            }
    255256        });
    256257    }
     258   
    257259    // we've found no fitting dropsites close enough from us.
    258260    // So'll try with far away.
    259261    if (!nearestResources || nearestResources.length === 0) {
     
    262264                return;
    263265            if (dropsite.position() && baseManager.dropsites[dropsite.id()][resource][4] > 400
    264266                && baseManager.dropsites[dropsite.id()][resource][5].length < maxPerDP) {
    265                 var dist = SquareVectorDistance(ent.position(), dropsite.position());
     267                var dist = API3.SquareVectorDistance(ent.position(), dropsite.position());
    266268                if (dist < minDropsiteDist){
    267269                    minDropsiteDist = dist;
    268270                    nearestResources = baseManager.dropsites[dropsite.id()][resource][1];
     
    271273            }
    272274        });
    273275    }
    274 
     276   
    275277    if (!nearestResources || nearestResources.length === 0){
    276278        if (resource === "food")
    277279            if (this.buildAnyField(gameState))
     
    353355        // some simple check for chickens: if they're in a square that's inaccessible, we won't gather from them.
    354356        if (supply.footprintRadius() < 1)
    355357        {
    356             var fakeMap = new Map(gameState.sharedScript,gameState.getMap().data);
     358            var fakeMap = new API3.Map(gameState.sharedScript,gameState.getMap().data);
    357359            var id = fakeMap.gamePosToMapPos(supply.position())[0] + fakeMap.width*fakeMap.gamePosToMapPos(supply.position())[1];
    358360            if ( (gameState.sharedScript.passabilityClasses["pathfinderObstruction"] & gameState.getMap().data[id]) )
    359361            {
     
    363365        }
    364366
    365367        // measure the distance to the resource (largely irrelevant)
    366          var dist = SquareVectorDistance(supply.position(), ent.position());
     368         var dist = API3.SquareVectorDistance(supply.position(), ent.position());
    367369                             
    368370        if (dist > 4900 && supply.hasClass("Animal"))
    369371        return;
    370372
    371373        // Add on a factor for the nearest dropsite if one exists
    372374        if (nearestDropsite !== undefined ){
    373             dist += 4*SquareVectorDistance(supply.position(), nearestDropsite.position());
     375            dist += 4*API3.SquareVectorDistance(supply.position(), nearestDropsite.position());
    374376            dist /= 5.0;
    375377        }
    376378                   
    377         var territoryOwner = Map.createTerritoryMap(gameState).getOwner(supply.position());
     379        var territoryOwner = API3.Map.createTerritoryMap(gameState).getOwner(supply.position());
    378380        if (territoryOwner != PlayerID && territoryOwner != 0) {
    379381            dist *= 5.0;
    380382            //return;
     
    395397        if (!nearestDropsite) {
    396398            ourDropsites.forEach(function (dropsite){ //}){
    397399                if (dropsite.position()){
    398                     var dist = SquareVectorDistance(pos, dropsite.position());
     400                    var dist = API3.SquareVectorDistance(pos, dropsite.position());
    399401                    if (dist < minDropsiteDist){
    400402                        minDropsiteDist = dist;
    401403                        nearestDropsite = dropsite;
     
    411413
    412414        // if the resource is far away, try to build a farm instead.
    413415        var tried = false;
    414         if (resource === "food" && SquareVectorDistance(pos,this.ent.position()) > 22500)
     416        if (resource === "food" && API3.SquareVectorDistance(pos,this.ent.position()) > 22500)
    415417        {
    416418            tried = this.buildAnyField(gameState);
    417             if (!tried && SquareVectorDistance(pos,this.ent.position()) > 62500) {
     419            if (!tried && API3.SquareVectorDistance(pos,this.ent.position()) > 62500) {
    418420                // TODO: ought to change behavior here.
    419421                return; // wait. a farm should appear.
    420422            }
     
    429431            else
    430432                gameState.turnCache["ressGathererNB"][nearestSupply.id()]++;
    431433           
    432             this.maxApproachTime = Math.max(30000, VectorDistance(pos,this.ent.position()) * 5000);
     434            this.maxApproachTime = Math.max(30000, API3.VectorDistance(pos,this.ent.position()) * 5000);
    433435            this.startApproachingResourceAmount = ent.resourceSupplyAmount();
    434436            this.startEnt = ent.id();
    435437            ent.gather(nearestSupply);
     
    472474    var dist = Math.min();
    473475    gameState.getOwnDropsites(resource).forEach(function(dropsite){
    474476        if (dropsite.position()){
    475             var d = SquareVectorDistance(self.ent.position(), dropsite.position());
     477            var d = API3.SquareVectorDistance(self.ent.position(), dropsite.position());
    476478            if (d < dist){
    477479                dist = d;
    478480                closestDropsite = dropsite;
     
    522524            return;
    523525                     
    524526        // measure the distance to the resource
    525         var dist = SquareVectorDistance(supply.position(), ent.position());
     527        var dist = API3.SquareVectorDistance(supply.position(), ent.position());
    526528
    527         var territoryOwner = Map.createTerritoryMap(gameState).getOwner(supply.position());
     529        var territoryOwner = API3.Map.createTerritoryMap(gameState).getOwner(supply.position());
    528530        if (territoryOwner != PlayerID && territoryOwner != 0) {
    529531            dist *= 3.0;
    530532        }
     
    547549        // find a fitting dropsites in case we haven't already.
    548550        gameState.getOwnDropsites("food").forEach(function (dropsite){ //}){
    549551            if (dropsite.position()){
    550                 var dist = SquareVectorDistance(pos, dropsite.position());
     552                var dist = API3.SquareVectorDistance(pos, dropsite.position());
    551553                if (dist < minDropsiteDist){
    552554                    minDropsiteDist = dist;
    553555                    nearestDropsite = dropsite;
     
    612614Worker.prototype.buildAnyField = function(gameState){
    613615    var self = this;
    614616    var okay = false;
    615     var foundations = gameState.getOwnFoundations().filter(Filters.byMetadata(PlayerID,"base",this.baseID));
     617    var foundations = gameState.getOwnFoundations().filter(API3.Filters.byMetadata(PlayerID,"base",this.baseID));
    616618    foundations.filterNearest(this.ent.position(), foundations.length);
    617619    foundations.forEach(function (found) {
    618620        if (found._template.BuildRestrictions.Category === "Field" && !okay) {
  • binaries/data/mods/public/simulation/ai/aegis/attack_plan.js

     
    66 * There is a basic support for naval expeditions here.
    77 */
    88
    9 function CityAttack(gameState, HQ, uniqueID, targetEnemy, type , targetFinder) {
     9function CityAttack(gameState, HQ, Config, uniqueID, targetEnemy, type , targetFinder) {
    1010   
     11    this.Config = Config;
    1112    //This is the list of IDs of the units in the plan
    1213    this.idList=[];
    1314   
     
    3334        return false;
    3435    }
    3536   
    36     var CCs = gameState.getOwnEntities().filter(Filters.byClass("CivCentre"));
     37    var CCs = gameState.getOwnEntities().filter(API3.Filters.byClass("CivCentre"));
    3738    if (CCs.length === 0)
    3839    {
    3940        this.failed = true;
     
    5051   
    5152    this.maxPreparationTime = 210*1000;
    5253    // 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)
     54    if (type !== "superSized" && this.Config.difficulty >= 1)
    5455        this.maxPreparationTime = 780000 - gameState.getTimeElapsed() < 120000 ? 120000 : 780000 - gameState.getTimeElapsed();
    5556   
    5657    this.pausingStart = 0;
     
    120121        return (strength[0] > 15 || strength[1] > 15);
    121122    };*/
    122123
    123     var filter = Filters.and(Filters.byMetadata(PlayerID, "plan",this.name),Filters.byOwner(PlayerID));
     124    var filter = API3.Filters.and(API3.Filters.byMetadata(PlayerID, "plan",this.name),API3.Filters.byOwner(PlayerID));
    124125    this.unitCollection = gameState.getOwnEntities().filter(filter);
    125126    this.unitCollection.registerUpdates();
    126127    this.unitCollection.length;
     
    136137        var cat = unitCat;
    137138        var Unit = this.unitStat[cat];
    138139
    139         filter = Filters.and(Filters.byClassesAnd(Unit["classes"]),Filters.and(Filters.byMetadata(PlayerID, "plan",this.name),Filters.byOwner(PlayerID)));
     140        filter = API3.Filters.and(API3.Filters.byClassesAnd(Unit["classes"]),API3.Filters.and(API3.Filters.byMetadata(PlayerID, "plan",this.name),API3.Filters.byOwner(PlayerID)));
    140141        this.unit[cat] = gameState.getOwnEntities().filter(filter);
    141142        this.unit[cat].registerUpdates();
    142143        this.unit[cat].length;
     
    186187    this.anyNotMinimal = true;  // used for support plans
    187188
    188189
    189     var myFortresses = gameState.getOwnTrainingFacilities().filter(Filters.byClass("GarrisonFortress"));
     190    var myFortresses = gameState.getOwnTrainingFacilities().filter(API3.Filters.byClass("GarrisonFortress"));
    190191    if (myFortresses.length !== 0)
    191192    {
    192193        // make this our rallypoint
     
    241242    //Engine.DumpHeap();
    242243   
    243244    // get a good path to an estimated target.
    244     this.pathFinder = new aStarPath(gameState,false,false, this.targetPlayer);
     245    this.pathFinder = new API3.aStarPath(gameState,false,false, this.targetPlayer);
    245246    //Engine.DumpImage("widthmap.png", this.pathFinder.widthMap, this.pathFinder.width,this.pathFinder.height,255);
    246247
    247248    this.pathWidth = 6; // prefer a path far from entities. This will avoid units getting stuck in trees and also results in less straight paths.
     
    316317        // no minsize as we don't want the plan to fail at the last minute though.
    317318        this.unitStat[name] = unitStats;
    318319        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)));
     320        var filter = API3.Filters.and(API3.Filters.byClassesAnd(Unit["classes"]),API3.Filters.and(API3.Filters.byMetadata(PlayerID, "plan",this.name),API3.Filters.byOwner(PlayerID)));
    320321        this.unit[name] = gameState.getOwnEntities().filter(filter);
    321322        this.unit[name].registerUpdates();
    322323        this.buildOrder.push([0, Unit["classes"], this.unit[name], Unit, name]);
     
    349350                for (var i in targets._entities)
    350351                {
    351352                    // we're sure it has a position has TargetFinder already checks that.
    352                     var dist = SquareVectorDistance(targets._entities[i].position(), this.rallyPoint);
     353                    var dist = API3.SquareVectorDistance(targets._entities[i].position(), this.rallyPoint);
    353354                    if (dist < maxDist || maxDist === -1)
    354355                    {
    355356                        maxDist = dist;
     
    400401            {
    401402                // my pathfinder returns arrays in arrays in arrays.
    402403                var waypointPos = this.path[i][0];
    403                 var territory = Map.createTerritoryMap(gameState);
     404                var territory = API3.Map.createTerritoryMap(gameState);
    404405                if (territory.getOwner(waypointPos) !== PlayerID || this.path[i][1] === true)
    405406                {
    406407                    // if we're suddenly out of our territory or this is the point where we change transportation method.
     
    426427            {
    427428                // my pathfinder returns arrays in arrays in arrays.
    428429                var waypointPos = this.path[i][0];
    429                 var territory = Map.createTerritoryMap(gameState);
     430                var territory = API3.Map.createTerritoryMap(gameState);
    430431                if (territory.getOwner(waypointPos) !== PlayerID || this.path[i][1] === true)
    431432                {
    432433                    // if we're suddenly out of our territory or this is the point where we change transportation method.
     
    650651    }
    651652    // no buildings, attack anything conquest critical, even units (it's assuming it won't move).
    652653    if (targets.length == 0) {
    653         targets = gameState.getEnemyEntities().filter(Filters.and( Filters.byOwner(this.targetPlayer),Filters.byClass("ConquestCritical")));
     654        targets = gameState.getEnemyEntities().filter(API3.Filters.and( API3.Filters.byOwner(this.targetPlayer),API3.Filters.byClass("ConquestCritical")));
    654655    }
    655656    return targets;
    656657};
     
    701702       
    702703        this.unitCollection.move(this.path[0][0][0], this.path[0][0][1]);
    703704        this.unitCollection.setStance("aggressive");
    704         this.unitCollection.filter(Filters.byClass("Siege")).setStance("defensive");
     705        this.unitCollection.filter(API3.Filters.byClass("Siege")).setStance("defensive");
    705706
    706707        this.state = "walking";
    707708    } else {
     
    750751
    751752                    if (attacker && attacker.position() && attacker.hasClass("Unit") && attacker.owner() != 0 && attacker.owner() != PlayerID) {
    752753                       
    753                         var territoryMap = Map.createTerritoryMap(gameState);
     754                        var territoryMap = API3.Map.createTerritoryMap(gameState);
    754755                        if ( +territoryMap.point(attacker.position()) - 64 === +this.targetPlayer)
    755756                        {
    756757                            attackedNB++;
     
    844845        }
    845846
    846847        // 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) {
     848        if (API3.SquareVectorDistance(this.position, this.position5TurnsAgo) < 10 && this.path.length > 0 && gameState.ai.playedTurn % 5 === 0) {
    848849            // check for stuck siege units
    849850           
    850             var sieges = this.unitCollection.filter(Filters.byClass("Siege"));
     851            var sieges = this.unitCollection.filter(API3.Filters.byClass("Siege"));
    851852            var farthest = 0;
    852853            var farthestEnt = -1;
    853854            sieges.forEach (function (ent) {
    854                 if (SquareVectorDistance(ent.position(),self.position) > farthest)
     855                if (API3.SquareVectorDistance(ent.position(),self.position) > farthest)
    855856                {
    856                     farthest = SquareVectorDistance(ent.position(),self.position);
     857                    farthest = API3.SquareVectorDistance(ent.position(),self.position);
    857858                    farthestEnt = ent;
    858859                }
    859860            });
     
    863864        if (gameState.ai.playedTurn % 5 === 0)
    864865            this.position5TurnsAgo = this.position;
    865866       
    866         if (this.lastPosition && SquareVectorDistance(this.position, this.lastPosition) < 20 && this.path.length > 0) {
     867        if (this.lastPosition && API3.SquareVectorDistance(this.position, this.lastPosition) < 20 && this.path.length > 0) {
    867868            this.unitCollection.moveIndiv(this.path[0][0][0], this.path[0][0][1]);
    868869            // 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")));
     870            var walls = gameState.getEnemyEntities().filter(API3.Filters.and(API3.Filters.byOwner(this.targetPlayer), API3.Filters.byClass("StoneWall")));
    870871            var nexttoWalls = false;
    871872            walls.forEach( function (ent) {
    872                 if (!nexttoWalls && SquareVectorDistance(self.position, ent.position()) < 800)
     873                if (!nexttoWalls && API3.SquareVectorDistance(self.position, ent.position()) < 800)
    873874                    nexttoWalls = true;
    874875            });
    875876            // there are walls but we can attack
    876             if (nexttoWalls && this.unitCollection.filter(Filters.byCanAttack("StoneWall")).length !== 0)
     877            if (nexttoWalls && this.unitCollection.filter(API3.Filters.byCanAttack("StoneWall")).length !== 0)
    877878            {
    878879                debug ("Attack Plan " +this.type +" " +this.name +" has met walls and is not happy.");
    879880                this.state = "arrived";
     
    886887        }
    887888       
    888889        // 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)
     890        if (API3.SquareVectorDistance(this.unitCollection.getCentrePosition(), this.targetPos) < 7500 ||
     891            API3.SquareVectorDistance(this.unitCollection.getCentrePosition(), this.path[0][0]) < 650) {
     892            if (this.unitCollection.filter(API3.Filters.byClass("Siege")).length !== 0
     893                && API3.SquareVectorDistance(this.unitCollection.getCentrePosition(), this.targetPos) >= 7500
     894                && API3.SquareVectorDistance(this.unitCollection.filter(API3.Filters.byClass("Siege")).getCentrePosition(), this.path[0][0]) >= 650)
    894895            {
    895896            } else {
    896897
     
    989990                    if (attacker && attacker.position() && attacker.hasClass("Unit") && attacker.owner() != 0 && attacker.owner() != PlayerID) {
    990991                        if (ourUnit.hasClass("Siege"))
    991992                        {
    992                             var collec = this.unitCollection.filterNearest(ourUnit.position(), 8).filter(Filters.not(Filters.byClass("Siege"))).toEntityArray();
     993                            var collec = this.unitCollection.filterNearest(ourUnit.position(), 8).filter(API3.Filters.not(API3.Filters.byClass("Siege"))).toEntityArray();
    993994                            if (collec.length !== 0)
    994995                            {
    995996                                collec[0].attack(attacker.id());
     
    10181019            this.unitCollUpdateArray = this.unitCollection.toIdArray();
    10191020        } else {
    10201021            // some stuffs for locality and speed
    1021             var territoryMap = Map.createTerritoryMap(gameState);
     1022            var territoryMap = API3.Map.createTerritoryMap(gameState);
    10221023            var timeElapsed = gameState.getTimeElapsed();
    10231024           
    10241025            // Let's check a few units each time we update. Currently 10
     
    10571058                        if (!enemy.position() || (enemy.hasClass("StoneWall") && ent.canAttackClass("StoneWall"))) {
    10581059                            return false;
    10591060                        }
    1060                         if (SquareVectorDistance(enemy.position(),ent.position()) > 3000) {
     1061                        if (API3.SquareVectorDistance(enemy.position(),ent.position()) > 3000) {
    10611062                            return false;
    10621063                        }
    10631064                        return true;
     
    10701071                            }
    10711072                            if (!enemy.hasClass("Support"))
    10721073                                return false;
    1073                             if (SquareVectorDistance(enemy.position(),ent.position()) > 10000) {
     1074                            if (API3.SquareVectorDistance(enemy.position(),ent.position()) > 10000) {
    10741075                                return false;
    10751076                            }
    10761077                            return true;
     
    10811082                            if (!enemy.position()) {
    10821083                                return false;
    10831084                            }
    1084                             if (SquareVectorDistance(enemy.position(),ent.position()) > 10000) {
     1085                            if (API3.SquareVectorDistance(enemy.position(),ent.position()) > 10000) {
    10851086                                return false;
    10861087                            }
    10871088                            return true;
     
    11201121                                ent.attack(mStruct[+rand].id());
    11211122                                //debug ("Siege units attacking a structure from " +mStruct[+rand].owner() + " , " +mStruct[+rand].templateName());
    11221123                            }
    1123                         } else if (SquareVectorDistance(self.targetPos, ent.position()) > 900 ){
     1124                        } else if (API3.SquareVectorDistance(self.targetPos, ent.position()) > 900 ){
    11241125                            //debug ("Siege units moving to " + uneval(self.targetPos));
    11251126                            ent.move(self.targetPos[0],self.targetPos[1]);
    11261127                        }
     
    11291130                            var rand = Math.floor(Math.random() * mUnit.length*0.99);
    11301131                            ent.attack(mUnit[(+rand)].id());
    11311132                            //debug ("Units attacking a unit from " +mUnit[+rand].owner() + " , " +mUnit[+rand].templateName());
    1132                         } else if (SquareVectorDistance(self.targetPos, ent.position()) > 900 ){
     1133                        } else if (API3.SquareVectorDistance(self.targetPos, ent.position()) > 900 ){
    11331134                            //debug ("Units moving to " + uneval(self.targetPos));
    11341135                            ent.move(self.targetPos[0],self.targetPos[1]);
    11351136                        } else if (mStruct.length !== 0) {
  • binaries/data/mods/public/simulation/ai/aegis/plan-transport.js

     
    1818var TransportPlan = function(gameState, units, destination, allAtOnce, escortSize, onlyIfOK) {
    1919    var self = this;
    2020
    21     this.ID = uniqueIDTPlans++;
     21    this.ID = playerGlobals[PlayerID].uniqueIDTPlans++;
    2222   
    2323    var unitsID = [];
    2424    if (units.length !== undefined)
     
    206206            var passabilityMap = gameState.getMap();
    207207            var territoryMap = gameState.ai.territoryMap;
    208208            var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction") | gameState.getPassabilityClassMask("building-shore");
    209             var obstructions = new Map(gameState.sharedScript);
     209            var obstructions = new API3.Map(gameState.sharedScript);
    210210           
    211211            // wanted map.
    212             var friendlyTiles = new Map(gameState.sharedScript);
     212            var friendlyTiles = new API3.Map(gameState.sharedScript);
    213213           
    214214            for (var j = 0; j < friendlyTiles.length; ++j)
    215215            {
     
    300300
    301301        // check if we need to move our units and ships closer together
    302302        var stillMoving = false;
    303         if (SquareVectorDistance(this.ships.getCentrePosition(),this.boardingSpot) > 1600)
     303        if (API3.SquareVectorDistance(this.ships.getCentrePosition(),this.boardingSpot) > 1600)
    304304        {
    305305            this.ships.move(this.boardingSpot[0],this.boardingSpot[1]);
    306306            stillMoving = true; // wait till ships are in position
    307307        }
    308         if (SquareVectorDistance(this.units.getCentrePosition(),this.boardingSpot) > 1600)
     308        if (API3.SquareVectorDistance(this.units.getCentrePosition(),this.boardingSpot) > 1600)
    309309        {
    310310            this.units.move(this.boardingSpot[0],this.boardingSpot[1]);
    311311            stillMoving = true; // wait till units are in position
     
    365365            var passabilityMap = gameState.getMap();
    366366            var territoryMap = gameState.ai.territoryMap;
    367367            var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction") | gameState.getPassabilityClassMask("building-shore");
    368             var obstructions = new Map(gameState.sharedScript);
     368            var obstructions = new API3.Map(gameState.sharedScript);
    369369           
    370370            // wanted map.
    371             var friendlyTiles = new Map(gameState.sharedScript);
     371            var friendlyTiles = new API3.Map(gameState.sharedScript);
    372372           
    373373            var wantedIndex = -1;
    374374           
     
    431431            return false;
    432432       
    433433        // check if we need to move ships
    434         if (SquareVectorDistance(this.ships.getCentrePosition(),this.unboardingSpot) > 400)
     434        if (API3.SquareVectorDistance(this.ships.getCentrePosition(),this.unboardingSpot) > 400)
    435435        {
    436436            this.ships.move(this.unboardingSpot[0],this.unboardingSpot[1]);
    437437        } else {
     
    447447            return false;
    448448       
    449449        // check if we need to move ships
    450         if (SquareVectorDistance(this.ships.getCentrePosition(),this.unboardingSpot) > 400)
     450        if (API3.SquareVectorDistance(this.ships.getCentrePosition(),this.unboardingSpot) > 400)
    451451        {
    452452            this.ships.move(this.unboardingSpot[0],this.unboardingSpot[1]);
    453453        } else {
  • binaries/data/mods/public/simulation/ai/aegis/aegis.js

     
    11// "local" global variables for stuffs that will need a unique ID
    22// 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.
     3var playerGlobals = [];
     4var g_debugEnabled = false;
    65
    76function AegisBot(settings) {
    8     BaseAI.call(this, settings);
     7    API3.BaseAI.call(this, settings);
    98
    10     Config.updateDifficulty(settings.difficulty);
     9    this.Config = new Config();
     10
     11    this.Config.updateDifficulty(settings.difficulty);
    1112   
    1213    this.turn = 0;
    1314
    1415    this.playedTurn = 0;
    15        
    16     this.priorities = Config.priorities;
     16   
     17    this.priorities = this.Config.priorities;
    1718
    1819    // this.queues can only be modified by the queue manager or things will go awry.
    1920    this.queues = {};
    2021    for (i in this.priorities)
    2122        this.queues[i] = new Queue();
    2223
    23     this.queueManager = new QueueManager(this.queues, this.priorities);
     24    this.queueManager = new QueueManager(this.Config, this.queues, this.priorities);
    2425
    25     this.HQ = new HQ();
     26    this.HQ = new HQ(this.Config);
    2627
    2728    this.firstTime = true;
    2829
     
    3233    this.defconChangeTime = -10000000;
    3334}
    3435
    35 AegisBot.prototype = new BaseAI();
     36AegisBot.prototype = new API3.BaseAI();
    3637
    3738AegisBot.prototype.CustomInit = function(gameState, sharedScript) {
    38    
     39
     40    playerGlobals[PlayerID] = {};
     41    playerGlobals[PlayerID].uniqueIDBOPlans = 0;    // training/building/research plans
     42    playerGlobals[PlayerID].uniqueIDBases = 1;  // base manager ID. Starts at one because "0" means "no base" on the map
     43    playerGlobals[PlayerID].uniqueIDTPlans = 1; // transport plans. starts at 1 because 0 might be used as none.   
     44
    3945    this.HQ.init(gameState,sharedScript.events,this.queues);
    40     debug ("Initialized with the difficulty " + Config.difficulty);
     46    debug ("Initialized with the difficulty " + this.Config.difficulty);
    4147
    42     var ents = gameState.getEntities().filter(Filters.byOwner(PlayerID));
     48    var ents = gameState.getEntities().filter(API3.Filters.byOwner(this.player));
    4349    var myKeyEntities = ents.filter(function(ent) {
    4450            return ent.hasClass("CivCentre");
    4551    });
    4652
    4753    if (myKeyEntities.length == 0){
    48         myKeyEntities = gameState.getEntities().filter(Filters.byOwner(PlayerID));
     54        myKeyEntities = gameState.getEntities().filter(API3.Filters.byOwner(this.player));
    4955    }
    5056   
    51     var filter = Filters.byClass("CivCentre");
    52     var enemyKeyEntities = gameState.getEntities().filter(Filters.not(Filters.byOwner(PlayerID))).filter(filter);
     57    var filter = API3.Filters.byClass("CivCentre");
     58    var enemyKeyEntities = gameState.getEntities().filter(API3.Filters.not(API3.Filters.byOwner(this.player))).filter(filter);
    5359   
    5460    if (enemyKeyEntities.length == 0){
    55         enemyKeyEntities = gameState.getEntities().filter(Filters.not(Filters.byOwner(PlayerID)));
     61        enemyKeyEntities = gameState.getEntities().filter(API3.Filters.not(API3.Filters.byOwner(this.player)));
    5662    }
    5763
    5864    this.myIndex = this.accessibility.getAccessValue(myKeyEntities.toEntityArray()[0].position());
    5965   
    60     this.pathFinder = new aStarPath(gameState, false, true);
     66    this.pathFinder = new API3.aStarPath(gameState, false, true);
    6167    this.pathsToMe = [];
    6268    this.pathInfo = { "angle" : 0, "needboat" : true, "mkeyPos" : myKeyEntities.toEntityArray()[0].position(), "ekeyPos" : enemyKeyEntities.toEntityArray()[0].position() };
    6369   
     
    6571    var pos = [this.pathInfo.mkeyPos[0] + 150*Math.cos(this.pathInfo.angle),this.pathInfo.mkeyPos[1] + 150*Math.sin(this.pathInfo.angle)];
    6672    var path = this.pathFinder.getPath(this.pathInfo.ekeyPos, pos, 2, 2);// uncomment for debug:*/, 300000, gameState);
    6773
    68     //Engine.DumpImage("initialPath" + PlayerID + ".png", this.pathFinder.TotorMap.map, this.pathFinder.TotorMap.width,this.pathFinder.TotorMap.height,255);
     74    //Engine.DumpImage("initialPath" + this.player + ".png", this.pathFinder.TotorMap.map, this.pathFinder.TotorMap.width,this.pathFinder.TotorMap.height,255);
    6975   
    7076    if (path !== undefined && path[1] !== undefined && path[1] == false) {
    7177        // path is viable and doesn't require boating.
     
    8187}
    8288
    8389AegisBot.prototype.OnUpdate = function(sharedScript) {
     90
    8491    if (this.gameFinished){
    8592        return;
    8693    }
     
    132139        var cityPhase = this.gameState.cityPhase();
    133140        // try going up phases.
    134141        // TODO: softcode this.
    135         if (this.gameState.canResearch(townPhase,true) && this.gameState.getTimeElapsed() > (Config.Economy.townPhase*1000) && this.gameState.getPopulation() > 40
     142        if (this.gameState.canResearch(townPhase,true) && this.gameState.getTimeElapsed() > (this.Config.Economy.townPhase*1000) && this.gameState.getPopulation() > 40
    136143            && this.gameState.findResearchers(townPhase,true).length != 0 && this.queues.majorTech.length() === 0
    137             && this.gameState.getOwnEntities().filter(Filters.byClass("Village")).length > 5)
     144            && this.gameState.getOwnEntities().filter(API3.Filters.byClass("Village")).length > 5)
    138145        {
    139146            this.queueManager.pauseQueue("villager", true);
    140147            this.queueManager.pauseQueue("citizenSoldier", true);
     
    142149            this.queues.majorTech.addItem(new ResearchPlan(this.gameState, townPhase,0,-1,true));   // we rush the town phase.
    143150            debug ("Trying to reach town phase");
    144151        }
    145         else if (this.gameState.canResearch(cityPhase,true) && this.gameState.getTimeElapsed() > (Config.Economy.cityPhase*1000)
     152        else if (this.gameState.canResearch(cityPhase,true) && this.gameState.getTimeElapsed() > (this.Config.Economy.cityPhase*1000)
    146153                && this.gameState.getOwnEntitiesByRole("worker").length > 85
    147154                && this.gameState.findResearchers(cityPhase, true).length != 0 && this.queues.majorTech.length() === 0) {
    148155            debug ("Trying to reach city phase");
     
    215222    // deactivated for now.
    216223    this.strategy = "normal";
    217224    // 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)
     225    if (!this.pathInfo.needboat && 0)//Math.random() < 0.2 && this.Config.difficulty == 2)
    219226    {
    220227        this.strategy = "rush";
    221228        // going to rush.
    222229        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.
     230        this.Config.Economy.townPhase = 480;
     231        this.Config.Economy.cityPhase = 900;
     232        this.Config.Economy.farmsteadStartTime = 600;
     233        this.Config.Economy.femaleRatio = 0;    // raise it since we'll want to rush age 2.
    227234    }
    228235};
    229236
     
    238245};*/
    239246
    240247function debug(output){
    241     if (Config.debug){
     248    if (g_debugEnabled){
    242249        if (typeof output === "string"){
    243250            warn(output);
    244251        }else{
  • binaries/data/mods/public/simulation/ai/aegis/queueplan-building.js

     
    44
    55    this.metadata = metadata;
    66
    7     this.ID = uniqueIDBOPlans++;
     7    this.ID = playerGlobals[PlayerID].uniqueIDBOPlans++;
    88
    99    this.template = gameState.getTemplate(this.type);
    1010    if (!this.template) {
     
    1212    }
    1313   
    1414    this.category = "building";
    15     this.cost = new Resources(this.template.cost());
     15    this.cost = new API3.Resources(this.template.cost());
    1616    this.number = 1; // The number of buildings to build
    1717   
    1818    if (!startTime)
     
    8181};
    8282
    8383ConstructionPlan.prototype.getCost = function() {
    84     var costs = new Resources();
     84    var costs = new API3.Resources();
    8585    costs.add(this.cost);
    8686    return costs;
    8787};
     
    9393
    9494    // First, find all tiles that are far enough away from obstructions:
    9595
    96     var obstructionMap = Map.createObstructionMap(gameState,0, template);
     96    var obstructionMap = API3.Map.createObstructionMap(gameState,0, template);
    9797   
    9898    //obstructionMap.dumpIm(template.buildCategory() + "_obstructions_pre.png");
    9999
     
    104104
    105105    // Compute each tile's closeness to friendly structures:
    106106
    107     var friendlyTiles = new Map(gameState.sharedScript);
     107    var friendlyTiles = new API3.Map(gameState.sharedScript);
    108108   
    109109    var alreadyHasHouses = false;
    110110
  • binaries/data/mods/public/simulation/ai/aegis/config.js

     
    1 // Baseconfig is the highest difficulty.
    2 var baseConfig = {
    3     "Military" : {
     1var Config = function() {
     2    this.debug = false; // 0 is sandbox, 1 is easy, 2 is medium, 3 is hard, 4 is very hard.
     3    this.difficulty = 2;    // overriden by the GUI
     4
     5    this.Military = {
    46        "fortressLapseTime" : 540, // Time to wait between building 2 fortresses
    57        "defenceBuildingTime" : 600, // Time to wait before building towers or fortresses
    68        "attackPlansStartTime" : 0, // time to wait before attacking. Start as soon as possible (first barracks)
     
    810        "popForBarracks1" : 15,
    911        "popForBarracks2" : 95,
    1012        "timeForBlacksmith" : 900,
    11     },
    12     "Economy" : {
     13    };
     14    this.Economy = {
    1315        "townPhase" : 180,  // time to start trying to reach town phase (might be a while after. Still need the requirements + ress )
    1416        "cityPhase" : 840,  // time to start trying to reach city phase
    1517        "popForMarket" : 80,
     
    1921        "targetNumBuilders" : 1.5, // Base number of builders per foundation.
    2022        "femaleRatio" : 0.4, // percent of females among the workforce.
    2123        "initialFields" : 2
    22     },
     24    };
    2325   
    2426    // Note: attack settings are set directly in attack_plan.js
    2527   
    2628    // defence
    27     "Defence" : {
     29    this.Defence =
     30    {
    2831        "defenceRatio" : 5, // see defence.js for more info.
    2932        "armyCompactSize" : 700,    // squared. Half-diameter of an army.
    3033        "armyBreakawaySize" : 900  // squared.
    31     },
     34    };
    3235   
    3336    // military
    34     "buildings" : {
     37    this.buildings =
     38    {
    3539        "moderate" : {
    3640            "default" : [ "structures/{civ}_barracks" ]
    3741        },
     
    5155            "default" : [ "structures/{civ}_fortress" ],
    5256            "celt" : [ "structures/{civ}_fortress_b", "structures/{civ}_fortress_g" ]
    5357        }
    54     },
     58    };
    5559
    5660    // qbot
    57     "priorities" : {  // Note these are dynamic, you are only setting the initial values
     61    this.priorities =
     62    {  // Note these are dynamic, you are only setting the initial values
    5863        "house" : 350,
    5964        "villager" : 40,
    6065        "citizenSoldier" : 60,
     
    6772        "majorTech" : 700,
    6873        "minorTech" : 50,
    6974        "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
     75    };
    7376};
    7477
    75 var Config = {
    76     "debug": false,
    77     "difficulty" : 2,   // overriden by the GUI
    78     updateDifficulty: function(difficulty)
     78//Config.prototype = new BaseConfig();
     79
     80Config.prototype.updateDifficulty = function(difficulty)
     81{
     82    this.difficulty = difficulty;
     83    // changing settings based on difficulty.
     84    if (this.difficulty === 1)
    7985    {
    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
     86        this.Military.defenceBuildingTime = 1200;
     87        this.Military.attackPlansStartTime = 960;
     88        this.Military.popForBarracks1 = 35;
     89        this.Military.popForBarracks2 = 150;    // shouldn't reach it
     90        this.Military.popForBlacksmith = 150;   // shouldn't reach it
    8991
    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
     92        this.Economy.cityPhase = 1800;
     93        this.Economy.popForMarket = 80;
     94        this.Economy.techStartTime = 600;
     95        this.Economy.femaleRatio = 0.6;
     96        this.Economy.initialFields = 1;
     97        // Config.Economy.targetNumWorkers will be set by AI scripts.
     98    }
     99    else if (this.difficulty === 0)
     100    {
     101        this.Military.defenceBuildingTime = 450;
     102        this.Military.attackPlansStartTime = 9600000;   // never
     103        this.Military.popForBarracks1 = 60;
     104        this.Military.popForBarracks2 = 150;    // shouldn't reach it
     105        this.Military.popForBlacksmith = 150;   // shouldn't reach it
    104106
    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         }
     107        this.Economy.cityPhase = 240000;
     108        this.Economy.popForMarket = 200;
     109        this.Economy.techStartTime = 1800;
     110        this.Economy.femaleRatio = 0.2;
     111        this.Economy.initialFields = 1;
     112        // Config.Economy.targetNumWorkers will be set by AI scripts.
    112113    }
    113114};
    114 
    115 Config.__proto__ = baseConfig;
  • binaries/data/mods/public/simulation/ai/aegis/queueplan-training.js

     
    22    this.type = gameState.applyCiv(type);
    33    this.metadata = metadata;
    44
    5     this.ID = uniqueIDBOPlans++;
     5    this.ID = playerGlobals[PlayerID].uniqueIDBOPlans++;
    66   
    77    this.template = gameState.getTemplate(this.type);
    88    if (!this.template)
    99        return false;
    1010
    1111    this.category = "unit";
    12     this.cost = new Resources(this.template.cost(), this.template._template.Cost.Population);
     12    this.cost = new API3.Resources(this.template.cost(), this.template._template.Cost.Population);
    1313    if (!number)
    1414        this.number = 1;
    1515    else
     
    7373};
    7474
    7575TrainingPlan.prototype.getCost = function(){
    76     var multCost = new Resources();
     76    var multCost = new API3.Resources();
    7777    multCost.add(this.cost);
    7878    multCost.multiply(this.number);
    7979    return multCost;
  • binaries/data/mods/public/simulation/ai/aegis/enemy-watcher.js

     
    1010   
    1111    // using global entity collections, shared by any AI that knows the name of this.
    1212   
    13     var filter = Filters.and(Filters.byClass("Structure"), Filters.byOwner(this.watched));
     13    var filter = API3.Filters.and(API3.Filters.byClass("Structure"), API3.Filters.byOwner(this.watched));
    1414    this.enemyBuildings = gameState.updatingGlobalCollection("player-" +this.watched + "-structures", filter);
    1515
    16     filter = Filters.and(Filters.byClass("Unit"), Filters.byOwner(this.watched));
     16    filter = API3.Filters.and(API3.Filters.byClass("Unit"), API3.Filters.byOwner(this.watched));
    1717    this.enemyUnits = gameState.updatingGlobalCollection("player-" +this.watched + "-units", filter);
    1818
    19     filter = Filters.and(Filters.byClass("Worker"), Filters.byOwner(this.watched));
     19    filter = API3.Filters.and(API3.Filters.byClass("Worker"), API3.Filters.byOwner(this.watched));
    2020    this.enemyCivilians = gameState.updatingGlobalCollection("player-" +this.watched + "-civilians", filter);
    2121                             
    22     filter = Filters.and(Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), Filters.byOwner(this.watched));
     22    filter = API3.Filters.and(API3.Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), API3.Filters.byOwner(this.watched));
    2323    this.enemySoldiers = gameState.updatingGlobalCollection("player-" +this.watched + "-soldiers", filter);
    2424   
    25     filter = Filters.and(Filters.byClass("Worker"), Filters.byOwner(this.watched));
     25    filter = API3.Filters.and(API3.Filters.byClass("Worker"), API3.Filters.byOwner(this.watched));
    2626    this.enemyCivilians = gameState.getEnemyEntities().filter(filter);
    2727    this.enemyCivilians.registerUpdates();
    2828
    29     filter = Filters.and(Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), Filters.byOwner(this.watched));
     29    filter = API3.Filters.and(API3.Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), API3.Filters.byOwner(this.watched));
    3030    this.enemySoldiers = gameState.getEnemyEntities().filter(filter);
    3131    this.enemySoldiers.registerUpdates();
    3232
     
    4848};
    4949
    5050enemyWatcher.prototype.getEnemyBuildings = function(gameState, specialClass, OneTime) {
    51     var filter = Filters.byClass(specialClass);
     51    var filter = API3.Filters.byClass(specialClass);
    5252   
    5353    if (OneTime && gameState.getGEC("player-" +this.watched + "-structures-" +specialClass))
    5454        return gameState.getGEC("player-" +this.watched + "-structures-" +specialClass);
     
    121121            var armyID = gameState.player + "" + self.totalNBofArmies;
    122122            self.totalNBofArmies++,
    123123            enemy.setMetadata(PlayerID, "EnemyWatcherArmy",armyID);
    124             var filter = Filters.byMetadata(PlayerID, "EnemyWatcherArmy",armyID);
     124            var filter = API3.Filters.byMetadata(PlayerID, "EnemyWatcherArmy",armyID);
    125125            var army = self.enemySoldiers.filter(filter);
    126126            self.armies[armyID] = army;
    127127            self.armies[armyID].registerUpdates();
     
    204204               
    205205                self.totalNBofArmies++,
    206206                enemy.setMetadata(PlayerID, "EnemyWatcherArmy",newArmyID);
    207                 var filter = Filters.byMetadata(PlayerID, "EnemyWatcherArmy",newArmyID);
     207                var filter = API3.Filters.byMetadata(PlayerID, "EnemyWatcherArmy",newArmyID);
    208208                var newArmy = self.enemySoldiers.filter(filter);
    209209                self.armies[newArmyID] = newArmy;
    210210                self.armies[newArmyID].registerUpdates();
  • binaries/data/mods/public/simulation/ai/aegis/entitycollection-extend.js

     
    66            ents[id] = gameState.entities._entities[id];
    77        }
    88    }
    9     return new EntityCollection(gameState.sharedScript, ents);
     9    return new API3.EntityCollection(gameState.sharedScript, ents);
    1010}
  • binaries/data/mods/public/simulation/ai/aegis/queue.js

     
    4343// returns the maximal account we'll accept for this queue.
    4444// Currently 100% of the cost of the first element and 80% of that of the second
    4545Queue.prototype.maxAccountWanted = function(gameState) {
    46     var cost = new Resources();
     46    var cost = new API3.Resources();
    4747    if (this.queue.length > 0 && this.queue[0].isGo(gameState))
    4848        cost.add(this.queue[0].getCost());
    4949    if (this.queue.length > 1 && this.queue[1].isGo(gameState))
     
    5656};
    5757
    5858Queue.prototype.queueCost = function(){
    59     var cost = new Resources();
     59    var cost = new API3.Resources();
    6060    for (var key in this.queue){
    6161        cost.add(this.queue[key].getCost());
    6262    }
  • binaries/data/mods/public/simulation/ai/aegis/headquarters.js

     
    1212    -picking new CC locations.
    1313 */
    1414
    15 var HQ = function() {
    16     this.targetNumBuilders = Config.Economy.targetNumBuilders; // number of workers we want building stuff
     15var HQ = function(Config) {
    1716   
    18     this.dockStartTime =  Config.Economy.dockStartTime * 1000;
    19     this.techStartTime = Config.Economy.techStartTime * 1000;
     17    this.Config = Config;
     18    this.targetNumBuilders = this.Config.Economy.targetNumBuilders; // number of workers we want building stuff
    2019   
     20    this.dockStartTime =  this.Config.Economy.dockStartTime * 1000;
     21    this.techStartTime = this.Config.Economy.techStartTime * 1000;
     22   
    2123    this.dockFailed = false;    // sanity check
    2224    this.waterMap = false;  // set by the aegis.js file.
    2325   
     
    2729    this.baseManagers = {};
    2830   
    2931    // 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;
     32    this.femaleRatio = this.Config.Economy.femaleRatio;
    3133   
    3234    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();
     35    this.fortressLapseTime = this.Config.Military.fortressLapseTime * 1000;
     36    this.defenceBuildingTime = this.Config.Military.defenceBuildingTime * 1000;
     37    this.attackPlansStartTime = this.Config.Military.attackPlansStartTime * 1000;
     38    this.defenceManager = new Defence(this.Config);
    3739   
    3840    this.navalManager = new NavalManager();
    3941   
     
    4547// More initialisation for stuff that needs the gameState
    4648HQ.prototype.init = function(gameState, events, queues){
    4749    // 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));
     50    this.basesMap = new API3.Map(gameState.sharedScript, new Uint8Array(gameState.getMap().data.length));
    4951    this.basesMap.setMaxVal(255);
    5052
    51     if (Config.Economy.targetNumWorkers)
    52         this.targetNumWorkers = Config.Economy.targetNumWorkers;
     53    if (this.Config.Economy.targetNumWorkers)
     54        this.targetNumWorkers = this.Config.Economy.targetNumWorkers;
    5355    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);
     56        this.targetNumWorkers = Math.max(Math.floor(gameState.getPopulationMax()*(0.2 + Math.min(+(this.Config.difficulty)*0.125,0.3))), 1);
    5557
    5658
    5759    // Let's get our initial situation here.
    5860    // TODO: improve on this.
    5961    // TODO: aknowledge bases, assign workers already.
    60     var ents = gameState.getEntities().filter(Filters.byOwner(PlayerID));
     62    var ents = gameState.getEntities().filter(API3.Filters.byOwner(PlayerID));
    6163   
    6264    var workersNB = 0;
    6365    var hasScout = false;
    6466    var treasureAmount = { 'food': 0, 'wood': 0, 'stone': 0, 'metal': 0 };
    6567    var hasCC = false;
    6668   
    67     if (ents.filter(Filters.byClass("CivCentre")).length > 0)
     69    if (ents.filter(API3.Filters.byClass("CivCentre")).length > 0)
    6870        hasCC = true;
    69     workersNB = ents.filter(Filters.byClass("Worker")).length;
    70     if (ents.filter(Filters.byClass("Cavalry")).length > 0)
     71    workersNB = ents.filter(API3.Filters.byClass("Worker")).length;
     72    if (ents.filter(API3.Filters.byClass("Cavalry")).length > 0)
    7173        hasScout = true;
    7274   
    7375    // tODO: take multiple CCs into account.
    7476    if (hasCC)
    7577    {
    76         var CC = ents.filter(Filters.byClass("CivCentre")).toEntityArray()[0];
     78        var CC = ents.filter(API3.Filters.byClass("CivCentre")).toEntityArray()[0];
    7779        for (i in treasureAmount)
    7880            gameState.getResourceSupplies(i).forEach( function (ent) {
    79                 if (ent.resourceSupplyType().generic === "treasure" && SquareVectorDistance(ent.position(), CC.position()) < 5000)
     81                if (ent.resourceSupplyType().generic === "treasure" && API3.SquareVectorDistance(ent.position(), CC.position()) < 5000)
    8082                    treasureAmount[i] += ent.resourceSupplyMax();
    8183            });
    82         this.baseManagers[1] = new BaseManager();
     84        this.baseManagers[1] = new BaseManager(this.Config);
    8385        this.baseManagers[1].init(gameState, events);
    8486        this.baseManagers[1].setAnchor(CC);
    8587        this.baseManagers[1].initTerritory(this, gameState);
    8688        this.baseManagers[1].initGatheringFunctions(this, gameState);
    8789       
    88         if (Config.debug)
     90        if (this.Config.debug)
    8991            this.basesMap.dumpIm("basesMap.png");
    9092        var self = this;
    9193
     
    111113        }
    112114    }
    113115   
    114     var map = new Map(gameState.sharedScript, gameState.sharedScript.CCResourceMaps["wood"].map);
    115     if (Config.debug)
     116    var map = new API3.Map(gameState.sharedScript, gameState.sharedScript.CCResourceMaps["wood"].map);
     117    if (this.Config.debug)
    116118        map.dumpIm("map_CC_Wood.png");
    117119   
    118120    //this.reassignIdleWorkers(gameState);
     
    125127   
    126128    // load units and buildings from the config files
    127129   
    128     if (civ in Config.buildings.moderate){
    129         this.bModerate = Config.buildings.moderate[civ];
     130    if (civ in this.Config.buildings.moderate){
     131        this.bModerate = this.Config.buildings.moderate[civ];
    130132    }else{
    131         this.bModerate = Config.buildings.moderate['default'];
     133        this.bModerate = this.Config.buildings.moderate['default'];
    132134    }
    133135   
    134     if (civ in Config.buildings.advanced){
    135         this.bAdvanced = Config.buildings.advanced[civ];
     136    if (civ in this.Config.buildings.advanced){
     137        this.bAdvanced = this.Config.buildings.advanced[civ];
    136138    }else{
    137         this.bAdvanced = Config.buildings.advanced['default'];
     139        this.bAdvanced = this.Config.buildings.advanced['default'];
    138140    }
    139141   
    140     if (civ in Config.buildings.fort){
    141         this.bFort = Config.buildings.fort[civ];
     142    if (civ in this.Config.buildings.fort){
     143        this.bFort = this.Config.buildings.fort[civ];
    142144    }else{
    143         this.bFort = Config.buildings.fort['default'];
     145        this.bFort = this.Config.buildings.fort['default'];
    144146    }
    145147   
    146148    for (var i in this.bAdvanced){
     
    156158    }
    157159   
    158160    var enemies = gameState.getEnemyEntities();
    159     var filter = Filters.byClassesOr(["CitizenSoldier", "Champion", "Hero", "Siege"]);
     161    var filter = API3.Filters.byClassesOr(["CitizenSoldier", "Champion", "Hero", "Siege"]);
    160162    this.enemySoldiers = enemies.filter(filter); // TODO: cope with diplomacy changes
    161163    this.enemySoldiers.registerUpdates();
    162164   
     
    193195                if (ent.isOwn(PlayerID) && ent.getMetadata(PlayerID, "base") === -1)
    194196                {
    195197                    // Okay so let's try to create a new base around this.
    196                     var bID = uniqueIDBases;
    197                     this.baseManagers[bID] = new BaseManager();
     198                    var bID = playerGlobals[PlayerID].uniqueIDBases;
     199                    this.baseManagers[bID] = new BaseManager(this.Config);
    198200                    this.baseManagers[bID].init(gameState, events, true);
    199201                    this.baseManagers[bID].setAnchor(ent);
    200202                    this.baseManagers[bID].initTerritory(this, gameState);
     
    411413// TODO: improve choice alogrithm
    412414HQ.prototype.switchWorkerBase = function(gameState, worker, type) {
    413415    var bestBase = 0;
     416
    414417    for (var i in this.baseManagers)
    415418    {
    416419        if (this.baseManagers[i].willGather[type] >= 1)
     
    545548    // Then checks for a good spot in the territory. If none, and town/city phase, checks outside
    546549    // The AI will currently not build a CC if it wouldn't connect with an existing CC.
    547550   
    548     var territory = Map.createTerritoryMap(gameState);
     551    var territory = API3.Map.createTerritoryMap(gameState);
    549552   
    550     var obstructions = Map.createObstructionMap(gameState, 0);
     553    var obstructions = API3.Map.createObstructionMap(gameState, 0);
    551554    obstructions.expandInfluences();
    552555
    553556    // copy the resource map as initialization.
    554     var friendlyTiles = new Map(gameState.sharedScript, gameState.sharedScript.CCResourceMaps[resource].map, true);
     557    var friendlyTiles = new API3.Map(gameState.sharedScript, gameState.sharedScript.CCResourceMaps[resource].map, true);
    555558    friendlyTiles.setMaxVal(255);
    556     var ents = gameState.getOwnEntities().filter(Filters.byClass("CivCentre")).toEntityArray();
    557     var eEnts = gameState.getEnemyEntities().filter(Filters.byClass("CivCentre")).toEntityArray();
     559    var ents = gameState.getOwnEntities().filter(API3.Filters.byClass("CivCentre")).toEntityArray();
     560    var eEnts = gameState.getEnemyEntities().filter(API3.Filters.byClass("CivCentre")).toEntityArray();
    558561
    559562    var dps = gameState.getOwnDropsites().toEntityArray();
    560563
     
    576579            var entPos = ents[i].position();
    577580            entPos = [entPos[0]/4.0,entPos[1]/4.0];
    578581           
    579             var dist = SquareVectorDistance(entPos, pos);
     582            var dist = API3.SquareVectorDistance(entPos, pos);
    580583            if (dist < 2120)
    581584            {
    582585                canBuild = false;
     
    598601                var entPos = eEnts[i].position();
    599602                entPos = [entPos[0]/4.0,entPos[1]/4.0];
    600603                // 7100 works well as a limit.
    601                 if (SquareVectorDistance(entPos, pos) < 2500)
     604                if (API3.SquareVectorDistance(entPos, pos) < 2500)
    602605                {
    603606                    canBuild = false;
    604607                    continue;
     
    620623                continue;
    621624            }
    622625            dpPos = [dpPos[0]/4.0,dpPos[1]/4.0];
    623             if (SquareVectorDistance(dpPos, pos) < 100)
     626            if (API3.SquareVectorDistance(dpPos, pos) < 100)
    624627            {
    625628                friendlyTiles.map[j] = 0;
    626629                continue;
    627             } else if (SquareVectorDistance(dpPos, pos) < 400)
     630            } else if (API3.SquareVectorDistance(dpPos, pos) < 400)
    628631                friendlyTiles.map[j] /= 2;
    629632        }
    630633
     
    645648    var best = friendlyTiles.findBestTile(6, obstructions);
    646649    var bestIdx = best[0];
    647650
    648     if (Config.debug)
     651    if (this.Config.debug)
    649652    {
    650653        friendlyTiles.map[bestIdx] = 270;
    651654        friendlyTiles.dumpIm("cc_placement_base_" + gameState.getTimeElapsed() + "_" + resource + "_" + best[1] + ".png",301);
     
    674677};
    675678
    676679HQ.prototype.buildMarket = function(gameState, queues){
    677     if (gameState.getPopulation() > Config.Economy.popForMarket && gameState.currentPhase() >= 2 ) {
     680    if (gameState.getPopulation() > this.Config.Economy.popForMarket && gameState.currentPhase() >= 2 ) {
    678681        if (queues.economicBuilding.countQueuedUnitsWithClass("BarterMarket") === 0 &&
    679682            gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_market")) === 0){
    680683            //only ever build one storehouse/CC/market at a time
     
    685688
    686689// Build a farmstead to go to town phase faster and prepare for research. Only really active on higher diff mode.
    687690HQ.prototype.buildFarmstead = function(gameState, queues){
    688     if (gameState.getPopulation() > Config.Economy.popForFarmstead) {
     691    if (gameState.getPopulation() > this.Config.Economy.popForFarmstead) {
    689692        // achtung: "DropsiteFood" does not refer to CCs.
    690693        if (queues.economicBuilding.countQueuedUnitsWithClass("DropsiteFood") === 0 &&
    691694            gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_farmstead")) === 0){
     
    752755        if (numPlanned < 3 || (numPlanned < 5 && gameState.getPopulation() > 80))
    753756        {
    754757            var plan = new ConstructionPlan(gameState, "structures/{civ}_house", { "base" : 1 });
     758            // make the difficulty available to the isGo function without having to pass it as argument
     759            var difficulty = this.Config.difficulty;
    755760            // change the starting condition to "less than 15 slots left".
    756761            plan.isGo = function (gameState) {
    757762                var HouseNb = gameState.countEntitiesByType(gameState.applyCiv("foundation|structures/{civ}_house"), true);
     
    761766                    freeSlots = gameState.getPopulationLimit() + HouseNb*5 - gameState.getPopulation();
    762767                else
    763768                    freeSlots = gameState.getPopulationLimit() + HouseNb*10 - gameState.getPopulation();
    764                 if (gameState.getPopulation() > 55 && Config.difficulty > 1)
     769                if (gameState.getPopulation() > 55 && difficulty > 1)
    765770                    return (freeSlots <= 21);
    766                 else if (gameState.getPopulation() >= 20 && Config.difficulty !== 0)
     771                else if (gameState.getPopulation() >= 20 && difficulty !== 0)
    767772                    return (freeSlots <= 16);
    768773                else
    769774                    return (freeSlots <= 10);
     
    781786    var capacity = { "wood" : 0, "stone" : 0, "metal" : 0 }
    782787    var need = { "wood" : true, "stone" : true, "metal" : true };
    783788    var posss = [];
     789
    784790    for (i in this.baseManagers)
    785791    {
    786792        var base = this.baseManagers[i];
    787793        for (type in count)
    788794        {
    789             if (base.getResourceLevel(gameState, type, "all") > 1500*Math.max(Config.difficulty,2))
     795            if (base.getResourceLevel(gameState, type, "all") > 1500*Math.max(this.Config.difficulty,2))
    790796                count[type]++;
    791797            capacity[type] += base.getWorkerCapacity(gameState, type);
    792798            if (base.willGather[type] !== 2)
     
    796802    for (type in count)
    797803    {
    798804        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)
     805            || capacity[type] < gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byMetadata(PlayerID, "subrole", "gatherer"), API3.Filters.byMetadata(PlayerID, "gather-type", type))).length * 1.05)
    800806        {
    801807            // plan a new base.
    802808            if (gameState.countFoundationsWithType(gameState.applyCiv("structures/{civ}_civil_centre")) === 0 && queues.civilCentre.length() === 0) {
     
    821827// TODO: Fortresses are placed randomly atm.
    822828HQ.prototype.buildDefences = function(gameState, queues){
    823829   
    824     var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(Filters.not(Filters.byHasMetadata(PlayerID,"plan"))).length;
     830    var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(API3.Filters.not(API3.Filters.byHasMetadata(PlayerID,"plan"))).length;
    825831   
    826832    if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv('structures/{civ}_defense_tower'))
    827833        + queues.defenceBuilding.length() < gameState.getEntityLimits()["DefenseTower"] && queues.defenceBuilding.length() < 4 && gameState.currentPhase() > 1) {
     
    878884};
    879885
    880886HQ.prototype.buildBlacksmith = function(gameState, queues){
    881     if (gameState.getTimeElapsed() > Config.Military.timeForBlacksmith*1000) {
     887    if (gameState.getTimeElapsed() > this.Config.Military.timeForBlacksmith*1000) {
    882888        if (queues.militaryBuilding.length() === 0 &&
    883889            gameState.countEntitiesAndQueuedByType(gameState.applyCiv("structures/{civ}_blacksmith")) === 0) {
    884890            var tp = gameState.getTemplate(gameState.applyCiv("structures/{civ}_blacksmith"));
     
    894900// TODO: building placement is bad. Choice of buildings is also fairly dumb.
    895901HQ.prototype.constructTrainingBuildings = function(gameState, queues) {
    896902    Engine.ProfileStart("Build buildings");
    897     var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(Filters.not(Filters.byHasMetadata(PlayerID, "plan"))).length;
     903    var workersNumber = gameState.getOwnEntitiesByRole("worker").filter(API3.Filters.not(API3.Filters.byHasMetadata(PlayerID, "plan"))).length;
    898904
    899     if (workersNumber > Config.Military.popForBarracks1) {
     905    if (workersNumber > this.Config.Military.popForBarracks1) {
    900906        if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) + queues.militaryBuilding.length() < 1) {
    901907            debug ("Trying to build barracks");
    902908            queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
    903909        }
    904910    }
    905911   
    906     if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 2 && workersNumber > Config.Military.popForBarracks2)
     912    if (gameState.countEntitiesAndQueuedByType(gameState.applyCiv(this.bModerate[0])) < 2 && workersNumber > this.Config.Military.popForBarracks2)
    907913        if (queues.militaryBuilding.length() < 1)
    908914            queues.militaryBuilding.addItem(new ConstructionPlan(gameState, this.bModerate[0], { "base" : 1 }));
    909915   
     
    917923            }
    918924        }
    919925    //build advanced military buildings
    920     if (workersNumber >= Config.Military.popForBarracks2 - 15 && gameState.currentPhase() > 2){
     926    if (workersNumber >= this.Config.Military.popForBarracks2 - 15 && gameState.currentPhase() > 2){
    921927        if (queues.militaryBuilding.length() === 0){
    922928            var inConst = 0;
    923929            for (var i in this.bAdvanced)
     
    950956
    951957// TODO: use pop(). Currently unused as this is too gameable.
    952958HQ.prototype.garrisonAllFemales = function(gameState) {
    953     var buildings = gameState.getOwnEntities().filter(Filters.byCanGarrison()).toEntityArray();
    954     var females = gameState.getOwnEntities().filter(Filters.byClass("Support"));
     959    var buildings = gameState.getOwnEntities().filter(API3.Filters.byCanGarrison()).toEntityArray();
     960    var females = gameState.getOwnEntities().filter(API3.Filters.byClass("Support"));
    955961   
    956962    var cache = {};
    957963   
     
    976982};
    977983HQ.prototype.ungarrisonAll = function(gameState) {
    978984    this.hasGarrisonedFemales = false;
    979     var buildings = gameState.getOwnEntities().filter(Filters.and(Filters.byClass("Structure"),Filters.byCanGarrison())).toEntityArray();
     985    var buildings = gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byClass("Structure"),API3.Filters.byCanGarrison())).toEntityArray();
    980986    buildings.forEach( function (struct) {
    981987        if (struct.garrisoned() && struct.garrisoned().length)
    982988            struct.unloadAll();
     
    10471053
    10481054// Some functions are run every turn
    10491055// Others once in a while
    1050 HQ.prototype.update = function(gameState, queues, events) {
     1056HQ.prototype.update = function(gameState, queues, events) { 
    10511057    Engine.ProfileStart("Headquarters update");
    10521058   
    10531059    this.checkEvents(gameState,events,queues);
     
    10571063    this.trainMoreWorkers(gameState, queues);
    10581064   
    10591065    // sandbox doesn't expand.
    1060     if (Config.difficulty !== 0)
     1066    if (this.Config.difficulty !== 0)
    10611067        this.checkBasesRessLevel(gameState, queues);
    10621068
    10631069    this.buildMoreHouses(gameState,queues);
     
    10651071    if (gameState.getTimeElapsed() > this.techStartTime && gameState.currentPhase() > 2)
    10661072        this.tryResearchTechs(gameState,queues);
    10671073   
    1068     if (Config.difficulty > 1)
     1074    if (this.Config.difficulty > 1)
    10691075        this.tryBartering(gameState);
    10701076   
    10711077    this.buildFarmstead(gameState, queues);
     
    10871093    for (i in this.baseManagers)
    10881094    {
    10891095        this.baseManagers[i].checkEvents(gameState, events, queues)
    1090         if ( ( (+i + gameState.ai.playedTurn) % (uniqueIDBases - 1)) === 0)
     1096        if ( ( (+i + gameState.ai.playedTurn) % (playerGlobals[PlayerID].uniqueIDBases - 1)) === 0)
    10911097            this.baseManagers[i].update(gameState, queues, events);
    10921098    }
    10931099
     
    11741180    if (gameState.ai.strategy === "rush" && this.startedAttacks["CityAttack"].length !== 0) {
    11751181        // and then we revert.
    11761182        gameState.ai.strategy = "normal";
    1177         Config.Economy.femaleRatio = 0.4;
     1183        this.Config.Economy.femaleRatio = 0.4;
    11781184        gameState.ai.modules.economy.targetNumWorkers = Math.max(Math.floor(gameState.getPopulationMax()*0.55), 1);
    11791185    } else if (gameState.ai.strategy === "rush" && this.upcomingAttacks["CityAttack"].length === 0)
    11801186    {
    1181         Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1, "rush")
     1187        Lalala = new CityAttack(gameState, this, this.Config, this.TotalAttackNumber, -1, "rush")
    11821188        this.TotalAttackNumber++;
    11831189        this.upcomingAttacks["CityAttack"].push(Lalala);
    11841190        debug ("Starting a little something");
     
    11931199            } else {
    11941200                // basically only the first plan, really.
    11951201                if (this.upcomingAttacks["CityAttack"].length == 0 && gameState.getTimeElapsed() < 12*60000) {
    1196                     var Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1);
     1202                    var Lalala = new CityAttack(gameState, this, this.Config, this.TotalAttackNumber, -1);
    11971203                    if (Lalala.failed)
    11981204                    {
    11991205                        this.attackPlansEncounteredWater = true; // hack
     
    12021208                        this.TotalAttackNumber++;
    12031209                        this.upcomingAttacks["CityAttack"].push(Lalala);
    12041210                    }
    1205                 } else if (this.upcomingAttacks["CityAttack"].length == 0 && Config.difficulty !== 0) {
    1206                     var Lalala = new CityAttack(gameState, this,this.TotalAttackNumber, -1, "superSized");
     1211                } else if (this.upcomingAttacks["CityAttack"].length == 0 && this.Config.difficulty !== 0) {
     1212                    var Lalala = new CityAttack(gameState, this, this.Config, this.TotalAttackNumber, -1, "superSized");
    12071213                    if (Lalala.failed)
    12081214                    {
    12091215                        this.attackPlansEncounteredWater = true; // hack
     
    12431249    this.buildDropsites(gameState, queues);
    12441250    Engine.ProfileStop();
    12451251
    1246     if (Config.difficulty !== 0)
     1252    if (this.Config.difficulty !== 0)
    12471253        this.tryBartering(gameState);
    12481254       
    12491255    this.buildFarmstead(gameState, queues);
  • binaries/data/mods/public/simulation/ai/aegis/queueplan-research.js

     
    11var ResearchPlan = function(gameState, type, startTime, expectedTime, rush) {
    22    this.type = type;
    33
    4     this.ID = uniqueIDBOPlans++;
     4    this.ID = playerGlobals[PlayerID].uniqueIDBOPlans++;
    55
    66    this.template = gameState.getTemplate(this.type);
    77    if (!this.template || this.template.researchTime === undefined) {
    88        return false;
    99    }
    1010    this.category = "technology";
    11     this.cost = new Resources(this.template.cost(),0);
     11    this.cost = new API3.Resources(this.template.cost(),0);
    1212    this.number = 1; // Obligatory for compatibility
    1313   
    1414    if (!startTime)
     
    6767};
    6868
    6969ResearchPlan.prototype.getCost = function(){
    70     var costs = new Resources();
     70    var costs = new API3.Resources();
    7171    costs.add(this.cost);
    7272    return costs;
    7373};
  • binaries/data/mods/public/simulation/ai/aegis/queue-manager.js

     
    1717//
    1818// This system should be improved. It's probably not flexible enough.
    1919
    20 var QueueManager = function(queues, priorities) {
     20var QueueManager = function(Config, queues, priorities) {
     21    this.Config = Config;
    2122    this.queues = queues;
    2223    this.priorities = priorities;
    2324    this.account = {};
     
    2829    this.queueArrays = [];
    2930    for (var p in this.queues) {
    3031        this.account[p] = 0;
    31         this.accounts[p] = new Resources();
     32        this.accounts[p] = new API3.Resources();
    3233        this.queueArrays.push([p,this.queues[p]]);
    3334    }
    3435    this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
     
    4748};
    4849
    4950QueueManager.prototype.getTotalAccountedResources = function(gameState) {
    50     var resources = new Resources();
     51    var resources = new API3.Resources();
    5152    for (var key in this.queues) {
    5253        resources.add(this.accounts[key]);
    5354    }
     
    5556};
    5657
    5758QueueManager.prototype.currentNeeds = function(gameState) {
    58     var needs = new Resources();
     59    var needs = new API3.Resources();
    5960    // get out current resources, not removing accounts.
    6061    var current = this.getAvailableResources(gameState, true);
    6162    //queueArrays because it's faster.
     
    8384};
    8485
    8586QueueManager.prototype.futureNeeds = function(gameState) {
    86     var needs = new Resources();
     87    var needs = new API3.Resources();
    8788    // get out current resources, not removing accounts.
    8889    var current = this.getAvailableResources(gameState, true);
    8990    //queueArrays because it's faster.
     
    143144                // estimate time based on priority + cost + nb
    144145                // TODO: work on this.
    145146                for (type in qCosts)
     147                {
    146148                    qCosts[type] += (cost[type] + Math.min(cost[type],this.priorities[name]));
     149                }
    147150                qTime += 30000;
    148151            } else {
    149152                // TODO: work on this.
     
    282285
    283286// nice readable HTML version.
    284287QueueManager.prototype.HTMLprintQueues = function(gameState){
    285     if (!Config.debug)
     288    if (!this.Config.debug)
    286289        return;
    287290    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> ");
    288291    for (var i in this.queues){
     
    457460        if (queue.length() > 0 && !queue.paused)
    458461        {
    459462            var item = queue.getNext();
    460             var total = new Resources();
     463            var total = new API3.Resources();
    461464            total.add(this.accounts[name]);
    462465            if (total.canAfford(item.getCost()))
    463466            {
     
    517520        this.queues[queueName] = new Queue();
    518521        this.priorities[queueName] = priority;
    519522        this.account[queueName] = 0;
    520         this.accounts[queueName] = new Resources();
     523        this.accounts[queueName] = new API3.Resources();
    521524
    522525        var self = this;
    523526        this.queueArrays = [];
    524527        for (var p in this.queues)
     528        {
    525529            this.queueArrays.push([p,this.queues[p]]);
     530        }
    526531        this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
    527532    }
    528533}
     
    539544        var self = this;
    540545        this.queueArrays = [];
    541546        for (var p in this.queues)
     547        {
    542548            this.queueArrays.push([p,this.queues[p]]);
     549        }
    543550        this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
    544551    }
    545552}
     
    548555    if (this.queues[queueName] !== undefined)
    549556        this.priorities[queueName] = newPriority;
    550557    this.queueArrays = [];
    551     for (var p in this.queues) {
     558    for (var p in this.queues)
     559    {
    552560        this.queueArrays.push([p,this.queues[p]]);
    553561    }
    554562    this.queueArrays.sort(function (a,b) { return (self.priorities[b[0]] - self.priorities[a[0]]) });
  • binaries/data/mods/public/simulation/ai/aegis/map-module.js

     
    11// other map functions
    22
    3 Map.createObstructionMap = function(gameState, accessIndex, template){
     3API3.Map.createObstructionMap = function(gameState, accessIndex, template){
    44    var passabilityMap = gameState.getMap();
    55    var territoryMap = gameState.ai.territoryMap;
    66   
     
    3131            for (var y = 0; y < passabilityMap.height; ++y)
    3232            {
    3333                var i = x + y*passabilityMap.width;
    34                 var tilePlayer = (territoryMap.data[i] & TERRITORY_PLAYER_MASK);
     34                var tilePlayer = (territoryMap.data[i] & 0x3F);
    3535               
    3636                if (gameState.ai.myIndex !== gameState.ai.accessibility.landPassMap[i])
    3737                {
     
    8888        var obstructionTiles = new Uint8Array(passabilityMap.data.length);
    8989        for (var i = 0; i < passabilityMap.data.length; ++i)
    9090        {
    91             var tilePlayer = (territoryMap.data[i] & TERRITORY_PLAYER_MASK);
     91            var tilePlayer = (territoryMap.data[i] & 0x3F);
    9292            var invalidTerritory = (
    9393                                    (!buildOwn && tilePlayer == playerID) ||
    9494                                    (!buildAlly && gameState.isPlayerAlly(tilePlayer) && tilePlayer != playerID) ||
     
    105105        }
    106106    }
    107107   
    108     var map = new Map(gameState.sharedScript, obstructionTiles);
     108    var map = new API3.Map(gameState.sharedScript, obstructionTiles);
    109109    map.setMaxVal(255);
    110110   
    111111    if (template && template.buildDistance()){
     
    127127
    128128
    129129
    130 Map.createTerritoryMap = function(gameState) {
     130API3.Map.createTerritoryMap = function(gameState) {
    131131    var map = gameState.ai.territoryMap;
    132132   
    133     var ret = new Map(gameState.sharedScript, map.data);
     133    var ret = new API3.Map(gameState.sharedScript, map.data);
    134134   
    135135    ret.getOwner = function(p) {
    136         return this.point(p) & TERRITORY_PLAYER_MASK;
     136        return this.point(p) & 0x3F;
    137137    }
    138138    ret.getOwnerIndex = function(p) {
    139         return this.map[p] & TERRITORY_PLAYER_MASK;
     139        return this.map[p] & 0x3F;
    140140    }
    141141    return ret;
    142142};
  • binaries/data/mods/public/simulation/ai/aegis/naval-manager.js

     
    3434// More initialisation for stuff that needs the gameState
    3535NavalManager.prototype.init = function(gameState, events, queues) {
    3636    // finished docks
    37     this.docks = gameState.getOwnEntities().filter(Filters.and(Filters.byClass("Dock"), Filters.not(Filters.isFoundation())));
     37    this.docks = gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byClass("Dock"), API3.Filters.not(API3.Filters.isFoundation())));
    3838    this.docks.allowQuickIter();
    3939    this.docks.registerUpdates();
    4040   
    41     this.ships = gameState.getOwnEntities().filter(Filters.byClass("Ship"));
     41    this.ships = gameState.getOwnEntities().filter(API3.Filters.byClass("Ship"));
    4242    // 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"));
     43    this.tpShips = this.ships.filter(API3.Filters.byCanGarrison());
     44    this.warships = this.ships.filter(API3.Filters.byClass("Warship"));
    4545
    4646    this.ships.registerUpdates();
    4747    this.tpShips.registerUpdates();
     
    5252        if (gameState.ai.accessibility.regionType[i] !== "water")
    5353        {
    5454            // 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));
     55            this.seaShips.push(new API3.EntityCollection(gameState.sharedScript));
     56            this.seaTpShips.push(new API3.EntityCollection(gameState.sharedScript));
     57            this.seaWarships.push(new API3.EntityCollection(gameState.sharedScript));
    5858            this.wantedTpShips.push(0);
    5959            this.wantedWarships.push(0);
    6060        } else {
    61             var collec = this.ships.filter(Filters.byStaticMetadata(PlayerID, "sea", i));
     61            var collec = this.ships.filter(API3.Filters.byStaticMetadata(PlayerID, "sea", i));
    6262            collec.registerUpdates();
    6363            this.seaShips.push(collec);
    64             collec = this.tpShips.filter(Filters.byStaticMetadata(PlayerID, "sea", i));
     64            collec = this.tpShips.filter(API3.Filters.byStaticMetadata(PlayerID, "sea", i));
    6565            collec.registerUpdates();
    6666            this.seaTpShips.push(collec);
    67             var collec = this.warships.filter(Filters.byStaticMetadata(PlayerID, "sea", i));
     67            var collec = this.warships.filter(API3.Filters.byStaticMetadata(PlayerID, "sea", i));
    6868            collec.registerUpdates();
    6969            this.seaWarships.push(collec);
    7070           
  • binaries/data/mods/public/simulation/ai/aegis/base-manager.js

     
    1010    -updating whatever needs updating, keeping track of stuffs (rebuilding needs…)
    1111 */
    1212
    13 var BaseManager = function() {
     13var BaseManager = function(Config) {
     14    this.Config = Config;
    1415    this.farmingFields = false;
    15     this.ID = uniqueIDBases++;
     16    this.ID = playerGlobals[PlayerID].uniqueIDBases++;
    1617   
    1718    // anchor building: seen as the main building of the base. Needs to have territorial influence
    1819    this.anchor = undefined;
     
    3435BaseManager.prototype.init = function(gameState, events, unconstructed){
    3536    this.constructing = unconstructed;
    3637    // 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)));
     38    this.units = gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byClass("Unit"),API3.Filters.byMetadata(PlayerID, "base", this.ID)));
     39    this.buildings = gameState.getOwnEntities().filter(API3.Filters.and(API3.Filters.byClass("Structure"),API3.Filters.byMetadata(PlayerID, "base", this.ID)));
    3940   
    40     this.workers = this.units.filter(Filters.byMetadata(PlayerID,"role","worker"));
     41    this.workers = this.units.filter(API3.Filters.byMetadata(PlayerID,"role","worker"));
    4142
    4243    this.workers.allowQuickIter();
    4344    this.buildings.allowQuickIter();
     
    136137        var type = types[i];
    137138        // TODO: set us as "X" gatherer
    138139       
    139         this.buildings.filter(Filters.isDropsite(type)).forEach(function(ent) { self.initializeDropsite(gameState, ent,type) });
     140        this.buildings.filter(API3.Filters.isDropsite(type)).forEach(function(ent) { self.initializeDropsite(gameState, ent,type) });
    140141
    141142        if (this.getResourceLevel(gameState, type, "all") > 1000)
    142143            this.willGather[type] = 1;
     
    249250        for (i in this.dropsites)
    250251        {
    251252            var dp = gameState.getEntityById(i);
    252             var distance = SquareVectorDistance(supply.position(), dp.position());
     253            var distance = API3.SquareVectorDistance(supply.position(), dp.position());
    253254            if (distance < dist && distance < this.bigRadius[type])
    254255            {
    255256                closest = dp.id();
     
    278279        resources.filter( function (supply) { //}){
    279280            if (!supply.position() || !ent.position())
    280281                return;
    281             var distance = SquareVectorDistance(supply.position(), ent.position());
     282            var distance = API3.SquareVectorDistance(supply.position(), ent.position());
    282283           
    283284            if (supply.getMetadata(PlayerID, "linked-dropsite") == undefined || supply.getMetadata(PlayerID, "linked-dropsite-dist") > distance) {
    284285                if (distance < self.bigRadius[type]) {
     
    294295            }
    295296        });
    296297        // This one is both for the nearby and the linked
    297         var filter = Filters.byMetadata(PlayerID, "linked-dropsite", ent.id());
     298        var filter = API3.Filters.byMetadata(PlayerID, "linked-dropsite", ent.id());
    298299        var collection = resources.filter(filter);
    299300        collection.registerUpdates();
    300301       
    301         filter = Filters.byMetadata(PlayerID, "linked-dropsite-close",true);
     302        filter = API3.Filters.byMetadata(PlayerID, "linked-dropsite-close",true);
    302303        var collection2 = collection.filter(filter);
    303304        collection2.registerUpdates();
    304305
    305         filter = Filters.byMetadata(PlayerID, "linked-dropsite-nearby",true);
     306        filter = API3.Filters.byMetadata(PlayerID, "linked-dropsite-nearby",true);
    306307        var collection3 = collection.filter(filter);
    307308        collection3.registerUpdates();
    308309
    309         filter = Filters.byMetadata(PlayerID, "linked-to-dropsite", ent.id());
     310        filter = API3.Filters.byMetadata(PlayerID, "linked-to-dropsite", ent.id());
    310311        var WkCollection = this.workers.filter(filter);
    311312        WkCollection.registerUpdates();
    312313       
     
    318319        // TODO: get workers on those resources and do something with them.
    319320    }
    320321   
    321     if (Config.debug)
     322    if (this.Config.debug)
    322323    {
    323324        // Make resources glow wildly
    324325        if (type == "food") {
    325326            self.dropsites[ent.id()][type][2].forEach(function(ent){
    326                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0.5,0,0]});
     327                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0.5,0,0]});
    327328            });
    328329            self.dropsites[ent.id()][type][1].forEach(function(ent){
    329                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [2,0,0]});
     330                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [2,0,0]});
    330331            });
    331332            self.dropsites[ent.id()][type][0].forEach(function(ent){
    332                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,0,0]});
     333                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,0,0]});
    333334            });
    334335        }
    335336        if (type == "wood") {
    336337            self.dropsites[ent.id()][type][2].forEach(function(ent){
    337                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0.5,0]});
     338                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0.5,0]});
    338339            });
    339340            self.dropsites[ent.id()][type][1].forEach(function(ent){
    340                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,2,0]});
     341                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,2,0]});
    341342            });
    342343            self.dropsites[ent.id()][type][0].forEach(function(ent){
    343                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,0]});
     344                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,0]});
    344345            });
    345346        }
    346347        if (type == "stone") {
    347348            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]});
     349                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0.5,0.5,0]});
    349350            });
    350351            self.dropsites[ent.id()][type][1].forEach(function(ent){
    351                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [2,2,0]});
     352                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [2,2,0]});
    352353            });
    353354            self.dropsites[ent.id()][type][0].forEach(function(ent){
    354                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,10,0]});
     355                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [10,10,0]});
    355356            });
    356357        }
    357358        if (type == "metal") {
    358359            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]});
     360                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,0.5,0.5]});
    360361            });
    361362            self.dropsites[ent.id()][type][1].forEach(function(ent){
    362                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,2,2]});
     363                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,2,2]});
    363364            });
    364365            self.dropsites[ent.id()][type][0].forEach(function(ent){
    365                 Engine.PostCommand({"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,10]});
     366                Engine.PostCommand(PlayerID,{"type": "set-shading-color", "entities": [ent.id()], "rgb": [0,10,10]});
    366367            });
    367368        }
    368369    }
     
    407408    // Then checks for a good spot in the territory. If none, and town/city phase, checks outside
    408409    // The AI will currently not build a CC if it wouldn't connect with an existing CC.
    409410   
    410     var territory = Map.createTerritoryMap(gameState);
     411    var territory = API3.Map.createTerritoryMap(gameState);
    411412   
    412     var obstructions = Map.createObstructionMap(gameState,this.accessIndex,storeHousePlate);
     413    var obstructions = API3.Map.createObstructionMap(gameState,this.accessIndex,storeHousePlate);
    413414    obstructions.expandInfluences();
    414415   
    415416    // copy the resource map as initialization.
    416     var friendlyTiles = new Map(gameState.sharedScript, gameState.sharedScript.resourceMaps[resource].map, true);
     417    var friendlyTiles = new API3.Map(gameState.sharedScript, gameState.sharedScript.resourceMaps[resource].map, true);
    417418
    418     var DPFoundations = gameState.getOwnFoundations().filter(Filters.byType(gameState.applyCiv("foundation|structures/{civ}_storehouse")));
     419    var DPFoundations = gameState.getOwnFoundations().filter(API3.Filters.byType(gameState.applyCiv("foundation|structures/{civ}_storehouse")));
    419420   
    420421    // TODO: might be better to check dropsites someplace else.
    421422    // loop over this in this.terrytoryindices. It's usually a little too much, but it's always enough.
     
    434435        {
    435436            var pos = [j%friendlyTiles.width, Math.floor(j/friendlyTiles.width)];
    436437            var dpPos = gameState.getEntityById(i).position();
    437             if (dpPos && SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 250)
     438            if (dpPos && API3.SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 250)
    438439            {
    439440                friendlyTiles.map[j] = 0;
    440441                continue;
    441             } else if (dpPos && SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 450)
     442            } else if (dpPos && API3.SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 450)
    442443                friendlyTiles.map[j] /= 2;
    443444        }
    444445        for (var i in DPFoundations._entities)
    445446        {
    446447            var pos = [j%friendlyTiles.width, Math.floor(j/friendlyTiles.width)];
    447448            var dpPos = gameState.getEntityById(i).position();
    448             if (dpPos && SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 250)
     449            if (dpPos && API3.SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 250)
    449450                friendlyTiles.map[j] = 0;
    450             else if (dpPos && SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 450)
     451            else if (dpPos && API3.SquareVectorDistance(friendlyTiles.gamePosToMapPos(dpPos), pos) < 450)
    451452                friendlyTiles.map[j] /= 2;
    452453        }
    453454    }
    454455   
    455     if (Config.debug)
     456    if (this.Config.debug)
    456457        friendlyTiles.dumpIm("DP_" + resource + "_" + gameState.getTimeElapsed() + ".png");
    457458   
    458459    var best = friendlyTiles.findBestTile(2, obstructions); // try to find a spot to place a DP.
     
    535536    if (searchType == "all")
    536537    {
    537538        // return all resources in the base area.
    538         gameState.getResourceSupplies(type).filter(Filters.byTerritory(gameState.ai.HQ.basesMap, this.ID)).forEach( function (ent) { //}){
     539        gameState.getResourceSupplies(type).filter(API3.Filters.byTerritory(gameState.ai.HQ.basesMap, this.ID)).forEach( function (ent) { //}){
    539540            count += ent.resourceSupplyAmount();
    540541        });
    541542        return count;
     
    589590            if (!this.isFarming && count < 1600 && queues.field.length === 0)
    590591            {
    591592                // tell the queue manager we'll be trying to build fields shortly.
    592                 for (var  i = 0; i < Config.Economy.initialFields;++i)
     593                for (var  i = 0; i < this.Config.Economy.initialFields;++i)
    593594                {
    594595                    var plan = new ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID });
    595596                    plan.isGo = function() { return false; };   // don't start right away.
     
    604605            if (this.isFarming)
    605606            {
    606607                var numFarms = 0;
    607                 this.buildings.filter(Filters.byClass("Field")).forEach(function (field) {
     608                this.buildings.filter(API3.Filters.byClass("Field")).forEach(function (field) {
    608609                    if (field.resourceSupplyAmount() > 400)
    609610                        numFarms++;
    610611                });
     
    646647
    647648BaseManager.prototype.assignRolelessUnits = function(gameState) {
    648649    // TODO: make this cleverer.
    649     var roleless = this.units.filter(Filters.not(Filters.byHasMetadata(PlayerID, "role")));
     650    var roleless = this.units.filter(API3.Filters.not(API3.Filters.byHasMetadata(PlayerID, "role")));
    650651    var self = this;
    651652    roleless.forEach(function(ent) {
    652653        if (ent.hasClass("Worker") || ent.hasClass("CitizenSoldier")) {
     
    702703    var self = this;
    703704
    704705    // 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")));
     706    var filter = API3.Filters.or(API3.Filters.byMetadata(PlayerID,"subrole","idle"), API3.Filters.not(API3.Filters.byHasMetadata(PlayerID,"subrole")));
    706707    var idleWorkers = gameState.updatingCollection("idle-workers-base-" + this.ID, filter, this.workers);
    707708
    708709    if (idleWorkers.length) {
     
    735736};
    736737
    737738BaseManager.prototype.workersBySubrole = function(gameState, subrole) {
    738     return gameState.updatingCollection("subrole-" + subrole +"-base-" + this.ID, Filters.byMetadata(PlayerID, "subrole", subrole), this.workers, true);
     739    return gameState.updatingCollection("subrole-" + subrole +"-base-" + this.ID, API3.Filters.byMetadata(PlayerID, "subrole", subrole), this.workers, true);
    739740};
    740741
    741742BaseManager.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"));
     743    return gameState.updatingCollection("workers-gathering-" + type +"-base-" + this.ID, API3.Filters.byMetadata(PlayerID, "gather-type", type), this.workersBySubrole(gameState, "gatherer"));
    743744};
    744745
    745746
    746747// returns an entity collection of workers.
    747748// They are idled immediatly and their subrole set to idle.
    748749BaseManager.prototype.pickBuilders = function(gameState, number) {
    749     var collec = new EntityCollection(gameState.sharedScript);
     750    var collec = new API3.EntityCollection(gameState.sharedScript);
    750751    // TODO: choose better.
    751     var workers = this.workers.filter(Filters.not(Filters.byClass("Cavalry"))).toEntityArray();
     752    var workers = this.workers.filter(API3.Filters.not(API3.Filters.byClass("Cavalry"))).toEntityArray();
    752753    workers.sort(function (a,b) {
    753754        var vala = 0, valb = 0;
    754755        if (a.getMetadata(PlayerID,"subrole") == "builder")
     
    771772}
    772773
    773774BaseManager.prototype.assignToFoundations = function(gameState, noRepair) {
     775
    774776    // If we have some foundations, and we don't have enough builder-workers,
    775777    // try reassigning some other workers who are nearby
    776778   
     
    778780   
    779781    var self = this;
    780782   
    781     var foundations = this.buildings.filter(Filters.and(Filters.isFoundation(),Filters.not(Filters.byClass("Field")))).toEntityArray();
     783    var foundations = this.buildings.filter(API3.Filters.and(API3.Filters.isFoundation(),API3.Filters.not(API3.Filters.byClass("Field")))).toEntityArray();
    782784    var damagedBuildings = this.buildings.filter(function (ent) { if (ent.needsRepair() && ent.getMetadata(PlayerID, "plan") == undefined) { return true; } return false; }).toEntityArray();
    783785   
    784786    // Check if nothing to build
    785787    if (!foundations.length && !damagedBuildings.length){
    786788        return;
    787789    }
    788     var workers = this.workers.filter(Filters.not(Filters.byClass("Cavalry")));
     790    var workers = this.workers.filter(API3.Filters.not(API3.Filters.byClass("Cavalry")));
    789791    var builderWorkers = this.workersBySubrole(gameState, "builder");
    790     var idleBuilderWorkers = this.workersBySubrole(gameState, "builder").filter(Filters.isIdle());
     792    var idleBuilderWorkers = this.workersBySubrole(gameState, "builder").filter(API3.Filters.isIdle());
    791793
    792794    // 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)
     795    if (this.constructing == true && this.buildings.filter(API3.Filters.and(API3.Filters.isFoundation(), API3.Filters.byMetadata(PlayerID, "baseAnchor", true))).length !== 0)
    794796    {
    795         foundations = this.buildings.filter(Filters.byMetadata(PlayerID, "baseAnchor", true)).toEntityArray();
     797        foundations = this.buildings.filter(API3.Filters.byMetadata(PlayerID, "baseAnchor", true)).toEntityArray();
    796798        var tID = foundations[0].id();
    797799        workers.forEach(function (ent) { //}){
    798800            var target = ent.getMetadata(PlayerID, "target-foundation");
     
    832834       
    833835        var assigned = gameState.getOwnEntitiesByMetadata("target-foundation", target.id()).length;
    834836
    835         var targetNB = Config.Economy.targetNumBuilders;    // TODO: dynamic that.
     837        var targetNB = this.Config.Economy.targetNumBuilders;   // TODO: dynamic that.
    836838        if (target.hasClass("CivCentre") || target.buildTime() > 150 || target.hasClass("House"))
    837839            targetNB *= 2;
    838840        if (target.getMetadata(PlayerID, "baseAnchor") == true)
     
    844846                var addedToThis = 0;
    845847               
    846848                idleBuilderWorkers.forEach(function(ent) {
    847                     if (ent.position() && SquareVectorDistance(ent.position(), target.position()) < 10000 && assigned + addedToThis < targetNB)
     849                    if (ent.position() && API3.SquareVectorDistance(ent.position(), target.position()) < 10000 && assigned + addedToThis < targetNB)
    848850                    {
    849851                        addedWorkers++;
    850852                        addedToThis++;
     
    876878        } else if (noRepair && !target.hasClass("CivCentre"))
    877879            continue;
    878880       
    879         var territory = Map.createTerritoryMap(gameState);
     881        var territory = API3.Map.createTerritoryMap(gameState);
    880882        if (territory.getOwner(target.position()) !== PlayerID || territory.getOwner([target.position()[0] + 5, target.position()[1]]) !== PlayerID)
    881883            continue;
    882884       
  • binaries/data/mods/public/simulation/ai/aegis/defence.js

     
    11// directly imported from Marilyn, with slight modifications to work with qBot.
    22
    3 function Defence(){
     3function Defence(Config){
    44    this.defenceRatio = Config.Defence.defenceRatio;// How many defenders we want per attacker.  Need to balance fewer losses vs. lost economy
    55                            // note: the choice should be a no-brainer most of the time: better deflect the attack.
    66                            // This is also sometimes forcebly overcome by the defense manager.
     
    5454   
    5555    // a litlle cache-ing
    5656    if (!this.idleDefs) {
    57         var filter = Filters.and(Filters.byMetadata(PlayerID, "role", "defence"), Filters.isIdle());
     57        var filter = API3.Filters.and(API3.Filters.byMetadata(PlayerID, "role", "defence"), API3.Filters.isIdle());
    5858        this.idleDefs = gameState.getOwnEntities().filter(filter);
    5959        this.idleDefs.registerUpdates();
    6060    }
    6161    if (!this.defenders) {
    62         var filter = Filters.byMetadata(PlayerID, "role", "defence");
     62        var filter = API3.Filters.byMetadata(PlayerID, "role", "defence");
    6363        this.defenders = gameState.getOwnEntities().filter(filter);
    6464        this.defenders.registerUpdates();
    6565    }
    6666    /*if (!this.listedEnemyCollection) {
    67         var filter = Filters.byMetadata(PlayerID, "listed-enemy", true);
     67        var filter = API3.Filters.byMetadata(PlayerID, "listed-enemy", true);
    6868        this.listedEnemyCollection = gameState.getEnemyEntities().filter(filter);
    6969        this.listedEnemyCollection.registerUpdates();
    7070    }
    71     this.myBuildings = gameState.getOwnEntities().filter(Filters.byClass("Structure")).toEntityArray();
    72     this.myUnits = gameState.getOwnEntities().filter(Filters.byClass("Unit"));
     71    this.myBuildings = gameState.getOwnEntities().filter(API3.Filters.byClass("Structure")).toEntityArray();
     72    this.myUnits = gameState.getOwnEntities().filter(API3.Filters.byClass("Unit"));
    7373    */
    74     var filter = Filters.and(Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), Filters.byOwner(PlayerID));
     74    var filter = API3.Filters.and(API3.Filters.byClassesOr(["CitizenSoldier", "Hero", "Champion", "Siege"]), API3.Filters.byOwner(PlayerID));
    7575    this.myUnits = gameState.updatingGlobalCollection("player-" +PlayerID + "-soldiers", filter);
    7676   
    77     filter = Filters.and(Filters.byClass("Structure"), Filters.byOwner(PlayerID));
     77    filter = API3.Filters.and(API3.Filters.byClass("Structure"), API3.Filters.byOwner(PlayerID));
    7878    this.myBuildings = gameState.updatingGlobalCollection("player-" +PlayerID + "-structures", filter);
    7979
    80     this.territoryMap = Map.createTerritoryMap(gameState);  // used by many func
     80    this.territoryMap = API3.Map.createTerritoryMap(gameState); // used by many func
    8181
    8282    // First step: we deal with enemy armies, those are the highest priority.
    8383    this.defendFromEnemies(gameState, events, HQ);
     
    151151            if (army.getCentrePosition() === undefined)
    152152            {
    153153            } else {
    154                 if (SquareVectorDistance(army.getCentrePosition(), entity.position()) < this.armyCompactSize)
     154                if (API3.SquareVectorDistance(army.getCentrePosition(), entity.position()) < this.armyCompactSize)
    155155                {
    156156                    entity.setMetadata(PlayerID, "inArmy", armyIndex);
    157157                    army.addEnt(entity);
     
    163163    if (HQ)
    164164    {
    165165        var self = this;
    166         var close = HQ.enemyWatchers[entity.owner()].enemySoldiers.filter(Filters.byDistance(entity.position(), self.armyCompactSize));
     166        var close = HQ.enemyWatchers[entity.owner()].enemySoldiers.filter(API3.Filters.byDistance(entity.position(), self.armyCompactSize));
    167167        if (!minNBForArmy || close.length >= minNBForArmy)
    168168        {
    169169            // 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())]);
     170            var newArmy = new API3.EntityCollection(gameState.sharedScript, {}, [API3.Filters.byOwner(entity.owner())]);
    171171            newArmy.addEnt(entity);
    172172            newArmy.freeze();
    173173            newArmy.registerUpdates();
     
    184184        }
    185185    } else {
    186186        // 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())]);
     187        var newArmy = new API3.EntityCollection(gameState.sharedScript, {}, [API3.Filters.byOwner(entity.owner())]);
    188188        newArmy.addEnt(entity);
    189189        newArmy.freeze();
    190190        newArmy.registerUpdates();
     
    210210    {
    211211        if (!this.myBuildings._entities[i].hasClass("ConquestCritical"))
    212212            continue;
    213         if (SquareVectorDistance(this.myBuildings._entities[i].position(), entity.position()) < 6000)
     213        if (API3.SquareVectorDistance(this.myBuildings._entities[i].position(), entity.position()) < 6000)
    214214            return true;
    215215    }
    216216    return false;
     
    313313            } else {
    314314                army.forEach(function (ent) { //}){
    315315                    // check if the unit is a breakaway
    316                     if (ent.position() && SquareVectorDistance(position, ent.position()) > self.armyBreakawaySize)
     316                    if (ent.position() && API3.SquareVectorDistance(position, ent.position()) > self.armyBreakawaySize)
    317317                    {
    318318                        ent.setMetadata(PlayerID, "inArmy", undefined);
    319319                        army.removeEnt(ent);
     
    322322                    } else {
    323323                        // check if we have registered that unit already.
    324324                        if (self.listOfEnemies[ent.id()] === undefined) {
    325                             self.listOfEnemies[ent.id()] = new EntityCollection(gameState.sharedScript, {}, [Filters.byOwner(ent.owner())]);
     325                            self.listOfEnemies[ent.id()] = new API3.EntityCollection(gameState.sharedScript, {}, [API3.Filters.byOwner(ent.owner())]);
    326326                            self.listOfEnemies[ent.id()].freeze();
    327327                            self.listOfEnemies[ent.id()].addEnt(ent);
    328328                            self.listOfEnemies[ent.id()].registerUpdates();
    329329                           
    330                             self.attackerCache[ent.id()] = self.myUnits.filter(Filters.byTargetedEntity(ent.id()));
     330                            self.attackerCache[ent.id()] = self.myUnits.filter(API3.Filters.byTargetedEntity(ent.id()));
    331331                            self.attackerCache[ent.id()].registerUpdates();
    332332                            nbOfAttackers++;
    333333                            self.nbAttackers++;
     
    373373   
    374374    if (this.nbAttackers === 0 && this.nbDefenders === 0) {
    375375        // Release all our units
    376         this.myUnits.filter(Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
     376        this.myUnits.filter(API3.Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
    377377            defender.stopMoving();
    378378            if (defender.getMetadata(PlayerID, "formerrole"))
    379379                defender.setMetadata(PlayerID, "role", defender.getMetadata(PlayerID, "formerrole") );
     
    387387        return;
    388388    } else if (this.nbAttackers === 0 && this.nbDefenders !== 0) {
    389389        // Release all our units
    390         this.myUnits.filter(Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
     390        this.myUnits.filter(API3.Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
    391391            defender.stopMoving();
    392392            if (defender.getMetadata(PlayerID, "formerrole"))
    393393                defender.setMetadata(PlayerID, "role", defender.getMetadata(PlayerID, "formerrole") );
     
    419419    }
    420420   
    421421    // 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) { //}){
     422    if (this.myUnits.filter(API3.Filters.byMetadata(PlayerID, "role","defence")).length > nbOfAttackers*this.defenceRatio*1.2) {
     423        this.myUnits.filter(API3.Filters.byMetadata(PlayerID, "role","defence")).forEach(function (defender) { //}){
    424424            if ( defender.isIdle() || (defender.unitAIOrderData() && defender.unitAIOrderData()["target"])) {
    425425                if ( defender.isIdle() || (self.attackerCache[defender.unitAIOrderData()["target"]] && self.attackerCache[defender.unitAIOrderData()["target"]].length > 3)) {
    426426                    // okay release me.
     
    437437    }
    438438   
    439439
    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")));
     440    var nonDefenders = this.myUnits.filter(API3.Filters.or(API3.Filters.not(API3.Filters.byMetadata(PlayerID, "role","defence")),API3.Filters.isIdle()));
     441    nonDefenders = nonDefenders.filter(API3.Filters.not(API3.Filters.byClass("Female")));
     442    nonDefenders = nonDefenders.filter(API3.Filters.not(API3.Filters.byMetadata(PlayerID, "subrole","attacking")));
    443443    var defenceRatio = this.defenceRatio;
    444444   
    445445    if (newEnemies.length + this.nbAttackers > (this.nbDefenders + nonDefenders.length) * 0.8 && this.nbAttackers > 9)
     
    457457    if ( (nonDefenders.length + this.nbDefenders > newEnemies.length + this.nbAttackers)
    458458        || this.nbDefenders + nonDefenders.length < 4)
    459459    {
    460         var buildings = gameState.getOwnEntities().filter(Filters.byCanGarrison()).toEntityArray();
     460        var buildings = gameState.getOwnEntities().filter(API3.Filters.byCanGarrison()).toEntityArray();
    461461        buildings.forEach( function (struct) {
    462462            if (struct.garrisoned() && struct.garrisoned().length)
    463463                struct.unloadAll();
     
    513513        {
    514514            var ent = nonDefenders._entities[id];
    515515            if (ent.position())
    516                 data.push([id, ent, SquareVectorDistance(enemy.position(), ent.position())]);
     516                data.push([id, ent, API3.SquareVectorDistance(enemy.position(), ent.position())]);
    517517        }
    518518        // refine the defenders we want. Since it's the distance squared, it has the effect
    519519        // of tending to always prefer closer units, though this refinement should change it slighty.
     
    547547        for each (var val in data.slice(0, Math.min(nonDefenders._length, defRatio - assigned)))
    548548            ret[val[0]] = val[1];
    549549       
    550         var defs = new EntityCollection(nonDefenders._ai, ret);
     550        var defs = new API3.EntityCollection(nonDefenders._ai, ret);
    551551
    552552        // successfully sorted
    553553        defs.forEach(function (defender) { //}){
     
    571571        /*if (gameState.defcon() <= 3)
    572572        {
    573573            // 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"));
     574            var buildings = gameState.getOwnEntities().filter(API3.Filters.byCanGarrison()).toEntityArray();
     575            var females = gameState.getOwnEntities().filter(API3.Filters.byClass("Support"));
    576576               
    577577            var cache = {};
    578578            var garrisoned = false;
     
    580580                garrisoned = false;
    581581                if (ent.position())
    582582                {
    583                     if (SquareVectorDistance(ent.position(), enemy.position()) < 3500)
     583                    if (API3.SquareVectorDistance(ent.position(), enemy.position()) < 3500)
    584584                    {
    585585                        for (var i in buildings)
    586586                        {
     
    646646                        if (territory === PlayerID)
    647647                        {
    648648                            // 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);
     649                            this.listOfWantedUnits[attacker.id()] = new API3.EntityCollection(gameState.sharedScript);
    650650                            this.listOfWantedUnits[attacker.id()].addEnt(attacker);
    651651                            this.listOfWantedUnits[attacker.id()].freeze();
    652652                            this.listOfWantedUnits[attacker.id()].registerUpdates();
    653653
    654                             var filter = Filters.byTargetedEntity(attacker.id());
     654                            var filter = API3.Filters.byTargetedEntity(attacker.id());
    655655                            this.WantedUnitsAttacker[attacker.id()] = this.myUnits.filter(filter);
    656656                            this.WantedUnitsAttacker[attacker.id()].registerUpdates();
    657657                        }
     
    666666                           
    667667                            // Right now, to make the AI less gameable, we'll mark any surrounding resource as inaccessible.
    668668                            // usual tower range is 80. Be on the safe side.
    669                             var close = gameState.getResourceSupplies("wood").filter(Filters.byDistance(attacker.position(), 90));
     669                            var close = gameState.getResourceSupplies("wood").filter(API3.Filters.byDistance(attacker.position(), 90));
    670670                            close.forEach(function (supply) { //}){
    671671                                supply.setMetadata(PlayerID, "inaccessible", true);
    672672                            });
     
    683683                                    if (this.reevaluateEntity(gameState, attacker))
    684684                                    {
    685685                                        var position = attacker.position();
    686                                         var close = HQ.enemyWatchers[attacker.owner()].enemySoldiers.filter(Filters.byDistance(position, self.armyCompactSize));
     686                                        var close = HQ.enemyWatchers[attacker.owner()].enemySoldiers.filter(API3.Filters.byDistance(position, self.armyCompactSize));
    687687                                       
    688688                                        if (close.length > 2 || ourUnit.hasClass("Support") || attacker.hasClass("Siege"))
    689689                                        {
     
    692692                                            armyID = attacker.getMetadata(PlayerID, "inArmy");
    693693                                           
    694694                                            close.forEach(function (ent) { //}){
    695                                                 if (SquareVectorDistance(position, ent.position()) < self.armyCompactSize)
     695                                                if (API3.SquareVectorDistance(position, ent.position()) < self.armyCompactSize)
    696696                                                {
    697697                                                    ent.setMetadata(PlayerID, "inArmy", armyID);
    698698                                                          self.enemyArmy[ent.owner()][armyID].addEnt(ent);
     
    708708                                        // let's try to garrison this support unit.
    709709                                        if (ourUnit.position())
    710710                                        {
    711                                             var buildings = gameState.getOwnEntities().filter(Filters.byCanGarrison()).filterNearest(ourUnit.position(),4).toEntityArray();
     711                                            var buildings = gameState.getOwnEntities().filter(API3.Filters.byCanGarrison()).filterNearest(ourUnit.position(),4).toEntityArray();
    712712                                            var garrisoned = false;
    713713                                            for (var i in buildings)
    714714                                            {
  • 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/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/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/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/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/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/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/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};
  • 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";
     
    221106
    222107            // Get the constructor name from the metadata
    223108            std::string constructor;
    224             if (!m_ScriptInterface.GetProperty(metadata.get(), "constructor", constructor))
     109            if (!m_ScriptInterface->GetProperty(metadata.get(), "constructor", constructor))
    225110            {
    226111                LOGERROR(L"Failed to create AI player: %ls: missing 'constructor'", path.string().c_str());
    227112                return false;
     
    229114
    230115            // Get the constructor function from the loaded scripts
    231116            CScriptVal ctor;
    232             if (!m_ScriptInterface.GetProperty(m_ScriptInterface.GetGlobalObject(), constructor.c_str(), ctor)
     117            if (!m_ScriptInterface->GetProperty(m_ScriptInterface->GetGlobalObject(), constructor.c_str(), ctor)
    233118                || ctor.undefined())
    234119            {
    235120                LOGERROR(L"Failed to create AI player: %ls: can't find constructor '%hs'", path.string().c_str(), constructor.c_str());
    236121                return false;
    237122            }
    238123
    239             m_ScriptInterface.GetProperty(metadata.get(), "useShared", m_UseSharedComponent);
     124            m_ScriptInterface->GetProperty(metadata.get(), "useShared", m_UseSharedComponent);
    240125           
    241126            CScriptVal obj;
    242127
     
    244129            {
    245130                // Set up the data to pass as the constructor argument
    246131                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);
     132                m_ScriptInterface->Eval(L"({})", settings);
     133                m_ScriptInterface->SetProperty(settings.get(), "player", m_Player, false);
     134                m_ScriptInterface->SetProperty(settings.get(), "difficulty", m_Difficulty, false);
    250135                ENSURE(m_Worker.m_HasLoadedEntityTemplates);
    251                 m_ScriptInterface.SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false);
     136                m_ScriptInterface->SetProperty(settings.get(), "templates", m_Worker.m_EntityTemplates, false);
    252137
    253                 obj = m_ScriptInterface.CallConstructor(ctor.get(), settings.get());
     138                obj = m_ScriptInterface->CallConstructor(ctor.get(), settings.get());
    254139            }
    255140            else
    256141            {
    257142                // For deserialization, we want to create the object with the correct prototype
    258143                // but don't want to actually run the constructor again
    259144                // XXX: actually we don't currently use this path for deserialization - maybe delete it?
    260                 obj = m_ScriptInterface.NewObjectFromConstructor(ctor.get());
     145                obj = m_ScriptInterface->NewObjectFromConstructor(ctor.get());
    261146            }
    262147
    263148            if (obj.undefined())
     
    266151                return false;
    267152            }
    268153
    269             m_Obj = CScriptValRooted(m_ScriptInterface.GetContext(), obj);
     154            m_Obj = CScriptValRooted(m_ScriptInterface->GetContext(), obj);
    270155            return true;
    271156        }
    272157
    273         void Run(CScriptVal state)
     158        void Run(CScriptVal state, int playerID)
    274159        {
    275160            m_Commands.clear();
    276             m_ScriptInterface.CallFunctionVoid(m_Obj.get(), "HandleMessage", state);
     161            m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "HandleMessage", state, playerID);
    277162        }
    278163        // overloaded with a sharedAI part.
    279164        // javascript can handle both natively on the same function.
    280         void Run(CScriptVal state, CScriptValRooted SharedAI)
     165        void Run(CScriptVal state, int playerID, CScriptValRooted SharedAI)
    281166        {
    282167            m_Commands.clear();
    283             m_ScriptInterface.CallFunctionVoid(m_Obj.get(), "HandleMessage", state, SharedAI);
     168            m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "HandleMessage", state, playerID, SharedAI);
    284169        }
    285170        void InitAI(CScriptVal state, CScriptValRooted SharedAI)
    286171        {
    287172            m_Commands.clear();
    288             m_ScriptInterface.CallFunctionVoid(m_Obj.get(), "Init", state, SharedAI);
     173            m_ScriptInterface->CallFunctionVoid(m_Obj.get(), "Init", state, m_Player, SharedAI);
    289174        }
    290175
    291176        CAIWorker& m_Worker;
     
    294179        uint8_t m_Difficulty;
    295180        bool m_UseSharedComponent;
    296181       
    297         ScriptInterface m_ScriptInterface;
     182        shared_ptr<ScriptInterface> m_ScriptInterface;
    298183        CScriptValRooted m_Obj;
    299184        std::vector<shared_ptr<ScriptInterface::StructuredClone> > m_Commands;
    300         std::set<std::wstring> m_LoadedModules;
    301185    };
    302186
    303187public:
     
    313197        // removed as soon whenever the new pathfinder is committed
    314198        // And the AIs can stop relying on their own little hands.
    315199        m_ScriptRuntime(ScriptInterface::CreateRuntime(33554432)),
    316         m_ScriptInterface("Engine", "AI", m_ScriptRuntime),
     200        m_ScriptInterface(new ScriptInterface("Engine", "AI", m_ScriptRuntime)),
    317201        m_TurnNum(0),
    318202        m_CommandsComputed(true),
    319203        m_HasLoadedEntityTemplates(false),
     
    321205    {
    322206
    323207        // 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();
     208        m_ScriptInterface->ReplaceNondeterministicRNG(m_RNG);
     209        m_ScriptInterface->LoadGlobalScripts();
    326210
    327         m_ScriptInterface.SetCallbackData(NULL);
     211        m_ScriptInterface->SetCallbackData(static_cast<void*> (this));
    328212
    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");
     213        m_ScriptInterface->RegisterFunction<void, int, CScriptValRooted, CAIWorker::PostCommand>("PostCommand");
     214        m_ScriptInterface->RegisterFunction<void, std::wstring, CAIWorker::IncludeModule>("IncludeModule");
     215        m_ScriptInterface->RegisterFunction<void, CAIWorker::DumpHeap>("DumpHeap");
     216        m_ScriptInterface->RegisterFunction<void, CAIWorker::ForceGC>("ForceGC");
    332217       
    333         m_ScriptInterface.RegisterFunction<void, std::wstring, std::vector<u32>, u32, u32, u32, CAIWorker::DumpImage>("DumpImage");
     218        m_ScriptInterface->RegisterFunction<void, std::wstring, std::vector<u32>, u32, u32, u32, CAIWorker::DumpImage>("DumpImage");
    334219    }
    335220
    336221    ~CAIWorker()
     
    343228        m_PassabilityMapVal = CScriptValRooted();
    344229        m_TerritoryMapVal = CScriptValRooted();
    345230    }
     231   
     232    bool LoadScripts(const std::wstring& moduleName)
     233    {
     234        // Ignore modules that are already loaded
     235        if (m_LoadedModules.find(moduleName) != m_LoadedModules.end())
     236            return true;
    346237
    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)
     238        // Mark this as loaded, to prevent it recursively loading itself
     239        m_LoadedModules.insert(moduleName);
     240
     241        // Load and execute *.js
     242        VfsPaths pathnames;
     243        vfs::GetPathnames(g_VFS, L"simulation/ai/" + moduleName + L"/", L"*.js", pathnames);
     244        for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
     245        {
     246            if (!m_ScriptInterface->LoadGlobalScriptFile(*it))
     247            {
     248                LOGERROR(L"Failed to load script %ls", it->string().c_str());
     249                return false;
     250            }
     251        }
     252
     253        return true;
     254    }
     255   
     256    static void IncludeModule(void* cbdata, std::wstring name)
    351257    {
    352         if (cbdata == NULL) {
    353             debug_warn(L"Warning: the shared component has tried to push an engine command. Ignoring.");
    354             return;
     258        CAIWorker* self = static_cast<CAIWorker*> (cbdata);
     259        self->LoadScripts(name);
     260    }
     261
     262    static void PostCommand(void* cbdata, int playerid, CScriptValRooted cmd)
     263    {
     264        CAIWorker* self = static_cast<CAIWorker*> (cbdata);
     265        self->PostCommand(playerid, cmd);
     266    }
     267   
     268    void PostCommand(int playerid, CScriptValRooted cmd)
     269    {
     270        bool playerFound = false;
     271        for (int i=0; i<m_Players.size(); i++)
     272        {
     273            if (m_Players[i]->m_Player == playerid)
     274            {
     275                m_Players[i]->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(cmd.get()));
     276                playerFound = true;
     277            }
    355278        }
    356         CAIPlayer* self = static_cast<CAIPlayer*> (cbdata);
    357         self->m_Commands.push_back(self->m_ScriptInterface.WriteStructuredClone(cmd.get()));
     279       
     280        if (!playerFound)
     281            LOGERROR(L"Invalid playerid in PostCommand!"); 
    358282    }
    359283    // The next two ought to be implmeneted someday but for now as it returns "null" it can't
    360284    static void DumpHeap(void* cbdata)
     
    364288            return;
    365289        }
    366290        CAIWorker* self = static_cast<CAIWorker*> (cbdata);
    367         self->m_ScriptInterface.DumpHeap();
     291        self->m_ScriptInterface->DumpHeap();
    368292    }
    369293    static void ForceGC(void* cbdata)
    370294    {
     
    374298        }
    375299        CAIWorker* self = static_cast<CAIWorker*> (cbdata);
    376300        PROFILE3("AI compute GC");
    377         JS_GC(self->m_ScriptInterface.GetContext());
     301        JS_GC(self->m_ScriptInterface->GetContext());
    378302    }
    379303   
    380304    /**
     
    424348       
    425349        // reset the value so it can be used to determine if we actually initialized it.
    426350        m_HasSharedComponent = false;
    427                
     351       
     352        if (LoadScripts(L"common-api-v3"))
     353            m_HasSharedComponent = true;
     354        else
     355            return false;
     356        /*     
    428357        VfsPaths sharedPathnames;
    429358        // Check for "shared" module.
    430359        vfs::GetPathnames(g_VFS, L"simulation/ai/common-api-v3/", L"*.js", sharedPathnames);
    431360        for (VfsPaths::iterator it = sharedPathnames.begin(); it != sharedPathnames.end(); ++it)
    432361        {
    433             if (!m_ScriptInterface.LoadGlobalScriptFile(*it))
     362            if (!m_ScriptInterface->LoadGlobalScriptFile(*it))
    434363            {
    435364                LOGERROR(L"Failed to load shared script %ls", it->string().c_str());
    436365                return false;
     
    439368        }
    440369        if (!m_HasSharedComponent)
    441370            return false;
    442        
     371        */
    443372        // mainly here for the error messages
    444373        OsPath path = L"simulation/ai/common-api-v2/";
    445374       
    446         // Constructor name is SharedScript
     375        // Constructor name is SharedScript, it's in the module API3
     376        // TODO: Hardcoding this bad, we need a smarter way.
     377        CScriptVal AIModule;
    447378        CScriptVal ctor;
    448         if (!m_ScriptInterface.GetProperty(m_ScriptInterface.GetGlobalObject(), "SharedScript", ctor)
     379        if (!m_ScriptInterface->GetProperty(m_ScriptInterface->GetGlobalObject(), "API3", AIModule) || AIModule.undefined())
     380        {
     381            LOGERROR(L"Failed to create shared AI component: %ls: can't find module '%hs'", path.string().c_str(), "API3");
     382            return false;
     383        }
     384       
     385        if (!m_ScriptInterface->GetProperty(AIModule.get(), "SharedScript", ctor)
    449386            || ctor.undefined())
    450387        {
    451388            LOGERROR(L"Failed to create shared AI component: %ls: can't find constructor '%hs'", path.string().c_str(), "SharedScript");
     
    454391       
    455392        // Set up the data to pass as the constructor argument
    456393        CScriptVal settings;
    457         m_ScriptInterface.Eval(L"({})", settings);
     394        m_ScriptInterface->Eval(L"({})", settings);
    458395        CScriptVal playersID;
    459         m_ScriptInterface.Eval(L"({})", playersID);
     396        m_ScriptInterface->Eval(L"({})", playersID);
    460397       
    461398        for (size_t i = 0; i < m_Players.size(); ++i)
    462399        {
    463             jsval val = m_ScriptInterface.ToJSVal(m_ScriptInterface.GetContext(), m_Players[i]->m_Player);
    464             m_ScriptInterface.SetPropertyInt(playersID.get(), i, CScriptVal(val), true);
     400            jsval val = m_ScriptInterface->ToJSVal(m_ScriptInterface->GetContext(), m_Players[i]->m_Player);
     401            m_ScriptInterface->SetPropertyInt(playersID.get(), i, CScriptVal(val), true);
    465402        }
    466403       
    467         m_ScriptInterface.SetProperty(settings.get(), "players", playersID);
     404        m_ScriptInterface->SetProperty(settings.get(), "players", playersID);
    468405        ENSURE(m_HasLoadedEntityTemplates);
    469         m_ScriptInterface.SetProperty(settings.get(), "templates", m_EntityTemplates, false);
     406        m_ScriptInterface->SetProperty(settings.get(), "templates", m_EntityTemplates, false);
    470407       
    471408        if (hasTechs)
    472409        {
    473             m_ScriptInterface.SetProperty(settings.get(), "techTemplates", m_TechTemplates, false);
     410            m_ScriptInterface->SetProperty(settings.get(), "techTemplates", m_TechTemplates, false);
    474411        }
    475412        else
    476413        {
    477414            // won't get the tech templates directly.
    478415            CScriptVal fakeTech;
    479             m_ScriptInterface.Eval("({})", fakeTech);
    480             m_ScriptInterface.SetProperty(settings.get(), "techTemplates", fakeTech, false);
     416            m_ScriptInterface->Eval("({})", fakeTech);
     417            m_ScriptInterface->SetProperty(settings.get(), "techTemplates", fakeTech, false);
    481418        }
    482         m_SharedAIObj = CScriptValRooted(m_ScriptInterface.GetContext(),m_ScriptInterface.CallConstructor(ctor.get(), settings.get()));
     419        m_SharedAIObj = CScriptValRooted(m_ScriptInterface->GetContext(),m_ScriptInterface->CallConstructor(ctor.get(), settings.get()));
    483420   
    484421       
    485422        if (m_SharedAIObj.undefined())
     
    493430
    494431    bool AddPlayer(const std::wstring& aiName, player_id_t player, uint8_t difficulty, bool callConstructor)
    495432    {
    496         shared_ptr<CAIPlayer> ai(new CAIPlayer(*this, aiName, player, difficulty, m_ScriptRuntime, m_RNG));
     433        shared_ptr<CAIPlayer> ai(new CAIPlayer(*this, aiName, player, difficulty, m_ScriptInterface));
    497434        if (!ai->Initialise(callConstructor))
    498435            return false;
    499436       
     
    501438        if (!m_HasSharedComponent)
    502439            m_HasSharedComponent = ai->m_UseSharedComponent;
    503440
    504         m_ScriptInterface.MaybeGC();
     441        m_ScriptInterface->MaybeGC();
    505442
    506443        m_Players.push_back(ai);
    507444
     
    513450        // this will be run last by InitGame.Js, passing the full game representation.
    514451        // For now it will run for the shared Component.
    515452        // This is NOT run during deserialization.
    516         CScriptVal state = m_ScriptInterface.ReadStructuredClone(gameState);
    517         JSContext* cx = m_ScriptInterface.GetContext();
     453        CScriptVal state = m_ScriptInterface->ReadStructuredClone(gameState);
     454        JSContext* cx = m_ScriptInterface->GetContext();
    518455
    519456        m_PassabilityMapVal = CScriptValRooted(cx, ScriptInterface::ToJSVal(cx, passabilityMap));
    520457        m_TerritoryMapVal = CScriptValRooted(cx, ScriptInterface::ToJSVal(cx, territoryMap));
    521458        if (m_HasSharedComponent)
    522459        {
    523             m_ScriptInterface.SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
    524             m_ScriptInterface.SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
     460            m_ScriptInterface->SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
     461            m_ScriptInterface->SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
    525462
    526             m_ScriptInterface.CallFunctionVoid(m_SharedAIObj.get(), "init", state);
    527             m_ScriptInterface.MaybeGC();
     463            m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "init", state);
     464            m_ScriptInterface->MaybeGC();
    528465           
    529466            for (size_t i = 0; i < m_Players.size(); ++i)
    530467            {
     
    545482        {
    546483            m_PassabilityMap = passabilityMap;
    547484
    548             JSContext* cx = m_ScriptInterface.GetContext();
     485            JSContext* cx = m_ScriptInterface->GetContext();
    549486            m_PassabilityMapVal = CScriptValRooted(cx, ScriptInterface::ToJSVal(cx, m_PassabilityMap));
    550487        }
    551488
     
    553490        {
    554491            m_TerritoryMap = territoryMap;
    555492
    556             JSContext* cx = m_ScriptInterface.GetContext();
     493            JSContext* cx = m_ScriptInterface->GetContext();
    557494            m_TerritoryMapVal = CScriptValRooted(cx, ScriptInterface::ToJSVal(cx, m_TerritoryMap));
    558495        }
    559496
     
    583520    }
    584521
    585522    void RegisterTechTemplates(const shared_ptr<ScriptInterface::StructuredClone>& techTemplates) {
    586         JSContext* cx = m_ScriptInterface.GetContext();
    587         m_TechTemplates = CScriptValRooted(cx, m_ScriptInterface.ReadStructuredClone(techTemplates));
     523        JSContext* cx = m_ScriptInterface->GetContext();
     524        m_TechTemplates = CScriptValRooted(cx, m_ScriptInterface->ReadStructuredClone(techTemplates));
    588525    }
    589526   
    590527    void LoadEntityTemplates(const std::vector<std::pair<std::string, const CParamNode*> >& templates)
    591528    {
    592529        m_HasLoadedEntityTemplates = true;
    593530
    594         m_ScriptInterface.Eval("({})", m_EntityTemplates);
     531        m_ScriptInterface->Eval("({})", m_EntityTemplates);
    595532
    596533        for (size_t i = 0; i < templates.size(); ++i)
    597534        {
    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);
     535            jsval val = templates[i].second->ToJSVal(m_ScriptInterface->GetContext(), false);
     536            m_ScriptInterface->SetProperty(m_EntityTemplates.get(), templates[i].first.c_str(), CScriptVal(val), true);
    600537        }
    601538
    602539        // Since the template data is shared between AI players, freeze it
    603540        // to stop any of them changing it and confusing the other players
    604         m_ScriptInterface.FreezeObject(m_EntityTemplates.get(), true);
     541        m_ScriptInterface->FreezeObject(m_EntityTemplates.get(), true);
    605542    }
    606543
    607544    void Serialize(std::ostream& stream, bool isDebug)
     
    610547
    611548        if (isDebug)
    612549        {
    613             CDebugSerializer serializer(m_ScriptInterface, stream);
     550            CDebugSerializer serializer(*m_ScriptInterface, stream);
    614551            serializer.Indent(4);
    615552            SerializeState(serializer);
    616553        }
    617554        else
    618555        {
    619             CStdSerializer serializer(m_ScriptInterface, stream);
     556            CStdSerializer serializer(*m_ScriptInterface, stream);
    620557            // TODO: see comment in Deserialize()
    621558            serializer.SetSerializablePrototypes(m_SerializablePrototypes);
    622559            SerializeState(serializer);
     
    637574        if (m_HasSharedComponent)
    638575        {
    639576            CScriptVal sharedData;
    640             if (!m_ScriptInterface.CallFunction(m_SharedAIObj.get(), "Serialize", sharedData))
     577            if (!m_ScriptInterface->CallFunction(m_SharedAIObj.get(), "Serialize", sharedData))
    641578                LOGERROR(L"AI shared script Serialize call failed");
    642579            serializer.ScriptVal("sharedData", sharedData);
    643580        }
     
    650587            serializer.NumberU32_Unbounded("num commands", (u32)m_Players[i]->m_Commands.size());
    651588            for (size_t j = 0; j < m_Players[i]->m_Commands.size(); ++j)
    652589            {
    653                 CScriptVal val = m_ScriptInterface.ReadStructuredClone(m_Players[i]->m_Commands[j]);
     590                CScriptVal val = m_ScriptInterface->ReadStructuredClone(m_Players[i]->m_Commands[j]);
    654591                serializer.ScriptVal("command", val);
    655592            }
    656593
    657             bool hasCustomSerialize = m_ScriptInterface.HasProperty(m_Players[i]->m_Obj.get(), "Serialize");
     594            bool hasCustomSerialize = m_ScriptInterface->HasProperty(m_Players[i]->m_Obj.get(), "Serialize");
    658595            if (hasCustomSerialize)
    659596            {
    660597                CScriptVal scriptData;
    661                 if (!m_ScriptInterface.CallFunction(m_Players[i]->m_Obj.get(), "Serialize", scriptData))
     598                if (!m_ScriptInterface->CallFunction(m_Players[i]->m_Obj.get(), "Serialize", scriptData))
    662599                    LOGERROR(L"AI script Serialize call failed");
    663600                serializer.ScriptVal("data", scriptData);
    664601            }
     
    673610    {
    674611        ENSURE(m_CommandsComputed); // deserializing while we're still actively computing would be bad
    675612
    676         CStdDeserializer deserializer(m_ScriptInterface, stream);
     613        CStdDeserializer deserializer(*m_ScriptInterface, stream);
    677614
    678615        m_PlayerMetadata.clear();
    679616        m_Players.clear();
     
    695632        {
    696633            CScriptVal sharedData;
    697634            deserializer.ScriptVal("sharedData", sharedData);
    698             if (!m_ScriptInterface.CallFunctionVoid(m_SharedAIObj.get(), "Deserialize", sharedData))
     635            if (!m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "Deserialize", sharedData))
    699636                LOGERROR(L"AI shared script Deserialize call failed");
    700637        }
    701638
     
    717654            {
    718655                CScriptVal val;
    719656                deserializer.ScriptVal("command", val);
    720                 m_Players.back()->m_Commands.push_back(m_ScriptInterface.WriteStructuredClone(val.get()));
     657                m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val.get()));
    721658            }
    722659           
    723660            // TODO: this is yucky but necessary while the AIs are sharing data between contexts;
     
    726663            //  prototypes could be stored in their ScriptInterface
    727664            deserializer.SetSerializablePrototypes(m_DeserializablePrototypes);
    728665
    729             bool hasCustomDeserialize = m_ScriptInterface.HasProperty(m_Players.back()->m_Obj.get(), "Deserialize");
     666            bool hasCustomDeserialize = m_ScriptInterface->HasProperty(m_Players.back()->m_Obj.get(), "Deserialize");
    730667            if (hasCustomDeserialize)
    731668            {
    732669                CScriptVal scriptData;
    733670                deserializer.ScriptVal("data", scriptData);
    734671                if (m_Players[i]->m_UseSharedComponent)
    735672                {
    736                     if (!m_ScriptInterface.CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData, m_SharedAIObj))
     673                    if (!m_ScriptInterface->CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData, m_SharedAIObj))
    737674                        LOGERROR(L"AI script Deserialize call failed");
    738675                }
    739                 else if (!m_ScriptInterface.CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData))
     676                else if (!m_ScriptInterface->CallFunctionVoid(m_Players.back()->m_Obj.get(), "Deserialize", scriptData))
    740677                {
    741678                    LOGERROR(L"AI script deserialize() call failed");
    742679                }
     
    770707        if (m_PlayerMetadata.find(path) == m_PlayerMetadata.end())
    771708        {
    772709            // Load and cache the AI player metadata
    773             m_PlayerMetadata[path] = m_ScriptInterface.ReadJSONFile(path);
     710            m_PlayerMetadata[path] = m_ScriptInterface->ReadJSONFile(path);
    774711        }
    775712
    776713        return m_PlayerMetadata[path];
     
    786723            if (m_TurnNum++ % 50 == 0)
    787724            {
    788725                PROFILE3("AI compute GC");
    789                 m_ScriptInterface.MaybeGC();
     726                m_ScriptInterface->MaybeGC();
    790727            }
    791728            return;
    792729        }
     
    795732        CScriptVal state;
    796733        {
    797734            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);
     735            state = m_ScriptInterface->ReadStructuredClone(m_GameState);
     736            m_ScriptInterface->SetProperty(state.get(), "passabilityMap", m_PassabilityMapVal, true);
     737            m_ScriptInterface->SetProperty(state.get(), "territoryMap", m_TerritoryMapVal, true);
    801738        }
    802739
    803740        // It would be nice to do
    804         //   m_ScriptInterface.FreezeObject(state.get(), true);
     741        //   m_ScriptInterface->FreezeObject(state.get(), true);
    805742        // to prevent AI scripts accidentally modifying the state and
    806743        // affecting other AI scripts they share it with. But the performance
    807744        // cost is far too high, so we won't do that.
     
    810747        if (m_HasSharedComponent)
    811748        {
    812749            PROFILE3("AI run shared component");
    813             m_ScriptInterface.CallFunctionVoid(m_SharedAIObj.get(), "onUpdate", state);
     750            m_ScriptInterface->CallFunctionVoid(m_SharedAIObj.get(), "onUpdate", state);
    814751        }
    815752       
    816753        for (size_t i = 0; i < m_Players.size(); ++i)
     
    818755            PROFILE3("AI script");
    819756            PROFILE2_ATTR("player: %d", m_Players[i]->m_Player);
    820757            PROFILE2_ATTR("script: %ls", m_Players[i]->m_AIName.c_str());
     758
    821759            if (m_HasSharedComponent && m_Players[i]->m_UseSharedComponent)
    822                 m_Players[i]->Run(state,m_SharedAIObj);
     760                m_Players[i]->Run(state, m_Players[i]->m_Player, m_SharedAIObj);
    823761            else
    824                 m_Players[i]->Run(state);
     762                m_Players[i]->Run(state, m_Players[i]->m_Player);
    825763        }
    826764
    827765        // Run GC if we are about to overflow
    828         if (JS_GetGCParameter(m_ScriptInterface.GetRuntime(), JSGC_BYTES) > 33000000)
     766        if (JS_GetGCParameter(m_ScriptInterface->GetRuntime(), JSGC_BYTES) > 33000000)
    829767        {
    830768            PROFILE3("AI compute GC");
    831769
    832             JS_GC(m_ScriptInterface.GetContext());
     770            JS_GC(m_ScriptInterface->GetContext());
    833771        }
    834772       
    835773        // Run the GC every so often.
     
    838776        /*if (m_TurnNum++ % 20 == 0)
    839777        {
    840778            PROFILE3("AI compute GC");
    841             m_ScriptInterface.MaybeGC();
     779            m_ScriptInterface->MaybeGC();
    842780        }*/
    843781    }
    844782
    845783    shared_ptr<ScriptRuntime> m_ScriptRuntime;
    846     ScriptInterface m_ScriptInterface;
     784    shared_ptr<ScriptInterface> m_ScriptInterface;
    847785    boost::rand48 m_RNG;
    848786    u32 m_TurnNum;
    849787
     
    858796    CScriptValRooted m_SharedAIObj;
    859797    std::vector<SCommandSets> m_Commands;
    860798   
     799    std::set<std::wstring> m_LoadedModules;
     800   
    861801    shared_ptr<ScriptInterface::StructuredClone> m_GameState;
    862802    Grid<u16> m_PassabilityMap;
    863803    CScriptValRooted m_PassabilityMapVal;