Add pulse contract and isolation valves

This commit is contained in:
2026-05-14 10:11:35 +02:00
parent c5688d2c0d
commit 6db3e60fd1
15 changed files with 195 additions and 27 deletions

View File

@@ -9,22 +9,17 @@ public sealed class SimulationEngine
public LevelState InteractProp(LevelState level)
{
return PlayerActionSystem.InteractProp(level, ResolveStep);
return PlayerActionSystem.InteractProp(level, ResolvePulse);
}
public LevelState InteractLeak(LevelState level, ECarrierType carrier, bool useRemedy)
{
return PlayerActionSystem.InteractLeak(level, carrier, useRemedy, ResolveStep);
return PlayerActionSystem.InteractLeak(level, carrier, useRemedy, ResolvePulse);
}
public LevelState ApplyHeatShield(LevelState level)
{
return PlayerActionSystem.ApplyHeatShield(level, ResolveStep);
}
private LevelState ResolveStep(LevelState level)
{
return ResolveStep(level, true);
return PlayerActionSystem.ApplyHeatShield(level, ResolvePulse);
}
public LevelState ActivateReactor(LevelState level)
@@ -32,14 +27,26 @@ public sealed class SimulationEngine
return ReactorSystem.Activate(level);
}
public LevelState EndTurn(LevelState level)
public LevelState AdvancePulseForDebug(LevelState level)
{
return ResolvePulse(level);
}
public LevelState AdvanceStepForDebug(LevelState level)
{
return ResolveStep(level);
}
[Obsolete("Use AdvancePulseForDebug. Player-facing wait/turn advancement is not part of normal gameplay.")]
public LevelState EndTurn(LevelState level)
{
return AdvancePulseForDebug(level);
}
[Obsolete("Use AdvancePulseForDebug. Player-facing wait/turn advancement is not part of normal gameplay.")]
public LevelState AdvanceTurn(LevelState level)
{
return ResolveStep(level);
return AdvancePulseForDebug(level);
}
public IReadOnlyList<Forecast> Forecast(LevelState level)
@@ -47,7 +54,41 @@ public sealed class SimulationEngine
return ForecastSystem.Forecast(level, simulated => ResolveStep(simulated, false));
}
private LevelState ResolveStep(LevelState level, bool refreshForecasts)
private LevelState ResolvePulse(LevelState level)
{
var next = ValidateAndPropagate(level);
if (next.Global.LevelState == ELevelState.Lost)
return next;
for (var i = 0; i < Balancing.Current.StepsPerPulse; i++)
next = ResolveStepContent(next);
next = ReactorSystem.DeriveState(next);
next = SurfaceInteractionSystem.AdvanceDurations(next);
next = next with {
Global = next.Global with {
Turn = next.Global.Pulse + 1,
Pulse = next.Global.Pulse + 1
}
};
return next with { Forecasts = Forecast(next) };
}
private LevelState ResolveStep(LevelState level, bool refreshForecasts = true)
{
var next = ValidateAndPropagate(level);
if (next.Global.LevelState == ELevelState.Lost)
return next;
next = ResolveStepContent(next);
next = ReactorSystem.DeriveState(next);
next = SurfaceInteractionSystem.AdvanceDurations(next);
return refreshForecasts ? next with { Forecasts = Forecast(next) } : next;
}
private LevelState ValidateAndPropagate(LevelState level)
{
var report = m_Validator.Validate(level);
if (!report.IsValid)
@@ -57,18 +98,16 @@ public sealed class SimulationEngine
next = NetworkPropagationSystem.Propagate(next);
next = ConsumerSystem.Resolve(next);
next = StructuralIntegritySystem.Resolve(next);
return next;
}
private static LevelState ResolveStepContent(LevelState level)
{
var next = level;
next = LeakSystem.Inject(next);
next = SurfaceInteractionSystem.Resolve(next);
next = RobotSafetySystem.Resolve(next);
next = ReactorSystem.DeriveState(next);
next = SurfaceInteractionSystem.AdvanceDurations(next);
next = next with {
Global = next.Global with {
Turn = next.Global.Turn + 1
}
};
return refreshForecasts ? next with { Forecasts = Forecast(next) } : next;
next = next with { Global = next.Global with { Step = next.Global.Step + 1 } };
return next;
}
private readonly LevelValidator m_Validator = new();