petra: fixes and tweaks of the previous commits for capture

This was SVN commit r16606.
This commit is contained in:
mimo 2015-05-01 14:13:59 +00:00
parent 385c47fe6b
commit 7d20695412
3 changed files with 67 additions and 31 deletions

View File

@ -233,6 +233,15 @@ m.Army.prototype.removeOwn = function (gameState, id, Entity)
return true;
};
// Special army set to capture a gaia building
m.Army.prototype.isCapturing = function (gameState)
{
if (this.foeEntities.length != 1)
return false;
let ent = gameState.getEntityById(this.foeEntities[0]);
return (ent && ent.hasClass("Structure"));
};
// this one is "undefined entity" proof because it's called at odd times.
// Orders a unit to attack an enemy.
// overridden by specific army classes.
@ -244,9 +253,9 @@ m.Army.prototype.assignUnit = function (gameState, entID)
// assumes we already cleared dead units.
m.Army.prototype.clear = function (gameState)
{
while(this.foeEntities.length > 0)
while (this.foeEntities.length > 0)
this.removeFoe(gameState,this.foeEntities[0]);
while(this.ownEntities.length > 0)
while (this.ownEntities.length > 0)
this.removeOwn(gameState,this.ownEntities[0]);
this.assignedAgainst = {};
@ -351,6 +360,9 @@ m.Army.prototype.checkEvents = function (gameState, events)
// this only checks for breakaways.
m.Army.prototype.onUpdate = function (gameState)
{
if (this.isCapturing(gameState))
return [];
var breakaways = [];
// TODO: assign unassigned defenders, cleanup of a few things.
// perhaps occasional strength recomputation

View File

@ -154,7 +154,7 @@ m.DefenseManager.prototype.checkEnemyUnits = function(gameState)
this.makeIntoArmy(gameState, ent.id());
}
if ( i !== 0)
if (i !== 0 || this.armies.length > 1 || gameState.ai.HQ.numActiveBase() === 0)
return;
// look for possible gaia buildings inside our territory (may happen when enemy resign or after structure decay)
for (let ent of gameState.getEnemyStructures(i).values())
@ -170,9 +170,9 @@ m.DefenseManager.prototype.checkEnemyUnits = function(gameState)
m.DefenseManager.prototype.checkEnemyArmies = function(gameState, events)
{
for (var o = 0; o < this.armies.length; ++o)
for (var i = 0; i < this.armies.length; ++i)
{
var army = this.armies[o];
var army = this.armies[i];
army.checkEvents(gameState, events); // must be called every turn for all armies
// this returns a list of IDs: the units that broke away from the army for being too far.
@ -184,32 +184,34 @@ m.DefenseManager.prototype.checkEnemyArmies = function(gameState, events)
if (army.getState(gameState) === 0)
{
army.clear(gameState);
this.armies.splice(o--,1);
this.armies.splice(i--,1);
continue;
}
}
// Check if we can't merge it with another.
for (var o = 0; o < this.armies.length; ++o)
// Check if we can't merge it with another
for (let i = 0; i < this.armies.length - 1; ++i)
{
var army = this.armies[o];
for (var p = o+1; p < this.armies.length; ++p)
let army = this.armies[i];
if (army.isCapturing(gameState))
continue;
for (let j = i+1; j < this.armies.length; ++j)
{
var otherArmy = this.armies[p];
if (API3.SquareVectorDistance(army.foePosition, otherArmy.foePosition) < this.armyMergeSize)
{
// no need to clear here.
army.merge(gameState, otherArmy);
this.armies.splice(p--,1);
}
let otherArmy = this.armies[j];
if (otherArmy.isCapturing(gameState) ||
API3.SquareVectorDistance(army.foePosition, otherArmy.foePosition) > this.armyMergeSize)
continue;
// no need to clear here.
army.merge(gameState, otherArmy);
this.armies.splice(j--,1);
}
}
if (gameState.ai.playedTurn % 5 !== 0)
return;
// Check if any army is no more dangerous (possibly because it has defeated us and destroyed our base)
for (var o = 0; o < this.armies.length; ++o)
for (var i = 0; i < this.armies.length; ++i)
{
var army = this.armies[o];
var army = this.armies[i];
army.recalculatePosition(gameState);
var owner = this.territoryMap.getOwner(army.foePosition);
if (gameState.isPlayerAlly(owner))
@ -217,11 +219,12 @@ m.DefenseManager.prototype.checkEnemyArmies = function(gameState, events)
else if (owner !== 0) // enemy army back in its territory
{
army.clear(gameState);
this.armies.splice(o--,1);
this.armies.splice(i--,1);
continue;
}
// army in neutral territory // TODO check smaller distance with all our buildings instead of only ccs with big distance
// army in neutral territory
// TODO check smaller distance with all our buildings instead of only ccs with big distance
var stillDangerous = false;
let bases = gameState.updatingGlobalCollection("allCCs", API3.Filters.byClass("CivCentre"));
for (let base of bases.values())
@ -241,7 +244,7 @@ m.DefenseManager.prototype.checkEnemyArmies = function(gameState, events)
continue;
army.clear(gameState);
this.armies.splice(o--,1);
this.armies.splice(i--,1);
}
};
@ -335,6 +338,18 @@ m.DefenseManager.prototype.assignDefenders = function(gameState)
gameState.ai.HQ.trainEmergencyUnits(gameState, armiesPos);
};
m.DefenseManager.prototype.abortArmy = function(gameState, army)
{
army.clear(gameState);
for (let i = 0; i < this.armies.length; ++i)
{
if (this.armies[i].ID !== army.ID)
continue;
this.armies.splice(i, 1);
break;
}
};
// If our defense structures are attacked, garrison soldiers inside when possible
// and if a support unit is attacked and has less than 55% health, garrison it inside the nearest healing structure
// and if a ranged siege unit (not used for defense) is attacked, garrison it in the nearest fortress
@ -349,6 +364,13 @@ m.DefenseManager.prototype.checkEvents = function(gameState, events)
if (target.hasClass("Ship")) // TODO integrate ships later need to be sure it is accessible
continue;
if (target.getMetadata(PlayerID, "PartOfArmy") !== undefined)
{
let army = this.getArmy(target.getMetadata(PlayerID, "PartOfArmy"));
if (army.isCapturing(gameState))
this.abortArmy(gameState, army);
}
if (target.hasClass("Support") && target.healthLevel() < 0.55 && !target.getMetadata(PlayerID, "transport")
&& target.getMetadata(PlayerID, "plan") !== -2 && target.getMetadata(PlayerID, "plan") !== -3)
{

View File

@ -17,15 +17,6 @@ m.GarrisonManager = function()
m.GarrisonManager.prototype.update = function(gameState, queues)
{
for (let [id, gmin] of this.decayingStructures.entries())
{
let ent = gameState.getEntityById(id);
if (!ent || ent.owner() !== PlayerID)
this.decayingStructures.delete(id);
else if (this.numberOfGarrisonedUnits(ent) < gmin)
gameState.ai.HQ.defenseManager.garrisonRangedUnitsInside(gameState, ent, {"min": gmin, "type": "decay"});
}
for (let [id, list] of this.holders.entries())
{
let holder = gameState.getEntityById(id);
@ -134,6 +125,17 @@ m.GarrisonManager.prototype.update = function(gameState, queues)
holder.setMetadata(PlayerID, "holderTimeUpdate", gameState.ai.elapsedTime);
}
}
// Warning new garrison orders (as in the following lines) should be done after having updated the holders
// (or TODO we should add a test that the garrison order is from a previous turn when updating)
for (let [id, gmin] of this.decayingStructures.entries())
{
let ent = gameState.getEntityById(id);
if (!ent || ent.owner() !== PlayerID)
this.decayingStructures.delete(id);
else if (this.numberOfGarrisonedUnits(ent) < gmin)
gameState.ai.HQ.defenseManager.garrisonRangedUnitsInside(gameState, ent, {"min": gmin, "type": "decay"});
}
};
// TODO should add the units garrisoned inside garrisoned units