namespace ReactorMaintenance.Simulation.Tests; public sealed class LevelEditorTests { [Fact] public void DoorToolPlacesSingleFloorDoorProp() { var level = LevelState.Create("Door editor", 6, 6); var next = LevelEditor.Apply(level, new(2, 2), new() { Tool = EEditorTool.Door }); Assert.Equal(EPropType.Door, next.GetProp(new(2, 2)).Type); Assert.Equal(EDoorState.Closed, next.GetProp(new(2, 2)).DoorState); } [Fact] public void DoorToolTogglesExistingDoorState() { var level = LevelState.Create("Door editor", 6, 6); level = LevelEditor.Apply(level, new(2, 2), new() { Tool = EEditorTool.Door }); var opened = LevelEditor.Apply(level, new(2, 2), new() { Tool = EEditorTool.Door }); var closed = LevelEditor.Apply(opened, new(2, 2), new() { Tool = EEditorTool.Door }); Assert.Equal(EDoorState.Open, opened.GetProp(new(2, 2)).DoorState); Assert.Equal(EDoorState.Closed, closed.GetProp(new(2, 2)).DoorState); } [Fact] public void WallToolPreservesUndergroundNetworks() { var level = LevelState.Create("Wall editor", 6, 6); var position = new GridPosition(2, 2); level = LevelEditor.Apply(level, position, new() { Tool = EEditorTool.Underground, Carrier = ECarrierType.Fuel }); level = LevelEditor.Apply(level, position, new() { Tool = EEditorTool.Underground, Carrier = ECarrierType.Water }); level = LevelEditor.Apply(level, position, new() { Tool = EEditorTool.Underground, Carrier = ECarrierType.Electricity }); var next = LevelEditor.Apply(level, position, new() { Tool = EEditorTool.Wall }); Assert.Equal(EUndergroundState.Intact, next.GetUnderground(position, ECarrierType.Fuel).State); Assert.Equal(EUndergroundState.Intact, next.GetUnderground(position, ECarrierType.Water).State); Assert.Equal(EUndergroundState.Intact, next.GetUnderground(position, ECarrierType.Electricity).State); } [Fact] public void UndergroundToolCanPaintAdjacentCellsRepeatedly() { var level = LevelState.Create("Network editor", 6, 6); var command = new EditorToolCommand { Tool = EEditorTool.Underground, Carrier = ECarrierType.Fuel }; level = LevelEditor.Apply(level, new(1, 1), command); level = LevelEditor.Apply(level, new(2, 1), command); level = LevelEditor.Apply(level, new(3, 1), command); Assert.Equal(EUndergroundState.Intact, level.GetUnderground(new(1, 1), ECarrierType.Fuel).State); Assert.Equal(EUndergroundState.Intact, level.GetUnderground(new(2, 1), ECarrierType.Fuel).State); Assert.Equal(EUndergroundState.Intact, level.GetUnderground(new(3, 1), ECarrierType.Fuel).State); } [Fact] public void ConsumerToolPlacesCarrierAgnosticConsumer() { var level = LevelState.Create("Consumer editor", 6, 6); var next = LevelEditor.Apply(level, new(2, 2), new() { Tool = EEditorTool.Consumer, Carrier = ECarrierType.Fuel }); Assert.Equal(EPropType.Consumer, next.GetProp(new(2, 2)).Type); Assert.Equal(EConsumerServiceState.Unknown, next.GetProp(new(2, 2)).FuelServiceState); Assert.Equal(EConsumerServiceState.Unknown, next.GetProp(new(2, 2)).WaterServiceState); Assert.Equal(EConsumerServiceState.Unknown, next.GetProp(new(2, 2)).ElectricityServiceState); } [Fact] public void ElectricityLeakUsesAuthoredWallAccessFace() { var level = LevelState.Create("Electricity leak editor", 6, 6); level = level.SetTerrain(new(2, 2), ECellTerrain.Wall); var next = LevelEditor.SetLeak(level, new(2, 2), new(2, 3), ECarrierType.Electricity); var rejected = LevelEditor.SetLeak(next, new(2, 2), new(4, 4), ECarrierType.Electricity); Assert.Single(next.Leaks); Assert.Equal(new(2, 3), next.Leaks[0].AccessPosition); Assert.Equal(EUndergroundState.Leaking, next.GetUnderground(new(2, 2), ECarrierType.Electricity).State); Assert.Equal(next.Leaks, rejected.Leaks); } [Fact] public void ElectricityLeakAccessCyclesAcrossAdjacentFloorFaces() { var level = LevelState.Create("Electricity leak editor", 6, 6); level = level.SetTerrain(new(2, 2), ECellTerrain.Wall); level = level.SetTerrain(new(2, 1), ECellTerrain.Wall); level = LevelEditor.Apply(level, new(2, 2), new() { Tool = EEditorTool.Underground, Carrier = ECarrierType.Electricity }); var first = LevelEditor.CycleElectricityLeakAccess(level, new(2, 2)); var second = LevelEditor.CycleElectricityLeakAccess(first, new(2, 2)); Assert.Single(first.Leaks); Assert.Equal(new(3, 2), first.Leaks[0].AccessPosition); Assert.Single(second.Leaks); Assert.Equal(new(2, 3), second.Leaks[0].AccessPosition); } [Fact] public void ReactorControlToolCreatesUnboundReactorState() { var level = LevelState.Create("Reactor editor", 6, 6); var next = LevelEditor.Apply(level, new(2, 2), new() { Tool = EEditorTool.ReactorControl }); Assert.Single(next.Reactors); Assert.Equal(new(2, 2), next.Reactors[0].ControlPosition); Assert.Equal(1, next.Reactors[0].ReactorId); } [Fact] public void MoveOccupantMovesRobotToFloorDestination() { var level = LevelState.Create("Move editor", 6, 6) with { Robot = new() { Position = new(1, 1) } }; var next = LevelEditor.MoveOccupant(level, new(1, 1), new(3, 3)); Assert.Equal(new(3, 3), next.Robot.Position); } [Fact] public void MoveOccupantMovesPropAndUpdatesReactorControlPosition() { var level = LevelState.Create("Move editor", 6, 6); level = LevelEditor.Apply(level, new(1, 1), new() { Tool = EEditorTool.ReactorControl }); var next = LevelEditor.MoveOccupant(level, new(1, 1), new(3, 3)); Assert.Equal(EPropType.None, next.GetProp(new(1, 1)).Type); Assert.Equal(EPropType.ReactorControl, next.GetProp(new(3, 3)).Type); Assert.Equal(new(3, 3), next.Reactors[0].ControlPosition); } [Fact] public void MoveOccupantMovesSourcesAsProps() { var level = LevelState.Create("Move editor", 6, 6); level = LevelEditor.Apply(level, new(1, 1), new() { Tool = EEditorTool.Flow, Carrier = ECarrierType.Fuel }); var result = LevelEditor.TryMoveOccupant(level, new(1, 1), new(3, 3)); Assert.True(result.Success, result.Reason); Assert.Equal(EPropType.None, result.Level.GetProp(new(1, 1)).Type); Assert.Equal(EPropType.Flow, result.Level.GetProp(new(3, 3)).Type); Assert.Equal(ECarrierType.Fuel, result.Level.GetProp(new(3, 3)).Carrier); } [Fact] public void MoveOccupantMovesFuelLeakToFloorDestination() { var level = LevelState.Create("Move editor", 6, 6); level = LevelEditor.SetLeak(level, new(1, 1), new(1, 1), ECarrierType.Fuel); var result = LevelEditor.TryMoveOccupant(level, new(1, 1), new(3, 3)); Assert.True(result.Success, result.Reason); Assert.Single(result.Level.Leaks); Assert.Equal(new(3, 3), result.Level.Leaks[0].UndergroundPosition); Assert.Equal(new(3, 3), result.Level.Leaks[0].AccessPosition); Assert.Equal(EUndergroundState.Leaking, result.Level.GetUnderground(new(3, 3), ECarrierType.Fuel).State); Assert.Equal(EUndergroundState.Absent, result.Level.GetUnderground(new(1, 1), ECarrierType.Fuel).State); } [Fact] public void MoveOccupantMovesElectricityLeakAccessFace() { var level = LevelState.Create("Move editor", 6, 6); level = level.SetTerrain(new(2, 2), ECellTerrain.Wall); level = LevelEditor.SetLeak(level, new(2, 2), new(2, 3), ECarrierType.Electricity); var result = LevelEditor.TryMoveOccupant(level, new(2, 3), new(3, 2)); Assert.True(result.Success, result.Reason); Assert.Single(result.Level.Leaks); Assert.Equal(new(2, 2), result.Level.Leaks[0].UndergroundPosition); Assert.Equal(new(3, 2), result.Level.Leaks[0].AccessPosition); } [Fact] public void MoveOccupantReportsInvalidStartAndDestinationReasons() { var level = LevelState.Create("Move editor", 6, 6); level = level.SetTerrain(new(3, 3), ECellTerrain.Wall); level = level.SetProp(new(1, 1), new() { Type = EPropType.Consumer }); level = level.SetProp(new(2, 2), new() { Type = EPropType.Consumer }); var invalidStart = LevelEditor.TryMoveOccupant(level, new(4, 4), new(5, 5)); var invalidDestination = LevelEditor.TryMoveOccupant(level, new(1, 1), new(2, 2)); Assert.False(invalidStart.Success); Assert.Contains("No movable", invalidStart.Reason); Assert.False(invalidDestination.Success); Assert.Contains("occupied", invalidDestination.Reason); } }