mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-07-23 14:54:10 +00:00
make Petra support passability and territory maps of different resolutions, addresses #2960
This was SVN commit r16072.
This commit is contained in:
@@ -9,20 +9,13 @@ var API3 = function(m)
|
||||
m.Map = function Map(sharedScript, type, originalMap, actualCopy)
|
||||
{
|
||||
// get the correct dimensions according to the map type
|
||||
if (type === "territory")
|
||||
if (type === "territory" || type === "resource")
|
||||
{
|
||||
var map = sharedScript.territoryMap;
|
||||
this.width = map.width;
|
||||
this.height = map.height;
|
||||
this.cellSize = map.cellSize;
|
||||
}
|
||||
else if (type === "resource")
|
||||
{
|
||||
this.cellSize = 4;
|
||||
var map = sharedScript.passabilityMap;
|
||||
this.width = map.width * map.cellSize / this.cellSize;
|
||||
this.height = map.height * map.cellSize / this.cellSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
var map = sharedScript.passabilityMap;
|
||||
@@ -402,37 +395,41 @@ m.Map.prototype.findBestTile = function(radius, obstructionTiles)
|
||||
let bestVal = -1;
|
||||
for (let i = 0; i < this.length; ++i)
|
||||
{
|
||||
if (obstructionTiles.map[i] > radius)
|
||||
let v = this.map[i];
|
||||
if (v > bestVal)
|
||||
{
|
||||
let v = this.map[i];
|
||||
if (v > bestVal)
|
||||
{
|
||||
bestVal = v;
|
||||
bestIdx = i;
|
||||
}
|
||||
var j = API3.getMaxMapIndex(i, this, obstructionTiles);
|
||||
if (obstructionTiles.map[j] <= radius)
|
||||
continue;
|
||||
bestVal = v;
|
||||
bestIdx = j;
|
||||
}
|
||||
}
|
||||
|
||||
return [bestIdx, bestVal];
|
||||
};
|
||||
|
||||
// returns the point with the lowest radius in the immediate vicinity
|
||||
m.Map.prototype.findLowestNeighbor = function(x,y)
|
||||
// returns the point with the lowest (but still > radius) point in the immediate vicinity
|
||||
m.Map.prototype.findLowestNeighbor = function(x,y,radius)
|
||||
{
|
||||
var lowestPt = [0,0];
|
||||
var lowestcoeff = 99999;
|
||||
x = Math.floor(x/4);
|
||||
y = Math.floor(y/4);
|
||||
var lowestcoeff = undefined;
|
||||
x = Math.floor(x/this.cellSize);
|
||||
y = Math.floor(y/this.cellSize);
|
||||
for (let xx = x-1; xx <= x+1; ++xx)
|
||||
{
|
||||
for (let yy = y-1; yy <= y+1; ++yy)
|
||||
if (xx >= 0 && xx < this.width && yy >= 0 && yy < this.width)
|
||||
if (this.map[xx+yy*this.width] <= lowestcoeff)
|
||||
{
|
||||
lowestcoeff = this.map[xx+yy*this.width];
|
||||
lowestPt = [(xx+0.5)*4, (yy+0.5)*4];
|
||||
}
|
||||
{
|
||||
if (xx < 0 || xx >= this.width || yy < 0 || yy >= this.width)
|
||||
continue;
|
||||
if (lowestcoeff && this.map[xx+yy*this.width] > lowestcoeff)
|
||||
continue;
|
||||
lowestcoeff = this.map[xx+yy*this.width];
|
||||
lowestPt = [(xx+0.5)*4, (yy+0.5)*4];
|
||||
}
|
||||
}
|
||||
return lowestPt;
|
||||
}
|
||||
};
|
||||
|
||||
m.Map.prototype.dumpIm = function(name, threshold)
|
||||
{
|
||||
|
||||
@@ -159,6 +159,24 @@ m.SharedScript.prototype.init = function(state, deserialization)
|
||||
this.territoryMap = state.territoryMap;
|
||||
this.territoryMap.cellSize = this.sizeMap / this.territoryMap.width;
|
||||
|
||||
/*
|
||||
var landPassMap = new Uint8Array(this.passabilityMap.data.length);
|
||||
var waterPassMap = new Uint8Array(this.passabilityMap.data.length);
|
||||
var obstructionMap = new Uint8Array(this.passabilityMap.data.length);
|
||||
var obstructionMaskLand = this.passabilityClasses["default"];
|
||||
var obstructionMaskWater = this.passabilityClasses["ship"];
|
||||
var obstructionMask = this.passabilityClasses["pathfinderObstruction"];
|
||||
for (var i = 0; i < this.passabilityMap.data.length; ++i)
|
||||
{
|
||||
landPassMap[i] = (this.passabilityMap.data[i] & obstructionMaskLand) ? 0 : 255;
|
||||
waterPassMap[i] = (this.passabilityMap.data[i] & obstructionMaskWater) ? 0 : 255;
|
||||
obstructionMap[i] = (this.passabilityMap.data[i] & obstructionMask) ? 0 : 255;
|
||||
}
|
||||
Engine.DumpImage("LandPassMap.png", landPassMap, this.passabilityMap.width, this.passabilityMap.height, 255);
|
||||
Engine.DumpImage("WaterPassMap.png", waterPassMap, this.passabilityMap.width, this.passabilityMap.height, 255);
|
||||
Engine.DumpImage("ObstrctionMap.png", obstructionMap, this.passabilityMap.width, this.passabilityMap.height, 255);
|
||||
*/
|
||||
|
||||
if (!deserialization)
|
||||
{
|
||||
this._entities = new Map();
|
||||
|
||||
@@ -195,8 +195,9 @@ m.TerrainAnalysis.prototype.updateMapWithEvents = function(sharedAI)
|
||||
let ent = e.entityObj;
|
||||
if (ent.hasClass("Geology"))
|
||||
{
|
||||
let x = this.gamePosToMapPos(ent.position())[0];
|
||||
let y = this.gamePosToMapPos(ent.position())[1];
|
||||
let pos = this.gamePosToMapPos(ent.position());
|
||||
let x = pos[0];
|
||||
let y = pos[1];
|
||||
// remove it. Don't really care about surrounding and possible overlappings.
|
||||
let radius = Math.floor(ent.obstructionRadius() / this.cellSize);
|
||||
for (let xx = -radius; xx <= radius;xx++)
|
||||
@@ -208,8 +209,9 @@ m.TerrainAnalysis.prototype.updateMapWithEvents = function(sharedAI)
|
||||
}
|
||||
else if (ent.hasClass("ForestPlant"))
|
||||
{
|
||||
let x = this.gamePosToMapPos(ent.position())[0];
|
||||
let y = this.gamePosToMapPos(ent.position())[1];
|
||||
let pos = this.gamePosToMapPos(ent.position());
|
||||
let x = pos[0];
|
||||
let y = pos[1];
|
||||
let nbOfNeigh = 0;
|
||||
for (let xx = -1; xx <= 1;xx++)
|
||||
for (let yy = -1; yy <= 1;yy++)
|
||||
@@ -238,11 +240,10 @@ m.TerrainAnalysis.prototype.updateMapWithEvents = function(sharedAI)
|
||||
* it can also determine if any point is "probably" reachable, assuming the unit can get close enough
|
||||
* for optimizations it's called after the TerrainAnalyser has finished initializing his map
|
||||
* so this can use the land regions already.
|
||||
|
||||
*/
|
||||
m.Accessibility = function() {
|
||||
|
||||
}
|
||||
m.Accessibility = function()
|
||||
{
|
||||
};
|
||||
|
||||
m.copyPrototype(m.Accessibility, m.TerrainAnalysis);
|
||||
|
||||
@@ -262,13 +263,17 @@ m.Accessibility.prototype.init = function(rawState, terrainAnalyser)
|
||||
// So start at 2.
|
||||
this.regionID = 2;
|
||||
|
||||
for (var i = 0; i < this.landPassMap.length; ++i) {
|
||||
if (this.map[i] !== 0) { // any non-painted, non-inacessible area.
|
||||
for (var i = 0; i < this.landPassMap.length; ++i)
|
||||
{
|
||||
if (this.map[i] !== 0)
|
||||
{ // any non-painted, non-inacessible area.
|
||||
if (this.landPassMap[i] === 0 && this.floodFill(i,this.regionID,false))
|
||||
this.regionType[this.regionID++] = "land";
|
||||
if (this.navalPassMap[i] === 0 && this.floodFill(i,this.regionID,true))
|
||||
this.regionType[this.regionID++] = "water";
|
||||
} else if (this.landPassMap[i] === 0) { // any non-painted, inacessible area.
|
||||
}
|
||||
else if (this.landPassMap[i] === 0)
|
||||
{ // any non-painted, inacessible area.
|
||||
this.floodFill(i,1,false);
|
||||
this.floodFill(i,1,true);
|
||||
}
|
||||
@@ -318,7 +323,8 @@ m.Accessibility.prototype.init = function(rawState, terrainAnalyser)
|
||||
//Engine.DumpImage("NavalPassMap.png", this.navalPassMap, this.width, this.height, 255);
|
||||
};
|
||||
|
||||
m.Accessibility.prototype.getAccessValue = function(position, onWater) {
|
||||
m.Accessibility.prototype.getAccessValue = function(position, onWater)
|
||||
{
|
||||
var gamePos = this.gamePosToMapPos(position);
|
||||
if (onWater === true)
|
||||
return this.navalPassMap[gamePos[0] + this.width*gamePos[1]];
|
||||
|
||||
@@ -69,12 +69,59 @@ m.ShallowClone = function(obj)
|
||||
}
|
||||
|
||||
// Picks a random element from an array
|
||||
m.PickRandom = function(list){
|
||||
m.PickRandom = function(list)
|
||||
{
|
||||
if (list.length === 0)
|
||||
return undefined;
|
||||
else
|
||||
return list[Math.floor(Math.random()*list.length)];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Utility functions for conversions of maps of different sizes
|
||||
// It expects that cell size of map 1 is a multiple of cell size of map 2
|
||||
|
||||
// return the index of map2 with max content from indices contained inside the cell i of map1
|
||||
m.getMaxMapIndex = function(i, map1, map2)
|
||||
{
|
||||
var ratio = map1.cellSize / map2.cellSize;
|
||||
var ix = (i % map1.width) * ratio;
|
||||
var iy = Math.floor(i / map1.width) * ratio;
|
||||
var index = undefined;
|
||||
for (var kx = 0; kx < ratio; ++kx)
|
||||
for (var ky = 0; ky < ratio; ++ky)
|
||||
if (!index || map2.map[ix+kx+(iy+ky)*map2.width] > map2.map[index])
|
||||
index = ix+kx+(iy+ky)*map2.width;
|
||||
return index;
|
||||
};
|
||||
|
||||
// return the list of indices of map2 contained inside the cell i of map1
|
||||
// map1.cellSize must be a multiple of map2.cellSize
|
||||
m.getMapIndices = function(i, map1, map2)
|
||||
{
|
||||
var ratio = map1.cellSize / map2.cellSize; // TODO check that this is integer >= 1 ?
|
||||
var ix = (i % map1.width) * ratio;
|
||||
var iy = Math.floor(i / map1.width) * ratio;
|
||||
var ret = [];
|
||||
for (var kx = 0; kx < ratio; ++kx)
|
||||
for (var ky = 0; ky < ratio; ++ky)
|
||||
ret.push(ix+kx+(iy+ky)*map2.width);
|
||||
return ret;
|
||||
};
|
||||
|
||||
// return the list of points of map2 contained inside the cell i of map1
|
||||
// map1.cellSize must be a multiple of map2.cellSize
|
||||
m.getMapPoints = function(i, map1, map2)
|
||||
{
|
||||
var ratio = map1.cellSize / map2.cellSize; // TODO check that this is integer >= 1 ?
|
||||
var ix = (i % map1.width) * ratio;
|
||||
var iy = Math.floor(i / map1.width) * ratio;
|
||||
var ret = [];
|
||||
for (var kx = 0; kx < ratio; ++kx)
|
||||
for (var ky = 0; ky < ratio; ++ky)
|
||||
ret.push([ix+kx, iy+ky]);
|
||||
return ret;
|
||||
};
|
||||
|
||||
return m;
|
||||
|
||||
|
||||
@@ -298,17 +298,21 @@ m.BaseManager.prototype.findBestDropsiteLocation = function(gameState, resource)
|
||||
var DPFoundations = gameState.getOwnFoundations().filter(API3.Filters.byType(gameState.applyCiv("foundation|structures/{civ}_storehouse"))).toEntityArray();
|
||||
var ccEnts = gameState.getOwnStructures().filter(API3.Filters.byClass("CivCentre")).toEntityArray();
|
||||
|
||||
var width = obstructions.width;
|
||||
var bestIdx = undefined;
|
||||
var bestVal = undefined;
|
||||
var radius = Math.ceil(template.obstructionRadius() / obstructions.cellSize);
|
||||
|
||||
var territoryMap = gameState.sharedScript.territoryMap;
|
||||
var width = territoryMap.width;
|
||||
var cellSize = territoryMap.cellSize;
|
||||
|
||||
for (var p = 0; p < this.territoryIndices.length; ++p)
|
||||
{
|
||||
var j = this.territoryIndices[p];
|
||||
if (obstructions.map[j] <= radius) // check room around
|
||||
var i = API3.getMaxMapIndex(j, territoryMap, obstructions);
|
||||
if (obstructions.map[i] <= radius) // check room around
|
||||
continue;
|
||||
|
||||
|
||||
// we add 3 times the needed resource and once the other two (not food)
|
||||
var total = 0;
|
||||
for (var i in gameState.sharedScript.resourceMaps)
|
||||
@@ -322,8 +326,7 @@ m.BaseManager.prototype.findBestDropsiteLocation = function(gameState, resource)
|
||||
|
||||
total = 0.7*total; // Just a normalisation factor as the locateMap is limited to 255
|
||||
|
||||
var pos = [j%width+0.5, Math.floor(j/width)+0.5];
|
||||
pos = [gameState.cellSize*pos[0], gameState.cellSize*pos[1]];
|
||||
var pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)];
|
||||
for (var i in this.dropsites)
|
||||
{
|
||||
if (!gameState.getEntityById(i))
|
||||
@@ -388,8 +391,9 @@ m.BaseManager.prototype.findBestDropsiteLocation = function(gameState, resource)
|
||||
|
||||
if (bestVal <= 0)
|
||||
return {"quality": bestVal, "pos": [0, 0]};
|
||||
var x = ((bestIdx % width) + 0.5) * gameState.cellSize;
|
||||
var z = (Math.floor(bestIdx / width) + 0.5) * gameState.cellSize;
|
||||
var i = API3.getMaxMapIndex(bestIdx, territoryMap, obstructions);
|
||||
var x = ((i % obstructions.width) + 0.5) * obstructions.cellSize;
|
||||
var z = (Math.floor(i / obstructions.width) + 0.5) * obstructions.cellSize;
|
||||
return {"quality": bestVal, "pos": [x, z]};
|
||||
};
|
||||
|
||||
|
||||
@@ -53,10 +53,10 @@ m.HQ.prototype.init = function(gameState, queues, deserializing)
|
||||
this.territoryMap = m.createTerritoryMap(gameState);
|
||||
// initialize base map. Each pixel is a base ID, or 0 if not or not accessible
|
||||
this.basesMap = new API3.Map(gameState.sharedScript, "territory");
|
||||
// area of 10 cells on the border of the map : 0=inside map, 1=border map, 2=outside map
|
||||
// area of n cells on the border of the map : 0=inside map, 1=border map, 2=border+inaccessible
|
||||
this.borderMap = m.createBorderMap(gameState);
|
||||
// initialize frontier map. Each cell is 2 if on the near frontier, 1 on the frontier and 0 otherwise
|
||||
this.frontierMap = m.createFrontierMap(gameState, this.borderMap);
|
||||
this.frontierMap = m.createFrontierMap(gameState);
|
||||
// list of allowed regions
|
||||
this.allowedRegions = {};
|
||||
|
||||
@@ -64,14 +64,16 @@ m.HQ.prototype.init = function(gameState, queues, deserializing)
|
||||
this.navalMap = false;
|
||||
this.navalRegions = [];
|
||||
|
||||
var totalSize = gameState.getMap().width * gameState.getMap().width;
|
||||
var passabilityMap = gameState.getMap();
|
||||
var totalSize = passabilityMap.width * passabilityMap.width;
|
||||
var minLandSize = Math.floor(0.2*totalSize);
|
||||
var minWaterSize = Math.floor(0.3*totalSize);
|
||||
var cellArea = passabilityMap.cellSize * passabilityMap.cellSize;
|
||||
for (var i = 0; i < gameState.ai.accessibility.regionSize.length; ++i)
|
||||
{
|
||||
if (i == gameState.ai.myIndex)
|
||||
this.allowedRegions[i] = true;
|
||||
else if (gameState.ai.accessibility.regionType[i] === "land" && gameState.ai.accessibility.regionSize[i] > 20)
|
||||
else if (gameState.ai.accessibility.regionType[i] === "land" && cellArea*gameState.ai.accessibility.regionSize[i] > 320)
|
||||
{
|
||||
var seaIndex = this.getSeaIndex(gameState, gameState.ai.myIndex, i);
|
||||
if (!seaIndex)
|
||||
@@ -94,7 +96,7 @@ m.HQ.prototype.init = function(gameState, queues, deserializing)
|
||||
if (this.Config.debug > 2)
|
||||
{
|
||||
for (var region in this.allowedRegions)
|
||||
API3.warn(" >>> zone " + region + " taille " + gameState.ai.accessibility.regionSize[region]);
|
||||
API3.warn(" >>> zone " + region + " taille " + cellArea*gameState.ai.accessibility.regionSize[region]);
|
||||
}
|
||||
|
||||
if (this.Config.difficulty < 2)
|
||||
@@ -315,9 +317,11 @@ m.HQ.prototype.start = function(gameState, deserializing)
|
||||
break;
|
||||
}
|
||||
}
|
||||
var cell = gameState.getMap().cellSize;
|
||||
startingSize = startingSize * cell * cell;
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("starting size " + startingSize + "(cut at 1500 for fish pushing)");
|
||||
if (startingSize < 1500)
|
||||
API3.warn("starting size " + startingSize + "(cut at 24000 for fish pushing)");
|
||||
if (startingSize < 24000)
|
||||
{
|
||||
this.saveSpace = true;
|
||||
this.Config.Economy.popForDock = Math.min(this.Config.Economy.popForDock, 16);
|
||||
@@ -796,27 +800,29 @@ m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource,
|
||||
for (var dp of dpEnts.values())
|
||||
dpList.push({"pos": dp.position()});
|
||||
|
||||
var width = this.territoryMap.width;
|
||||
var radius = Math.ceil(template.obstructionRadius() / gameState.cellSize);
|
||||
var bestIdx = undefined;
|
||||
var bestVal = undefined;
|
||||
var radius = Math.ceil(template.obstructionRadius() / obstructions.cellSize);
|
||||
|
||||
var width = this.territoryMap.width;
|
||||
var cellSize = this.territoryMap.cellSize;
|
||||
|
||||
for (var j = 0; j < this.territoryMap.length; ++j)
|
||||
{
|
||||
if (this.territoryMap.getOwnerIndex(j) != 0 || this.borderMap.map[j] == 2)
|
||||
if (this.territoryMap.getOwnerIndex(j) != 0)
|
||||
continue;
|
||||
// We require that it is accessible
|
||||
var index = gameState.ai.accessibility.landPassMap[j];
|
||||
if (!this.allowedRegions[index])
|
||||
continue;
|
||||
// and with enough room around to build the cc
|
||||
if (obstructions.map[j] <= radius)
|
||||
var i = API3.getMaxMapIndex(j, this.territoryMap, obstructions);
|
||||
if (obstructions.map[i] <= radius)
|
||||
continue;
|
||||
|
||||
var norm = 0.5; // TODO adjust it, knowing that we will sum 5 maps
|
||||
// checking distance to other cc
|
||||
var pos = [j%width+0.5, Math.floor(j/width)+0.5];
|
||||
pos = [gameState.cellSize*pos[0], gameState.cellSize*pos[1]];
|
||||
var pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)];
|
||||
var minDist = Math.min();
|
||||
|
||||
for (var cc of ccList)
|
||||
@@ -873,7 +879,7 @@ m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource,
|
||||
if (norm == 0)
|
||||
continue;
|
||||
|
||||
if (this.borderMap.map[j] == 1) // disfavor the borders of the map
|
||||
if (this.borderMap.map[j] > 0) // disfavor the borders of the map
|
||||
norm *= 0.5;
|
||||
|
||||
var val = 2*gameState.sharedScript.CCResourceMaps[resource].map[j]
|
||||
@@ -899,19 +905,19 @@ m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource,
|
||||
if (bestVal < cut)
|
||||
return false;
|
||||
|
||||
var x = (bestIdx%width + 0.5) * gameState.cellSize;
|
||||
var z = (Math.floor(bestIdx/width) + 0.5) * gameState.cellSize;
|
||||
var i = API3.getMaxMapIndex(bestIdx, this.territoryMap, obstructions);
|
||||
var x = (i % obstructions.width + 0.5) * obstructions.cellSize;
|
||||
var z = (Math.floor(i / obstructions.width) + 0.5) * obstructions.cellSize;
|
||||
|
||||
// Define a minimal number of wanted ships in the seas reaching this new base
|
||||
var index = gameState.ai.accessibility.landPassMap[bestIdx];
|
||||
var index = gameState.ai.accessibility.landPassMap[i];
|
||||
for each (var base in this.baseManagers)
|
||||
{
|
||||
if (base.anchor && base.accessIndex != index)
|
||||
{
|
||||
var sea = this.getSeaIndex(gameState, base.accessIndex, index);
|
||||
if (sea !== undefined)
|
||||
this.navalManager.setMinimalTransportShips(gameState, sea, 1);
|
||||
}
|
||||
if (!base.anchor || base.accessIndex === index)
|
||||
continue;
|
||||
var sea = this.getSeaIndex(gameState, base.accessIndex, index);
|
||||
if (sea !== undefined)
|
||||
this.navalManager.setMinimalTransportShips(gameState, sea, 1);
|
||||
}
|
||||
|
||||
return [x,z];
|
||||
@@ -945,28 +951,30 @@ m.HQ.prototype.findStrategicCCLocation = function(gameState, template)
|
||||
var obstructions = m.createObstructionMap(gameState, 0, template);
|
||||
obstructions.expandInfluences();
|
||||
|
||||
var width = this.territoryMap.width;
|
||||
var radius = Math.ceil(template.obstructionRadius() / gameState.cellSize);
|
||||
var bestIdx = undefined;
|
||||
var bestVal = undefined;
|
||||
var radius = Math.ceil(template.obstructionRadius() / obstructions.cellSize);
|
||||
|
||||
var width = this.territoryMap.width;
|
||||
var cellSize = this.territoryMap.cellSize;
|
||||
var currentVal, delta;
|
||||
var distcc0, distcc1, distcc2;
|
||||
|
||||
for (var j = 0; j < this.territoryMap.length; ++j)
|
||||
{
|
||||
if (this.territoryMap.getOwnerIndex(j) != 0 || this.borderMap.map[j] == 2)
|
||||
if (this.territoryMap.getOwnerIndex(j) != 0)
|
||||
continue;
|
||||
// We require that it is accessible
|
||||
var index = gameState.ai.accessibility.landPassMap[j];
|
||||
if (!this.allowedRegions[index])
|
||||
continue;
|
||||
// and with enough room around to build the cc
|
||||
if (obstructions.map[j] <= radius)
|
||||
var i = API3.getMaxMapIndex(j, this.territoryMap, obstructions);
|
||||
if (obstructions.map[i] <= radius)
|
||||
continue;
|
||||
|
||||
// checking distances to other cc
|
||||
var pos = [j%width+0.5, Math.floor(j/width)+0.5];
|
||||
pos = [gameState.cellSize*pos[0], gameState.cellSize*pos[1]];
|
||||
var pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)];
|
||||
var minDist = Math.min();
|
||||
distcc0 = undefined;
|
||||
|
||||
@@ -1015,7 +1023,7 @@ m.HQ.prototype.findStrategicCCLocation = function(gameState, template)
|
||||
currentVal += delta*delta;
|
||||
}
|
||||
// disfavor border of the map
|
||||
if (this.borderMap.map[j] == 1)
|
||||
if (this.borderMap.map[j] > 0)
|
||||
currentVal += 10000;
|
||||
|
||||
if (bestVal !== undefined && currentVal > bestVal)
|
||||
@@ -1032,19 +1040,19 @@ m.HQ.prototype.findStrategicCCLocation = function(gameState, template)
|
||||
if (bestVal === undefined)
|
||||
return undefined;
|
||||
|
||||
var x = (bestIdx%width + 0.5) * gameState.cellSize;
|
||||
var z = (Math.floor(bestIdx/width) + 0.5) * gameState.cellSize;
|
||||
var i = API3.getMaxMapIndex(bestIdx, this.territoryMap, obstructions);
|
||||
var x = (i % obstructions.width + 0.5) * obstructions.cellSize;
|
||||
var z = (Math.floor(i / obstructions.width) + 0.5) * obstructions.cellSize;
|
||||
|
||||
// Define a minimal number of wanted ships in the seas reaching this new base
|
||||
var index = gameState.ai.accessibility.landPassMap[bestIdx];
|
||||
var index = gameState.ai.accessibility.landPassMap[i];
|
||||
for each (var base in this.baseManagers)
|
||||
{
|
||||
if (base.anchor && base.accessIndex != index)
|
||||
{
|
||||
var sea = this.getSeaIndex(gameState, base.accessIndex, index);
|
||||
if (sea !== undefined)
|
||||
this.navalManager.setMinimalTransportShips(gameState, sea, 1);
|
||||
}
|
||||
if (!base.anchor || base.accessIndex === index)
|
||||
continue;
|
||||
var sea = this.getSeaIndex(gameState, base.accessIndex, index);
|
||||
if (sea !== undefined)
|
||||
this.navalManager.setMinimalTransportShips(gameState, sea, 1);
|
||||
}
|
||||
|
||||
return [x,z];
|
||||
@@ -1067,12 +1075,14 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
|
||||
var obstructions = m.createObstructionMap(gameState, 0, template);
|
||||
obstructions.expandInfluences();
|
||||
|
||||
var width = this.territoryMap.width;
|
||||
var bestIdx = undefined;
|
||||
var bestVal = undefined;
|
||||
var radius = Math.ceil(template.obstructionRadius() / gameState.cellSize);
|
||||
var radius = Math.ceil(template.obstructionRadius() / obstructions.cellSize);
|
||||
var isNavalMarket = template.hasClass("NavalMarket");
|
||||
|
||||
var width = this.territoryMap.width;
|
||||
var cellSize = this.territoryMap.cellSize;
|
||||
|
||||
for (var j = 0; j < this.territoryMap.length; ++j)
|
||||
{
|
||||
// do not try on the border of our territory
|
||||
@@ -1080,14 +1090,15 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
|
||||
continue;
|
||||
if (this.basesMap.map[j] == 0) // only in our territory
|
||||
continue;
|
||||
if (obstructions.map[j] <= radius) // check room around
|
||||
// with enough room around to build the cc
|
||||
var i = API3.getMaxMapIndex(j, this.territoryMap, obstructions);
|
||||
if (obstructions.map[i] <= radius)
|
||||
continue;
|
||||
var index = gameState.ai.accessibility.landPassMap[j];
|
||||
var index = gameState.ai.accessibility.landPassMap[i];
|
||||
if (!this.allowedRegions[index])
|
||||
continue;
|
||||
|
||||
var pos = [j%width+0.5, Math.floor(j/width)+0.5];
|
||||
pos = [gameState.cellSize*pos[0], gameState.cellSize*pos[1]];
|
||||
var pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)];
|
||||
// checking distances to other markets
|
||||
var maxDist = 0;
|
||||
for (var market of markets)
|
||||
@@ -1124,8 +1135,9 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
|
||||
(expectedGain < 8 && (!template.hasClass("BarterMarket") || gameState.getOwnStructures().filter(API3.Filters.byClass("BarterMarket")).length > 0)))
|
||||
return false;
|
||||
|
||||
var x = (bestIdx%width + 0.5) * gameState.cellSize;
|
||||
var z = (Math.floor(bestIdx/width) + 0.5) * gameState.cellSize;
|
||||
var i = API3.getMaxMapIndex(bestIdx, this.territoryMap, obstructions);
|
||||
var x = (i % obstructions.width + 0.5) * obstructions.cellSize;
|
||||
var z = (Math.floor(i / obstructions.width) + 0.5) * obstructions.cellSize;
|
||||
return [x, z, this.basesMap.map[bestIdx], expectedGain];
|
||||
};
|
||||
|
||||
@@ -1154,16 +1166,17 @@ m.HQ.prototype.findDefensiveLocation = function(gameState, template)
|
||||
var obstructions = m.createObstructionMap(gameState, 0, template);
|
||||
obstructions.expandInfluences();
|
||||
|
||||
var width = this.territoryMap.width;
|
||||
var bestIdx = undefined;
|
||||
var bestVal = undefined;
|
||||
var width = this.territoryMap.width;
|
||||
var cellSize = this.territoryMap.cellSize;
|
||||
|
||||
var isTower = template.hasClass("Tower");
|
||||
var isFortress = template.hasClass("Fortress");
|
||||
if (isFortress)
|
||||
var radius = Math.floor(template.obstructionRadius() / gameState.cellSize) + 2;
|
||||
var radius = Math.floor((template.obstructionRadius() + 8) / obstructions.cellSize);
|
||||
else
|
||||
var radius = Math.ceil(template.obstructionRadius() / gameState.cellSize);
|
||||
var radius = Math.ceil(template.obstructionRadius() / obstructions.cellSize);
|
||||
|
||||
for (var j = 0; j < this.territoryMap.length; ++j)
|
||||
{
|
||||
@@ -1177,11 +1190,12 @@ m.HQ.prototype.findDefensiveLocation = function(gameState, template)
|
||||
}
|
||||
if (this.basesMap.map[j] == 0) // inaccessible cell
|
||||
continue;
|
||||
if (obstructions.map[j] <= radius) // check room around
|
||||
// and with enough room around to build the cc
|
||||
var i = API3.getMaxMapIndex(j, this.territoryMap, obstructions);
|
||||
if (obstructions.map[i] <= radius)
|
||||
continue;
|
||||
|
||||
var pos = [j%width+0.5, Math.floor(j/width)+0.5];
|
||||
pos = [gameState.cellSize*pos[0], gameState.cellSize*pos[1]];
|
||||
var pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)];
|
||||
// checking distances to other structures
|
||||
var minDist = Math.min();
|
||||
|
||||
@@ -1240,8 +1254,9 @@ m.HQ.prototype.findDefensiveLocation = function(gameState, template)
|
||||
if (bestVal === undefined)
|
||||
return undefined;
|
||||
|
||||
var x = (bestIdx%width + 0.5) * gameState.cellSize;
|
||||
var z = (Math.floor(bestIdx/width) + 0.5) * gameState.cellSize;
|
||||
var i = API3.getMaxMapIndex(bestIdx, this.territoryMap, obstructions);
|
||||
var x = (i % obstructions.width + 0.5) * obstructions.cellSize;
|
||||
var z = (Math.floor(i / obstructions.width) + 0.5) * obstructions.cellSize;
|
||||
return [x, z, this.basesMap.map[bestIdx]];
|
||||
};
|
||||
|
||||
@@ -1774,11 +1789,13 @@ m.HQ.prototype.updateTerritories = function(gameState)
|
||||
return;
|
||||
this.lastTerritoryUpdate = gameState.ai.playedTurn;
|
||||
|
||||
var passabilityMap = gameState.getMap();
|
||||
var width = this.territoryMap.width;
|
||||
var cellSize = this.territoryMap.cellSize;
|
||||
var expansion = 0;
|
||||
for (var j = 0; j < this.territoryMap.length; ++j)
|
||||
{
|
||||
if (this.borderMap.map[j] == 2)
|
||||
if (this.borderMap.map[j] > 1)
|
||||
continue;
|
||||
if (this.territoryMap.getOwnerIndex(j) != PlayerID)
|
||||
{
|
||||
@@ -1796,18 +1813,27 @@ m.HQ.prototype.updateTerritories = function(gameState)
|
||||
}
|
||||
else if (this.basesMap.map[j] == 0)
|
||||
{
|
||||
var index = gameState.ai.accessibility.landPassMap[j];
|
||||
if (!this.allowedRegions[index])
|
||||
var landPassable = false;
|
||||
var ind = API3.getMapIndices(j, this.territoryMap, passabilityMap);
|
||||
var access;
|
||||
for (var k of ind)
|
||||
{
|
||||
if (!this.allowedRegions[gameState.ai.accessibility.landPassMap[k]])
|
||||
continue;
|
||||
landPassable = true;
|
||||
access = gameState.ai.accessibility.landPassMap[k];
|
||||
break;
|
||||
}
|
||||
if (!landPassable)
|
||||
continue;
|
||||
var distmin = Math.min();
|
||||
var baseID = undefined;
|
||||
var pos = [j%width+0.5, Math.floor(j/width)+0.5];
|
||||
pos = [gameState.cellSize*pos[0], gameState.cellSize*pos[1]];
|
||||
var pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)];
|
||||
for each (var base in this.baseManagers)
|
||||
{
|
||||
if (!base.anchor || !base.anchor.position())
|
||||
continue;
|
||||
if (base.accessIndex != index)
|
||||
if (base.accessIndex != access)
|
||||
continue;
|
||||
var dist = API3.SquareVectorDistance(base.anchor.position(), pos);
|
||||
if (dist >= distmin)
|
||||
@@ -1823,14 +1849,15 @@ m.HQ.prototype.updateTerritories = function(gameState)
|
||||
}
|
||||
}
|
||||
|
||||
this.frontierMap = m.createFrontierMap(gameState, this.borderMap);
|
||||
this.frontierMap = m.createFrontierMap(gameState);
|
||||
|
||||
if (!expansion)
|
||||
return;
|
||||
// We've increased our territory, so we may have some new room to build
|
||||
this.stopBuilding = [];
|
||||
// And if sufficient expansion, check if building a new market would improve our present trade routes
|
||||
if (expansion > 60)
|
||||
var cellArea = this.territoryMap.cellSize * this.territoryMap.cellSize;
|
||||
if (expansion * cellArea > 960)
|
||||
this.tradeManager.routeProspection = true;
|
||||
};
|
||||
|
||||
@@ -1875,7 +1902,7 @@ m.HQ.prototype.update = function(gameState, queues, events)
|
||||
return;
|
||||
if (!ent.position())
|
||||
return;
|
||||
var idlePos = ent.setMetadata(PlayerID, "idlePos");
|
||||
var idlePos = ent.getMetadata(PlayerID, "idlePos");
|
||||
if (idlePos === undefined || idlePos[0] !== ent.position()[0] || idlePos[1] !== ent.position()[1])
|
||||
{
|
||||
ent.setMetadata(PlayerID, "idlePos", ent.position());
|
||||
|
||||
@@ -38,7 +38,10 @@ m.createObstructionMap = function(gameState, accessIndex, template)
|
||||
for (var y = 0; y < passabilityMap.height; ++y)
|
||||
{
|
||||
var i = x + y*passabilityMap.width;
|
||||
var tilePlayer = (territoryMap.data[i] & m.TERRITORY_PLAYER_MASK);
|
||||
var xter = Math.floor((x+0.5)*passabilityMap.cellSize / territoryMap.cellSize);
|
||||
var yter = Math.floor((y+0.5)*passabilityMap.cellSize / territoryMap.cellSize);
|
||||
var iter = xter + yter*territoryMap.width;
|
||||
var tilePlayer = (territoryMap.data[iter] & m.TERRITORY_PLAYER_MASK);
|
||||
|
||||
//if (gameState.ai.myIndex !== gameState.ai.accessibility.landPassMap[i])
|
||||
//{
|
||||
@@ -100,7 +103,12 @@ m.createObstructionMap = function(gameState, accessIndex, template)
|
||||
|
||||
for (var i = 0; i < passabilityMap.data.length; ++i)
|
||||
{
|
||||
var tilePlayer = (territoryMap.data[i] & m.TERRITORY_PLAYER_MASK);
|
||||
var x = i % passabilityMap.width;
|
||||
var y = Math.floor(i / passabilityMap.width);
|
||||
var xter = Math.floor((x+0.5)*passabilityMap.cellSize / territoryMap.cellSize);
|
||||
var yter = Math.floor((y+0.5)*passabilityMap.cellSize / territoryMap.cellSize);
|
||||
var iter = xter + yter*territoryMap.width;
|
||||
var tilePlayer = (territoryMap.data[iter] & m.TERRITORY_PLAYER_MASK);
|
||||
var invalidTerritory = (
|
||||
(!buildOwn && tilePlayer == playerID) ||
|
||||
(!buildAlly && gameState.isPlayerAlly(tilePlayer) && tilePlayer != playerID) ||
|
||||
@@ -150,41 +158,56 @@ m.createTerritoryMap = function(gameState)
|
||||
return ret;
|
||||
};
|
||||
|
||||
// TODO check if not already done in obstruction maps
|
||||
// flag cells around the border of the map (2 if all points into that cell are inaccessible, 1 otherwise)
|
||||
m.createBorderMap = function(gameState)
|
||||
{
|
||||
var map = new API3.Map(gameState.sharedScript, "territory");
|
||||
var width = map.width;
|
||||
var border = Math.round(60 / map.cellSize);
|
||||
var passabilityMap = gameState.sharedScript.passabilityMap;
|
||||
var obstructionLandMask = gameState.getPassabilityClassMask("default");
|
||||
var obstructionWaterMask = gameState.getPassabilityClassMask("ship");
|
||||
if (gameState.ai.circularMap)
|
||||
{
|
||||
var ic = (width - 1) / 2;
|
||||
var radmax = (ic-3)*(ic-3); // we assume three inaccessible cells all around
|
||||
var radcut = (ic - border) * (ic - border);
|
||||
for (var j = 0; j < map.length; ++j)
|
||||
{
|
||||
var dx = j%width - ic;
|
||||
var dy = Math.floor(j/width) - ic;
|
||||
var radius = dx*dx + dy*dy;
|
||||
if (radius > radmax)
|
||||
map.map[j] = 2;
|
||||
else if (radius > (ic - border)*(ic - border))
|
||||
map.map[j] = 1;
|
||||
if (radius < radcut)
|
||||
continue;
|
||||
map.map[j] = 2;
|
||||
var ind = API3.getMapIndices(j, map, passabilityMap);
|
||||
for (var k of ind)
|
||||
{
|
||||
if ((passabilityMap.data[j] & obstructionLandMask) && (passabilityMap.data[j] & obstructionWaterMask))
|
||||
continue;
|
||||
map.map[j] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var borderCut = width - border;
|
||||
for (var j = 0; j < map.length; ++j)
|
||||
{
|
||||
var ix = j%width;
|
||||
var iy = Math.floor(j/width);
|
||||
if (ix < border || ix >= width - border)
|
||||
map.map[j] = 1;
|
||||
if (iy < border || iy >= width - border)
|
||||
map.map[j] = 1;
|
||||
if (ix < 3 || ix >= width - 3) // we assume three inaccessible cells all around
|
||||
map.map[j] = 2;
|
||||
if (iy < 3 || iy >= width - 3)
|
||||
if (ix < border || ix >= borderCut || iy < border || iy >= borderCut)
|
||||
{
|
||||
map.map[j] = 2;
|
||||
var ind = API3.getMapIndices(j, map, passabilityMap);
|
||||
for (var k of ind)
|
||||
{
|
||||
if ((passabilityMap.data[j] & obstructionLandMask) && (passabilityMap.data[j] & obstructionWaterMask))
|
||||
continue;
|
||||
map.map[j] = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,9 +216,10 @@ m.createBorderMap = function(gameState)
|
||||
};
|
||||
|
||||
// map of our frontier : 2 means narrow border, 1 means large border
|
||||
m.createFrontierMap = function(gameState, borderMap)
|
||||
m.createFrontierMap = function(gameState)
|
||||
{
|
||||
var territoryMap = gameState.ai.HQ.territoryMap;
|
||||
var borderMap = gameState.ai.HQ.borderMap;
|
||||
const around = [ [-0.7,0.7], [0,1], [0.7,0.7], [1,0], [0.7,-0.7], [0,-1], [-0.7,-0.7], [-1,0] ];
|
||||
|
||||
var map = new API3.Map(gameState.sharedScript, "territory");
|
||||
@@ -205,7 +229,7 @@ m.createFrontierMap = function(gameState, borderMap)
|
||||
|
||||
for (var j = 0; j < territoryMap.length; ++j)
|
||||
{
|
||||
if (territoryMap.getOwnerIndex(j) !== PlayerID || (borderMap && borderMap.map[j] > 1))
|
||||
if (territoryMap.getOwnerIndex(j) !== PlayerID || borderMap.map[j] > 1)
|
||||
continue;
|
||||
var ix = j%width;
|
||||
var iz = Math.floor(j/width);
|
||||
@@ -217,7 +241,7 @@ m.createFrontierMap = function(gameState, borderMap)
|
||||
var jz = iz + Math.round(insideSmall*a[1]);
|
||||
if (jz < 0 || jz >= width)
|
||||
continue;
|
||||
if (borderMap && borderMap.map[jx+width*jz] > 1)
|
||||
if (borderMap.map[jx+width*jz] > 1)
|
||||
continue;
|
||||
if (!gameState.isPlayerAlly(territoryMap.getOwnerIndex(jx+width*jz)))
|
||||
{
|
||||
@@ -230,7 +254,7 @@ m.createFrontierMap = function(gameState, borderMap)
|
||||
jz = iz + Math.round(insideLarge*a[1]);
|
||||
if (jz < 0 || jz >= width)
|
||||
continue;
|
||||
if (borderMap && borderMap.map[jx+width*jz] > 1)
|
||||
if (borderMap.map[jx+width*jz] > 1)
|
||||
continue;
|
||||
if (!gameState.isPlayerAlly(territoryMap.getOwnerIndex(jx+width*jz)))
|
||||
map.map[j] = 1;
|
||||
@@ -241,11 +265,12 @@ m.createFrontierMap = function(gameState, borderMap)
|
||||
return map;
|
||||
};
|
||||
|
||||
// return an measure of the proximity to our frontier (including our allies)
|
||||
// 0=inside, 1=less than 3 tiles, 2= less than 6 tiles, 3= less than 9 tiles, 4=less than 12 tiles, 5=above 12 tiles
|
||||
m.getFrontierProximity = function(gameState, j, borderMap)
|
||||
// return a measure of the proximity to our frontier (including our allies)
|
||||
// 0=inside, 1=less than 16m, 2= less than 32m, 3= less than 48m, 4=less than 64m, 5=above 64m
|
||||
m.getFrontierProximity = function(gameState, j)
|
||||
{
|
||||
var territoryMap = gameState.ai.HQ.territoryMap;
|
||||
var territoryMap = gameState.ai.HQ.territoryMap;
|
||||
var borderMap = gameState.ai.HQ.borderMap;
|
||||
const around = [ [-0.7,0.7], [0,1], [0.7,0.7], [1,0], [0.7,-0.7], [0,-1], [-0.7,-0.7], [-1,0] ];
|
||||
|
||||
var width = territoryMap.width;
|
||||
@@ -267,7 +292,7 @@ m.getFrontierProximity = function(gameState, j, borderMap)
|
||||
var jz = iz + Math.round(i*step*a[1]);
|
||||
if (jz < 0 || jz >= width)
|
||||
continue;
|
||||
if (borderMap && borderMap.map[jx+width*jz] > 1)
|
||||
if (borderMap.map[jx+width*jz] > 1)
|
||||
continue;
|
||||
if (gameState.isPlayerAlly(territoryMap.getOwnerIndex(jx+width*jz)))
|
||||
{
|
||||
|
||||
@@ -72,7 +72,7 @@ m.ConstructionPlan.prototype.start = function(gameState)
|
||||
var radius = (+this.template.get("Obstruction/Static/@depth"))/2;
|
||||
else
|
||||
var radius = 0;
|
||||
for (let step = 0; step < radius; step += gameState.cellSize)
|
||||
for (let step = 0; step < radius; step += 4)
|
||||
builders[0].construct(this.type, pos.x+step*sinang, pos.z+step*cosang,
|
||||
pos.angle, this.metadata);
|
||||
}
|
||||
@@ -135,18 +135,17 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
||||
}
|
||||
}
|
||||
|
||||
var cellSize = gameState.cellSize; // size of each tile
|
||||
|
||||
// First, find all tiles that are far enough away from obstructions:
|
||||
|
||||
var obstructionMap = m.createObstructionMap(gameState, 0, template);
|
||||
obstructionMap.expandInfluences();
|
||||
var obstructions = m.createObstructionMap(gameState, 0, template);
|
||||
obstructions.expandInfluences();
|
||||
|
||||
//obstructionMap.dumpIm(template.buildCategory() + "_obstructions.png");
|
||||
//obstructions.dumpIm(template.buildCategory() + "_obstructions.png");
|
||||
|
||||
// Compute each tile's closeness to friendly structures:
|
||||
|
||||
var friendlyTiles = new API3.Map(gameState.sharedScript, "passability");
|
||||
var placement = new API3.Map(gameState.sharedScript, "territory");
|
||||
var cellSize = placement.cellSize; // size of each tile
|
||||
|
||||
var alreadyHasHouses = false;
|
||||
|
||||
@@ -154,7 +153,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
||||
{
|
||||
var x = Math.floor(this.position[0] / cellSize);
|
||||
var z = Math.floor(this.position[1] / cellSize);
|
||||
friendlyTiles.addInfluence(x, z, 255);
|
||||
placement.addInfluence(x, z, 255);
|
||||
}
|
||||
else // No position was specified so try and find a sensible place to build
|
||||
{
|
||||
@@ -163,15 +162,15 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
||||
if (this.metadata && this.metadata.base !== undefined)
|
||||
{
|
||||
var base = this.metadata.base;
|
||||
for (var j = 0; j < friendlyTiles.map.length; ++j)
|
||||
for (var j = 0; j < placement.map.length; ++j)
|
||||
if (gameState.ai.HQ.basesMap.map[j] == base)
|
||||
friendlyTiles.map[j] = 45;
|
||||
placement.map[j] = 45;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var j = 0; j < friendlyTiles.map.length; ++j)
|
||||
for (var j = 0; j < placement.map.length; ++j)
|
||||
if (gameState.ai.HQ.basesMap.map[j] != 0)
|
||||
friendlyTiles.map[j] = 45;
|
||||
placement.map[j] = 45;
|
||||
}
|
||||
|
||||
if (!gameState.ai.HQ.requireHouses || !template.hasClass("House"))
|
||||
@@ -184,38 +183,38 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
||||
if (ent.resourceDropsiteTypes() && ent.resourceDropsiteTypes().indexOf("food") !== -1)
|
||||
{
|
||||
if (template.hasClass("Field"))
|
||||
friendlyTiles.addInfluence(x, z, 20, 50);
|
||||
placement.addInfluence(x, z, 20, 50);
|
||||
else // If this is not a field add a negative influence because we want to leave this area for fields
|
||||
friendlyTiles.addInfluence(x, z, 20, -20);
|
||||
placement.addInfluence(x, z, 20, -20);
|
||||
}
|
||||
else if (template.hasClass("House"))
|
||||
{
|
||||
if (ent.hasClass("House"))
|
||||
{
|
||||
friendlyTiles.addInfluence(x, z, 15, 40); // houses are close to other houses
|
||||
placement.addInfluence(x, z, 15, 40); // houses are close to other houses
|
||||
alreadyHasHouses = true;
|
||||
}
|
||||
else
|
||||
friendlyTiles.addInfluence(x, z, 15, -40); // and further away from other stuffs
|
||||
placement.addInfluence(x, z, 15, -40); // and further away from other stuffs
|
||||
}
|
||||
else if (template.hasClass("Farmstead") && (!ent.hasClass("Field")
|
||||
&& (!ent.hasClass("StoneWall") || ent.hasClass("Gates"))))
|
||||
friendlyTiles.addInfluence(x, z, 25, -25); // move farmsteads away to make room (StoneWall test needed for iber)
|
||||
placement.addInfluence(x, z, 25, -25); // move farmsteads away to make room (StoneWall test needed for iber)
|
||||
else if (template.hasClass("GarrisonFortress") && ent.genericName() == "House")
|
||||
friendlyTiles.addInfluence(x, z, 30, -50);
|
||||
placement.addInfluence(x, z, 30, -50);
|
||||
else if (template.hasClass("Military"))
|
||||
friendlyTiles.addInfluence(x, z, 10, -40);
|
||||
placement.addInfluence(x, z, 10, -40);
|
||||
});
|
||||
}
|
||||
|
||||
if (template.hasClass("Farmstead"))
|
||||
{
|
||||
for (var j = 0; j < friendlyTiles.map.length; ++j)
|
||||
for (var j = 0; j < placement.map.length; ++j)
|
||||
{
|
||||
var value = friendlyTiles.map[j] - (gameState.sharedScript.resourceMaps["wood"].map[j])/3;
|
||||
friendlyTiles.map[j] = value >= 0 ? value : 0;
|
||||
var value = placement.map[j] - (gameState.sharedScript.resourceMaps["wood"].map[j])/3;
|
||||
placement.map[j] = value >= 0 ? value : 0;
|
||||
if (gameState.ai.HQ.borderMap.map[j] > 0)
|
||||
friendlyTiles.map[j] /= 2; // we need space around farmstead, so disfavor map border
|
||||
placement.map[j] /= 2; // we need space around farmstead, so disfavor map border
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -228,44 +227,44 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
||||
if (this.metadata && this.metadata.base !== undefined)
|
||||
{
|
||||
var base = this.metadata.base;
|
||||
for (var j = 0; j < friendlyTiles.map.length; ++j)
|
||||
for (var j = 0; j < placement.map.length; ++j)
|
||||
{
|
||||
if (gameState.ai.HQ.basesMap.map[j] != base)
|
||||
friendlyTiles.map[j] = 0;
|
||||
placement.map[j] = 0;
|
||||
else if (favorBorder && gameState.ai.HQ.borderMap.map[j] > 0)
|
||||
friendlyTiles.map[j] += 50;
|
||||
else if (disfavorBorder && gameState.ai.HQ.borderMap.map[j] == 0 && friendlyTiles.map[j] > 0)
|
||||
friendlyTiles.map[j] += 10;
|
||||
placement.map[j] += 50;
|
||||
else if (disfavorBorder && gameState.ai.HQ.borderMap.map[j] == 0 && placement.map[j] > 0)
|
||||
placement.map[j] += 10;
|
||||
|
||||
if (friendlyTiles.map[j] > 0)
|
||||
if (placement.map[j] > 0)
|
||||
{
|
||||
var x = (j % friendlyTiles.width + 0.5) * cellSize;
|
||||
var z = (Math.floor(j / friendlyTiles.width) + 0.5) * cellSize;
|
||||
var x = (j % placement.width + 0.5) * cellSize;
|
||||
var z = (Math.floor(j / placement.width) + 0.5) * cellSize;
|
||||
if (gameState.ai.HQ.isDangerousLocation([x, z]))
|
||||
friendlyTiles.map[j] = 0;
|
||||
placement.map[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var j = 0; j < friendlyTiles.map.length; ++j)
|
||||
for (var j = 0; j < placement.map.length; ++j)
|
||||
{
|
||||
if (gameState.ai.HQ.basesMap.map[j] == 0)
|
||||
friendlyTiles.map[j] = 0;
|
||||
placement.map[j] = 0;
|
||||
else if (favorBorder && gameState.ai.HQ.borderMap.map[j] > 0)
|
||||
friendlyTiles.map[j] += 50;
|
||||
else if (disfavorBorder && gameState.ai.HQ.borderMap.map[j] == 0 && friendlyTiles.map[j] > 0)
|
||||
friendlyTiles.map[j] += 10;
|
||||
placement.map[j] += 50;
|
||||
else if (disfavorBorder && gameState.ai.HQ.borderMap.map[j] == 0 && placement.map[j] > 0)
|
||||
placement.map[j] += 10;
|
||||
|
||||
if (preferredBase && gameState.ai.HQ.basesMap.map[j] == this.metadata.preferredBase)
|
||||
friendlyTiles.map[j] += 200;
|
||||
placement.map[j] += 200;
|
||||
|
||||
if (friendlyTiles.map[j] > 0)
|
||||
if (placement.map[j] > 0)
|
||||
{
|
||||
var x = (j % friendlyTiles.width + 0.5) * cellSize;
|
||||
var z = (Math.floor(j / friendlyTiles.width) + 0.5) * cellSize;
|
||||
var x = (j % placement.width + 0.5) * cellSize;
|
||||
var z = (Math.floor(j / placement.width) + 0.5) * cellSize;
|
||||
if (gameState.ai.HQ.isDangerousLocation([x, z]))
|
||||
friendlyTiles.map[j] = 0;
|
||||
placement.map[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,24 +277,24 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
||||
var radius = 0;
|
||||
if (template.hasClass("Fortress") || this.type === gameState.applyCiv("structures/{civ}_siege_workshop")
|
||||
|| this.type === gameState.applyCiv("structures/{civ}_elephant_stables"))
|
||||
radius = Math.floor(template.obstructionRadius() / cellSize) + 3;
|
||||
radius = Math.floor((template.obstructionRadius() + 12) / obstructions.cellSize);
|
||||
else if (template.resourceDropsiteTypes() === undefined && !template.hasClass("House") && !template.hasClass("Field"))
|
||||
radius = Math.ceil(template.obstructionRadius() / cellSize) + 1;
|
||||
radius = Math.ceil((template.obstructionRadius() + 4) / obstructions.cellSize);
|
||||
else
|
||||
radius = Math.ceil(template.obstructionRadius() / cellSize);
|
||||
radius = Math.ceil(template.obstructionRadius() / obstructions.cellSize);
|
||||
|
||||
// Find the best non-obstructed
|
||||
if (template.hasClass("House") && !alreadyHasHouses)
|
||||
{
|
||||
// try to get some space first
|
||||
var bestTile = friendlyTiles.findBestTile(10, obstructionMap);
|
||||
// try to get some space to place several houses first
|
||||
var bestTile = placement.findBestTile(3*radius, obstructions);
|
||||
var bestIdx = bestTile[0];
|
||||
var bestVal = bestTile[1];
|
||||
}
|
||||
|
||||
if (bestVal === undefined || bestVal == -1)
|
||||
{
|
||||
var bestTile = friendlyTiles.findBestTile(radius, obstructionMap);
|
||||
var bestTile = placement.findBestTile(radius, obstructions);
|
||||
var bestIdx = bestTile[0];
|
||||
var bestVal = bestTile[1];
|
||||
}
|
||||
@@ -303,11 +302,11 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
||||
if (bestVal <= 0)
|
||||
return false;
|
||||
|
||||
var x = ((bestIdx % friendlyTiles.width) + 0.5) * cellSize;
|
||||
var z = (Math.floor(bestIdx / friendlyTiles.width) + 0.5) * cellSize;
|
||||
var x = ((bestIdx % obstructions.width) + 0.5) * obstructions.cellSize;
|
||||
var z = (Math.floor(bestIdx / obstructions.width) + 0.5) * obstructions.cellSize;
|
||||
|
||||
if (template.hasClass("House") || template.hasClass("Field") || template.resourceDropsiteTypes() !== undefined)
|
||||
var secondBest = obstructionMap.findLowestNeighbor(x,z);
|
||||
var secondBest = obstructions.findLowestNeighbor(x,z);
|
||||
else
|
||||
var secondBest = [x,z];
|
||||
|
||||
@@ -324,8 +323,8 @@ m.ConstructionPlan.prototype.findDockPosition = function(gameState)
|
||||
var cellSize = gameState.cellSize; // size of each tile
|
||||
var territoryMap = gameState.ai.HQ.territoryMap;
|
||||
|
||||
var obstructionMap = m.createObstructionMap(gameState, 0, template);
|
||||
//obstructionMap.dumpIm(template.buildCategory() + "_obstructions.png");
|
||||
var obstructions = m.createObstructionMap(gameState, 0, template);
|
||||
//obstructions.dumpIm(template.buildCategory() + "_obstructions.png");
|
||||
|
||||
var bestIdx = undefined;
|
||||
var bestVal = 0;
|
||||
@@ -333,7 +332,7 @@ m.ConstructionPlan.prototype.findDockPosition = function(gameState)
|
||||
var navalPassMap = gameState.ai.accessibility.navalPassMap;
|
||||
for (let j = 0; j < territoryMap.length; ++j)
|
||||
{
|
||||
if (obstructionMap.map[j] <= 0)
|
||||
if (obstructions.map[j] <= 0)
|
||||
continue;
|
||||
if (this.metadata)
|
||||
{
|
||||
@@ -347,7 +346,7 @@ m.ConstructionPlan.prototype.findDockPosition = function(gameState)
|
||||
continue;
|
||||
|
||||
// if not in our (or allied) territory, we do not want it too far to be able to defend it
|
||||
let nearby = m.getFrontierProximity(gameState, j, gameState.ai.HQ.borderMap);
|
||||
let nearby = m.getFrontierProximity(gameState, j);
|
||||
if (nearby > 4)
|
||||
continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user