cleanup code

This commit is contained in:
2026-05-10 18:37:30 +02:00
parent d22c4a7528
commit 6c7fa070f6
18 changed files with 215 additions and 213 deletions

View File

@@ -20,9 +20,9 @@ insert_final_newline = false
# Organize usings # Organize usings
dotnet_separate_import_directive_groups = false dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false dotnet_sort_system_directives_first = false
file_header_template = file_header_template = # this. and Me. preferences
# this. and Me. preferences
dotnet_style_qualification_for_event = false:suggestion dotnet_style_qualification_for_event = false:suggestion
dotnet_style_qualification_for_field = false:suggestion dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_method = false:suggestion dotnet_style_qualification_for_method = false:suggestion

View File

@@ -1,4 +1,4 @@
# Windows-specific instructions # Windows-specific instructions
- After the implementation is finished, run `python D:\Code\crlf.py $file1 $file2 ...` for changed files you recognize, in order to normalize all line endings of all touched files to CRLF. - After the implementation is finished, run `python D:\Code\crlf.py $file1 $file2 ...` for changed files you recognize, in order to normalize all line endings of all touched files to CRLF.
- After every iteration, run `jb cleanupcode --build=False '$file1' '$file2' ...` for every C# file you touched. - After every iteration, run `jb cleanupcode '$file1' '$file2' ...` for every C# file you touched.

View File

@@ -4,8 +4,6 @@ namespace ReactorMaintenance.Simulation;
public abstract class Balancing public abstract class Balancing
{ {
public static Balancing Current { get; set; } = new NormalBalancing();
public float ClampValue(float value) public float ClampValue(float value)
{ {
return Math.Clamp(value, MinValue, MaxValue); return Math.Clamp(value, MinValue, MaxValue);
@@ -107,6 +105,8 @@ public abstract class Balancing
return a > b ? a : b; return a > b ? a : b;
} }
public static Balancing Current { get; set; } = new NormalBalancing();
public abstract int DefaultLevelWidth { get; } public abstract int DefaultLevelWidth { get; }
public abstract int DefaultLevelHeight { get; } public abstract int DefaultLevelHeight { get; }
public abstract int MinimumLevelSize { get; } public abstract int MinimumLevelSize { get; }

View File

@@ -2,15 +2,6 @@
public sealed record JunctionFlow public sealed record JunctionFlow
{ {
public GridPosition Position { get; init; } = new(0, 0);
public PropState Prop { get; init; } = new();
public ECarrierType Carrier { get; init; }
public IReadOnlyList<GridPosition> Branches { get; init; } = Array.Empty<GridPosition>();
public GridPosition? IncomingBranch { get; init; }
public IReadOnlyList<GridPosition> OutgoingBranches { get; init; } = Array.Empty<GridPosition>();
public IReadOnlyList<string> Errors { get; init; } = Array.Empty<string>();
public bool IsValid => Errors.Count == 0;
public float WeightFor(GridPosition outgoingBranch) public float WeightFor(GridPosition outgoingBranch)
{ {
var index = IndexOfOutgoingBranch(outgoingBranch); var index = IndexOfOutgoingBranch(outgoingBranch);
@@ -31,4 +22,13 @@ public sealed record JunctionFlow
return -1; return -1;
} }
public GridPosition Position { get; init; } = new(0, 0);
public PropState Prop { get; init; } = new();
public ECarrierType Carrier { get; init; }
public IReadOnlyList<GridPosition> Branches { get; init; } = Array.Empty<GridPosition>();
public GridPosition? IncomingBranch { get; init; }
public IReadOnlyList<GridPosition> OutgoingBranches { get; init; } = Array.Empty<GridPosition>();
public IReadOnlyList<string> Errors { get; init; } = Array.Empty<string>();
public bool IsValid => Errors.Count == 0;
} }

View File

@@ -2,6 +2,8 @@
public static class JunctionFlowAnalyzer public static class JunctionFlowAnalyzer
{ {
private sealed record SourceBranch(GridPosition Position, int? Distance);
public static IReadOnlyList<JunctionFlow> Analyze(LevelState level) public static IReadOnlyList<JunctionFlow> Analyze(LevelState level)
{ {
var flows = new List<JunctionFlow>(); var flows = new List<JunctionFlow>();
@@ -92,6 +94,4 @@ public static class JunctionFlowAnalyzer
return null; return null;
} }
private sealed record SourceBranch(GridPosition Position, int? Distance);
} }

View File

@@ -111,7 +111,7 @@ public static class LevelEditor
return SetFloorProp(level, position, new() { Type = EPropType.Door }); return SetFloorProp(level, position, new() { Type = EPropType.Door });
return SetFloorProp(level, position, new() { Type = EPropType.Door }) with { return SetFloorProp(level, position, new() { Type = EPropType.Door }) with {
Doors = [.. level.Doors, new DoorState { A = position, B = neighbor }] Doors = [.. level.Doors, new() { A = position, B = neighbor }]
}; };
} }
@@ -125,7 +125,7 @@ public static class LevelEditor
return levelWithProp with { return levelWithProp with {
Reactors = [ Reactors = [
.. level.Reactors, .. level.Reactors,
new ReactorBinding { new() {
ReactorId = id, ReactorId = id,
ControlPosition = position, ControlPosition = position,
FuelConsumerPosition = position, FuelConsumerPosition = position,
@@ -152,7 +152,7 @@ public static class LevelEditor
return next with { return next with {
Leaks = [ Leaks = [
.. next.Leaks, .. next.Leaks,
new LeakState { new() {
Carrier = carrier, Carrier = carrier,
UndergroundPosition = position, UndergroundPosition = position,
AccessPosition = accessPosition AccessPosition = accessPosition

View File

@@ -5,7 +5,11 @@ namespace ReactorMaintenance.Simulation;
public static class LevelSerializer public static class LevelSerializer
{ {
private const int c_CurrentVersion = 2; private sealed record LevelFile
{
public int Version { get; init; }
public LevelState? Level { get; init; }
}
public static string Serialize(LevelState level) public static string Serialize(LevelState level)
{ {
@@ -29,14 +33,10 @@ public static class LevelSerializer
return level; return level;
} }
private const int c_CurrentVersion = 2;
private static readonly JsonSerializerOptions s_Options = new() { private static readonly JsonSerializerOptions s_Options = new() {
WriteIndented = true, WriteIndented = true,
Converters = { new JsonStringEnumConverter() } Converters = { new JsonStringEnumConverter() }
}; };
private sealed record LevelFile
{
public int Version { get; init; }
public LevelState? Level { get; init; }
}
} }

View File

@@ -12,7 +12,7 @@ public static class LevelStateExtensions
if (!level.InBounds(position)) if (!level.InBounds(position))
throw new ArgumentOutOfRangeException(nameof(position), $"Position {position.X},{position.Y} is outside {level.Width}x{level.Height}."); throw new ArgumentOutOfRangeException(nameof(position), $"Position {position.X},{position.Y} is outside {level.Width}x{level.Height}.");
return position.Y * level.Width + position.X; return (position.Y * level.Width) + position.X;
} }
public static ECellTerrain GetTerrain(this LevelState level, GridPosition position) public static ECellTerrain GetTerrain(this LevelState level, GridPosition position)
@@ -111,6 +111,6 @@ public static class LevelStateExtensions
private static bool SameEdge(GridPosition edgeA, GridPosition edgeB, GridPosition a, GridPosition b) private static bool SameEdge(GridPosition edgeA, GridPosition edgeB, GridPosition a, GridPosition b)
{ {
return edgeA == a && edgeB == b || edgeA == b && edgeB == a; return (edgeA == a && edgeB == b) || (edgeA == b && edgeB == a);
} }
} }

View File

@@ -30,7 +30,7 @@ public static class LevelStateFactory
for (var x = 0; x < width; x++) for (var x = 0; x < width; x++)
{ {
if (x == 0 || y == 0 || x == width - 1 || y == height - 1) if (x == 0 || y == 0 || x == width - 1 || y == height - 1)
terrain[y * width + x] = ECellTerrain.Wall; terrain[(y * width) + x] = ECellTerrain.Wall;
} }
} }

View File

@@ -2,6 +2,24 @@
internal sealed class SimulationCoreSystem internal sealed class SimulationCoreSystem
{ {
private sealed class SurfaceDelta
{
public SurfaceState Apply(SurfaceState surface)
{
return surface with {
Fuel = surface.Fuel + Fuel,
Coolant = surface.Coolant + Coolant,
Electricity = surface.Electricity + Electricity,
Heat = surface.Heat + Heat
};
}
public float Fuel { get; set; }
public float Coolant { get; set; }
public float Electricity { get; set; }
public float Heat { get; set; }
}
public LevelState MoveRobot(LevelState level, GridPosition destination) public LevelState MoveRobot(LevelState level, GridPosition destination)
{ {
if (!CanSpendAction(level) || !level.IsFloor(destination) || level.Robot.Position.ManhattanDistance(destination) != 1) if (!CanSpendAction(level) || !level.IsFloor(destination) || level.Robot.Position.ManhattanDistance(destination) != 1)
@@ -252,7 +270,7 @@ internal sealed class SimulationCoreSystem
if (surface[accessIndex].Blocks(leak.Carrier)) if (surface[accessIndex].Blocks(leak.Carrier))
continue; continue;
var amount = Balancing.Current.LeakBaseAmount + underground.Amount * Balancing.Current.LeakAmountScale + underground.Intensity * Balancing.Current.LeakIntensityScale; var amount = Balancing.Current.LeakBaseAmount + (underground.Amount * Balancing.Current.LeakAmountScale) + (underground.Intensity * Balancing.Current.LeakIntensityScale);
surface[accessIndex] = AddSurfaceCarrier(surface[accessIndex], leak.Carrier, amount); surface[accessIndex] = AddSurfaceCarrier(surface[accessIndex], leak.Carrier, amount);
} }
@@ -447,7 +465,7 @@ internal sealed class SimulationCoreSystem
ERulePredicateKind.TurnAtLeast => level.Global.Turn >= predicate.Turn, ERulePredicateKind.TurnAtLeast => level.Global.Turn >= predicate.Turn,
ERulePredicateKind.LevelStateIs => level.Global.LevelState == predicate.LevelState, ERulePredicateKind.LevelStateIs => level.Global.LevelState == predicate.LevelState,
ERulePredicateKind.ReactorReadyIs => ReactorMatches(level, predicate, reactor => reactor.Ready), ERulePredicateKind.ReactorReadyIs => ReactorMatches(level, predicate, reactor => reactor.Ready),
ERulePredicateKind.ReactorLostIs => (level.Global.LevelState == ELevelState.Lost) == predicate.BoolValue, ERulePredicateKind.ReactorLostIs => level.Global.LevelState == ELevelState.Lost == predicate.BoolValue,
ERulePredicateKind.ReactorWonIs => ReactorWonMatches(level, predicate), ERulePredicateKind.ReactorWonIs => ReactorWonMatches(level, predicate),
ERulePredicateKind.PropStateAt => level.InBounds(predicate.Position) && level.GetProp(predicate.Position).SwitchState == predicate.PropSwitchState, ERulePredicateKind.PropStateAt => level.InBounds(predicate.Position) && level.GetProp(predicate.Position).SwitchState == predicate.PropSwitchState,
ERulePredicateKind.ConsumerStateAt => level.InBounds(predicate.Position) && level.GetProp(predicate.Position).ServiceState == predicate.ConsumerServiceState, ERulePredicateKind.ConsumerStateAt => level.InBounds(predicate.Position) && level.GetProp(predicate.Position).ServiceState == predicate.ConsumerServiceState,
@@ -684,23 +702,5 @@ internal sealed class SimulationCoreSystem
} }
} }
private sealed class SurfaceDelta
{
public SurfaceState Apply(SurfaceState surface)
{
return surface with {
Fuel = surface.Fuel + Fuel,
Coolant = surface.Coolant + Coolant,
Electricity = surface.Electricity + Electricity,
Heat = surface.Heat + Heat
};
}
public float Fuel { get; set; }
public float Coolant { get; set; }
public float Electricity { get; set; }
public float Heat { get; set; }
}
private readonly LevelValidator m_Validator = new(); private readonly LevelValidator m_Validator = new();
} }

View File

@@ -42,7 +42,8 @@
<ToggleButton IsChecked="{Binding IsSelected, Mode=TwoWay}" <ToggleButton IsChecked="{Binding IsSelected, Mode=TwoWay}"
Checked="ToolToggle_Checked" ToolTipService.ToolTip="{Binding Label}" Checked="ToolToggle_Checked" ToolTipService.ToolTip="{Binding Label}"
Width="112" MinHeight="46" Padding="6" Margin="0,0,8,8"> Width="112" MinHeight="46" Padding="6" Margin="0,0,8,8">
<TextBlock Text="{Binding Label}" TextWrapping="WrapWholeWords" TextAlignment="Center" <TextBlock Text="{Binding Label}" TextWrapping="WrapWholeWords"
TextAlignment="Center"
FontSize="12" /> FontSize="12" />
</ToggleButton> </ToggleButton>
</DataTemplate> </DataTemplate>
@@ -50,7 +51,8 @@
</ItemsControl> </ItemsControl>
<TextBlock Text="Left click selects or paints. Right click clears surface prop and hazards." <TextBlock Text="Left click selects or paints. Right click clears surface prop and hazards."
Foreground="#9EA7AE" TextWrapping="Wrap" /> Foreground="#9EA7AE" TextWrapping="Wrap" />
<TextBlock Text="Door chooses the first adjacent floor edge. Reactor controls auto-bind to the first available consumers." <TextBlock
Text="Door chooses the first adjacent floor edge. Reactor controls auto-bind to the first available consumers."
Foreground="#9EA7AE" Foreground="#9EA7AE"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</StackPanel> </StackPanel>

View File

@@ -1,9 +1,9 @@
using Microsoft.Graphics.Canvas; using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text; using Microsoft.Graphics.Canvas.Text;
using Microsoft.Graphics.Canvas.UI;
using Microsoft.Graphics.Canvas.UI.Xaml; using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.UI; using Microsoft.UI;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Input;
using ReactorMaintenance.Simulation; using ReactorMaintenance.Simulation;
using System.Globalization; using System.Globalization;
@@ -22,7 +22,7 @@ public sealed partial class MainWindow
{ {
public Rect CellRect(GridPosition position) public Rect CellRect(GridPosition position)
{ {
return new(OriginX + position.X * CellSize, OriginY + position.Y * CellSize, CellSize, CellSize); return new(OriginX + (position.X * CellSize), OriginY + (position.Y * CellSize), CellSize, CellSize);
} }
} }
@@ -202,7 +202,7 @@ public sealed partial class MainWindow
var totalDeltaX = point.Position.X - m_LeftPointerDownPoint.X; var totalDeltaX = point.Position.X - m_LeftPointerDownPoint.X;
var totalDeltaY = point.Position.Y - m_LeftPointerDownPoint.Y; var totalDeltaY = point.Position.Y - m_LeftPointerDownPoint.Y;
if (Math.Sqrt(totalDeltaX * totalDeltaX + totalDeltaY * totalDeltaY) > c_ClickPixelThreshold) if (Math.Sqrt((totalDeltaX * totalDeltaX) + (totalDeltaY * totalDeltaY)) > c_ClickPixelThreshold)
m_DragExceededClickThreshold = true; m_DragExceededClickThreshold = true;
m_PanX += deltaX; m_PanX += deltaX;
@@ -319,7 +319,7 @@ public sealed partial class MainWindow
drawing.DrawRectangle(rect, color, cell.State == EUndergroundState.Leaking ? 4 : 2); drawing.DrawRectangle(rect, color, cell.State == EUndergroundState.Leaking ? 4 : 2);
if (cell.Amount > 0 || cell.Intensity > 0) if (cell.Amount > 0 || cell.Intensity > 0)
drawing.FillCircle((float)(rect.X + rect.Width / 2), (float)(rect.Y + rect.Height / 2), (float)Math.Max(2, rect.Width * 0.08), color); drawing.FillCircle((float)(rect.X + (rect.Width / 2)), (float)(rect.Y + (rect.Height / 2)), (float)Math.Max(2, rect.Width * 0.08), color);
} }
private void DrawSurface(CanvasDrawingSession drawing, CanvasLayout layout) private void DrawSurface(CanvasDrawingSession drawing, CanvasLayout layout)
@@ -341,7 +341,7 @@ public sealed partial class MainWindow
if (amount <= 0) if (amount <= 0)
return; return;
var alpha = (byte)Math.Clamp(40 + amount / Balancing.Current.MaxValue * 130, 40, 170); var alpha = (byte)Math.Clamp(40 + (amount / Balancing.Current.MaxValue * 130), 40, 170);
drawing.FillRectangle(Inset(rect, inset), ColorHelper.FromArgb(alpha, color.R, color.G, color.B)); drawing.FillRectangle(Inset(rect, inset), ColorHelper.FromArgb(alpha, color.R, color.G, color.B));
} }
@@ -431,7 +431,7 @@ public sealed partial class MainWindow
{ {
var availableWidth = Math.Max(1, LevelCanvas.ActualWidth); var availableWidth = Math.Max(1, LevelCanvas.ActualWidth);
var availableHeight = Math.Max(1, LevelCanvas.ActualHeight); var availableHeight = Math.Max(1, LevelCanvas.ActualHeight);
return new((availableWidth - cellSize * m_Level.Width) / 2, (availableHeight - cellSize * m_Level.Height) / 2); return new((availableWidth - (cellSize * m_Level.Width)) / 2, (availableHeight - (cellSize * m_Level.Height)) / 2);
} }
private void ClampPan() private void ClampPan()
@@ -459,8 +459,8 @@ public sealed partial class MainWindow
m_Zoom = Math.Clamp(m_Zoom * zoomFactor, c_MinZoom, c_MaxZoom); m_Zoom = Math.Clamp(m_Zoom * zoomFactor, c_MinZoom, c_MaxZoom);
var newCellSize = GetBaseCellSize() * m_Zoom; var newCellSize = GetBaseCellSize() * m_Zoom;
var originWithoutPan = GetCenteredOrigin(newCellSize); var originWithoutPan = GetCenteredOrigin(newCellSize);
m_PanX = point.X - originWithoutPan.X - cellX * newCellSize; m_PanX = point.X - originWithoutPan.X - (cellX * newCellSize);
m_PanY = point.Y - originWithoutPan.Y - cellY * newCellSize; m_PanY = point.Y - originWithoutPan.Y - (cellY * newCellSize);
ClampPan(); ClampPan();
LevelCanvas.Invalidate(); LevelCanvas.Invalidate();
} }
@@ -523,11 +523,11 @@ public sealed partial class MainWindow
level = level.SetProp(new(11, 4), new() { Type = EPropType.AllSeeingEyeTerminal }); level = level.SetProp(new(11, 4), new() { Type = EPropType.AllSeeingEyeTerminal });
level = level.SetProp(new(11, 6), new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.HeatShield }); level = level.SetProp(new(11, 6), new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.HeatShield });
level = level.SetUnderground(new(4, 5), ECarrierType.Coolant, new() { State = EUndergroundState.Leaking }) with { level = level.SetUnderground(new(4, 5), ECarrierType.Coolant, new() { State = EUndergroundState.Leaking }) with {
Leaks = [new LeakState { Carrier = ECarrierType.Coolant, UndergroundPosition = new(4, 5), AccessPosition = new(4, 5) }], Leaks = [new() { Carrier = ECarrierType.Coolant, UndergroundPosition = new(4, 5), AccessPosition = new(4, 5) }],
Doors = [new DoorState { A = new(8, 5), B = new(9, 5), State = EDoorState.Closed }], Doors = [new() { A = new(8, 5), B = new(9, 5), State = EDoorState.Closed }],
Robot = new() { Position = new(10, 5) }, Robot = new() { Position = new(10, 5) },
Reactors = [ Reactors = [
new ReactorBinding { new() {
ReactorId = 1, ReactorId = 1,
ControlPosition = new(10, 5), ControlPosition = new(10, 5),
FuelConsumerPosition = new(5, 3), FuelConsumerPosition = new(5, 3),
@@ -594,12 +594,12 @@ public sealed partial class MainWindow
private static Rect Inset(Rect rect, double fraction) private static Rect Inset(Rect rect, double fraction)
{ {
var inset = rect.Width * fraction; var inset = rect.Width * fraction;
return new(rect.X + inset, rect.Y + inset, rect.Width - inset * 2, rect.Height - inset * 2); return new(rect.X + inset, rect.Y + inset, rect.Width - (inset * 2), rect.Height - (inset * 2));
} }
private static Point Center(Rect rect) private static Point Center(Rect rect)
{ {
return new(rect.X + rect.Width / 2, rect.Y + rect.Height / 2); return new(rect.X + (rect.Width / 2), rect.Y + (rect.Height / 2));
} }
private static void DrawImage(CanvasDrawingSession drawing, CanvasBitmap? image, Rect rect, float opacity = 1) private static void DrawImage(CanvasDrawingSession drawing, CanvasBitmap? image, Rect rect, float opacity = 1)
@@ -699,22 +699,22 @@ public sealed partial class MainWindow
private static readonly Color c_FuelColor = ColorHelper.FromArgb(255, 220, 170, 68); private static readonly Color c_FuelColor = ColorHelper.FromArgb(255, 220, 170, 68);
private static readonly Color c_CoolantColor = ColorHelper.FromArgb(255, 57, 174, 196); private static readonly Color c_CoolantColor = ColorHelper.FromArgb(255, 57, 174, 196);
private static readonly Color c_ElectricityColor = ColorHelper.FromArgb(255, 236, 226, 82); private static readonly Color c_ElectricityColor = ColorHelper.FromArgb(255, 236, 226, 82);
private readonly IReadOnlyList<EditorToolViewModel> m_EditorTools = [];
private readonly SimulationEngine m_Simulation = new(); private readonly SimulationEngine m_Simulation = new();
private StorageFile? m_CurrentFile; private StorageFile? m_CurrentFile;
private LevelState m_Level;
private IReadOnlyList<EditorToolViewModel> m_EditorTools = [];
private bool m_LeftPointerDown;
private bool m_DragExceededClickThreshold; private bool m_DragExceededClickThreshold;
private Point m_LeftPointerDownPoint; private CanvasBitmap? m_HeatSprite;
private Point m_LastPanPoint; private Point m_LastPanPoint;
private GridPosition? m_SelectedCell; private CanvasBitmap? m_LeakSprite;
private EEditorTool m_SelectedTool = EEditorTool.Cursor; private bool m_LeftPointerDown;
private double m_Zoom = 1; private Point m_LeftPointerDownPoint;
private LevelState m_Level;
private double m_PanX; private double m_PanX;
private double m_PanY; private double m_PanY;
private CanvasBitmap? m_TerrainTilemap;
private CanvasBitmap? m_RobotSprite; private CanvasBitmap? m_RobotSprite;
private CanvasBitmap? m_LeakSprite; private GridPosition? m_SelectedCell;
private CanvasBitmap? m_HeatSprite; private EEditorTool m_SelectedTool = EEditorTool.Cursor;
private CanvasBitmap? m_TerrainTilemap;
private double m_Zoom = 1;
} }

View File

@@ -34,7 +34,7 @@ public sealed class SimulationEngineTests
{ {
var level = LevelState.Create("Leak", 6, 6); var level = LevelState.Create("Leak", 6, 6);
level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, new() { State = EUndergroundState.Leaking, Amount = 5, Intensity = 5 }) with { level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, new() { State = EUndergroundState.Leaking, Amount = 5, Intensity = 5 }) with {
Leaks = [new LeakState { Carrier = ECarrierType.Fuel, UndergroundPosition = new(2, 2), AccessPosition = new(2, 2) }] Leaks = [new() { Carrier = ECarrierType.Fuel, UndergroundPosition = new(2, 2), AccessPosition = new(2, 2) }]
}; };
level = level.SetProp(new(2, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel }); level = level.SetProp(new(2, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel });
@@ -50,7 +50,7 @@ public sealed class SimulationEngineTests
level = level.SetUnderground(new(2, 2), ECarrierType.Fuel, new() { State = EUndergroundState.Leaking, Amount = 5, Intensity = 5 }); 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 { level = level.SetSurface(new(2, 2), new() { Fuel = 5 }) with {
Robot = new() { Position = new(2, 2), FuelNeutralizers = 1 }, Robot = new() { Position = new(2, 2), FuelNeutralizers = 1 },
Leaks = [new LeakState { Carrier = ECarrierType.Fuel, UndergroundPosition = new(2, 2), AccessPosition = new(2, 2) }] Leaks = [new() { Carrier = ECarrierType.Fuel, UndergroundPosition = new(2, 2), AccessPosition = new(2, 2) }]
}; };
var next = m_Engine.InteractLeak(level, ECarrierType.Fuel, true); var next = m_Engine.InteractLeak(level, ECarrierType.Fuel, true);
@@ -65,7 +65,7 @@ public sealed class SimulationEngineTests
{ {
var level = LevelState.Create("Door", 6, 6); var level = LevelState.Create("Door", 6, 6);
level = level.SetSurface(new(2, 2), new() { Heat = 8 }) with { level = level.SetSurface(new(2, 2), new() { Heat = 8 }) with {
Doors = [new DoorState { A = new(2, 2), B = new(3, 2), State = EDoorState.Closed }] Doors = [new() { A = new(2, 2), B = new(3, 2), State = EDoorState.Closed }]
}; };
var next = m_Engine.AdvanceTurn(level); var next = m_Engine.AdvanceTurn(level);
@@ -155,11 +155,11 @@ public sealed class SimulationEngineTests
{ {
var level = LevelState.Create("Rule", 6, 6) with { var level = LevelState.Create("Rule", 6, 6) with {
RuleEvents = [ RuleEvents = [
new RuleEventState { new() {
Phase = ERuleEventPhase.EndOfTurn, Phase = ERuleEventPhase.EndOfTurn,
ForecastText = "containment failure", ForecastText = "containment failure",
Predicates = [new RulePredicate { Kind = ERulePredicateKind.TurnAtLeast, Turn = 0 }], Predicates = [new() { Kind = ERulePredicateKind.TurnAtLeast, Turn = 0 }],
Effects = [new RuleEffect { Kind = ERuleEffectKind.MarkTerminalLoss, Message = "CONTAINMENT FAILURE" }] Effects = [new() { Kind = ERuleEffectKind.MarkTerminalLoss, Message = "CONTAINMENT FAILURE" }]
} }
] ]
}; };
@@ -177,10 +177,10 @@ public sealed class SimulationEngineTests
level = AddLine(level, ECarrierType.Fuel, new(2, 2), new(3, 2)); level = AddLine(level, ECarrierType.Fuel, new(2, 2), new(3, 2));
level = level.SetProp(new(2, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel }) with { level = level.SetProp(new(2, 2), new() { Type = EPropType.Flow, Carrier = ECarrierType.Fuel }) with {
RuleEvents = [ RuleEvents = [
new RuleEventState { new() {
Phase = ERuleEventPhase.EndOfTurn, Phase = ERuleEventPhase.EndOfTurn,
Predicates = [new RulePredicate { Kind = ERulePredicateKind.NetworkBandAt, Position = new(3, 2), Carrier = ECarrierType.Fuel, NetworkValue = ENetworkValueKind.Amount, Band = EBand.Critical }], Predicates = [new() { Kind = ERulePredicateKind.NetworkBandAt, Position = new(3, 2), Carrier = ECarrierType.Fuel, NetworkValue = ENetworkValueKind.Amount, Band = EBand.Critical }],
Effects = [new RuleEffect { Kind = ERuleEffectKind.EmitWarning, Message = "fuel pressure high" }] Effects = [new() { Kind = ERuleEffectKind.EmitWarning, Message = "fuel pressure high" }]
} }
] ]
}; };
@@ -195,10 +195,10 @@ public sealed class SimulationEngineTests
{ {
var level = BuildReadyLevel() with { var level = BuildReadyLevel() with {
RuleEvents = [ RuleEvents = [
new RuleEventState { new() {
Phase = ERuleEventPhase.EndOfTurn, Phase = ERuleEventPhase.EndOfTurn,
Predicates = [new RulePredicate { Kind = ERulePredicateKind.ReactorReadyIs, ReactorId = 1, BoolValue = true }], Predicates = [new() { Kind = ERulePredicateKind.ReactorReadyIs, ReactorId = 1, BoolValue = true }],
Effects = [new RuleEffect { Kind = ERuleEffectKind.EmitWarning, Message = "reactor ready rule" }] Effects = [new() { Kind = ERuleEffectKind.EmitWarning, Message = "reactor ready rule" }]
} }
] ]
}; };
@@ -214,10 +214,10 @@ public sealed class SimulationEngineTests
var level = LevelState.Create("Inventory rule", 6, 6) with { var level = LevelState.Create("Inventory rule", 6, 6) with {
Robot = new() { Position = new(1, 1), FuelNeutralizers = 1 }, Robot = new() { Position = new(1, 1), FuelNeutralizers = 1 },
RuleEvents = [ RuleEvents = [
new RuleEventState { new() {
Phase = ERuleEventPhase.StartOfSimulation, Phase = ERuleEventPhase.StartOfSimulation,
Predicates = [new RulePredicate { Kind = ERulePredicateKind.RobotInventoryAtLeast, Remedy = ERemedyType.FuelNeutralizer, InventoryCount = 1 }], Predicates = [new() { Kind = ERulePredicateKind.RobotInventoryAtLeast, Remedy = ERemedyType.FuelNeutralizer, InventoryCount = 1 }],
Effects = [new RuleEffect { Kind = ERuleEffectKind.EmitWarning, Message = "fuel kit detected" }] Effects = [new() { Kind = ERuleEffectKind.EmitWarning, Message = "fuel kit detected" }]
} }
] ]
}; };
@@ -234,19 +234,19 @@ public sealed class SimulationEngineTests
level = level.SetSurface(new(2, 2), new() { Fuel = 5, Heat = 5 }) with { level = level.SetSurface(new(2, 2), new() { Fuel = 5, Heat = 5 }) with {
Robot = new() { Position = new(1, 1), FuelNeutralizers = 2 }, Robot = new() { Position = new(1, 1), FuelNeutralizers = 2 },
Doors = [ Doors = [
new DoorState { A = new(2, 2), B = new(1, 2), State = EDoorState.Closed }, new() { A = new(2, 2), B = new(1, 2), State = EDoorState.Closed },
new DoorState { A = new(2, 2), B = new(3, 2), State = EDoorState.Closed }, new() { A = new(2, 2), B = new(3, 2), State = EDoorState.Closed },
new DoorState { A = new(2, 2), B = new(2, 1), State = EDoorState.Closed }, new() { A = new(2, 2), B = new(2, 1), State = EDoorState.Closed },
new DoorState { A = new(2, 2), B = new(2, 3), State = EDoorState.Closed } new() { A = new(2, 2), B = new(2, 3), State = EDoorState.Closed }
], ],
RuleEvents = [ RuleEvents = [
new RuleEventState { new() {
Phase = ERuleEventPhase.StartOfSimulation, Phase = ERuleEventPhase.StartOfSimulation,
Predicates = [new RulePredicate { Kind = ERulePredicateKind.TurnAtLeast, Turn = 0 }], Predicates = [new() { Kind = ERulePredicateKind.TurnAtLeast, Turn = 0 }],
Effects = [ Effects = [
new RuleEffect { Kind = ERuleEffectKind.RemoveSurfaceHazard, Position = new(2, 2), Carrier = ECarrierType.Fuel, Amount = 2 }, new() { Kind = ERuleEffectKind.RemoveSurfaceHazard, Position = new(2, 2), Carrier = ECarrierType.Fuel, Amount = 2 },
new RuleEffect { Kind = ERuleEffectKind.RemoveHeat, Position = new(2, 2), Amount = 3 }, new() { Kind = ERuleEffectKind.RemoveHeat, Position = new(2, 2), Amount = 3 },
new RuleEffect { Kind = ERuleEffectKind.RemoveInventory, Remedy = ERemedyType.FuelNeutralizer, Amount = 1 } new() { Kind = ERuleEffectKind.RemoveInventory, Remedy = ERemedyType.FuelNeutralizer, Amount = 1 }
] ]
} }
] ]
@@ -266,10 +266,10 @@ public sealed class SimulationEngineTests
level = level.SetTerrain(new(2, 2), ECellTerrain.Wall); level = level.SetTerrain(new(2, 2), ECellTerrain.Wall);
level = level.SetUnderground(new(2, 2), ECarrierType.Electricity, new() { State = EUndergroundState.Intact }) with { level = level.SetUnderground(new(2, 2), ECarrierType.Electricity, new() { State = EUndergroundState.Intact }) with {
RuleEvents = [ RuleEvents = [
new RuleEventState { new() {
Phase = ERuleEventPhase.StartOfSimulation, Phase = ERuleEventPhase.StartOfSimulation,
Predicates = [new RulePredicate { Kind = ERulePredicateKind.TurnAtLeast, Turn = 0 }], Predicates = [new() { Kind = ERulePredicateKind.TurnAtLeast, Turn = 0 }],
Effects = [new RuleEffect { Kind = ERuleEffectKind.StartLeak, Position = new(2, 2), AccessPosition = new(2, 3), Carrier = ECarrierType.Electricity }] Effects = [new() { Kind = ERuleEffectKind.StartLeak, Position = new(2, 2), AccessPosition = new(2, 3), Carrier = ECarrierType.Electricity }]
} }
] ]
}; };
@@ -287,11 +287,11 @@ public sealed class SimulationEngineTests
var level = LevelState.Create("Invalid rules", 6, 6); var level = LevelState.Create("Invalid rules", 6, 6);
level = level.SetTerrain(new(2, 2), ECellTerrain.Wall) with { level = level.SetTerrain(new(2, 2), ECellTerrain.Wall) with {
RuleEvents = [ RuleEvents = [
new RuleEventState { new() {
Predicates = [new RulePredicate { Kind = ERulePredicateKind.PropStateAt, Position = new(1, 1) }], Predicates = [new() { Kind = ERulePredicateKind.PropStateAt, Position = new(1, 1) }],
Effects = [ Effects = [
new RuleEffect { Kind = ERuleEffectKind.AddSurfaceHazard, Position = new(2, 2), Carrier = ECarrierType.Fuel, Amount = 1 }, new() { Kind = ERuleEffectKind.AddSurfaceHazard, Position = new(2, 2), Carrier = ECarrierType.Fuel, Amount = 1 },
new RuleEffect { Kind = ERuleEffectKind.RepairNetworkCell, Position = new(3, 3), Carrier = ECarrierType.Coolant } new() { Kind = ERuleEffectKind.RepairNetworkCell, Position = new(3, 3), Carrier = ECarrierType.Coolant }
] ]
} }
] ]
@@ -312,7 +312,7 @@ public sealed class SimulationEngineTests
level = level.SetTerrain(new(2, 2), ECellTerrain.Wall); level = level.SetTerrain(new(2, 2), ECellTerrain.Wall);
level = level with { level = level with {
Surface = level.Surface.ToArray(), Surface = level.Surface.ToArray(),
Reactors = [new ReactorBinding { ControlPosition = new(3, 3), FuelConsumerPosition = new(1, 1), CoolantConsumerPosition = new(1, 1), ElectricityConsumerPosition = new(1, 1) }] Reactors = [new() { ControlPosition = new(3, 3), FuelConsumerPosition = new(1, 1), CoolantConsumerPosition = new(1, 1), ElectricityConsumerPosition = new(1, 1) }]
}; };
level.Surface[level.Index(new(2, 2))] = new() { Heat = 1 }; level.Surface[level.Index(new(2, 2))] = new() { Heat = 1 };
@@ -367,7 +367,7 @@ public sealed class SimulationEngineTests
return level with { return level with {
Robot = new() { Position = new(5, 3) }, Robot = new() { Position = new(5, 3) },
Reactors = [ Reactors = [
new ReactorBinding { new() {
ReactorId = 1, ReactorId = 1,
ControlPosition = new(5, 3), ControlPosition = new(5, 3),
FuelConsumerPosition = new(3, 2), FuelConsumerPosition = new(3, 2),