Add branch-aware junction flow

This commit is contained in:
2026-05-10 17:29:19 +02:00
parent b232c0319f
commit cb28eee1dd
6 changed files with 251 additions and 54 deletions

View File

@@ -1,4 +1,4 @@
namespace ReactorMaintenance.Simulation.Tests;
namespace ReactorMaintenance.Simulation.Tests;
public sealed class SimulationEngineTests
{
@@ -86,6 +86,57 @@ public sealed class SimulationEngineTests
Assert.NotEqual(ELevelState.Lost, next.Global.LevelState);
}
[Fact]
public void TJunctionRatioSplitsFlowAcrossInferredOutgoingBranches()
{
var level = BuildTJunctionLevel(ETJunctionMode.TwoTwo);
var next = m_Engine.AdvanceTurn(level);
Assert.True(next.GetUnderground(new(2, 2), ECarrierType.Fuel).Amount > 0);
Assert.Equal(next.GetUnderground(new(2, 2), ECarrierType.Fuel).Amount, next.GetUnderground(new(3, 3), ECarrierType.Fuel).Amount);
Assert.True(next.GetUnderground(new(2, 2), ECarrierType.Fuel).Amount < next.GetUnderground(new(2, 3), ECarrierType.Fuel).Amount);
}
[Fact]
public void TJunctionZeroWeightBranchReceivesNoIntentionalOutflow()
{
var level = BuildTJunctionLevel(ETJunctionMode.ZeroFour);
var next = m_Engine.AdvanceTurn(level);
Assert.Equal(0, next.GetUnderground(new(2, 2), ECarrierType.Fuel).Amount);
Assert.True(next.GetUnderground(new(3, 3), ECarrierType.Fuel).Amount > 0);
}
[Fact]
public void ValidatorRejectsAmbiguousJunctionSourceBranches()
{
var level = BuildTJunctionLevel(ETJunctionMode.TwoTwo);
level = level.SetProp(new(3, 3), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel });
var report = new LevelValidator().Validate(level);
Assert.False(report.IsValid);
Assert.Contains(report.Errors, error => error.Message.Contains("Ambiguous junction flow", StringComparison.Ordinal));
}
[Fact]
public void NonJunctionCellsAcceptBestFlowFromMultipleSourcePaths()
{
var level = LevelState.Create("Best path", 7, 7);
level = AddHorizontalUnderground(level, ECarrierType.Fuel, 1, 5, 3);
level = level.SetProp(new(1, 3), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel });
level = level.SetProp(new(5, 3), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel });
level = level.SetProp(new(3, 3), new() { Type = EPropType.Consumer, Carrier = ECarrierType.Fuel });
var report = new LevelValidator().Validate(level);
var next = m_Engine.AdvanceTurn(level);
Assert.True(report.IsValid);
Assert.Equal(EConsumerServiceState.Producing, next.GetProp(new(3, 3)).ServiceState);
}
[Fact]
public void RobotLosesOnUnsafeElementHazard()
{
@@ -199,5 +250,24 @@ public sealed class SimulationEngineTests
return level;
}
private static LevelState BuildTJunctionLevel(ETJunctionMode mode)
{
var level = LevelState.Create("T junction", 6, 6);
level = level.SetUnderground(new(1, 3), ECarrierType.Fuel, new() { State = EUndergroundState.Intact });
level = level.SetUnderground(new(2, 3), ECarrierType.Fuel, new() { State = EUndergroundState.Intact });
level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, new() { State = EUndergroundState.Intact });
level = level.SetUnderground(new(3, 3), ECarrierType.Fuel, new() { State = EUndergroundState.Intact });
level = level.SetProp(new(1, 3), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel });
return level.SetProp(new(2, 3), new() { Type = EPropType.TJunction, Carrier = ECarrierType.Fuel, TJunctionMode = mode });
}
private static LevelState AddHorizontalUnderground(LevelState level, ECarrierType carrier, int startX, int endX, int y)
{
for (var x = startX; x <= endX; x++)
level = level.SetUnderground(new(x, y), carrier, new() { State = EUndergroundState.Intact });
return level;
}
private readonly SimulationEngine m_Engine = new();
}
}