namespace ReactorMaintenance.Simulation.Tests; public sealed class SimulationEngineTests { [Fact] public void NetworkPropagationSuppliesConsumerServicesAndReadiesReactor() { var level = BuildReadyLevel(); var next = m_Engine.AdvancePulseForDebug(level); var consumer = next.GetProp(new(3, 3)); Assert.Equal(EConsumerServiceState.Producing, consumer.FuelServiceState); Assert.Equal(EConsumerServiceState.Producing, consumer.WaterServiceState); Assert.Equal(EConsumerServiceState.Producing, consumer.ElectricityServiceState); Assert.Equal(ELevelState.Ready, next.Global.LevelState); Assert.Empty(next.Forecasts); } [Fact] public void ReactorNeedsPositiveFlowOnlyForNetworksBeneathControl() { var level = BuildReadyLevel(); level = level.SetUnderground(new(5, 3), ECarrierType.Fuel, new() { State = EUndergroundState.Intact }); var next = m_Engine.AdvancePulseForDebug(level); Assert.NotEqual(ELevelState.Ready, next.Global.LevelState); } [Fact] public void ReactorActivatesOnlyAtReadyControl() { var level = m_Engine.AdvancePulseForDebug(BuildReadyLevel()) with { Robot = new() { Position = new(5, 3) } }; var activated = m_Engine.ActivateReactor(level); Assert.Equal(ELevelState.Won, activated.Global.LevelState); Assert.True(activated.Reactors[0].Activated); } [Fact] public void DisabledConsumerReportsDisabledOnlyForNetworksBeneathIt() { var level = LevelState.Create("Disabled", 6, 6); level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, new() { State = EUndergroundState.Intact }); level = level.SetProp(new(2, 2), new() { Type = EPropType.Consumer, SwitchState = EPropSwitchState.Disabled }); var next = m_Engine.AdvancePulseForDebug(level); var consumer = next.GetProp(new(2, 2)); Assert.Equal(EConsumerServiceState.Disabled, consumer.FuelServiceState); Assert.Equal(EConsumerServiceState.Unknown, consumer.WaterServiceState); Assert.Equal(EConsumerServiceState.Unknown, consumer.ElectricityServiceState); Assert.Equal(EConsumerServiceState.Disabled, consumer.ServiceState); } [Fact] public void MovementIsQuickAndDoesNotResolveSimulationStep() { var level = LevelState.Create("Quick", 6, 6) with { Robot = new() { Position = new(1, 1) } }; var next = m_Engine.MoveRobot(level, new(2, 1)); Assert.Equal(new(2, 1), next.Robot.Position); Assert.Equal(0, next.Global.Pulse); } [Fact] public void DoorInteractionIsLengthyAndResolvesSimulationStep() { var level = DoorLevel(); level = level with { Robot = new() { Position = new(3, 2) } }; var next = m_Engine.InteractProp(level); Assert.Equal(EDoorState.Open, next.GetProp(new(3, 2)).DoorState); Assert.Equal(1, next.Global.Pulse); Assert.Equal(Balancing.Current.StepsPerPulse, next.Global.Step); } [Fact] public void UnpoweredDoorInteractionChangesNoDoorStateButStillPulses() { var level = DoorLevel(powered: false) with { Robot = new() { Position = new(3, 2) } }; var next = m_Engine.InteractProp(level); Assert.Equal(EDoorState.Closed, next.GetProp(new(3, 2)).DoorState); Assert.Equal(1, next.Global.Pulse); } [Fact] public void PoweredTerminalInteractionEnablesLocalForecastsUntilRobotLeaves() { var level = TerminalLevel(); var activated = m_Engine.InteractProp(level); var moved = m_Engine.MoveRobot(activated, new(2, 1)); Assert.True(activated.GetProp(new(1, 1)).Active); Assert.NotEmpty(activated.Forecasts); Assert.Empty(moved.Forecasts); } [Fact] public void UnpoweredTerminalInteractionRevealsNothingButStillPulses() { var level = TerminalLevel(false); var next = m_Engine.InteractProp(level); Assert.False(next.GetProp(new(1, 1)).Active); Assert.Empty(next.Forecasts); Assert.Equal(1, next.Global.Pulse); } [Fact] public void EveryAcceptedLengthyActionAdvancesOneFixedPulse() { var level = DoorLevel() with { Robot = new() { Position = new(3, 2) } }; var next = m_Engine.InteractProp(level); Assert.Equal(1, next.Global.Pulse); Assert.Equal(Balancing.Current.StepsPerPulse, next.Global.Step); } [Fact] public void DebugStepAdvancementDoesNotAdvancePulse() { var level = BuildReadyLevel(); var next = m_Engine.AdvanceStepForDebug(level); Assert.Equal(0, next.Global.Pulse); Assert.Equal(1, next.Global.Step); } [Fact] public void IsolationValveOpenAllowsPropagationAndClosedBlocksDownstreamFeed() { var open = IsolationValveLevel(EPropSwitchState.Enabled); var closed = IsolationValveLevel(EPropSwitchState.Disabled); var openResult = m_Engine.AdvancePulseForDebug(open); var closedResult = m_Engine.AdvancePulseForDebug(closed); Assert.True(openResult.GetUnderground(new(3, 2), ECarrierType.Fuel).Amount > 0); Assert.Equal(ELevelState.Ready, openResult.Global.LevelState); Assert.Equal(0, closedResult.GetUnderground(new(3, 2), ECarrierType.Fuel).Amount); Assert.NotEqual(ELevelState.Ready, closedResult.Global.LevelState); } [Fact] public void TogglingIsolationValveIsLengthyAndAdvancesOneFixedPulse() { var level = IsolationValveLevel(EPropSwitchState.Enabled) with { Robot = new() { Position = new(2, 2) } }; var next = m_Engine.InteractProp(level); Assert.Equal(EPropSwitchState.Disabled, next.GetProp(new(2, 2)).SwitchState); Assert.Equal(1, next.Global.Pulse); Assert.Equal(Balancing.Current.StepsPerPulse, next.Global.Step); } [Fact] public void ClosedInferredDoorBlocksAdjacentHeatFlow() { var level = DoorLevel(); level = level.SetSurface(new(3, 2), new() { Heat = 8 }); var next = m_Engine.AdvancePulseForDebug(level); Assert.Equal(0, next.GetSurface(new(4, 2)).Heat); } [Fact] public void StructuralIntegrityCreatesLeakWhenWeakCellHasPositivePressure() { var level = LevelState.Create("Integrity leak", 6, 6); level = AddLine(level, ECarrierType.Fuel, new(1, 2), new(2, 2)); level = level.SetProp(new(1, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel }); level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, level.GetUnderground(new(2, 2), ECarrierType.Fuel) with { StructuralIntegrity = Balancing.Current.StructuralIntegrityLeakThreshold }); var next = m_Engine.AdvancePulseForDebug(level); Assert.Equal(EUndergroundState.Leaking, next.GetUnderground(new(2, 2), ECarrierType.Fuel).State); Assert.Contains(next.Leaks, leak => leak.Carrier == ECarrierType.Fuel && leak.UndergroundPosition == new GridPosition(2, 2)); Assert.True(next.GetSurface(new(2, 2)).Fuel > 0); } [Fact] public void HighPressureWorsensNonMaxStructuralIntegrity() { var level = LevelState.Create("Integrity damage", 6, 6); level = AddLine(level, ECarrierType.Fuel, new(1, 2), new(2, 2)); level = level.SetProp(new(1, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel }); level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, level.GetUnderground(new(2, 2), ECarrierType.Fuel) with { StructuralIntegrity = Balancing.Current.MaxStructuralIntegrity - 1 }); var next = m_Engine.AdvancePulseForDebug(level); Assert.True(next.GetUnderground(new(2, 2), ECarrierType.Fuel).StructuralIntegrity < Balancing.Current.MaxStructuralIntegrity - 1); } [Fact] public void RepairingLeakRestoresStructuralIntegrity() { var level = LevelState.Create("Repair", 6, 6); level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, new() { State = EUndergroundState.Leaking, Amount = 5, Intensity = 5, StructuralIntegrity = 0 }) with { Robot = new() { Position = new(2, 2) }, Leaks = [new() { Carrier = ECarrierType.Fuel, UndergroundPosition = new(2, 2), AccessPosition = new(2, 2) }] }; var next = m_Engine.InteractLeak(level, ECarrierType.Fuel, false); Assert.True(next.Leaks[0].Repaired); Assert.Equal(EUndergroundState.Intact, next.GetUnderground(new(2, 2), ECarrierType.Fuel).State); Assert.Equal(Balancing.Current.MaxStructuralIntegrity, next.GetUnderground(new(2, 2), ECarrierType.Fuel).StructuralIntegrity); } [Fact] public void ElementRemedyClearsHazardAndBlocksImmediateReentry() { var level = LevelState.Create("Remedy", 6, 6); level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, new() { State = EUndergroundState.Leaking, Amount = 5, Intensity = 5 }); level = level.SetSurface(new(2, 2), new() { Fuel = 5 }) with { Robot = new() { Position = new(2, 2), FuelNeutralizers = 1 }, Leaks = [new() { Carrier = ECarrierType.Fuel, UndergroundPosition = new(2, 2), AccessPosition = new(2, 2) }] }; var next = m_Engine.InteractLeak(level, ECarrierType.Fuel, true); Assert.Equal(0, next.GetSurface(new(2, 2)).Fuel); Assert.True(next.GetSurface(new(2, 2)).FuelBlockTurns > 0); Assert.Equal(0, next.Robot.FuelNeutralizers); } [Fact] public void HeatShieldPreventsRobotHeatLoss() { var level = LevelState.Create("Heat shield", 6, 6); level = level.SetSurface(new(2, 2), new() { Heat = Balancing.Current.RobotHeatSafetyThreshold }) with { Robot = new() { Position = new(2, 2), HeatImmunitySteps = 1 } }; var next = m_Engine.AdvancePulseForDebug(level); Assert.NotEqual(ELevelState.Lost, next.Global.LevelState); } [Fact] public void UnsafeEntryLossOnlyHappensWhenMovingIntoUnsafeDestination() { var level = LevelState.Create("Unsafe", 5, 5) with { Robot = new() { Position = new(1, 1) } }; level = level.SetSurface(new(2, 1), new() { Heat = Balancing.Current.RobotHeatSafetyThreshold }); var next = m_Engine.MoveRobot(level, new(2, 1)); Assert.Equal(ELevelState.Lost, next.Global.LevelState); Assert.Equal("UNSAFE ENTRY LOSS", next.Global.Status); } [Fact] public void FuelOnlyAndWaterOnlyCellsAreSafeToEnter() { var fuel = LevelState.Create("Fuel safe", 5, 5) with { Robot = new() { Position = new(1, 1) } }; fuel = fuel.SetSurface(new(2, 1), new() { Fuel = Balancing.Current.MaxValue }); var water = LevelState.Create("Water safe", 5, 5) with { Robot = new() { Position = new(1, 1) } }; water = water.SetSurface(new(2, 1), new() { Water = Balancing.Current.MaxValue }); Assert.NotEqual(ELevelState.Lost, m_Engine.MoveRobot(fuel, new(2, 1)).Global.LevelState); Assert.NotEqual(ELevelState.Lost, m_Engine.MoveRobot(water, new(2, 1)).Global.LevelState); } [Fact] public void PulseDoesNotLoseStationaryRobotWhenCellBecomesUnsafe() { var level = LevelState.Create("Stationary", 5, 5) with { Robot = new() { Position = new(2, 2) } }; level = level.SetSurface(new(2, 2), new() { Heat = Balancing.Current.RobotHeatSafetyThreshold }); var next = m_Engine.AdvancePulseForDebug(level); Assert.NotEqual(ELevelState.Lost, next.Global.LevelState); } [Fact] public void WaterDilutesFuelAndQuenchesHeatBeforeIgnition() { var level = LevelState.Create("Mitigation", 5, 5); level = level.SetSurface(new(2, 2), new() { Fuel = Balancing.Current.FuelCaution, Water = Balancing.Current.WaterCritical, Heat = Balancing.Current.HeatCaution }); var next = m_Engine.AdvanceStepForDebug(level); Assert.True(next.GetSurface(new(2, 2)).Fuel < level.GetSurface(new(2, 2)).Fuel); Assert.True(next.GetSurface(new(2, 2)).Heat < level.GetSurface(new(2, 2)).Heat); } [Fact] public void HotCellsEvaporateWaterFasterThanColdCells() { var level = LevelState.Create("Evaporation", 5, 5); level = level.SetSurface(new(1, 1), new() { Water = 5 }); level = level.SetSurface(new(2, 1), new() { Water = 5, Heat = 6 }); var next = m_Engine.AdvanceStepForDebug(level); Assert.True(next.GetSurface(new(2, 1)).Water < next.GetSurface(new(1, 1)).Water); Assert.True(next.GetSurface(new(2, 1)).Heat < 6); } [Fact] public void WetCellsConductElectricityFasterThanDryCells() { var wet = LevelState.Create("Wet conduct", 5, 5); wet = wet.SetSurface(new(1, 1), new() { Electricity = 8, Water = Balancing.Current.WaterCaution }); var dry = LevelState.Create("Dry conduct", 5, 5); dry = dry.SetSurface(new(1, 1), new() { Electricity = 8 }); var wetNext = m_Engine.AdvanceStepForDebug(wet); var dryNext = m_Engine.AdvanceStepForDebug(dry); Assert.True(wetNext.GetSurface(new(2, 1)).Electricity > dryNext.GetSurface(new(2, 1)).Electricity); } [Fact] public void FuelAndElectricityCanIgniteIntoHeat() { var level = LevelState.Create("Ignite", 5, 5); level = level.SetSurface(new(2, 2), new() { Fuel = Balancing.Current.FuelCritical, Electricity = Balancing.Current.ElectricityCritical }); var next = m_Engine.AdvanceStepForDebug(level); Assert.True(next.GetSurface(new(2, 2)).Heat > 0); Assert.True(next.GetSurface(new(2, 2)).Fuel < level.GetSurface(new(2, 2)).Fuel); } [Fact] public void JunctionRatioSplitsFlowAcrossInferredOutgoingBranches() { var level = BuildJunctionLevel(2); var next = m_Engine.AdvancePulseForDebug(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 JunctionZeroWeightBranchReceivesNoIntentionalOutflow() { var level = BuildJunctionLevel(0); var next = m_Engine.AdvancePulseForDebug(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 = BuildJunctionLevel(2); 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 ValidatorRejectsInvalidDoorGeometryAndWallHazards() { var level = LevelState.Create("Invalid", 6, 6); level = level.SetProp(new(2, 2), new() { Type = EPropType.Door }); level = level.SetTerrain(new(4, 4), ECellTerrain.Wall); level = level with { Surface = level.Surface.ToArray() }; level.Surface[level.Index(new(4, 4))] = new() { Heat = 1 }; var report = new LevelValidator().Validate(level); Assert.False(report.IsValid); Assert.Contains(report.Errors, error => error.Message.Contains("Door must be surrounded", StringComparison.Ordinal)); Assert.Contains(report.Errors, error => error.Message.Contains("Wall cell", StringComparison.Ordinal)); } [Fact] public void ValidatorRejectsIsolationValveOnMultipleCarriers() { var level = LevelState.Create("Invalid valve", 5, 5); level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, new() { State = EUndergroundState.Intact }); level = level.SetUnderground(new(2, 2), ECarrierType.Water, new() { State = EUndergroundState.Intact }); level = level.SetProp(new(2, 2), new() { Type = EPropType.IsolationValve, Carrier = ECarrierType.Fuel }); var report = new LevelValidator().Validate(level); Assert.False(report.IsValid); Assert.Contains(report.Errors, error => error.Message.Contains("exactly one matching underground carrier", StringComparison.Ordinal)); } [Fact] public void LevelSerializationRoundTripsCurrentSchemaOnly() { var level = BuildReadyLevel(); var json = LevelSerializer.Serialize(level); var loaded = LevelSerializer.Deserialize(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); } [Fact] public void LevelSerializationRoundTripsPropDoorsAndElectricityLeakFaces() { var level = BuildReadyLevel(); level = level.SetTerrain(new(6, 4), ECellTerrain.Wall); level = level.SetUnderground(new(6, 4), ECarrierType.Electricity, new() { State = EUndergroundState.Leaking }) with { Leaks = [new() { Carrier = ECarrierType.Electricity, UndergroundPosition = new(6, 4), AccessPosition = new(6, 3) }] }; level = DoorLevel(level); var loaded = LevelSerializer.Deserialize(LevelSerializer.Serialize(level)); Assert.Equal(EPropType.Door, loaded.GetProp(new(3, 2)).Type); Assert.Single(loaded.Leaks); Assert.Equal(new(6, 3), loaded.Leaks[0].AccessPosition); } [Fact] public void LevelSerializationRoundTripsValveAndSprinklerFields() { var level = SprinklerLevel(EPropSwitchState.Disabled); level = level.SetUnderground(new(3, 3), ECarrierType.Fuel, new() { State = EUndergroundState.Intact }); level = level.SetProp(new(3, 3), new() { Type = EPropType.IsolationValve, Carrier = ECarrierType.Fuel, SwitchState = EPropSwitchState.Disabled }); var loaded = LevelSerializer.Deserialize(LevelSerializer.Serialize(level)); Assert.Equal(EPropType.IsolationValve, loaded.GetProp(new(3, 3)).Type); Assert.Equal(EPropSwitchState.Disabled, loaded.GetProp(new(3, 3)).SwitchState); Assert.Equal(new(2, 1), loaded.GetProp(new(3, 2)).LinkedPosition); Assert.Equal(new(2, 2), loaded.GetProp(new(2, 1)).OutletPosition); } [Fact] public void LevelSerializationRejectsOldSchema() { var json = """ { "Version": 2, "Level": {} } """; var exception = Assert.Throws(() => LevelSerializer.Deserialize(json)); 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); level = AddLine(level, ECarrierType.Fuel, new(2, 3), new(3, 3)); level = AddLine(level, ECarrierType.Water, new(2, 3), new(3, 3)); level = AddLine(level, ECarrierType.Electricity, new(2, 3), new(3, 3)); level = level.SetProp(new(2, 3), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel }); level = level.SetProp(new(2, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Water }); level = level.SetUnderground(new(2, 2), ECarrierType.Water, new() { State = EUndergroundState.Intact }); level = level.SetUnderground(new(2, 3), ECarrierType.Water, new() { State = EUndergroundState.Intact }); level = level.SetProp(new(2, 4), new() { Type = EPropType.Flow, Carrier = ECarrierType.Electricity }); level = level.SetUnderground(new(2, 4), ECarrierType.Electricity, new() { State = EUndergroundState.Intact }); level = level.SetUnderground(new(2, 3), ECarrierType.Electricity, new() { State = EUndergroundState.Intact }); level = level.SetProp(new(3, 3), new() { Type = EPropType.Consumer }); level = level.SetProp(new(5, 3), new() { Type = EPropType.ReactorControl, ReactorId = 1 }); return level with { Robot = new() { Position = new(5, 3) }, Reactors = [new() { ReactorId = 1, ControlPosition = new(5, 3) }] }; } private static LevelState DoorLevel(LevelState? seed = null, bool powered = true) { var level = seed ?? LevelState.Create("Door", 6, 6); level = level.SetTerrain(new(3, 1), ECellTerrain.Wall); level = level.SetTerrain(new(3, 3), ECellTerrain.Wall); if (powered) { level = AddLine(level, ECarrierType.Electricity, new(2, 2), new(3, 2)); level = level.SetProp(new(2, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Electricity }); } else { level = level.SetUnderground(new(3, 2), ECarrierType.Electricity, new() { State = EUndergroundState.Intact }); } return level.SetProp(new(3, 2), new() { Type = EPropType.Door, DoorState = EDoorState.Closed }); } private static LevelState AddLine(LevelState level, ECarrierType carrier, GridPosition a, GridPosition b) { level = level.SetUnderground(a, carrier, new() { State = EUndergroundState.Intact }); level = level.SetUnderground(b, carrier, new() { State = EUndergroundState.Intact }); return level; } private static LevelState BuildJunctionLevel(int mode) { var level = LevelState.Create("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.Junction, Carrier = ECarrierType.Fuel, JunctionMode = mode }); } private static LevelState IsolationValveLevel(EPropSwitchState valveState) { var level = LevelState.Create("Valve", 6, 5); level = AddLine(level, ECarrierType.Fuel, new(1, 2), new(2, 2)); level = AddLine(level, ECarrierType.Fuel, new(2, 2), new(3, 2)); level = level.SetProp(new(1, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel }); level = level.SetProp(new(2, 2), new() { Type = EPropType.IsolationValve, Carrier = ECarrierType.Fuel, SwitchState = valveState }); level = level.SetProp(new(3, 2), new() { Type = EPropType.ReactorControl, ReactorId = 1 }); return level with { RequiredFuelConsumers = 0, RequiredWaterConsumers = 0, RequiredElectricityConsumers = 0, Robot = new() { Position = new(3, 2) }, Reactors = [new() { ReactorId = 1, ControlPosition = new(3, 2) }] }; } 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 static LevelState TerminalLevel(bool powered = true) { var level = BuildReadyLevel(); level = level.SetProp(new(1, 1), new() { Type = EPropType.AllSeeingEyeTerminal }); level = level.SetUnderground(new(1, 1), ECarrierType.Electricity, new() { State = EUndergroundState.Intact }); if (powered) { level = level.SetUnderground(new(1, 2), ECarrierType.Electricity, new() { State = EUndergroundState.Intact }); level = level.SetProp(new(1, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Electricity }); } return level with { Robot = new() { Position = new(1, 1) } }; } private readonly SimulationEngine m_Engine = new(); }