Index: binaries/data/mods/public/simulation/ai/common-api/shared.js =================================================================== --- binaries/data/mods/public/simulation/ai/common-api/shared.js +++ binaries/data/mods/public/simulation/ai/common-api/shared.js @@ -115,18 +115,6 @@ this.accessibility = new m.Accessibility(); this.accessibility.init(state, this.terrainAnalyzer); - // Resource types: ignore = not used for resource maps - // abundant = abundant resource with small amount each - // sparse = sparse resource, but huge amount each - // The following maps are defined in TerrainAnalysis.js and are used for some building placement (cc, dropsites) - // They are updated by checking for create and destroy events for all resources - this.normalizationFactor = { "abundant": 50, "sparse": 90 }; - this.influenceRadius = { "abundant": 36, "sparse": 48 }; - this.ccInfluenceRadius = { "abundant": 60, "sparse": 120 }; - this.resourceMaps = {}; // Contains maps showing the density of resources - this.ccResourceMaps = {}; // Contains maps showing the density of resources, optimized for CC placement. - this.createResourceMaps(); - this.gameState = {}; for (let player of this._players) { @@ -385,21 +373,40 @@ descendant.prototype[p] = parent.prototype[p]; }; -/** creates a map of resource density */ -m.SharedScript.prototype.createResourceMaps = function() +/** + * Creates a map of resource density, updated by checking for create and destroy events for all resources. + * @param {Object} parameters - An object containing the normalisationFactor, ccInfluenceRadius and influenceRadius for each resouce. + * @param {string} reference - The reference name of the specific map, to differentiate between different AIs. + */ +m.SharedScript.prototype.createResourceMaps = function(parameters, reference) { + if (!this.maps) + this.maps = {}; + + if (this.maps[reference]) + return; + + this.maps[reference] = { + "normalizationFactor": parameters.normalisationFactor, + "influenceRadius": parameters.influenceRadius, + "ccInfluenceRadius": parameters.ccInfluenceRadius, + "resourceMaps": {}, // Contains maps showing the density of resources + "ccResourceMaps": {}, // Contains maps showing the density of resources, optimized for CC placement. + }; + for (const resource of Resources.GetCodes()) { - if (this.resourceMaps[resource] || - !(Resources.GetResource(resource).aiAnalysisInfluenceGroup in this.normalizationFactor)) + if (this.maps[reference].resourceMaps[resource] || + !this.maps[reference].normalizationFactor[resource]) continue; // We're creating them 8-bit. Things could go above 255 if there are really tons of resources // But at that point the precision is not really important anyway. And it saves memory. - this.resourceMaps[resource] = new m.Map(this, "resource"); - this.ccResourceMaps[resource] = new m.Map(this, "resource"); + this.maps[reference].resourceMaps[resource] = new m.Map(this, "resource"); + this.maps[reference].ccResourceMaps[resource] = new m.Map(this, "resource"); } + for (const ent of this._entities.values()) - this.addEntityToResourceMap(ent); + this.addEntityToResourceMap(ent, this.maps[reference]); }; /** @@ -409,33 +416,35 @@ { for (const e of events.Destroy) if (e.entityObj) - this.removeEntityFromResourceMap(e.entityObj); + for (const mapRef in this.maps) + this.removeEntityFromResourceMap(e.entityObj, this.maps[mapRef]); for (const e of events.Create) if (e.entity && this._entities.has(e.entity)) - this.addEntityToResourceMap(this._entities.get(e.entity)); + for (const mapRef in this.maps) + this.addEntityToResourceMap(this._entities.get(e.entity), this.maps[mapRef]); }; /** * @param {entity} entity - The entity to add to the resource map. */ -m.SharedScript.prototype.addEntityToResourceMap = function(entity) +m.SharedScript.prototype.addEntityToResourceMap = function(entity, map) { - this.changeEntityInResourceMapHelper(entity, 1); + this.changeEntityInResourceMapHelper(entity, map, 1); }; /** * @param {entity} entity - The entity to remove from the resource map. */ -m.SharedScript.prototype.removeEntityFromResourceMap = function(entity) +m.SharedScript.prototype.removeEntityFromResourceMap = function(entity, map) { - this.changeEntityInResourceMapHelper(entity, -1); + this.changeEntityInResourceMapHelper(entity, map, -1); }; /** * @param {entity} ent - The entity to add to the resource map. */ -m.SharedScript.prototype.changeEntityInResourceMapHelper = function(ent, multiplication = 1) +m.SharedScript.prototype.changeEntityInResourceMapHelper = function(ent, map, multiplication = 1) { if (!ent) return; @@ -443,19 +452,27 @@ if (!entPos) return; const resource = ent.resourceSupplyType()?.generic; - if (!resource || !this.resourceMaps[resource]) + if (!resource || !map.resourceMaps[resource]) return; - const cellSize = this.resourceMaps[resource].cellSize; + const cellSize = map.resourceMaps[resource].cellSize; const x = Math.floor(entPos[0] / cellSize); const y = Math.floor(entPos[1] / cellSize); - const grp = Resources.GetResource(resource).aiAnalysisInfluenceGroup; - const strength = multiplication * ent.resourceSupplyMax() / this.normalizationFactor[grp]; - this.resourceMaps[resource].addInfluence(x, y, this.influenceRadius[grp] / cellSize, strength / 2, "constant"); - this.resourceMaps[resource].addInfluence(x, y, this.influenceRadius[grp] / cellSize, strength / 2); - this.ccResourceMaps[resource].addInfluence(x, y, this.ccInfluenceRadius[grp] / cellSize, strength, "constant"); + const strength = multiplication * ent.resourceSupplyMax() / map.normalizationFactor[resource]; + map.resourceMaps[resource].addInfluence(x, y, map.influenceRadius[resource] / cellSize, strength / 2, "constant"); + map.resourceMaps[resource].addInfluence(x, y, map.influenceRadius[resource] / cellSize, strength / 2); + map.ccResourceMaps[resource].addInfluence(x, y, map.ccInfluenceRadius[resource] / cellSize, strength, "constant"); +}; + +m.SharedScript.prototype.getResourcesMaps = function(reference) +{ + return this.maps[reference].resourceMaps; +}; + +m.SharedScript.prototype.getCCResourcesMaps = function(reference) +{ + return this.maps[reference].ccResourceMaps; }; return m; }(API3); - Index: binaries/data/mods/public/simulation/ai/petra/baseManager.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/baseManager.js +++ binaries/data/mods/public/simulation/ai/petra/baseManager.js @@ -341,11 +341,12 @@ if (i < 0) // no room around continue; + const resourcesMaps = gameState.sharedScript.getResourcesMaps(PETRA.HQ.RESOURCE_MAP_IDENTIFIER); // We add 3 times the needed resource and once others that can be dropped here. - let total = 2 * gameState.sharedScript.resourceMaps[resource].map[j]; - for (const res in gameState.sharedScript.resourceMaps) + let total = 2 * resourcesMaps[resource].map[j]; + for (const res in resourcesMaps) if (droppableResources.indexOf(res) != -1) - total += gameState.sharedScript.resourceMaps[res].map[j]; + total += resourcesMaps[res].map[j]; total *= 0.7; // Just a normalisation factor as the locateMap is limited to 255 if (total <= bestVal) @@ -454,7 +455,7 @@ continue; } // Non food stuff - if (!gameState.sharedScript.resourceMaps[type] || queues.dropsites.hasQueuedUnits() || + if (!gameState.sharedScript.getResourcesMaps(PETRA.HQ.RESOURCE_MAP_IDENTIFIER)[type] || queues.dropsites.hasQueuedUnits() || gameState.getOwnFoundations().filter(API3.Filters.byClass("Storehouse")).hasEntities()) { this.gatherers[type].nextCheck = gameState.ai.playedTurn; Index: binaries/data/mods/public/simulation/ai/petra/config.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/config.js +++ binaries/data/mods/public/simulation/ai/petra/config.js @@ -202,6 +202,28 @@ 0.35, 0.2 ]; + + // The following values are used to make maps defined in TerrainAnalysis.js + // and are used for some building placement (cc, dropsites). + this.resources = { + // A lower value means more a abundant resource with smaller amount each. + // A higher value means a more sparse resource with larger amounts each. + "normalisationFactor": { + "metal": 90, + "stone": 90, + "wood": 50 + }, + "ccInfluenceRadius": { + "metal": 120, + "stone": 120, + "wood": 60 + }, + "influenceRadius": { + "metal": 48, + "stone": 48, + "wood": 36 + } + }; }; PETRA.Config.prototype.setConfig = function(gameState) Index: binaries/data/mods/public/simulation/ai/petra/headquarters.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/headquarters.js +++ binaries/data/mods/public/simulation/ai/petra/headquarters.js @@ -50,6 +50,11 @@ this.capturableTargetsTime = 0; }; +/** + * The identifier string to use when making and requesting a resource map. + */ +PETRA.HQ.RESOURCE_MAP_IDENTIFIER = "PetraAI" + /** More initialisation for stuff that needs the gameState */ PETRA.HQ.prototype.init = function(gameState, queues) { @@ -63,6 +68,8 @@ this.navalMap = false; this.navalRegions = {}; + gameState.sharedScript.createResourceMaps(this.Config.resources, PETRA.HQ.RESOURCE_MAP_IDENTIFIER); + this.treasures = gameState.getEntities().filter(ent => ent.isTreasure()); this.treasures.registerUpdates(); this.currentPhase = gameState.currentPhase(); @@ -784,10 +791,11 @@ if (this.borderMap.map[j] & PETRA.fullBorder_Mask) // disfavor the borders of the map norm *= 0.5; - let val = 2 * gameState.sharedScript.ccResourceMaps[resource].map[j]; - for (let res in gameState.sharedScript.resourceMaps) + const ccResourcesMaps = gameState.sharedScript.getCCResourcesMaps(PETRA.HQ.RESOURCE_MAP_IDENTIFIER); + let val = 2 * ccResourcesMaps[resource].map[j]; + for (let res in gameState.sharedScript.getResourcesMaps(PETRA.HQ.RESOURCE_MAP_IDENTIFIER)) if (res != "food") - val += gameState.sharedScript.ccResourceMaps[res].map[j]; + val += ccResourcesMaps[res].map[j]; val *= norm; // If oversea, be just above threshold to be accepted if nothing else Index: binaries/data/mods/public/simulation/ai/petra/queueplanBuilding.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/queueplanBuilding.js +++ binaries/data/mods/public/simulation/ai/petra/queueplanBuilding.js @@ -247,7 +247,7 @@ { for (let j = 0; j < placement.map.length; ++j) { - let value = placement.map[j] - gameState.sharedScript.resourceMaps.wood.map[j]/3; + let value = placement.map[j] - gameState.sharedScript.getResourcesMaps(PETRA.HQ.RESOURCE_MAP_IDENTIFIER).wood.map[j]/3; if (HQ.borderMap.map[j] & PETRA.fullBorder_Mask) value /= 2; // we need space around farmstead, so disfavor map border placement.set(j, value); @@ -835,7 +835,7 @@ */ PETRA.ConstructionPlan.prototype.getResourcesAround = function(gameState, types, i, radius) { - let resourceMaps = gameState.sharedScript.resourceMaps; + const resourceMaps = gameState.sharedScript.getResourcesMaps(PETRA.HQ.RESOURCE_MAP_IDENTIFIER); let w = resourceMaps.wood.width; let cellSize = resourceMaps.wood.cellSize; let size = Math.floor(radius / cellSize); Index: binaries/data/mods/public/simulation/data/resources/food.json =================================================================== --- binaries/data/mods/public/simulation/data/resources/food.json +++ binaries/data/mods/public/simulation/data/resources/food.json @@ -10,6 +10,5 @@ "meat": "Meat" }, "properties": ["barterable", "tradable", "tributable"], - "truePrice": 100, - "aiAnalysisInfluenceGroup": "ignore" + "truePrice": 100 } Index: binaries/data/mods/public/simulation/data/resources/metal.json =================================================================== --- binaries/data/mods/public/simulation/data/resources/metal.json +++ binaries/data/mods/public/simulation/data/resources/metal.json @@ -8,6 +8,5 @@ "ruins": "Ruins" }, "properties": ["barterable", "tradable", "tributable"], - "truePrice": 100, - "aiAnalysisInfluenceGroup": "sparse" + "truePrice": 100 } Index: binaries/data/mods/public/simulation/data/resources/stone.json =================================================================== --- binaries/data/mods/public/simulation/data/resources/stone.json +++ binaries/data/mods/public/simulation/data/resources/stone.json @@ -8,6 +8,5 @@ "ruins": "Ruins" }, "properties": ["barterable", "tradable", "tributable"], - "truePrice": 100, - "aiAnalysisInfluenceGroup": "sparse" + "truePrice": 100 } Index: binaries/data/mods/public/simulation/data/resources/wood.json =================================================================== --- binaries/data/mods/public/simulation/data/resources/wood.json +++ binaries/data/mods/public/simulation/data/resources/wood.json @@ -8,6 +8,5 @@ "ruins": "Ruins" }, "properties": ["barterable", "tradable", "tributable"], - "truePrice": 100, - "aiAnalysisInfluenceGroup": "abundant" + "truePrice": 100 }