feat: massive AI generation
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,224 +0,0 @@
|
||||
|
||||
namespace SpaceGame.Api.Factions.AI;
|
||||
|
||||
// ─── Planning State ────────────────────────────────────────────────────────────
|
||||
|
||||
public sealed class FactionPlanningState
|
||||
{
|
||||
public int MilitaryShipCount { get; set; }
|
||||
public int MinerShipCount { get; set; }
|
||||
public int TransportShipCount { get; set; }
|
||||
public int ConstructorShipCount { get; set; }
|
||||
public int ControlledSystemCount { get; set; }
|
||||
public int TargetSystemCount { get; set; }
|
||||
public bool HasShipFactory { get; set; }
|
||||
public int EnemyFactionCount { get; set; }
|
||||
public int EnemyShipCount { get; set; }
|
||||
public int EnemyStationCount { get; set; }
|
||||
public float OreStockpile { get; set; }
|
||||
public float RefinedMetalsAvailableStock { get; set; }
|
||||
public float RefinedMetalsUsageRate { get; set; }
|
||||
public float RefinedMetalsProjectedProductionRate { get; set; }
|
||||
public float RefinedMetalsProjectedNetRate { get; set; }
|
||||
public float RefinedMetalsLevelSeconds { get; set; }
|
||||
public string RefinedMetalsLevel { get; set; } = "unknown";
|
||||
public float HullpartsAvailableStock { get; set; }
|
||||
public float HullpartsUsageRate { get; set; }
|
||||
public float HullpartsProjectedProductionRate { get; set; }
|
||||
public float HullpartsProjectedNetRate { get; set; }
|
||||
public float HullpartsLevelSeconds { get; set; }
|
||||
public string HullpartsLevel { get; set; } = "unknown";
|
||||
public float ClaytronicsAvailableStock { get; set; }
|
||||
public float ClaytronicsUsageRate { get; set; }
|
||||
public float ClaytronicsProjectedProductionRate { get; set; }
|
||||
public float ClaytronicsProjectedNetRate { get; set; }
|
||||
public float ClaytronicsLevelSeconds { get; set; }
|
||||
public string ClaytronicsLevel { get; set; } = "unknown";
|
||||
public float WaterAvailableStock { get; set; }
|
||||
public float WaterUsageRate { get; set; }
|
||||
public float WaterProjectedProductionRate { get; set; }
|
||||
public float WaterProjectedNetRate { get; set; }
|
||||
public float WaterLevelSeconds { get; set; }
|
||||
public string WaterLevel { get; set; } = "unknown";
|
||||
|
||||
public bool HasRefinedMetalsProduction => RefinedMetalsProjectedProductionRate > 0.01f;
|
||||
public bool HasHullpartsProduction => HullpartsProjectedProductionRate > 0.01f;
|
||||
public bool HasClaytronicsProduction => ClaytronicsProjectedProductionRate > 0.01f;
|
||||
public bool HasWaterProduction => WaterProjectedProductionRate > 0.01f;
|
||||
|
||||
public bool HasWarIndustrySupplyChain =>
|
||||
IsCommodityOperational(RefinedMetalsProjectedProductionRate, RefinedMetalsProjectedNetRate, RefinedMetalsLevelSeconds, RefinedMetalsLevel, 240f)
|
||||
&& IsCommodityOperational(HullpartsProjectedProductionRate, HullpartsProjectedNetRate, HullpartsLevelSeconds, HullpartsLevel, 240f)
|
||||
&& IsCommodityOperational(ClaytronicsProjectedProductionRate, ClaytronicsProjectedNetRate, ClaytronicsLevelSeconds, ClaytronicsLevel, 240f);
|
||||
|
||||
public FactionPlanningState Clone() => (FactionPlanningState)MemberwiseClone();
|
||||
|
||||
internal static int ComputeTargetWarships(FactionPlanningState state)
|
||||
{
|
||||
var expansionDeficit = Math.Max(0, state.TargetSystemCount - state.ControlledSystemCount);
|
||||
return Math.Max(3, (state.ControlledSystemCount * 2) + (expansionDeficit * 3) + Math.Min(4, state.EnemyFactionCount + state.EnemyStationCount));
|
||||
}
|
||||
|
||||
internal static bool IsCommodityOperational(
|
||||
float projectedProductionRate,
|
||||
float projectedNetRate,
|
||||
float levelSeconds,
|
||||
string level,
|
||||
float targetLevelSeconds) =>
|
||||
projectedProductionRate > 0.01f
|
||||
&& projectedNetRate >= -0.01f
|
||||
&& levelSeconds >= targetLevelSeconds
|
||||
&& (string.Equals(level, "stable", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(level, "surplus", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
internal static float ComputeCommodityNeed(
|
||||
float projectedProductionRate,
|
||||
float usageRate,
|
||||
float projectedNetRate,
|
||||
float levelSeconds,
|
||||
string level,
|
||||
float targetLevelSeconds)
|
||||
{
|
||||
var levelWeight = level switch
|
||||
{
|
||||
"critical" => 140f,
|
||||
"low" => 80f,
|
||||
"stable" => 20f,
|
||||
_ => 0f,
|
||||
};
|
||||
var rateDeficit = MathF.Max(0f, usageRate - projectedProductionRate);
|
||||
var levelDeficit = MathF.Max(0f, targetLevelSeconds - levelSeconds) / MathF.Max(targetLevelSeconds, 1f);
|
||||
var instability = projectedNetRate < 0f ? MathF.Abs(projectedNetRate) * 80f : 0f;
|
||||
return levelWeight + (rateDeficit * 140f) + (levelDeficit * 120f) + instability;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Goals ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
public sealed class EnsureWarIndustryGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "ensure-war-industry";
|
||||
|
||||
public override bool IsSatisfied(FactionPlanningState state) =>
|
||||
state.EnemyFactionCount <= 0 || (state.HasWarIndustrySupplyChain && state.HasShipFactory);
|
||||
|
||||
public override float ComputePriority(FactionPlanningState state, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
if (state.EnemyFactionCount <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
var missingStages =
|
||||
(FactionPlanningState.IsCommodityOperational(state.RefinedMetalsProjectedProductionRate, state.RefinedMetalsProjectedNetRate, state.RefinedMetalsLevelSeconds, state.RefinedMetalsLevel, 240f) ? 0 : 1) +
|
||||
(FactionPlanningState.IsCommodityOperational(state.HullpartsProjectedProductionRate, state.HullpartsProjectedNetRate, state.HullpartsLevelSeconds, state.HullpartsLevel, 240f) ? 0 : 1) +
|
||||
(FactionPlanningState.IsCommodityOperational(state.ClaytronicsProjectedProductionRate, state.ClaytronicsProjectedNetRate, state.ClaytronicsLevelSeconds, state.ClaytronicsLevel, 240f) ? 0 : 1) +
|
||||
(state.HasShipFactory ? 0 : 1);
|
||||
var supplyNeed =
|
||||
FactionPlanningState.ComputeCommodityNeed(state.RefinedMetalsProjectedProductionRate, state.RefinedMetalsUsageRate, state.RefinedMetalsProjectedNetRate, state.RefinedMetalsLevelSeconds, state.RefinedMetalsLevel, 240f)
|
||||
+ FactionPlanningState.ComputeCommodityNeed(state.HullpartsProjectedProductionRate, state.HullpartsUsageRate, state.HullpartsProjectedNetRate, state.HullpartsLevelSeconds, state.HullpartsLevel, 240f)
|
||||
+ FactionPlanningState.ComputeCommodityNeed(state.ClaytronicsProjectedProductionRate, state.ClaytronicsUsageRate, state.ClaytronicsProjectedNetRate, state.ClaytronicsLevelSeconds, state.ClaytronicsLevel, 240f);
|
||||
|
||||
return missingStages <= 0 && supplyNeed <= 0.01f ? 0f : 110f + (missingStages * 22f) + (supplyNeed * 0.18f);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EnsureWaterSecurityGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "ensure-water-security";
|
||||
|
||||
public override bool IsSatisfied(FactionPlanningState state) =>
|
||||
FactionPlanningState.IsCommodityOperational(state.WaterProjectedProductionRate, state.WaterProjectedNetRate, state.WaterLevelSeconds, state.WaterLevel, 300f);
|
||||
|
||||
public override float ComputePriority(FactionPlanningState state, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
if (FactionPlanningState.IsCommodityOperational(state.WaterProjectedProductionRate, state.WaterProjectedNetRate, state.WaterLevelSeconds, state.WaterLevel, 300f))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
return 55f + FactionPlanningState.ComputeCommodityNeed(
|
||||
state.WaterProjectedProductionRate,
|
||||
state.WaterUsageRate,
|
||||
state.WaterProjectedNetRate,
|
||||
state.WaterLevelSeconds,
|
||||
state.WaterLevel,
|
||||
300f) * 0.25f;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EnsureWarFleetGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "ensure-war-fleet";
|
||||
|
||||
public override bool IsSatisfied(FactionPlanningState state) =>
|
||||
state.MilitaryShipCount >= FactionPlanningState.ComputeTargetWarships(state);
|
||||
|
||||
public override float ComputePriority(FactionPlanningState state, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
var deficit = FactionPlanningState.ComputeTargetWarships(state) - state.MilitaryShipCount;
|
||||
return deficit <= 0 ? 0f : 50f + (deficit * 10f);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ExterminateRivalGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "exterminate-rival";
|
||||
|
||||
public override bool IsSatisfied(FactionPlanningState state) =>
|
||||
state.EnemyFactionCount <= 0 || (state.EnemyShipCount <= 0 && state.EnemyStationCount <= 0);
|
||||
|
||||
public override float ComputePriority(FactionPlanningState state, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
if (state.EnemyFactionCount <= 0)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
return 140f + (state.EnemyStationCount * 25f) + (state.EnemyShipCount * 6f);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ExpandTerritoryGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "expand-territory";
|
||||
|
||||
public override bool IsSatisfied(FactionPlanningState state) =>
|
||||
state.ControlledSystemCount >= state.TargetSystemCount;
|
||||
|
||||
public override float ComputePriority(FactionPlanningState state, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
var deficit = state.TargetSystemCount - state.ControlledSystemCount;
|
||||
return deficit <= 0 ? 0f : 80f + (deficit * 15f);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EnsureMiningCapacityGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
private const int MinMiners = 2;
|
||||
|
||||
public override string Name => "ensure-mining-capacity";
|
||||
|
||||
public override bool IsSatisfied(FactionPlanningState state) => state.MinerShipCount >= MinMiners;
|
||||
|
||||
public override float ComputePriority(FactionPlanningState state, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
var deficit = MinMiners - state.MinerShipCount;
|
||||
return deficit <= 0 ? 0f : 70f + (deficit * 12f);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EnsureConstructionCapacityGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
private const int MinConstructors = 1;
|
||||
|
||||
public override string Name => "ensure-construction-capacity";
|
||||
|
||||
public override bool IsSatisfied(FactionPlanningState state) => state.ConstructorShipCount >= MinConstructors;
|
||||
|
||||
public override float ComputePriority(FactionPlanningState state, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
var deficit = MinConstructors - state.ConstructorShipCount;
|
||||
return deficit <= 0 ? 0f : 60f + (deficit * 10f);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user