1
0
forked from mirrors/0ad

Petra: try to improve cart shipyard placement

This was SVN commit r15286.
This commit is contained in:
mimo
2014-06-04 20:13:15 +00:00
parent d883fc332d
commit 0fcc074a65
4 changed files with 151 additions and 33 deletions
@@ -889,7 +889,7 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
return [-1, -1, -1];
// obstruction map
var obstructions = m.createObstructionMap(gameState, 0);
var obstructions = m.createObstructionMap(gameState, 0, template);
obstructions.expandInfluences();
var width = this.territoryMap.width;
@@ -906,8 +906,10 @@ m.HQ.prototype.findMarketLocation = function(gameState, template)
continue;
if (obstructions.map[j] <= radius) // check room around
continue;
var index = gameState.ai.accessibility.landPassMap[j];
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]];
// checking distances to other markets
@@ -1445,9 +1447,7 @@ m.HQ.prototype.updateTerritories = function(gameState)
continue;
var distmin = Math.min();
var baseID = undefined;
var ix = j%width;
var iy = Math.floor(j/width);
var pos = [ix+0.5, iy+0.5];
var pos = [j%width+0.5, Math.floor(j/width)+0.5];
pos = [gameState.cellSize*pos[0], gameState.cellSize*pos[1]];
for each (var base in this.baseManagers)
{
@@ -459,7 +459,7 @@ m.NavalManager.prototype.buildNavalStructures = function(gameState, queues)
if (gameState.countEntitiesAndQueuedByType(naval, true) < 1 && gameState.ai.HQ.canBuild(gameState, naval))
{
var sea = docks[0].getMetadata(PlayerID, "sea");
queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, naval, { "sea" : sea }));
queues.militaryBuilding.addItem(new m.ConstructionPlan(gameState, naval, { "sea": sea }));
break;
}
}
@@ -70,7 +70,7 @@ m.ConstructionPlan.prototype.start = function(gameState)
if (gameState.getTemplate(this.type).buildCategory() === "Dock")
{
// try to place it a bit inside the land if possible
for (var d = -10; d <= 0; d += 2)
for (var d = -10; d <= 2; d += 2)
builders[0].construct(this.type, pos.x+d*Math.sin(pos.angle), pos.z+d*Math.cos(pos.angle), pos.angle, this.metadata);
}
else if (pos.x == pos.xx && pos.z == pos.zz)
@@ -87,8 +87,12 @@ m.ConstructionPlan.prototype.start = function(gameState)
// TODO for dock, we should allow building them outside territory, and we should check that we are along the right sea
m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
{
var template = gameState.getTemplate(this.type);
if (template.buildCategory() === "Dock")
return this.findDockPosition(gameState);
if (!this.position)
{
if (template.hasClass("CivCentre"))
@@ -132,8 +136,7 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
// First, find all tiles that are far enough away from obstructions:
var obstructionMap = m.createObstructionMap(gameState, 0, template);
if (template.buildCategory() !== "Dock")
obstructionMap.expandInfluences();
obstructionMap.expandInfluences();
//obstructionMap.dumpIm(template.buildCategory() + "_obstructions.png");
@@ -256,8 +259,6 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
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;
else if (template.buildCategory() === "Dock")
radius = Math.ceil(template.obstructionRadius() / cellSize); // not used
else if (template.resourceDropsiteTypes() === undefined && !template.hasClass("House") && !template.hasClass("Field"))
radius = Math.ceil(template.obstructionRadius() / cellSize) + 1;
else
@@ -285,6 +286,128 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
var x = ((bestIdx % friendlyTiles.width) + 0.5) * cellSize;
var z = (Math.floor(bestIdx / friendlyTiles.width) + 0.5) * cellSize;
if (template.hasClass("House") || template.hasClass("Field") || template.resourceDropsiteTypes() !== undefined)
var secondBest = obstructionMap.findLowestNeighbor(x,z);
else
var secondBest = [x,z];
// default angle = 3*Math.PI/4;
return { "x": x, "z": z, "angle": 3*Math.PI/4, "xx": secondBest[0], "zz": secondBest[1],
"base": gameState.ai.HQ.basesMap.map[bestIdx] };
};
// Placement of buildings with Dock build category
// TODO for dock, we should allow building them outside territory, and we should check that we are along the right sea
m.ConstructionPlan.prototype.findDockPosition = function(gameState)
{
var template = gameState.getTemplate(this.type);
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.dumpIm(template.buildCategory() + "_obstructions.png");
// Compute each tile's closeness to friendly structures:
var friendlyTiles = new API3.Map(gameState.sharedScript);
if (this.position) // If a position was specified then place the building as close to it as possible
{
var x = Math.floor(this.position[0] / cellSize);
var z = Math.floor(this.position[1] / cellSize);
friendlyTiles.addInfluence(x, z, 255);
}
else // No position was specified so try and find a sensible place to build
{
// give a small > 0 level as the result of addInfluence is constrained to be > 0
// if we really need houses (i.e. townPhasing without enough village building), do not apply these constraints
if (this.metadata && this.metadata.base !== undefined)
{
var base = this.metadata.base;
for (var j = 0; j < friendlyTiles.map.length; ++j)
if (gameState.ai.HQ.basesMap.map[j] === base)
friendlyTiles.map[j] = 45;
}
else
{
for (var j = 0; j < friendlyTiles.map.length; ++j)
if (gameState.ai.HQ.basesMap.map[j] !== 0)
friendlyTiles.map[j] = 45;
}
if (!gameState.ai.HQ.requireHouses || !template.hasClass("House"))
{
gameState.getOwnStructures().forEach(function(ent) {
var pos = ent.position();
var x = Math.round(pos[0] / cellSize);
var z = Math.round(pos[1] / cellSize);
if (ent.resourceDropsiteTypes() && ent.resourceDropsiteTypes().indexOf("food") !== -1)
{
if (template.hasClass("Field"))
friendlyTiles.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);
}
else if (template.hasClass("GarrisonFortress") && ent.genericName() == "House")
friendlyTiles.addInfluence(x, z, 30, -50);
else if (template.hasClass("Military"))
friendlyTiles.addInfluence(x, z, 10, -40);
});
}
}
// requires to be inside our territory, and inside our base territory if required
// and if our first market, put it on border if possible to maximize distance with next market
var favorBorder = template.hasClass("BarterMarket");
var disfavorBorder = (template.buildCategory() === "Dock");
var preferredBase = (this.metadata && this.metadata.preferredBase);
if (this.metadata && this.metadata.base !== undefined)
{
var base = this.metadata.base;
for (var j = 0; j < friendlyTiles.map.length; ++j)
{
if (gameState.ai.HQ.basesMap.map[j] !== base)
friendlyTiles.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;
}
}
else
{
for (var j = 0; j < friendlyTiles.map.length; ++j)
{
if (gameState.ai.HQ.basesMap.map[j] === 0)
friendlyTiles.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;
if (preferredBase && gameState.ai.HQ.basesMap.map[j] === this.metadata.preferredBase)
friendlyTiles.map[j] += 200;
}
}
var radius = 1; // not used
if (bestVal === undefined || bestVal === -1)
{
var bestTile = friendlyTiles.findBestTile(radius, obstructionMap);
var bestIdx = bestTile[0];
var bestVal = bestTile[1];
}
if (bestVal <= 0)
return false;
var x = ((bestIdx % friendlyTiles.width) + 0.5) * cellSize;
var z = (Math.floor(bestIdx / friendlyTiles.width) + 0.5) * cellSize;
if (template.hasClass("House") || template.hasClass("Field") || template.resourceDropsiteTypes() !== undefined)
var secondBest = obstructionMap.findLowestNeighbor(x,z);
else
@@ -296,33 +419,28 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
// for Dock placement, we need to improve the position of the building as the position given here
// is only the position on the shore, while the need the position of the center of the building
// We also need to find the angle of the building
if (template.buildCategory() === "Dock")
{
var angle = this.getDockAngle(gameState, template, x, z);
if (!angle)
return false;
if (template.get("Obstruction") && template.get("Obstruction/Static"))
var radius = (+template.get("Obstruction/Static/@depth"))/2;
else if (template.get("Obstruction") && template.get("Obstruction/Unit"))
var radius = +template.get("Obstruction/Unit/@radius");
else
{
warn("Error: try to place a building without obstruction " + this.type);
var radius = 0;
}
// Position of the center of the building
x = x + radius*Math.sin(angle);
z = z + radius*Math.cos(angle);
}
var angle = this.getDockAngle(gameState, template, x, z);
if (!angle)
return false;
if (template.get("Obstruction") && template.get("Obstruction/Static"))
var radius = (+template.get("Obstruction/Static/@depth"))/2;
else if (template.get("Obstruction") && template.get("Obstruction/Unit"))
var radius = +template.get("Obstruction/Unit/@radius");
else
var angle = 3*Math.PI/4;
{
warn("Error: try to place a building without obstruction " + this.type);
var radius = 0;
}
// Position of the center of the building
x = x + radius*Math.sin(angle);
z = z + radius*Math.cos(angle);
// default angle = 3*Math.PI/4;
return { "x": x, "z": z, "angle": angle, "xx": secondBest[0], "zz": secondBest[1],
"base": gameState.ai.HQ.basesMap.map[bestIdx], "access": access };
};
// Algorithm taken from the function GetDockAngle in helpers/Commands.j
// Algorithm taken from the function GetDockAngle in helpers/Commands.js
m.ConstructionPlan.prototype.getDockAngle = function(gameState, template, x, z)
{
var radius = template.obstructionRadius();
@@ -348,7 +348,7 @@ m.TransportPlan.prototype.onSailing = function(gameState)
var self = this;
// Check that the units recovered on the previous turn have been reloaded
for each (var recov in this.recovered)
for (var recov of this.recovered)
{
var ent = gameState.getEntityById(recov.entId);
if (!ent) // entity destroyed
@@ -383,7 +383,7 @@ m.TransportPlan.prototype.onSailing = function(gameState)
// Check that the units unloaded on the previous turn have been really unloaded
var shipsToMove = {};
for each (var entId in this.unloaded)
for (var entId of this.unloaded)
{
var ent = gameState.getEntityById(entId);
if (!ent) // entity destroyed