feat(ai): improving agents planning and memory
This commit is contained in:
@@ -4,6 +4,9 @@ using static SpaceGame.Api.Shared.Runtime.SimulationRuntimeSupport;
|
||||
|
||||
internal static class FactionIndustryPlanner
|
||||
{
|
||||
private const float CommodityTargetLevelSeconds = 240f;
|
||||
private const float WaterTargetLevelSeconds = 300f;
|
||||
|
||||
internal static IndustryExpansionProject? AnalyzeCommodityNeed(SimulationWorld world, string factionId, string commodityId)
|
||||
{
|
||||
if (HasActiveExpansionProject(world, factionId))
|
||||
@@ -64,14 +67,13 @@ internal static class FactionIndustryPlanner
|
||||
.Select(itemId => new
|
||||
{
|
||||
ItemId = itemId,
|
||||
HasProducer = FactionHasProducerForCommodity(world, factionId, itemId),
|
||||
Pressure = GetCommodityPressure(world, factionId, itemId),
|
||||
Stockpile = GetCommodityStockpile(world, factionId, itemId),
|
||||
Commodity = FactionEconomyAnalyzer.Build(world, factionId).GetCommodity(itemId),
|
||||
})
|
||||
.Where(entry => !entry.HasProducer || entry.Pressure > 0.01f || entry.Stockpile < 120f)
|
||||
.OrderByDescending(entry => !entry.HasProducer ? 1 : 0)
|
||||
.ThenByDescending(entry => entry.Pressure)
|
||||
.ThenBy(entry => entry.Stockpile)
|
||||
.Where(entry => entry.Commodity.ProjectedProductionRatePerSecond <= 0.01f
|
||||
|| CommodityOperationalSignal.IsStrained(entry.Commodity, GetTargetLevelSeconds(entry.ItemId)))
|
||||
.OrderByDescending(entry => entry.Commodity.ProjectedProductionRatePerSecond <= 0.01f ? 1 : 0)
|
||||
.ThenByDescending(entry => CommodityOperationalSignal.ComputeNeedScore(entry.Commodity, GetTargetLevelSeconds(entry.ItemId)))
|
||||
.ThenBy(entry => entry.Commodity.AvailableStock)
|
||||
.Select(entry => entry.ItemId)
|
||||
.FirstOrDefault();
|
||||
|
||||
@@ -301,14 +303,20 @@ internal static class FactionIndustryPlanner
|
||||
.GroupBy(order => order.ItemId, StringComparer.Ordinal)
|
||||
.ToDictionary(group => group.Key, group => group.Sum(order => order.RemainingAmount), StringComparer.Ordinal);
|
||||
|
||||
if (CommanderPlanningService.FactionCommanderHasDirective(world, factionId, "produce-military-ships"))
|
||||
if (CommanderPlanningService.FactionCommanderHasIssuedTask(world, factionId, FactionIssuedTaskKind.ProduceShips, "military"))
|
||||
{
|
||||
demandByItem["hullparts"] = demandByItem.GetValueOrDefault("hullparts") + 120f;
|
||||
demandByItem["claytronics"] = demandByItem.GetValueOrDefault("claytronics") + 90f;
|
||||
}
|
||||
|
||||
return demandByItem
|
||||
.Select(entry => (ItemId: ResolveBottleneckCommodity(world, factionId, entry.Key), Score: entry.Value))
|
||||
.Select(entry =>
|
||||
{
|
||||
var itemId = ResolveBottleneckCommodity(world, factionId, entry.Key);
|
||||
var commodity = FactionEconomyAnalyzer.Build(world, factionId).GetCommodity(itemId);
|
||||
var score = entry.Value + CommodityOperationalSignal.ComputeNeedScore(commodity, GetTargetLevelSeconds(itemId));
|
||||
return (ItemId: itemId, Score: score);
|
||||
})
|
||||
.Where(entry => entry.ItemId is not null)
|
||||
.GroupBy(entry => entry.ItemId!, StringComparer.Ordinal)
|
||||
.Select(group => (ItemId: group.Key, Score: group.Sum(entry => entry.Score)))
|
||||
@@ -358,7 +366,11 @@ internal static class FactionIndustryPlanner
|
||||
|
||||
var weakestUnproducedInput = world.ProductionGraph.GetImmediateInputs(itemId)
|
||||
.Where(inputId => !FactionHasProducerForCommodity(world, factionId, inputId))
|
||||
.Select(inputId => (ItemId: inputId, Score: GetCommodityPressure(world, factionId, inputId), Stockpile: GetCommodityStockpile(world, factionId, inputId)))
|
||||
.Select(inputId =>
|
||||
{
|
||||
var commodity = FactionEconomyAnalyzer.Build(world, factionId).GetCommodity(inputId);
|
||||
return (ItemId: inputId, Score: CommodityOperationalSignal.ComputeNeedScore(commodity, GetTargetLevelSeconds(inputId)), Stockpile: commodity.AvailableStock);
|
||||
})
|
||||
.OrderByDescending(entry => entry.Score)
|
||||
.ThenBy(entry => entry.Stockpile)
|
||||
.FirstOrDefault();
|
||||
@@ -370,11 +382,15 @@ internal static class FactionIndustryPlanner
|
||||
}
|
||||
|
||||
var weakestInput = world.ProductionGraph.GetImmediateInputs(itemId)
|
||||
.Select(inputId => (ItemId: inputId, Score: GetCommodityPressure(world, factionId, inputId)))
|
||||
.Select(inputId =>
|
||||
{
|
||||
var commodity = FactionEconomyAnalyzer.Build(world, factionId).GetCommodity(inputId);
|
||||
return (ItemId: inputId, Score: CommodityOperationalSignal.ComputeNeedScore(commodity, GetTargetLevelSeconds(inputId)));
|
||||
})
|
||||
.OrderByDescending(entry => entry.Score)
|
||||
.FirstOrDefault();
|
||||
|
||||
return weakestInput.Score > GetCommodityPressure(world, factionId, itemId) * 0.6f
|
||||
return weakestInput.Score > GetCommodityNeedScore(world, factionId, itemId) * 0.6f
|
||||
? ResolveBottleneckCommodity(world, factionId, weakestInput.ItemId, visited)
|
||||
: itemId;
|
||||
}
|
||||
@@ -419,13 +435,14 @@ internal static class FactionIndustryPlanner
|
||||
&& string.Equals(site.TargetKind, "station-foundation", StringComparison.Ordinal)
|
||||
&& site.State is not ConstructionSiteStateKinds.Completed and not ConstructionSiteStateKinds.Destroyed);
|
||||
|
||||
private static float GetCommodityPressure(SimulationWorld world, string factionId, string itemId)
|
||||
private static float GetCommodityNeedScore(SimulationWorld world, string factionId, string itemId)
|
||||
{
|
||||
return FactionEconomyAnalyzer.Build(world, factionId).GetCommodity(itemId).ProjectedPressureScore;
|
||||
var commodity = FactionEconomyAnalyzer.Build(world, factionId).GetCommodity(itemId);
|
||||
return CommodityOperationalSignal.ComputeNeedScore(commodity, GetTargetLevelSeconds(itemId));
|
||||
}
|
||||
|
||||
private static float GetCommodityStockpile(SimulationWorld world, string factionId, string itemId) =>
|
||||
FactionEconomyAnalyzer.Build(world, factionId).GetCommodity(itemId).AvailableStock;
|
||||
private static float GetTargetLevelSeconds(string itemId) =>
|
||||
string.Equals(itemId, "water", StringComparison.Ordinal) ? WaterTargetLevelSeconds : CommodityTargetLevelSeconds;
|
||||
|
||||
private static CelestialRuntime? SelectFoundationCelestial(SimulationWorld world, string factionId, string commodityId)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user