145 lines
5.3 KiB
C#
145 lines
5.3 KiB
C#
using SpaceGame.Api.Simulation.Engine;
|
|
using SpaceGame.Api.Simulation.Model;
|
|
|
|
namespace SpaceGame.Api.Simulation.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 float OreStockpile { get; set; }
|
|
public float RefinedMetalsStockpile { get; set; }
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
// ─── Goals ─────────────────────────────────────────────────────────────────────
|
|
|
|
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 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);
|
|
}
|
|
}
|
|
|
|
// ─── Actions ───────────────────────────────────────────────────────────────────
|
|
|
|
public sealed class OrderShipProductionAction : GoapAction<FactionPlanningState>
|
|
{
|
|
private readonly string shipKind;
|
|
private readonly string shipId;
|
|
|
|
public OrderShipProductionAction(string shipKind, string shipId)
|
|
{
|
|
this.shipKind = shipKind;
|
|
this.shipId = shipId;
|
|
}
|
|
|
|
public override string Name => $"order-{shipId}-production";
|
|
public override float Cost => 1f;
|
|
|
|
public override bool CheckPreconditions(FactionPlanningState state) => state.HasShipFactory;
|
|
|
|
public override FactionPlanningState ApplyEffects(FactionPlanningState state)
|
|
{
|
|
switch (shipKind)
|
|
{
|
|
case "military": state.MilitaryShipCount++; break;
|
|
case "mining": state.MinerShipCount++; break;
|
|
case "transport": state.TransportShipCount++; break;
|
|
case "construction": state.ConstructorShipCount++; break;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
public override void Execute(SimulationEngine engine, SimulationWorld world, CommanderRuntime commander)
|
|
{
|
|
commander.ActiveDirectives.Add($"produce-{shipKind}-ships");
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
public override FactionPlanningState ApplyEffects(FactionPlanningState state)
|
|
{
|
|
state.ControlledSystemCount++;
|
|
return state;
|
|
}
|
|
|
|
public override void Execute(SimulationEngine engine, SimulationWorld world, CommanderRuntime commander)
|
|
{
|
|
commander.ActiveDirectives.Add("expand-territory");
|
|
}
|
|
}
|