Deepen faction economy and station planning
This commit is contained in:
@@ -12,20 +12,89 @@ public sealed class FactionPlanningState
|
||||
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 RefinedMetalsStockpile { get; set; }
|
||||
public float RefinedMetalsProductionRate { get; set; }
|
||||
public float RefinedMetalsShortageHorizonSeconds { get; set; }
|
||||
public float HullpartsStockpile { get; set; }
|
||||
public float HullpartsProductionRate { get; set; }
|
||||
public float HullpartsShortageHorizonSeconds { get; set; }
|
||||
public float ClaytronicsStockpile { get; set; }
|
||||
public float ClaytronicsProductionRate { get; set; }
|
||||
public float ClaytronicsShortageHorizonSeconds { get; set; }
|
||||
public float WaterStockpile { get; set; }
|
||||
public float WaterProductionRate { get; set; }
|
||||
public float WaterShortageHorizonSeconds { get; set; }
|
||||
|
||||
public bool HasRefinedMetalsProduction => RefinedMetalsProductionRate > 0.01f;
|
||||
public bool HasHullpartsProduction => HullpartsProductionRate > 0.01f;
|
||||
public bool HasClaytronicsProduction => ClaytronicsProductionRate > 0.01f;
|
||||
public bool HasWaterProduction => WaterProductionRate > 0.01f;
|
||||
|
||||
public bool HasWarIndustrySupplyChain =>
|
||||
HasRefinedMetalsProduction && HasHullpartsProduction && HasClaytronicsProduction;
|
||||
|
||||
public FactionPlanningState Clone() => (FactionPlanningState)MemberwiseClone();
|
||||
|
||||
internal static int ComputeTargetWarships(FactionPlanningState state)
|
||||
{
|
||||
var expansionDeficit = Math.Max(0, state.TargetSystemCount - state.ControlledSystemCount);
|
||||
return Math.Max(2, (state.ControlledSystemCount * 2) + (expansionDeficit * 3));
|
||||
return Math.Max(3, (state.ControlledSystemCount * 2) + (expansionDeficit * 3) + Math.Min(4, state.EnemyFactionCount + state.EnemyStationCount));
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 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 =
|
||||
(state.HasRefinedMetalsProduction ? 0 : 1) +
|
||||
(state.HasHullpartsProduction ? 0 : 1) +
|
||||
(state.HasClaytronicsProduction ? 0 : 1) +
|
||||
(state.HasShipFactory ? 0 : 1);
|
||||
|
||||
return missingStages <= 0 ? 0f : 125f + (missingStages * 18f);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EnsureWaterSecurityGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "ensure-water-security";
|
||||
|
||||
public override bool IsSatisfied(FactionPlanningState state) =>
|
||||
state.HasWaterProduction && state.WaterShortageHorizonSeconds >= 300f;
|
||||
|
||||
public override float ComputePriority(FactionPlanningState state, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
if (state.HasWaterProduction && state.WaterShortageHorizonSeconds >= 300f)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
if (float.IsPositiveInfinity(state.WaterShortageHorizonSeconds))
|
||||
{
|
||||
return state.HasWaterProduction ? 0f : 85f;
|
||||
}
|
||||
|
||||
return 55f + MathF.Max(0f, 300f - state.WaterShortageHorizonSeconds) * 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EnsureWarFleetGoal : GoapGoal<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "ensure-war-fleet";
|
||||
@@ -40,6 +109,24 @@ public sealed class EnsureWarFleetGoal : GoapGoal<FactionPlanningState>
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
@@ -100,7 +187,8 @@ public sealed class OrderShipProductionAction : GoapAction<FactionPlanningState>
|
||||
public override string Name => $"order-{shipId}-production";
|
||||
public override float Cost => 1f;
|
||||
|
||||
public override bool CheckPreconditions(FactionPlanningState state) => state.HasShipFactory;
|
||||
public override bool CheckPreconditions(FactionPlanningState state) =>
|
||||
state.HasShipFactory && state.HasWarIndustrySupplyChain;
|
||||
|
||||
public override FactionPlanningState ApplyEffects(FactionPlanningState state)
|
||||
{
|
||||
@@ -121,13 +209,86 @@ public sealed class OrderShipProductionAction : GoapAction<FactionPlanningState>
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PlanWarIndustryAction : GoapAction<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "plan-war-industry";
|
||||
public override float Cost => 2f;
|
||||
|
||||
public override bool CheckPreconditions(FactionPlanningState state) =>
|
||||
state.EnemyFactionCount > 0 && (!state.HasWarIndustrySupplyChain || !state.HasShipFactory);
|
||||
|
||||
public override FactionPlanningState ApplyEffects(FactionPlanningState state)
|
||||
{
|
||||
state.RefinedMetalsProductionRate = MathF.Max(state.RefinedMetalsProductionRate, 1f);
|
||||
state.HullpartsProductionRate = MathF.Max(state.HullpartsProductionRate, 1f);
|
||||
state.ClaytronicsProductionRate = MathF.Max(state.ClaytronicsProductionRate, 1f);
|
||||
state.HasShipFactory = true;
|
||||
return state;
|
||||
}
|
||||
|
||||
public override void Execute(SimulationEngine engine, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
commander.ActiveDirectives.Add("bootstrap-war-industry");
|
||||
|
||||
if (FactionIndustryPlanner.AnalyzeShipyardNeed(world, commander.FactionId) is not { } project)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FactionIndustryPlanner.EnsureExpansionSite(world, commander.FactionId, project);
|
||||
commander.ActiveDirectives.Add($"expand-industry:{project.CommodityId}:{project.SystemId}:{project.CelestialId}");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class PlanCommoditySupplyAction : GoapAction<FactionPlanningState>
|
||||
{
|
||||
private readonly string commodityId;
|
||||
|
||||
public PlanCommoditySupplyAction(string commodityId)
|
||||
{
|
||||
this.commodityId = commodityId;
|
||||
}
|
||||
|
||||
public override string Name => $"plan-{commodityId}-supply";
|
||||
public override float Cost => 2f;
|
||||
|
||||
public override bool CheckPreconditions(FactionPlanningState state) =>
|
||||
commodityId switch
|
||||
{
|
||||
"water" => !state.HasWaterProduction || state.WaterShortageHorizonSeconds < 300f,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
public override FactionPlanningState ApplyEffects(FactionPlanningState state)
|
||||
{
|
||||
if (string.Equals(commodityId, "water", StringComparison.Ordinal))
|
||||
{
|
||||
state.WaterProductionRate = MathF.Max(state.WaterProductionRate, 1f);
|
||||
state.WaterShortageHorizonSeconds = MathF.Max(state.WaterShortageHorizonSeconds, 600f);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public override void Execute(SimulationEngine engine, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
if (FactionIndustryPlanner.AnalyzeCommodityNeed(world, commander.FactionId, commodityId) is not { } project)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FactionIndustryPlanner.EnsureExpansionSite(world, commander.FactionId, project);
|
||||
commander.ActiveDirectives.Add($"expand-industry:{project.CommodityId}:{project.SystemId}:{project.CelestialId}");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ExpandToSystemAction : GoapAction<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "expand-to-system";
|
||||
public override float Cost => 3f;
|
||||
|
||||
public override bool CheckPreconditions(FactionPlanningState state) =>
|
||||
state.ConstructorShipCount > 0 && state.MilitaryShipCount >= 2;
|
||||
state.ConstructorShipCount > 0 && state.MilitaryShipCount >= 2 && state.HasWarIndustrySupplyChain;
|
||||
|
||||
public override FactionPlanningState ApplyEffects(FactionPlanningState state)
|
||||
{
|
||||
@@ -140,3 +301,28 @@ public sealed class ExpandToSystemAction : GoapAction<FactionPlanningState>
|
||||
commander.ActiveDirectives.Add("expand-territory");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class LaunchExterminationCampaignAction : GoapAction<FactionPlanningState>
|
||||
{
|
||||
public override string Name => "launch-extermination-campaign";
|
||||
public override float Cost => 1f;
|
||||
|
||||
public override bool CheckPreconditions(FactionPlanningState state) =>
|
||||
state.EnemyFactionCount > 0
|
||||
&& state.HasShipFactory
|
||||
&& state.MilitaryShipCount >= Math.Max(2, FactionPlanningState.ComputeTargetWarships(state) / 2);
|
||||
|
||||
public override FactionPlanningState ApplyEffects(FactionPlanningState state)
|
||||
{
|
||||
state.EnemyShipCount = 0;
|
||||
state.EnemyStationCount = 0;
|
||||
state.EnemyFactionCount = 0;
|
||||
return state;
|
||||
}
|
||||
|
||||
public override void Execute(SimulationEngine engine, SimulationWorld world, CommanderRuntime commander)
|
||||
{
|
||||
commander.ActiveDirectives.Add("attack-rival");
|
||||
commander.ActiveDirectives.Add("produce-military-ships");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user