feat(ai): improving agents planning and memory
This commit is contained in:
@@ -207,8 +207,11 @@ internal sealed class SimulationProjectionService
|
||||
faction.ShipsBuilt,
|
||||
faction.ShipsLost,
|
||||
faction.DefaultPolicySetId,
|
||||
faction.GoapState,
|
||||
faction.GoapPriorities)).ToList());
|
||||
faction.StrategicAssessment,
|
||||
faction.StrategicPriorities,
|
||||
faction.Blackboard,
|
||||
faction.Objectives,
|
||||
faction.IssuedTasks)).ToList());
|
||||
}
|
||||
|
||||
public void PrimeDeltaBaseline(SimulationWorld world)
|
||||
@@ -515,10 +518,18 @@ internal sealed class SimulationProjectionService
|
||||
|
||||
private static string BuildFactionSignature(FactionRuntime faction, CommanderRuntime? commander)
|
||||
{
|
||||
var goapSig = commander?.LastGoalPriorities is { } prios
|
||||
var prioritySig = commander?.LastStrategicPriorities is { } prios
|
||||
? string.Join(",", prios.Select(p => $"{p.Name}:{p.Priority:0.##}"))
|
||||
: string.Empty;
|
||||
return $"{faction.Credits:0.###}|{faction.PopulationTotal:0.###}|{faction.OreMined:0.###}|{faction.GoodsProduced:0.###}|{faction.ShipsBuilt}|{faction.ShipsLost}|{faction.DefaultPolicySetId}|{goapSig}";
|
||||
var objectiveSig = commander?.Objectives is { Count: > 0 } objectives
|
||||
? string.Join(",", objectives.Select(objective =>
|
||||
$"{objective.Kind}:{objective.State}:{objective.Priority:0.##}:{objective.BlockingReason}:{objective.InvalidationReason}"))
|
||||
: string.Empty;
|
||||
var taskSig = commander?.IssuedTasks is { Count: > 0 } tasks
|
||||
? string.Join(",", tasks.Select(task =>
|
||||
$"{task.Kind}:{task.State}:{task.Priority:0.##}:{task.ShipRole}:{task.CommodityId}:{task.TargetFactionId}:{task.TargetSiteId}"))
|
||||
: string.Empty;
|
||||
return $"{faction.Credits:0.###}|{faction.PopulationTotal:0.###}|{faction.OreMined:0.###}|{faction.GoodsProduced:0.###}|{faction.ShipsBuilt}|{faction.ShipsLost}|{faction.DefaultPolicySetId}|{prioritySig}|{objectiveSig}|{taskSig}";
|
||||
}
|
||||
|
||||
private static ResourceNodeDelta ToNodeDelta(ResourceNodeRuntime node) => new(
|
||||
@@ -759,12 +770,15 @@ internal sealed class SimulationProjectionService
|
||||
|
||||
private static FactionDelta ToFactionDelta(FactionRuntime faction, CommanderRuntime? commander)
|
||||
{
|
||||
FactionGoapStateSnapshot? goapState = null;
|
||||
IReadOnlyList<FactionGoapPrioritySnapshot>? goapPriorities = null;
|
||||
FactionPlanningStateSnapshot? strategicAssessment = null;
|
||||
IReadOnlyList<FactionStrategicPrioritySnapshot>? strategicPriorities = null;
|
||||
FactionBlackboardSnapshot? blackboard = null;
|
||||
IReadOnlyList<FactionObjectiveSnapshot>? objectives = null;
|
||||
IReadOnlyList<FactionIssuedTaskSnapshot>? issuedTasks = null;
|
||||
|
||||
if (commander?.LastPlanningState is { } ps)
|
||||
if (commander?.LastStrategicAssessment is { } ps)
|
||||
{
|
||||
goapState = new FactionGoapStateSnapshot(
|
||||
strategicAssessment = new FactionPlanningStateSnapshot(
|
||||
ps.MilitaryShipCount,
|
||||
ps.MinerShipCount,
|
||||
ps.TransportShipCount,
|
||||
@@ -773,20 +787,149 @@ internal sealed class SimulationProjectionService
|
||||
ps.TargetSystemCount,
|
||||
ps.HasShipFactory,
|
||||
NormalizeFiniteFloat(ps.OreStockpile),
|
||||
NormalizeFiniteFloat(ps.RefinedMetalsStockpile),
|
||||
NormalizeFiniteFloat(ps.RefinedMetalsProductionRate),
|
||||
NormalizeFiniteFloat(ps.HullpartsStockpile),
|
||||
NormalizeFiniteFloat(ps.HullpartsProductionRate),
|
||||
NormalizeFiniteFloat(ps.ClaytronicsStockpile),
|
||||
NormalizeFiniteFloat(ps.ClaytronicsProductionRate),
|
||||
NormalizeFiniteFloat(ps.WaterStockpile),
|
||||
NormalizeFiniteFloat(ps.WaterProductionRate),
|
||||
NormalizeFiniteFloat(ps.WaterShortageHorizonSeconds));
|
||||
NormalizeFiniteFloat(ps.RefinedMetalsAvailableStock),
|
||||
NormalizeFiniteFloat(ps.RefinedMetalsUsageRate),
|
||||
NormalizeFiniteFloat(ps.RefinedMetalsProjectedProductionRate),
|
||||
NormalizeFiniteFloat(ps.RefinedMetalsProjectedNetRate),
|
||||
NormalizeFiniteFloat(ps.RefinedMetalsLevelSeconds),
|
||||
ps.RefinedMetalsLevel,
|
||||
NormalizeFiniteFloat(ps.HullpartsAvailableStock),
|
||||
NormalizeFiniteFloat(ps.HullpartsUsageRate),
|
||||
NormalizeFiniteFloat(ps.HullpartsProjectedProductionRate),
|
||||
NormalizeFiniteFloat(ps.HullpartsProjectedNetRate),
|
||||
NormalizeFiniteFloat(ps.HullpartsLevelSeconds),
|
||||
ps.HullpartsLevel,
|
||||
NormalizeFiniteFloat(ps.ClaytronicsAvailableStock),
|
||||
NormalizeFiniteFloat(ps.ClaytronicsUsageRate),
|
||||
NormalizeFiniteFloat(ps.ClaytronicsProjectedProductionRate),
|
||||
NormalizeFiniteFloat(ps.ClaytronicsProjectedNetRate),
|
||||
NormalizeFiniteFloat(ps.ClaytronicsLevelSeconds),
|
||||
ps.ClaytronicsLevel,
|
||||
NormalizeFiniteFloat(ps.WaterAvailableStock),
|
||||
NormalizeFiniteFloat(ps.WaterUsageRate),
|
||||
NormalizeFiniteFloat(ps.WaterProjectedProductionRate),
|
||||
NormalizeFiniteFloat(ps.WaterProjectedNetRate),
|
||||
NormalizeFiniteFloat(ps.WaterLevelSeconds),
|
||||
ps.WaterLevel);
|
||||
}
|
||||
|
||||
if (commander?.LastGoalPriorities is { } prios)
|
||||
if (commander?.LastStrategicPriorities is { } prios)
|
||||
{
|
||||
goapPriorities = prios.Select(p => new FactionGoapPrioritySnapshot(p.Name, p.Priority)).ToList();
|
||||
strategicPriorities = prios.Select(p => new FactionStrategicPrioritySnapshot(p.Name, p.Priority)).ToList();
|
||||
}
|
||||
|
||||
if (commander?.FactionBlackboard is { } bb)
|
||||
{
|
||||
blackboard = new FactionBlackboardSnapshot(
|
||||
bb.PlanCycle,
|
||||
bb.UpdatedAtUtc,
|
||||
bb.TargetWarshipCount,
|
||||
bb.HasWarIndustrySupplyChain,
|
||||
bb.HasShipyard,
|
||||
bb.HasActiveExpansionProject,
|
||||
bb.ActiveExpansionCommodityId,
|
||||
bb.ActiveExpansionModuleId,
|
||||
bb.ActiveExpansionSiteId,
|
||||
bb.ActiveExpansionSystemId,
|
||||
bb.EnemyFactionCount,
|
||||
bb.EnemyShipCount,
|
||||
bb.EnemyStationCount,
|
||||
bb.MilitaryShipCount,
|
||||
bb.MinerShipCount,
|
||||
bb.TransportShipCount,
|
||||
bb.ConstructorShipCount,
|
||||
bb.ControlledSystemCount,
|
||||
bb.CommoditySignals.Select(signal => new FactionCommoditySignalSnapshot(
|
||||
signal.ItemId,
|
||||
NormalizeFiniteFloat(signal.AvailableStock),
|
||||
NormalizeFiniteFloat(signal.OnHand),
|
||||
NormalizeFiniteFloat(signal.ProductionRatePerSecond),
|
||||
NormalizeFiniteFloat(signal.CommittedProductionRatePerSecond),
|
||||
NormalizeFiniteFloat(signal.UsageRatePerSecond),
|
||||
NormalizeFiniteFloat(signal.NetRatePerSecond),
|
||||
NormalizeFiniteFloat(signal.ProjectedNetRatePerSecond),
|
||||
NormalizeFiniteFloat(signal.LevelSeconds),
|
||||
signal.Level,
|
||||
NormalizeFiniteFloat(signal.ProjectedProductionRatePerSecond),
|
||||
NormalizeFiniteFloat(signal.BuyBacklog),
|
||||
NormalizeFiniteFloat(signal.ReservedForConstruction))).ToList(),
|
||||
bb.ThreatSignals.Select(signal => new FactionThreatSignalSnapshot(
|
||||
signal.ScopeId,
|
||||
signal.ScopeKind,
|
||||
signal.EnemyShipCount,
|
||||
signal.EnemyStationCount)).ToList());
|
||||
}
|
||||
|
||||
if (commander?.Objectives is { Count: > 0 } runtimeObjectives)
|
||||
{
|
||||
objectives = runtimeObjectives
|
||||
.OrderByDescending(objective => objective.Priority)
|
||||
.Select(objective => new FactionObjectiveSnapshot(
|
||||
objective.Id,
|
||||
objective.Kind.ToString(),
|
||||
objective.State.ToString(),
|
||||
objective.Priority,
|
||||
objective.ParentObjectiveId,
|
||||
objective.TargetFactionId,
|
||||
objective.TargetSystemId,
|
||||
objective.TargetSiteId,
|
||||
objective.TargetRegionId,
|
||||
objective.CommodityId,
|
||||
objective.ModuleId,
|
||||
objective.BudgetWeight,
|
||||
objective.SlotCost,
|
||||
objective.CreatedAtCycle,
|
||||
objective.UpdatedAtCycle,
|
||||
objective.InvalidationReason,
|
||||
objective.BlockingReason,
|
||||
objective.PrerequisiteObjectiveIds.OrderBy(id => id, StringComparer.Ordinal).ToList(),
|
||||
objective.AssignedAssetIds.OrderBy(id => id, StringComparer.Ordinal).ToList(),
|
||||
objective.Steps
|
||||
.OrderByDescending(step => step.Priority)
|
||||
.Select(step => new FactionPlanStepSnapshot(
|
||||
step.Id,
|
||||
step.Kind.ToString(),
|
||||
step.Status.ToString(),
|
||||
step.Priority,
|
||||
step.CommodityId,
|
||||
step.ModuleId,
|
||||
step.TargetFactionId,
|
||||
step.TargetSiteId,
|
||||
step.BlockingReason,
|
||||
step.Notes,
|
||||
step.LastEvaluatedCycle,
|
||||
step.DependencyStepIds.OrderBy(id => id, StringComparer.Ordinal).ToList(),
|
||||
step.RequiredFacts.OrderBy(fact => fact, StringComparer.Ordinal).ToList(),
|
||||
step.ProducedFacts.OrderBy(fact => fact, StringComparer.Ordinal).ToList(),
|
||||
step.AssignedAssetIds.OrderBy(id => id, StringComparer.Ordinal).ToList(),
|
||||
step.IssuedTaskIds.OrderBy(id => id, StringComparer.Ordinal).ToList()))
|
||||
.ToList()))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
if (commander?.IssuedTasks is { Count: > 0 } runtimeTasks)
|
||||
{
|
||||
issuedTasks = runtimeTasks
|
||||
.OrderByDescending(task => task.Priority)
|
||||
.Select(task => new FactionIssuedTaskSnapshot(
|
||||
task.Id,
|
||||
task.Kind.ToString(),
|
||||
task.State.ToString(),
|
||||
task.ObjectiveId,
|
||||
task.StepId,
|
||||
task.Priority,
|
||||
task.ShipRole,
|
||||
task.CommodityId,
|
||||
task.ModuleId,
|
||||
task.TargetFactionId,
|
||||
task.TargetSystemId,
|
||||
task.TargetSiteId,
|
||||
task.CreatedAtCycle,
|
||||
task.UpdatedAtCycle,
|
||||
task.BlockingReason,
|
||||
task.Notes,
|
||||
task.AssignedAssetIds.OrderBy(id => id, StringComparer.Ordinal).ToList()))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return new FactionDelta(
|
||||
@@ -800,8 +943,11 @@ internal sealed class SimulationProjectionService
|
||||
faction.ShipsBuilt,
|
||||
faction.ShipsLost,
|
||||
faction.DefaultPolicySetId,
|
||||
goapState,
|
||||
goapPriorities);
|
||||
strategicAssessment,
|
||||
strategicPriorities,
|
||||
blackboard,
|
||||
objectives,
|
||||
issuedTasks);
|
||||
}
|
||||
|
||||
private static ShipSpatialStateSnapshot ToShipSpatialStateSnapshot(ShipSpatialStateRuntime state) => new(
|
||||
|
||||
Reference in New Issue
Block a user