mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-07-04 05:55:47 -07:00
Petra: complete the rework of starting game to allow more flexibility (i.e. support of nomad maps)
This was SVN commit r16142.
This commit is contained in:
parent
851d3d964a
commit
320cfa0bfc
8 changed files with 258 additions and 107 deletions
|
|
@ -457,6 +457,12 @@ m.Template = m.Class({
|
|||
return this.get("UnitMotion/WalkSpeed");
|
||||
},
|
||||
|
||||
trainingCategory: function() {
|
||||
if (!this.get("TrainingRestrictions") || !this.get("TrainingRestrictions/Category"))
|
||||
return undefined;
|
||||
return this.get("TrainingRestrictions/Category");
|
||||
},
|
||||
|
||||
buildCategory: function() {
|
||||
if (!this.get("BuildRestrictions") || !this.get("BuildRestrictions/Category"))
|
||||
return undefined;
|
||||
|
|
|
|||
|
|
@ -593,14 +593,8 @@ m.GameState.prototype.findTrainableUnits = function(classes, anticlasses)
|
|||
if (!okay)
|
||||
continue;
|
||||
|
||||
for (let limitedClass in limits)
|
||||
{
|
||||
if (!template.hasClass(limitedClass) || current[limitedClass] < limits[limitedClass])
|
||||
continue;
|
||||
okay = false;
|
||||
break;
|
||||
}
|
||||
if (!okay)
|
||||
let category = template.trainingCategory();
|
||||
if (category && limits[category] && current[category] >= limits[category])
|
||||
continue;
|
||||
|
||||
ret.push( [trainable, template] );
|
||||
|
|
|
|||
|
|
@ -409,24 +409,27 @@ m.BaseManager.prototype.checkResourceLevels = function (gameState, queues)
|
|||
{
|
||||
if (type == "food")
|
||||
{
|
||||
var count = this.getResourceLevel(gameState, type); // TODO animals are not accounted, may-be we should
|
||||
var numFarms = gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_field"), true);
|
||||
var numFound = gameState.countEntitiesByType(gameState.applyCiv("foundation|structures/{civ}_field"), true);
|
||||
var numQueue = queues.field.countQueuedUnits();
|
||||
if (gameState.ai.HQ.canBuild(gameState, "structures/{civ}_field")) // let's see if we need to add new farms.
|
||||
{
|
||||
var count = this.getResourceLevel(gameState, type); // TODO animals are not accounted, may-be we should
|
||||
var numFarms = gameState.countEntitiesByType(gameState.applyCiv("structures/{civ}_field"), true);
|
||||
var numFound = gameState.countEntitiesByType(gameState.applyCiv("foundation|structures/{civ}_field"), true);
|
||||
var numQueue = queues.field.countQueuedUnits();
|
||||
|
||||
// TODO if not yet farms, add a check on time used/lost and build farmstead if needed
|
||||
if (numFarms + numFound + numQueue === 0) // starting game, rely on fruits as long as we have enough of them
|
||||
{
|
||||
if (count < 600)
|
||||
queues.field.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID }));
|
||||
}
|
||||
else if (gameState.ai.HQ.canBuild(gameState, "structures/{civ}_field")) // let's see if we need to add new farms.
|
||||
{
|
||||
let goal = this.Config.Economy.provisionFields;
|
||||
if (gameState.ai.HQ.saveResources || gameState.ai.HQ.saveSpace)
|
||||
goal = Math.max(goal-1, 1);
|
||||
if (numFound + numQueue < goal)
|
||||
queues.field.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID }));
|
||||
// TODO if not yet farms, add a check on time used/lost and build farmstead if needed
|
||||
if (numFarms + numFound + numQueue === 0) // starting game, rely on fruits as long as we have enough of them
|
||||
{
|
||||
if (count < 600)
|
||||
queues.field.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID }));
|
||||
}
|
||||
else
|
||||
{
|
||||
let goal = this.Config.Economy.provisionFields;
|
||||
if (gameState.ai.HQ.saveResources || gameState.ai.HQ.saveSpace)
|
||||
goal = Math.max(goal-1, 1);
|
||||
if (numFound + numQueue < goal)
|
||||
queues.field.addItem(new m.ConstructionPlan(gameState, "structures/{civ}_field", { "base" : this.ID }));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (queues.dropsites.length() == 0 && gameState.countFoundationsByType(gameState.applyCiv("structures/{civ}_storehouse"), true) == 0)
|
||||
|
|
|
|||
|
|
@ -530,7 +530,7 @@ m.HQ.prototype.pickMostNeededResources = function(gameState)
|
|||
|
||||
// Returns the best position to build a new Civil Centre
|
||||
// Whose primary function would be to reach new resources of type "resource".
|
||||
m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource, fromStrategic)
|
||||
m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource, proximity, fromStrategic)
|
||||
{
|
||||
// This builds a map. The procedure is fairly simple. It adds the resource maps
|
||||
// (which are dynamically updated and are made so that they will facilitate DP placement)
|
||||
|
|
@ -555,6 +555,20 @@ m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource,
|
|||
var bestIdx = undefined;
|
||||
var bestVal = undefined;
|
||||
var radius = Math.ceil(template.obstructionRadius() / obstructions.cellSize);
|
||||
var scale = 250 * 250;
|
||||
var proxyAccess = undefined;
|
||||
var nbShips = this.navalManager.transportShips.length;
|
||||
if (proximity) // this is our first base
|
||||
{
|
||||
// if our first base, ensure room around
|
||||
radius = Math.ceil((template.obstructionRadius() + 8) / obstructions.cellSize);
|
||||
// scale is the typical scale at which we want to find a location for our first base
|
||||
// look for bigger scale if we start from a ship (access < 2) or from a small island
|
||||
var cellArea = gameState.getMap().cellSize * gameState.getMap().cellSize;
|
||||
proxyAccess = gameState.ai.accessibility.getAccessValue(proximity);
|
||||
if (proxyAccess < 2 || cellArea*gameState.ai.accessibility.regionSize[proxyAccess] < 24000)
|
||||
scale = 400 * 400;
|
||||
}
|
||||
|
||||
var width = this.territoryMap.width;
|
||||
var cellSize = this.territoryMap.cellSize;
|
||||
|
|
@ -567,6 +581,8 @@ m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource,
|
|||
var index = gameState.ai.accessibility.landPassMap[j];
|
||||
if (!this.landRegions[index])
|
||||
continue;
|
||||
if (proxyAccess && nbShips === 0 && proxyAccess !== index)
|
||||
continue;
|
||||
// and with enough room around to build the cc
|
||||
var i = API3.getMaxMapIndex(j, this.territoryMap, obstructions);
|
||||
if (obstructions.map[i] <= radius)
|
||||
|
|
@ -575,61 +591,71 @@ m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource,
|
|||
var norm = 0.5; // TODO adjust it, knowing that we will sum 5 maps
|
||||
// checking distance to other cc
|
||||
var pos = [cellSize * (j%width+0.5), cellSize * (Math.floor(j/width)+0.5)];
|
||||
var minDist = Math.min();
|
||||
|
||||
for (var cc of ccList)
|
||||
if (proximity) // this is our first cc, let's do it near our units
|
||||
{
|
||||
var dist = API3.SquareVectorDistance(cc.pos, pos);
|
||||
if (dist < 14000) // Reject if too near from any cc
|
||||
{
|
||||
norm = 0
|
||||
break;
|
||||
}
|
||||
if (!cc.ally)
|
||||
continue;
|
||||
if (dist < 30000) // Reject if too near from an allied cc
|
||||
{
|
||||
norm = 0
|
||||
break;
|
||||
}
|
||||
if (dist < 50000) // Disfavor if quite near an allied cc
|
||||
norm *= 0.5;
|
||||
if (dist < minDist)
|
||||
minDist = dist;
|
||||
var dist = API3.SquareVectorDistance(proximity, pos);
|
||||
norm /= (1 + dist/scale);
|
||||
}
|
||||
if (norm == 0)
|
||||
continue;
|
||||
if (minDist > 170000 && !this.navalMap) // Reject if too far from any allied cc (-> not connected)
|
||||
else
|
||||
{
|
||||
norm = 0;
|
||||
continue;
|
||||
}
|
||||
else if (minDist > 130000) // Disfavor if quite far from any allied cc
|
||||
{
|
||||
if (this.navalMap)
|
||||
var minDist = Math.min();
|
||||
|
||||
for (var cc of ccList)
|
||||
{
|
||||
if (minDist > 250000)
|
||||
var dist = API3.SquareVectorDistance(cc.pos, pos);
|
||||
if (dist < 14000) // Reject if too near from any cc
|
||||
{
|
||||
norm = 0
|
||||
break;
|
||||
}
|
||||
if (!cc.ally)
|
||||
continue;
|
||||
if (dist < 30000) // Reject if too near from an allied cc
|
||||
{
|
||||
norm = 0
|
||||
break;
|
||||
}
|
||||
if (dist < 50000) // Disfavor if quite near an allied cc
|
||||
norm *= 0.5;
|
||||
else
|
||||
norm *= 0.8;
|
||||
if (dist < minDist)
|
||||
minDist = dist;
|
||||
}
|
||||
else
|
||||
norm *= 0.5;
|
||||
}
|
||||
if (norm == 0)
|
||||
continue;
|
||||
|
||||
for (var dp of dpList)
|
||||
{
|
||||
var dist = API3.SquareVectorDistance(dp.pos, pos);
|
||||
if (dist < 3600)
|
||||
if (minDist > 170000 && !this.navalMap) // Reject if too far from any allied cc (not connected)
|
||||
{
|
||||
norm = 0;
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
else if (dist < 6400)
|
||||
norm *= 0.5;
|
||||
else if (minDist > 130000) // Disfavor if quite far from any allied cc
|
||||
{
|
||||
if (this.navalMap)
|
||||
{
|
||||
if (minDist > 250000)
|
||||
norm *= 0.5;
|
||||
else
|
||||
norm *= 0.8;
|
||||
}
|
||||
else
|
||||
norm *= 0.5;
|
||||
}
|
||||
|
||||
for (var dp of dpList)
|
||||
{
|
||||
var dist = API3.SquareVectorDistance(dp.pos, pos);
|
||||
if (dist < 3600)
|
||||
{
|
||||
norm = 0;
|
||||
break;
|
||||
}
|
||||
else if (dist < 6400)
|
||||
norm *= 0.5;
|
||||
}
|
||||
if (norm == 0)
|
||||
continue;
|
||||
}
|
||||
if (norm == 0)
|
||||
continue;
|
||||
|
||||
if (this.borderMap.map[j] > 0) // disfavor the borders of the map
|
||||
norm *= 0.5;
|
||||
|
|
@ -649,7 +675,7 @@ m.HQ.prototype.findEconomicCCLocation = function(gameState, template, resource,
|
|||
Engine.ProfileStop();
|
||||
|
||||
var cut = 60;
|
||||
if (fromStrategic) // be less restrictive
|
||||
if (fromStrategic || proximity) // be less restrictive
|
||||
cut = 30;
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("we have found a base for " + resource + " with best (cut=" + cut + ") = " + bestVal);
|
||||
|
|
@ -695,7 +721,7 @@ m.HQ.prototype.findStrategicCCLocation = function(gameState, template)
|
|||
++numAllyCC;
|
||||
}
|
||||
if (numAllyCC < 2)
|
||||
return this.findEconomicCCLocation(gameState, template, "wood", true);
|
||||
return this.findEconomicCCLocation(gameState, template, "wood", undefined, true);
|
||||
|
||||
Engine.ProfileStart("findStrategicCCLocation");
|
||||
|
||||
|
|
@ -1149,10 +1175,10 @@ m.HQ.prototype.checkBaseExpansion = function(gameState, queues)
|
|||
{
|
||||
if (queues.civilCentre.length() > 0)
|
||||
return;
|
||||
// first build one cc if none already available
|
||||
// first build one cc if all have been destroyed
|
||||
if (this.numActiveBase() < 1)
|
||||
{
|
||||
this.buildNewBase(gameState, queues);
|
||||
this.buildFirstBase(gameState);
|
||||
return;
|
||||
}
|
||||
// then expand if we have not enough room available for buildings
|
||||
|
|
@ -1176,7 +1202,7 @@ m.HQ.prototype.checkBaseExpansion = function(gameState, queues)
|
|||
}
|
||||
};
|
||||
|
||||
m.HQ.prototype.buildNewBase = function(gameState, queues, type)
|
||||
m.HQ.prototype.buildNewBase = function(gameState, queues, resource)
|
||||
{
|
||||
if (this.numActiveBase() > 0 && gameState.currentPhase() == 1 && !gameState.isResearching(gameState.townPhase()))
|
||||
return false;
|
||||
|
|
@ -1188,8 +1214,8 @@ m.HQ.prototype.buildNewBase = function(gameState, queues, type)
|
|||
|
||||
// base "-1" means new base.
|
||||
if (this.Config.debug > 1)
|
||||
API3.warn("new base planned with type " + type);
|
||||
queues.civilCentre.addItem(new m.ConstructionPlan(gameState, template, { "base": -1, "type": type }));
|
||||
API3.warn("new base planned with resource " + resource);
|
||||
queues.civilCentre.addItem(new m.ConstructionPlan(gameState, template, { "base": -1, "resource": resource }));
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -1520,9 +1546,9 @@ m.HQ.prototype.canBuild = function(gameState, structure)
|
|||
if (!template || !template.available(gameState))
|
||||
return false;
|
||||
var limits = gameState.getEntityLimits();
|
||||
for (var limitedClass in limits)
|
||||
if (template.hasClass(limitedClass) && gameState.getEntityCounts()[limitedClass] >= limits[limitedClass])
|
||||
return false;
|
||||
var category = template.buildCategory();
|
||||
if (category && limits[category] && gameState.getEntityCounts()[category] >= limits[category])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -388,6 +388,37 @@ m.NavalManager.prototype.splitTransport = function(gameState, plan)
|
|||
return (nbUnits !== 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* create a transport from a garrisoned ship to a land location
|
||||
* needed at start game when starting with a garrisoned ship
|
||||
*/
|
||||
m.NavalManager.prototype.createTransportIfNeeded = function(gameState, fromPos, toPos)
|
||||
{
|
||||
let fromAccess = gameState.ai.accessibility.getAccessValue(fromPos);
|
||||
if (fromAccess !== 1)
|
||||
return;
|
||||
let toAccess = gameState.ai.accessibility.getAccessValue(toPos);
|
||||
if (toAccess < 2)
|
||||
return;
|
||||
|
||||
for (let ship of this.ships.values())
|
||||
{
|
||||
if (!ship.isGarrisonHolder() || !ship.garrisoned().length)
|
||||
continue;
|
||||
if (ship.getMetadata(PlayerID, "transporter") !== undefined)
|
||||
continue;
|
||||
let units = [];
|
||||
for (let entId of ship.garrisoned())
|
||||
units.push(gameState.getEntityById(entId));
|
||||
// TODO check that the garrisoned units have not another purpose
|
||||
let plan = new m.TransportPlan(gameState, units, fromAccess, toAccess, toPos, ship);
|
||||
if (plan.failed)
|
||||
continue;
|
||||
plan.init(gameState);
|
||||
this.transportPlans.push(plan);
|
||||
}
|
||||
};
|
||||
|
||||
// set minimal number of needed ships when a new event (new base or new attack plan)
|
||||
m.NavalManager.prototype.setMinimalTransportShips = function(gameState, sea, number)
|
||||
{
|
||||
|
|
@ -606,15 +637,8 @@ m.NavalManager.prototype.getBestShip = function(gameState, sea, goal)
|
|||
if (!template.available(gameState))
|
||||
continue;
|
||||
|
||||
var aboveLimit = false;
|
||||
for (var limitedClass in limits)
|
||||
{
|
||||
if (!template.hasClass(limitedClass) || current[limitedClass] < limits[limitedClass])
|
||||
continue;
|
||||
aboveLimit = true;
|
||||
break;
|
||||
}
|
||||
if (aboveLimit)
|
||||
var category = template.trainingCategory();
|
||||
if (category && limits[category] && current[category] >= limits[category])
|
||||
continue;
|
||||
|
||||
var arrows = +(template.getDefaultArrow() || 0);
|
||||
|
|
@ -649,7 +673,7 @@ m.NavalManager.prototype.getBestShip = function(gameState, sea, goal)
|
|||
m.NavalManager.prototype.update = function(gameState, queues, events)
|
||||
{
|
||||
Engine.ProfileStart("Naval Manager update");
|
||||
|
||||
|
||||
this.checkEvents(gameState, queues, events);
|
||||
|
||||
// close previous transport plans if finished
|
||||
|
|
|
|||
|
|
@ -86,6 +86,10 @@ m.ConstructionPlan.prototype.start = function(gameState)
|
|||
}
|
||||
this.onStart(gameState);
|
||||
Engine.ProfileStop();
|
||||
|
||||
// TODO should have a ConstructionStarted event in case the construct order fails
|
||||
if (this.metadata && this.metadata.proximity)
|
||||
gameState.ai.HQ.navalManager.createTransportIfNeeded(gameState, this.metadata.proximity, [pos.x, pos.z]);
|
||||
};
|
||||
|
||||
// TODO for dock, we should allow building them outside territory, and we should check that we are along the right sea
|
||||
|
|
@ -101,8 +105,11 @@ m.ConstructionPlan.prototype.findGoodPosition = function(gameState)
|
|||
{
|
||||
if (template.hasClass("CivCentre"))
|
||||
{
|
||||
if (this.metadata.type)
|
||||
var pos = gameState.ai.HQ.findEconomicCCLocation(gameState, template, this.metadata.type);
|
||||
if (this.metadata.resource)
|
||||
{
|
||||
var proximity = this.metadata.proximity ? this.metadata.proximity : undefined;
|
||||
var pos = gameState.ai.HQ.findEconomicCCLocation(gameState, template, this.metadata.resource, proximity);
|
||||
}
|
||||
else
|
||||
var pos = gameState.ai.HQ.findStrategicCCLocation(gameState, template);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@ m.HQ.prototype.gameAnalysis = function(gameState)
|
|||
// Analysis of the terrain and the different access regions
|
||||
this.regionAnalysis(gameState);
|
||||
|
||||
this.attackManager.init(gameState);
|
||||
this.navalManager.init(gameState);
|
||||
this.tradeManager.init(gameState);
|
||||
|
||||
// Make a list of buildable structures from the config file
|
||||
this.structureAnalysis(gameState);
|
||||
|
||||
|
|
@ -30,7 +34,7 @@ m.HQ.prototype.gameAnalysis = function(gameState)
|
|||
// Assign entities and resources in the different bases
|
||||
this.assignStartingEntities(gameState);
|
||||
|
||||
// Check if we will ever be able to produce units
|
||||
// If no base yet, check if we can construct one. If not, dispatch our units to possible tasks/attacks
|
||||
this.canBuildUnits = true;
|
||||
if (!gameState.getOwnStructures().filter(API3.Filters.byClass("CivCentre")).length)
|
||||
{
|
||||
|
|
@ -42,12 +46,10 @@ m.HQ.prototype.gameAnalysis = function(gameState)
|
|||
this.canBuildUnits = false;
|
||||
this.dispatchUnits(gameState);
|
||||
}
|
||||
else
|
||||
this.buildFirstBase(gameState);
|
||||
}
|
||||
|
||||
this.attackManager.init(gameState);
|
||||
this.navalManager.init(gameState);
|
||||
this.tradeManager.init(gameState);
|
||||
|
||||
// configure our first base strategy
|
||||
if (this.baseManagers.length > 1)
|
||||
this.configFirstBase(gameState);
|
||||
|
|
@ -106,7 +108,7 @@ m.HQ.prototype.assignStartingEntities = function(gameState)
|
|||
if (!bestbase)
|
||||
{
|
||||
// entity outside our territory
|
||||
var bestbase = m.getBestBase(ent, gameState);
|
||||
bestbase = m.getBestBase(ent, gameState);
|
||||
bestbase.assignEntity(ent);
|
||||
if (bestbase.ID !== this.baseManagers[0].ID && ent.resourceDropsiteTypes() && !ent.hasClass("Elephant"))
|
||||
bestbase.assignResourceToDropsite(gameState, ent);
|
||||
|
|
@ -114,7 +116,7 @@ m.HQ.prototype.assignStartingEntities = function(gameState)
|
|||
// now assign entities garrisoned inside this entity
|
||||
if (ent.isGarrisonHolder() && ent.garrisoned().length)
|
||||
for (let id of ent.garrisoned())
|
||||
bestBase.assignEntity(gameState.getEntityByID(id));
|
||||
bestbase.assignEntity(gameState.getEntityById(id));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -226,6 +228,79 @@ m.HQ.prototype.structureAnalysis = function(gameState)
|
|||
this.bAdvanced[i] = gameState.applyCiv(this.bAdvanced[i]);
|
||||
};
|
||||
|
||||
/**
|
||||
* build our first base
|
||||
*/
|
||||
m.HQ.prototype.buildFirstBase = function(gameState)
|
||||
{
|
||||
var total = gameState.getResources();
|
||||
var template = gameState.getTemplate(gameState.applyCiv("structures/{civ}_civil_centre"));
|
||||
if (!total.canAfford(new API3.Resources(template.cost())))
|
||||
{
|
||||
/* API3.warn("not enough resource to build a cc, try with a dock");
|
||||
template = gameState.applyCiv("structures/{civ}_dock");
|
||||
if (!gameState.isDisabledTemplates(template))
|
||||
{
|
||||
template = gameState.getTemplate(template);
|
||||
if (!total.canAfford(new API3.Resources(template.cost())))
|
||||
{
|
||||
API3.warn("not enough resource for dock ... return");
|
||||
return;
|
||||
}
|
||||
API3.warn("but we could still build a dock if it was implemented");
|
||||
return;
|
||||
} */
|
||||
return;
|
||||
}
|
||||
|
||||
// We first choose as startingPoint the point where we have the more units
|
||||
let startingPoint = [];
|
||||
for (let ent of gameState.getOwnUnits().values())
|
||||
{
|
||||
if (!ent.hasClass("Worker") && !(ent.hasClass("Support") && ent.hasClass("Elephant")))
|
||||
continue;
|
||||
if (ent.hasClass("Cavalry"))
|
||||
continue;
|
||||
let pos = ent.position();
|
||||
if (!pos)
|
||||
{
|
||||
let holder = m.getHolder(ent, gameState);
|
||||
if (!holder || !holder.position())
|
||||
continue;
|
||||
pos = holder.position();
|
||||
}
|
||||
let gamepos = gameState.ai.accessibility.gamePosToMapPos(pos);
|
||||
let index = gamepos[0] + gamepos[1]*gameState.ai.accessibility.width;
|
||||
let land = gameState.ai.accessibility.landPassMap[index];
|
||||
let sea = gameState.ai.accessibility.navalPassMap[index];
|
||||
let found = false;
|
||||
for (let point of startingPoint)
|
||||
{
|
||||
if (land !== point.land || sea !== point.sea)
|
||||
continue;
|
||||
if (API3.SquareVectorDistance(point.pos, pos) > 2500)
|
||||
continue;
|
||||
point.weight += 1;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
startingPoint.push({"pos": pos, "land": land, "sea": sea, "weight": 1});
|
||||
}
|
||||
if (!startingPoint.length)
|
||||
{
|
||||
API3.warn("Petra error in buildFirstBase, can not find a starting position");
|
||||
return;
|
||||
}
|
||||
let imax = 0;
|
||||
for (let i = 1; i < startingPoint.length; ++i)
|
||||
if (startingPoint[i].weight > startingPoint[imax].weight)
|
||||
imax = i;
|
||||
|
||||
var template = gameState.applyCiv("structures/{civ}_civil_centre");
|
||||
gameState.ai.queues.civilCentre.addItem(new m.ConstructionPlan(gameState, template, { "base": -1, "resource": "wood", "proximity": startingPoint[imax].pos }));
|
||||
};
|
||||
|
||||
/**
|
||||
* set strategy if game without construction:
|
||||
* - if one of our allies has a cc, affect a small fraction of our army for his defense, the rest will attack
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ var PETRA = function(m)
|
|||
transporter = this.ID
|
||||
*/
|
||||
|
||||
m.TransportPlan = function(gameState, units, startIndex, endIndex, endPos)
|
||||
m.TransportPlan = function(gameState, units, startIndex, endIndex, endPos, ship)
|
||||
{
|
||||
this.ID = gameState.ai.uniqueIDs.transports++;
|
||||
this.debug = gameState.ai.Config.debug;
|
||||
|
|
@ -34,16 +34,32 @@ m.TransportPlan = function(gameState, units, startIndex, endIndex, endPos)
|
|||
this.startIndex = startIndex;
|
||||
// TODO only cases with land-sea-land are allowed for the moment
|
||||
// we could also have land-sea-land-sea-land
|
||||
this.sea = gameState.ai.HQ.getSeaIndex(gameState, startIndex, endIndex);
|
||||
if (!this.sea)
|
||||
if (startIndex === 1)
|
||||
{
|
||||
this.failed = true;
|
||||
if (this.debug > 1)
|
||||
API3.warn("transport plan with bad path: startIndex " + startIndex + " endIndex " + endIndex);
|
||||
return false;
|
||||
// special transport from already garrisoned ship
|
||||
if (!ship)
|
||||
{
|
||||
this.failed = true;
|
||||
return false;
|
||||
}
|
||||
this.sea = ship.getMetadata(PlayerID, "sea");
|
||||
ship.setMetadata(PlayerID, "transporter", this.ID);
|
||||
for (let ent of units)
|
||||
ent.setMetadata(PlayerID, "onBoard", "onBoard");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.sea = gameState.ai.HQ.getSeaIndex(gameState, startIndex, endIndex);
|
||||
if (!this.sea)
|
||||
{
|
||||
this.failed = true;
|
||||
if (this.debug > 1)
|
||||
API3.warn("transport plan with bad path: startIndex " + startIndex + " endIndex " + endIndex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (var ent of units)
|
||||
for (let ent of units)
|
||||
{
|
||||
ent.setMetadata(PlayerID, "transport", this.ID);
|
||||
ent.setMetadata(PlayerID, "endPos", endPos);
|
||||
|
|
@ -55,7 +71,7 @@ m.TransportPlan = function(gameState, units, startIndex, endIndex, endPos)
|
|||
|
||||
this.state = "boarding";
|
||||
this.boardingPos = {};
|
||||
this.needTransportShips = true;
|
||||
this.needTransportShips = (ship === undefined);
|
||||
this.nTry = {};
|
||||
return true;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue