Add sprinkler valve simulation contract

This commit is contained in:
2026-05-14 10:15:12 +02:00
parent 6db3e60fd1
commit 2ad7feef96
13 changed files with 194 additions and 6 deletions

View File

@@ -285,7 +285,7 @@ public sealed class SimulationEngineTests
var json = LevelSerializer.Serialize(level);
var loaded = LevelSerializer.Deserialize(json);
Assert.Contains("\"Version\": 3", json);
Assert.Contains("\"Version\": 4", json);
Assert.Equal(level.Name, loaded.Name);
Assert.Equal(EPropType.Consumer, loaded.GetProp(new(3, 3)).Type);
Assert.Equal(level.RequiredFuelConsumers, loaded.RequiredFuelConsumers);
@@ -323,6 +323,55 @@ public sealed class SimulationEngineTests
Assert.Contains("Unsupported level file version 2", exception.Message);
}
[Fact]
public void SprinklerValveDischargesOnlyWithLinkedEnabledControlAndFedWaterBranch()
{
var enabled = SprinklerLevel(EPropSwitchState.Enabled);
var disabled = SprinklerLevel(EPropSwitchState.Disabled);
var enabledResult = m_Engine.AdvancePulseForDebug(enabled);
var disabledResult = m_Engine.AdvancePulseForDebug(disabled);
Assert.True(enabledResult.GetSurface(new(2, 2)).Water > 0);
Assert.Equal(0, disabledResult.GetSurface(new(2, 2)).Water);
}
[Fact]
public void SprinklerDischargeAppliesLocalPressureDebt()
{
var enabled = m_Engine.AdvancePulseForDebug(SprinklerLevel(EPropSwitchState.Enabled));
var disabled = m_Engine.AdvancePulseForDebug(SprinklerLevel(EPropSwitchState.Disabled));
Assert.True(enabled.GetUnderground(new(2, 1), ECarrierType.Water).Intensity < disabled.GetUnderground(new(2, 1), ECarrierType.Water).Intensity);
}
[Fact]
public void DirectSprinklerValveInteractionIsInvalidAndDoesNotPulse()
{
var level = SprinklerLevel(EPropSwitchState.Enabled) with { Robot = new() { Position = new(2, 1) } };
var next = m_Engine.InteractProp(level);
Assert.Equal(0, next.Global.Pulse);
Assert.Equal("PROP NOT INTERACTIVE", next.Global.Status);
}
[Fact]
public void UnfedLeakDoesNotInjectFreshSurfaceWater()
{
var level = LevelState.Create("Unfed leak", 5, 5);
level = level.SetUnderground(new(2, 2), ECarrierType.Water, new() { State = EUndergroundState.Leaking }) with {
RequiredFuelConsumers = 0,
RequiredWaterConsumers = 0,
RequiredElectricityConsumers = 0,
Leaks = [new() { Carrier = ECarrierType.Water, UndergroundPosition = new(2, 2), AccessPosition = new(2, 2) }]
};
var next = m_Engine.AdvancePulseForDebug(level);
Assert.Equal(0, next.GetSurface(new(2, 2)).Water);
}
private static LevelState BuildReadyLevel()
{
var level = LevelState.Create("Ready", 8, 7);
@@ -387,5 +436,22 @@ public sealed class SimulationEngineTests
};
}
private static LevelState SprinklerLevel(EPropSwitchState controlState)
{
var level = LevelState.Create("Sprinkler", 5, 5);
level = level.SetTerrain(new(2, 1), ECellTerrain.Wall);
level = level.SetUnderground(new(1, 1), ECarrierType.Water, new() { State = EUndergroundState.Intact });
level = level.SetUnderground(new(2, 1), ECarrierType.Water, new() { State = EUndergroundState.Intact });
level = level.SetProp(new(1, 1), new() { Type = EPropType.Flow, Carrier = ECarrierType.Water });
level = level.SetProp(new(2, 1), new() { Type = EPropType.SprinklerValve, Carrier = ECarrierType.Water, OutletPosition = new(2, 2) });
level = level.SetProp(new(3, 2), new() { Type = EPropType.SprinklerControl, SwitchState = controlState, LinkedPosition = new(2, 1) });
return level with {
RequiredFuelConsumers = 0,
RequiredWaterConsumers = 0,
RequiredElectricityConsumers = 0,
Robot = new() { Position = new(3, 2) }
};
}
private readonly SimulationEngine m_Engine = new();
}