From 8a0cbe009addaefc2a9af1103ce15614e34e8d7f Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Tue, 8 Mar 2011 01:40:44 +0000 Subject: [PATCH] Stop the AI wasting time chasing after any animals except chickens. Make the AI behave better when it can't find any viable food sources. This was SVN commit r9046. --- .../public/simulation/ai/common-api/entity.js | 6 +- .../public/simulation/ai/testbot/economy.js | 104 ++++++++++-------- .../public/simulation/components/UnitAI.js | 5 +- 3 files changed, 65 insertions(+), 50 deletions(-) diff --git a/binaries/data/mods/public/simulation/ai/common-api/entity.js b/binaries/data/mods/public/simulation/ai/common-api/entity.js index 55051cd47b..7f02b35984 100644 --- a/binaries/data/mods/public/simulation/ai/common-api/entity.js +++ b/binaries/data/mods/public/simulation/ai/common-api/entity.js @@ -130,7 +130,11 @@ var EntityTemplate = Class({ isUnhuntable: function() { if (!this._template.UnitAI || !this._template.UnitAI.NaturalBehaviour) return false; - return (this._template.UnitAI.NaturalBehaviour == "skittish"); + + // return (this._template.UnitAI.NaturalBehaviour == "skittish"); + // Actually, since the AI is currently rubbish at hunting, skip all animals + // that aren't really weak: + return this._template.Health.Max >= 10; }, }); diff --git a/binaries/data/mods/public/simulation/ai/testbot/economy.js b/binaries/data/mods/public/simulation/ai/testbot/economy.js index 7b3a9afd84..99be5de422 100644 --- a/binaries/data/mods/public/simulation/ai/testbot/economy.js +++ b/binaries/data/mods/public/simulation/ai/testbot/economy.js @@ -75,8 +75,10 @@ var EconomyManager = Class({ } }, - pickMostNeededResource: function(gameState) + pickMostNeededResources: function(gameState) { + var self = this; + // Find what resource type we're most in need of var numGatherers = {}; for (var type in this.gatherWeights) @@ -87,19 +89,15 @@ var EconomyManager = Class({ numGatherers[ent.getMetadata("gather-type")] += 1; }); - var bestType = "food"; - var bestTypeVal = Infinity; // num gatherers divided by weight - for (var type in this.gatherWeights) - { - var v = numGatherers[type] / this.gatherWeights[type]; - if (v < bestTypeVal) - { - bestTypeVal = v; - bestType = type; - } - } + var types = Object.keys(this.gatherWeights); + types.sort(function(a, b) { + // Prefer fewer gatherers (divided by weight) + var va = numGatherers[a] / self.gatherWeights[a]; + var vb = numGatherers[b] / self.gatherWeights[b]; + return va - vb; + }); - return bestType; + return types; }, reassignRolelessUnits: function(gameState) @@ -133,43 +131,53 @@ var EconomyManager = Class({ idleWorkers.forEach(function(ent) { - var type = self.pickMostNeededResource(gameState); - - // Make sure there's actually some of that type - // (We probably shouldn't pick impossible ones in the first place) - if (!resourceSupplies[type]) - return; - - // Pick the closest one. - // TODO: we should care about distance to dropsites, not (just) to the worker, - // and gather rates of workers - - var workerPosition = ent.position(); - var supplies = []; - resourceSupplies[type].forEach(function(supply) { - // Skip targets that are too hard to hunt - if (supply.entity.isUnhuntable()) - return; - - var dist = VectorDistance(supply.position, workerPosition); - supplies.push({ dist: dist, entity: supply.entity }); - }); - - supplies.sort(function (a, b) { - // Prefer smaller distances - if (a.dist != b.dist) - return a.dist - b.dist; - - return false; - }); - - // Start gathering - if (supplies.length) + var types = self.pickMostNeededResources(gameState); + for each (var type in types) { - ent.gather(supplies[0].entity); - ent.setMetadata("subrole", "gatherer"); - ent.setMetadata("gather-type", type); + // Make sure there's actually some of that type + if (!resourceSupplies[type]) + continue; + + // Pick the closest one. + // TODO: we should care about distance to dropsites, not (just) to the worker, + // and gather rates of workers + + var workerPosition = ent.position(); + var supplies = []; + resourceSupplies[type].forEach(function(supply) { + // Skip targets that are too hard to hunt + if (supply.entity.isUnhuntable()) + return; + + var dist = VectorDistance(supply.position, workerPosition); + + // Skip targets that are far too far away (e.g. in the enemy base) + if (dist > 512) + return; + + supplies.push({ dist: dist, entity: supply.entity }); + }); + + supplies.sort(function (a, b) { + // Prefer smaller distances + if (a.dist != b.dist) + return a.dist - b.dist; + + return false; + }); + + // Start gathering + if (supplies.length) + { + ent.gather(supplies[0].entity); + ent.setMetadata("subrole", "gatherer"); + ent.setMetadata("gather-type", type); + return; + } } + + // Couldn't find any types to gather + ent.setMetadata("subrole", "idle"); }); } }, diff --git a/binaries/data/mods/public/simulation/components/UnitAI.js b/binaries/data/mods/public/simulation/components/UnitAI.js index 15156ea3af..c0434a7513 100644 --- a/binaries/data/mods/public/simulation/components/UnitAI.js +++ b/binaries/data/mods/public/simulation/components/UnitAI.js @@ -1182,7 +1182,10 @@ UnitAI.prototype.IsAnimal = function() */ UnitAI.prototype.IsUnhuntable = function() { - return (this.template.NaturalBehaviour && this.template.NaturalBehaviour == "skittish"); + // return (this.template.NaturalBehaviour && this.template.NaturalBehaviour == "skittish"); + // Actually, since the AI is currently rubbish at hunting, skip all animals + // that aren't really weak: + return this.IsAnimal() && Engine.QueryInterface(this.entity, IID_Health).GetMaxHitpoints() >= 10; }; UnitAI.prototype.IsIdle = function()