Fixed AI BaseBuilder low power check.

This was extremely borked:
The priority overrides for refinery, production and silo ignored power completely and never checked whether the structure might drive the AI into low power state; whereas the check for regular building checked whether the structure's power -exceeded- MinimumExcessPower (previously just 0). The catch is that power draw is represented by negative numbers, so the only buildings that would trigger this were - power plants.
Now it checks whether the sum of building power draw (negative) and AI's current power level are lower than MinimumExcessPower, if not, build the structure, if yes, build a power plant instead.
Additionally, this check is now performed for the early-game priority overrides as well.

Last but not least the AI would not(!) give power plants priority if it was already low on power. This has been fixed as well.
This commit is contained in:
reaperrr
2015-07-21 07:24:53 +02:00
parent a3eac88e36
commit 6ff394991d

View File

@@ -130,22 +130,27 @@ namespace OpenRA.Mods.Common.AI
return available.RandomOrDefault(ai.Random); return available.RandomOrDefault(ai.Random);
} }
bool HasSufficientPowerForActor(ActorInfo actorInfo)
{
return (actorInfo.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1)
.Sum(p => p.Amount) + playerPower.ExcessPower) >= ai.Info.MinimumExcessPower;
}
ActorInfo ChooseBuildingToBuild(ProductionQueue queue) ActorInfo ChooseBuildingToBuild(ProductionQueue queue)
{ {
var buildableThings = queue.BuildableItems(); var buildableThings = queue.BuildableItems();
// This gets used quite a bit, so let's cache it here
var power = GetProducibleBuilding("Power", buildableThings,
a => a.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(p => p.Amount));
// First priority is to get out of a low power situation // First priority is to get out of a low power situation
if (playerPower.ExcessPower < ai.Info.MinimumExcessPower) if (playerPower.ExcessPower < ai.Info.MinimumExcessPower)
{ {
var power = GetProducibleBuilding("Power", buildableThings, a => a.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(p => p.Amount));
if (power != null && power.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(p => p.Amount) > 0) if (power != null && power.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(p => p.Amount) > 0)
{ {
// TODO: Handle the case when of when we actually do need a power plant because we don't have enough but are also suffering from a power outage HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (low power)", queue.Actor.Owner, power.Name);
if (playerPower.PowerOutageRemainingTicks <= 0) return power;
{
HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (low power)", queue.Actor.Owner, power.Name);
return power;
}
} }
} }
@@ -153,33 +158,51 @@ namespace OpenRA.Mods.Common.AI
if (!ai.HasAdequateProc() || !ai.HasMinimumProc()) if (!ai.HasAdequateProc() || !ai.HasMinimumProc())
{ {
var refinery = GetProducibleBuilding("Refinery", buildableThings); var refinery = GetProducibleBuilding("Refinery", buildableThings);
if (refinery != null) if (refinery != null && HasSufficientPowerForActor(refinery))
{ {
HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (refinery)", queue.Actor.Owner, refinery.Name); HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (refinery)", queue.Actor.Owner, refinery.Name);
return refinery; return refinery;
} }
if (power != null && refinery != null && !HasSufficientPowerForActor(refinery))
{
HackyAI.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
return power;
}
} }
// Make sure that we can can spend as fast as we are earning // Make sure that we can can spend as fast as we are earning
if (ai.Info.NewProductionCashThreshold > 0 && playerResources.Resources > ai.Info.NewProductionCashThreshold) if (ai.Info.NewProductionCashThreshold > 0 && playerResources.Resources > ai.Info.NewProductionCashThreshold)
{ {
var production = GetProducibleBuilding("Production", buildableThings); var production = GetProducibleBuilding("Production", buildableThings);
if (production != null) if (production != null && HasSufficientPowerForActor(production))
{ {
HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (production)", queue.Actor.Owner, production.Name); HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (production)", queue.Actor.Owner, production.Name);
return production; return production;
} }
if (power != null && production != null && !HasSufficientPowerForActor(production))
{
HackyAI.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
return power;
}
} }
// Create some head room for resource storage if we really need it // Create some head room for resource storage if we really need it
if (playerResources.AlertSilo) if (playerResources.AlertSilo)
{ {
var silo = GetProducibleBuilding("Silo", buildableThings); var silo = GetProducibleBuilding("Silo", buildableThings);
if (silo != null) if (silo != null && HasSufficientPowerForActor(silo))
{ {
HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (silo)", queue.Actor.Owner, silo.Name); HackyAI.BotDebug("AI: {0} decided to build {1}: Priority override (silo)", queue.Actor.Owner, silo.Name);
return silo; return silo;
} }
if (power != null && silo != null && !HasSufficientPowerForActor(silo))
{
HackyAI.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
return power;
}
} }
// Build everything else // Build everything else
@@ -200,23 +223,18 @@ namespace OpenRA.Mods.Common.AI
continue; continue;
// Will this put us into low power? // Will this put us into low power?
var actor = world.Map.Rules.Actors[frac.Key]; var actor = world.Map.Rules.Actors[name];
var pis = actor.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1); if (playerPower.ExcessPower < ai.Info.MinimumExcessPower || !HasSufficientPowerForActor(actor))
if (playerPower.ExcessPower < ai.Info.MinimumExcessPower || playerPower.ExcessPower < pis.Sum(pi => pi.Amount))
{ {
// Try building a power plant instead // Try building a power plant instead
var power = GetProducibleBuilding("Power",
buildableThings, a => a.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(pi => pi.Amount));
if (power != null && power.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(pi => pi.Amount) > 0) if (power != null && power.Traits.WithInterface<PowerInfo>().Where(i => i.UpgradeMinEnabledLevel < 1).Sum(pi => pi.Amount) > 0)
{ {
// TODO: Handle the case when of when we actually do need a power plant because we don't have enough but are also suffering from a power outage
if (playerPower.PowerOutageRemainingTicks > 0) if (playerPower.PowerOutageRemainingTicks > 0)
HackyAI.BotDebug("AI: {0} is suffering from a power outage; not going to build {1}", queue.Actor.Owner, power.Name); HackyAI.BotDebug("{0} decided to build {1}: Priority override (is low power)", queue.Actor.Owner, power.Name);
else else
{
HackyAI.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name); HackyAI.BotDebug("{0} decided to build {1}: Priority override (would be low power)", queue.Actor.Owner, power.Name);
return power;
} return power;
} }
} }