1
0
forked from 0ad/0ad

Optimize enemy watchers usage. This should avoid massive lag later in the game.

This was SVN commit r12401.
This commit is contained in:
wraitii 2012-08-13 08:06:20 +00:00
parent 1f17407161
commit 9e9e1e3b78
6 changed files with 77 additions and 40 deletions

View File

@ -540,11 +540,11 @@ CityAttack.prototype.update = function(gameState, militaryManager, events){
// we must assume we've arrived at the end of the trail.
this.state = "arrived";
}
if (militaryManager.enemyWatchers[attacker.owner()]) {
toProcess[attacker.id()] = attacker;
var armyID = militaryManager.enemyWatchers[attacker.owner()].getArmyFromMember(attacker.id());
armyToProcess[armyID[0]] = armyID[1];
}
//if (militaryManager.enemyWatchers[attacker.owner()]) {
//toProcess[attacker.id()] = attacker;
//var armyID = militaryManager.enemyWatchers[attacker.owner()].getArmyFromMember(attacker.id());
//armyToProcess[armyID[0]] = armyID[1];
//}
}
// if we're being attacked by a building, flee.
if (attacker && ourUnit && attacker.hasClass("Structure")) {

View File

@ -431,9 +431,9 @@ Defence.prototype.MessageProcess = function(gameState,events, militaryManager) {
// If it's not part of a big army, depending on our priority we may want to kill it (using the same things as animals for that)
// TODO (perhaps not any more, but let's mark it anyway)
var army = militaryManager.enemyWatchers[attacker.owner()].getArmyFromMember(attacker.id());
if (army[1].length > 5) {
if (army !== undefined && army[1].length > 5) {
militaryManager.enemyWatchers[attacker.owner()].setAsDangerous(army[0]);
} else if (!militaryManager.enemyWatchers[attacker.owner()].isDangerous(army[0])) {
} else if (army !== undefined && !militaryManager.enemyWatchers[attacker.owner()].isDangerous(army[0])) {
// we register this unit as wanted, TODO register the whole army
// another function will deal with it.
var filter = Filters.and(Filters.byOwner(attacker.owner()),Filters.byID(attacker.id()));

View File

@ -775,11 +775,13 @@ EconomyManager.prototype.update = function(gameState, queues, events) {
for (var j in gathererGroups){
var a = eval(i);
var b = eval(j);
if (a["food.grain"]/b["food.grain"] > a["wood.tree"]/b["wood.tree"] && gathererGroups[i]["wood"].length > 0 && gathererGroups[j]["food"].length > 0){
for (var k = 0; k < Math.min(gathererGroups[i]["wood"].length, gathererGroups[j]["food"].length); k++){
gathererGroups[i]["wood"][k].setMetadata("gather-type", "food");
gathererGroups[j]["food"][k].setMetadata("gather-type", "wood");
}
if (a !== undefined && b !== undefined)
if (a["food.grain"]/b["food.grain"] > a["wood.tree"]/b["wood.tree"] && gathererGroups[i]["wood"].length > 0
&& gathererGroups[j]["food"].length > 0){
for (var k = 0; k < Math.min(gathererGroups[i]["wood"].length, gathererGroups[j]["food"].length); k++){
gathererGroups[i]["wood"][k].setMetadata("gather-type", "food");
gathererGroups[j]["food"][k].setMetadata("gather-type", "wood");
}
}
}
}

View File

@ -109,36 +109,46 @@ enemyWatcher.prototype.detectArmies = function(gameState){
//this.cleanDebug();
var self = this;
// let's loop through unmonitored enemy soldiers
this.unmonitoredEnemySoldiers.forEach( function (enemy) {
if (enemy.position() == undefined)
return;
// this was an unmonitored unit, we do not know any army associated with it. We assign it a new army (we'll merge later if needed)
enemy.setMetadata("monitored","true");
var armyID = uneval( gameState.player + "" + self.totalNBofArmies);
self.totalNBofArmies++,
enemy.setMetadata("EnemyWatcherArmy",armyID);
var filter = Filters.byMetadata("EnemyWatcherArmy",armyID);
var army = self.enemySoldiers.filter(filter);
self.armies[armyID] = army;
self.armies[armyID].registerUpdates();
self.armies[armyID].length;
});
this.mergeArmies(); // calls "scrap empty armies"
this.splitArmies(gameState);
if (gameState.ai.playedTurn % 4 === 0) {
Engine.ProfileStart("Looking for new soldiers");
// let's loop through unmonitored enemy soldiers
this.unmonitoredEnemySoldiers.forEach( function (enemy) { //}){
if (enemy.position() === undefined)
return;
// this was an unmonitored unit, we do not know any army associated with it. We assign it a new army (we'll merge later if needed)
enemy.setMetadata("monitored","true");
var armyID = gameState.player + "" + self.totalNBofArmies;
self.totalNBofArmies++,
enemy.setMetadata("EnemyWatcherArmy",armyID);
var filter = Filters.byMetadata("EnemyWatcherArmy",armyID);
var army = self.enemySoldiers.filter(filter);
self.armies[armyID] = army;
self.armies[armyID].registerUpdates();
self.armies[armyID].length;
});
Engine.ProfileStop();
} else if (gameState.ai.playedTurn % 8 === 3) {
Engine.ProfileStart("Merging");
this.mergeArmies(); // calls "scrap empty armies"
Engine.ProfileStop();
} else if (gameState.ai.playedTurn % 8 === 7) {
Engine.ProfileStart("Splitting");
this.splitArmies(gameState);
Engine.ProfileStop();
}
};
// this will merge any two army who are too close together. The distance for "army" is fairly big.
// note: this doesn't actually merge two entity collections... It simply changes the unit metadatas, and will clear the empty entity collection
enemyWatcher.prototype.mergeArmies = function(){
for (army in this.armies) {
var firstArmy = this.armies[army];
if (firstArmy.length > 0)
if (firstArmy.length !== 0)
for (otherArmy in this.armies) {
if (otherArmy !== army && this.armies[otherArmy].length > 0) {
if (otherArmy !== army && this.armies[otherArmy].length !== 0) {
var secondArmy = this.armies[otherArmy];
// we're not self merging, so we check if the two armies are close together
if (inRange(firstArmy.getCentrePosition(),secondArmy.getCentrePosition(), 3000 ) ) {
if (inRange(firstArmy.getApproximatePosition(4),secondArmy.getApproximatePosition(4), 3000 ) ) {
// okay so we merge the two together
// if the other one was dangerous and we weren't, we're now.
@ -173,15 +183,13 @@ enemyWatcher.prototype.splitArmies = function(gameState){
var self = this;
for (armyID in this.armies) {
var army = this.armies[armyID];
var centre = army.getCentrePosition();
var centre = army.getApproximatePosition(4);
army.forEach( function (enemy) {
if (enemy.position() == undefined)
return;
// debug ("entity " +enemy.templateName() + " is currently " +enemy.visibility(gameState.player));
if (!inRange(enemy.position(),centre, 3500) ) {
var newArmyID = uneval( gameState.player + "" + self.totalNBofArmies);
var newArmyID = gameState.player + "" + self.totalNBofArmies;
if (self.dangerousArmies.indexOf(armyID) !== -1)
self.dangerousArmies.push(newArmyID);

View File

@ -44,6 +44,27 @@ EntityCollection.prototype.getCentrePosition = function(){
}
};
EntityCollection.prototype.getApproximatePosition = function(sample){
var sumPos = [0, 0];
var i = 0;
for (var id in this._entities)
{
var ent = this._entities[id];
if (ent.position()) {
sumPos[0] += ent.position()[0];
sumPos[1] += ent.position()[1];
i++;
}
if (i === sample)
break;
}
if (sample === 0){
return undefined;
}else{
return [sumPos[0]/i, sumPos[1]/i];
}
};
EntityCollection.prototype.filterNearest = function(targetPos, n)
{
// Compute the distance of each entity

View File

@ -60,9 +60,11 @@ MilitaryAttackManager.prototype.init = function(gameState) {
// each enemy watchers keeps a list of entity collections about the enemy it watches
// It also keeps track of enemy armies, merging/splitting as needed
this.enemyWatchers = {};
this.ennWatcherIndex = [];
for (var i = 1; i <= 8; i++)
if (gameState.player != i && gameState.isPlayerEnemy(i)) {
this.enemyWatchers[i] = new enemyWatcher(gameState, i);
this.ennWatcherIndex.push(i);
}
};
@ -498,13 +500,17 @@ MilitaryAttackManager.prototype.update = function(gameState, queues, events) {
//this.trainMilitaryUnits(gameState, queues);
Engine.ProfileStart("Constructing military buildings and building defences");
this.constructTrainingBuildings(gameState, queues);
if(gameState.getTimeElapsed() > 300*1000)
this.buildDefences(gameState, queues);
for (watcher in this.enemyWatchers)
this.enemyWatchers[watcher].detectArmies(gameState,this);
Engine.ProfileStop();
Engine.ProfileStart("Updating enemy watchers");
this.enemyWatchers[ this.ennWatcherIndex[gameState.ai.playedTurn % this.ennWatcherIndex.length] ].detectArmies(gameState,this);
Engine.ProfileStop();
this.defenceManager.update(gameState, events, this);
/*Engine.ProfileStart("Plan new attacks");