Add sprinkler valve simulation contract
This commit is contained in:
@@ -155,6 +155,8 @@ public abstract class Balancing
|
|||||||
public abstract float LeakBaseAmount { get; }
|
public abstract float LeakBaseAmount { get; }
|
||||||
public abstract float LeakAmountScale { get; }
|
public abstract float LeakAmountScale { get; }
|
||||||
public abstract float LeakIntensityScale { get; }
|
public abstract float LeakIntensityScale { get; }
|
||||||
|
public abstract float SprinklerWaterPerStep { get; }
|
||||||
|
public abstract float SprinklerPressureDebt { get; }
|
||||||
public abstract float FlowTransferRatio { get; }
|
public abstract float FlowTransferRatio { get; }
|
||||||
public abstract float WarmCautionAmount { get; }
|
public abstract float WarmCautionAmount { get; }
|
||||||
public abstract float WarmCriticalAmount { get; }
|
public abstract float WarmCriticalAmount { get; }
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ public class NormalBalancing : Balancing
|
|||||||
public override float LeakBaseAmount => 0.5f;
|
public override float LeakBaseAmount => 0.5f;
|
||||||
public override float LeakAmountScale => 0.15f;
|
public override float LeakAmountScale => 0.15f;
|
||||||
public override float LeakIntensityScale => 0.1f;
|
public override float LeakIntensityScale => 0.1f;
|
||||||
|
public override float SprinklerWaterPerStep => 0.8f;
|
||||||
|
public override float SprinklerPressureDebt => 3.0f;
|
||||||
public override float FlowTransferRatio => 0.05f;
|
public override float FlowTransferRatio => 0.05f;
|
||||||
public override float WarmCautionAmount => 0.5f;
|
public override float WarmCautionAmount => 0.5f;
|
||||||
public override float WarmCriticalAmount => 1.0f;
|
public override float WarmCriticalAmount => 1.0f;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ public enum EEditorTool
|
|||||||
Junction,
|
Junction,
|
||||||
Door,
|
Door,
|
||||||
AllSeeingEyeTerminal,
|
AllSeeingEyeTerminal,
|
||||||
|
SprinklerControl,
|
||||||
|
SprinklerValve,
|
||||||
RemedySupply,
|
RemedySupply,
|
||||||
ReactorControl,
|
ReactorControl,
|
||||||
Leak,
|
Leak,
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ public static class LevelEditor
|
|||||||
EEditorTool.Junction => SetFloorProp(level, position, new() { Type = EPropType.Junction }),
|
EEditorTool.Junction => SetFloorProp(level, position, new() { Type = EPropType.Junction }),
|
||||||
EEditorTool.Door => ToggleOrSetDoor(level, position),
|
EEditorTool.Door => ToggleOrSetDoor(level, position),
|
||||||
EEditorTool.AllSeeingEyeTerminal => SetFloorProp(level, position, new() { Type = EPropType.AllSeeingEyeTerminal }),
|
EEditorTool.AllSeeingEyeTerminal => SetFloorProp(level, position, new() { Type = EPropType.AllSeeingEyeTerminal }),
|
||||||
|
EEditorTool.SprinklerControl => SetFloorProp(level, position, new() { Type = EPropType.SprinklerControl, SwitchState = EPropSwitchState.Enabled }),
|
||||||
|
EEditorTool.SprinklerValve => SetWallProp(level, position, new() { Type = EPropType.SprinklerValve, Carrier = ECarrierType.Water, OutletPosition = position.Neighbors().FirstOrDefault(level.IsFloor) }),
|
||||||
EEditorTool.RemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = command.RemedyType }),
|
EEditorTool.RemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = command.RemedyType }),
|
||||||
EEditorTool.ReactorControl => SetReactorControl(level, position),
|
EEditorTool.ReactorControl => SetReactorControl(level, position),
|
||||||
EEditorTool.Leak => SetLeak(level, position, command.Carrier),
|
EEditorTool.Leak => SetLeak(level, position, command.Carrier),
|
||||||
@@ -210,6 +212,11 @@ public static class LevelEditor
|
|||||||
return level.IsFloor(position) ? level.SetProp(position, prop) : level;
|
return level.IsFloor(position) ? level.SetProp(position, prop) : level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static LevelState SetWallProp(LevelState level, GridPosition position, PropState prop)
|
||||||
|
{
|
||||||
|
return level.InBounds(position) && level.GetTerrain(position) == ECellTerrain.Wall ? level.SetProp(position, prop) : level;
|
||||||
|
}
|
||||||
|
|
||||||
private static LevelState ToggleOrSetDoor(LevelState level, GridPosition position)
|
private static LevelState ToggleOrSetDoor(LevelState level, GridPosition position)
|
||||||
{
|
{
|
||||||
if (!level.IsFloor(position))
|
if (!level.IsFloor(position))
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public static class LevelSerializer
|
|||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int c_CurrentVersion = 3;
|
private const int c_CurrentVersion = 4;
|
||||||
|
|
||||||
private static readonly JsonSerializerOptions s_Options = new() {
|
private static readonly JsonSerializerOptions s_Options = new() {
|
||||||
WriteIndented = true,
|
WriteIndented = true,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public sealed class LevelValidator
|
|||||||
ValidateCells(level, errors);
|
ValidateCells(level, errors);
|
||||||
ValidateDoors(level, errors);
|
ValidateDoors(level, errors);
|
||||||
ValidateIsolationValves(level, errors);
|
ValidateIsolationValves(level, errors);
|
||||||
|
ValidateSprinklers(level, errors);
|
||||||
ValidateLeaks(level, errors);
|
ValidateLeaks(level, errors);
|
||||||
ValidateReactors(level, errors, warnings);
|
ValidateReactors(level, errors, warnings);
|
||||||
ValidateJunctions(level, errors);
|
ValidateJunctions(level, errors);
|
||||||
@@ -70,7 +71,7 @@ public sealed class LevelValidator
|
|||||||
if (surface.Fuel > 0 || surface.Water > 0 || surface.Electricity > 0 || surface.Heat > 0)
|
if (surface.Fuel > 0 || surface.Water > 0 || surface.Electricity > 0 || surface.Heat > 0)
|
||||||
errors.Add(new("Wall cell cannot store surface hazards.", position));
|
errors.Add(new("Wall cell cannot store surface hazards.", position));
|
||||||
|
|
||||||
if (prop.Type != EPropType.None)
|
if (prop.Type is not (EPropType.None or EPropType.SprinklerValve))
|
||||||
errors.Add(new("Prop must be placed on floor terrain.", position));
|
errors.Add(new("Prop must be placed on floor terrain.", position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,6 +98,39 @@ public sealed class LevelValidator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ValidateSprinklers(LevelState level, List<ValidationIssue> errors)
|
||||||
|
{
|
||||||
|
foreach (var position in LevelTraversal.AllPositions(level))
|
||||||
|
{
|
||||||
|
var prop = level.GetProp(position);
|
||||||
|
if (prop.Type == EPropType.SprinklerControl)
|
||||||
|
{
|
||||||
|
if (!level.IsFloor(position))
|
||||||
|
errors.Add(new("Sprinkler control must be placed on a floor cell.", position));
|
||||||
|
|
||||||
|
if (prop.LinkedPosition is not { } linked || !level.InBounds(linked) || level.GetProp(linked).Type != EPropType.SprinklerValve)
|
||||||
|
errors.Add(new("Sprinkler control must link to exactly one sprinkler valve.", position));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop.Type != EPropType.SprinklerValve)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (level.GetTerrain(position) != ECellTerrain.Wall)
|
||||||
|
errors.Add(new("Sprinkler valve must be wall-mounted.", position));
|
||||||
|
|
||||||
|
if (prop.OutletPosition is not { } outlet || !level.IsFloor(outlet) || position.ManhattanDistance(outlet) != 1)
|
||||||
|
errors.Add(new("Sprinkler valve must have one adjacent floor outlet.", position));
|
||||||
|
|
||||||
|
if (!level.GetUnderground(position, ECarrierType.Water).IsPresent)
|
||||||
|
errors.Add(new("Sprinkler valve must connect to a water underground cell.", position));
|
||||||
|
|
||||||
|
var linkedControls = LevelTraversal.AllPositions(level)
|
||||||
|
.Count(controlPosition => level.GetProp(controlPosition) is { Type: EPropType.SprinklerControl, LinkedPosition: var linkedPosition } && linkedPosition == position);
|
||||||
|
if (linkedControls != 1)
|
||||||
|
errors.Add(new("Sprinkler valve must have exactly one linked control.", position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void ValidateLeaks(LevelState level, List<ValidationIssue> errors)
|
private static void ValidateLeaks(LevelState level, List<ValidationIssue> errors)
|
||||||
{
|
{
|
||||||
foreach (var leak in level.Leaks)
|
foreach (var leak in level.Leaks)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ public enum EPropType
|
|||||||
Junction,
|
Junction,
|
||||||
Door,
|
Door,
|
||||||
AllSeeingEyeTerminal,
|
AllSeeingEyeTerminal,
|
||||||
|
SprinklerControl,
|
||||||
|
SprinklerValve,
|
||||||
RemedySupply,
|
RemedySupply,
|
||||||
ReactorControl
|
ReactorControl
|
||||||
}
|
}
|
||||||
@@ -24,6 +24,8 @@ public sealed record PropState
|
|||||||
public bool Depleted { get; init; }
|
public bool Depleted { get; init; }
|
||||||
public int ReactorId { get; init; }
|
public int ReactorId { get; init; }
|
||||||
public EDoorState DoorState { get; init; } = EDoorState.Closed;
|
public EDoorState DoorState { get; init; } = EDoorState.Closed;
|
||||||
|
public GridPosition? LinkedPosition { get; init; }
|
||||||
|
public GridPosition? OutletPosition { get; init; }
|
||||||
|
|
||||||
public bool IsEnabled => SwitchState == EPropSwitchState.Enabled;
|
public bool IsEnabled => SwitchState == EPropSwitchState.Enabled;
|
||||||
public bool IsOpen => SwitchState == EPropSwitchState.Enabled;
|
public bool IsOpen => SwitchState == EPropSwitchState.Enabled;
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ public sealed class SimulationEngine
|
|||||||
|
|
||||||
var next = level;
|
var next = level;
|
||||||
next = NetworkPropagationSystem.Propagate(next);
|
next = NetworkPropagationSystem.Propagate(next);
|
||||||
|
next = SprinklerSystem.ApplyPressureDebt(next);
|
||||||
next = ConsumerSystem.Resolve(next);
|
next = ConsumerSystem.Resolve(next);
|
||||||
next = StructuralIntegritySystem.Resolve(next);
|
next = StructuralIntegritySystem.Resolve(next);
|
||||||
return next;
|
return next;
|
||||||
@@ -104,6 +105,7 @@ public sealed class SimulationEngine
|
|||||||
private static LevelState ResolveStepContent(LevelState level)
|
private static LevelState ResolveStepContent(LevelState level)
|
||||||
{
|
{
|
||||||
var next = level;
|
var next = level;
|
||||||
|
next = SprinklerSystem.Discharge(next);
|
||||||
next = LeakSystem.Inject(next);
|
next = LeakSystem.Inject(next);
|
||||||
next = SurfaceInteractionSystem.Resolve(next);
|
next = SurfaceInteractionSystem.Resolve(next);
|
||||||
next = next with { Global = next.Global with { Step = next.Global.Step + 1 } };
|
next = next with { Global = next.Global with { Step = next.Global.Step + 1 } };
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ internal static class LeakSystem
|
|||||||
foreach (var leak in level.Leaks.Where(leak => !leak.Repaired))
|
foreach (var leak in level.Leaks.Where(leak => !leak.Repaired))
|
||||||
{
|
{
|
||||||
var underground = level.GetUnderground(leak.UndergroundPosition, leak.Carrier);
|
var underground = level.GetUnderground(leak.UndergroundPosition, leak.Carrier);
|
||||||
if (underground.State != EUndergroundState.Leaking)
|
if (underground is not { State: EUndergroundState.Leaking, Amount: > 0, Intensity: > 0 })
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var accessIndex = level.Index(leak.AccessPosition);
|
var accessIndex = level.Index(leak.AccessPosition);
|
||||||
|
|||||||
@@ -27,17 +27,23 @@ internal static class PlayerActionSystem
|
|||||||
if (prop.Type == EPropType.None)
|
if (prop.Type == EPropType.None)
|
||||||
return Refuse(level, "NO PROP");
|
return Refuse(level, "NO PROP");
|
||||||
|
|
||||||
|
var accepted = true;
|
||||||
var next = prop.Type switch {
|
var next = prop.Type switch {
|
||||||
EPropType.Flow or EPropType.Consumer or EPropType.IsolationValve => ToggleProp(level, position, prop),
|
EPropType.Flow or EPropType.Consumer or EPropType.IsolationValve => ToggleProp(level, position, prop),
|
||||||
|
EPropType.SprinklerControl => ToggleProp(level, position, prop),
|
||||||
EPropType.Junction => CycleJunctionMode(level, position, prop),
|
EPropType.Junction => CycleJunctionMode(level, position, prop),
|
||||||
EPropType.Door => ToggleDoor(level, position, prop),
|
EPropType.Door => ToggleDoor(level, position, prop),
|
||||||
EPropType.AllSeeingEyeTerminal => level with { Global = level.Global with { Status = "ALL-SEEING-EYE AVAILABLE" } },
|
EPropType.AllSeeingEyeTerminal => level with { Global = level.Global with { Status = "ALL-SEEING-EYE AVAILABLE" } },
|
||||||
EPropType.RemedySupply => PickUpRemedy(level, position, prop),
|
EPropType.RemedySupply => PickUpRemedy(level, position, prop),
|
||||||
EPropType.ReactorControl => ReactorSystem.Activate(level),
|
EPropType.ReactorControl => ReactorSystem.Activate(level),
|
||||||
_ => level
|
_ => Refuse(level, "PROP NOT INTERACTIVE")
|
||||||
};
|
};
|
||||||
|
|
||||||
return prop.Type == EPropType.AllSeeingEyeTerminal || prop.Type == EPropType.ReactorControl ? next : resolveLengthyAction(next);
|
accepted = next.Global.Status != "PROP NOT INTERACTIVE";
|
||||||
|
if (!accepted || prop.Type == EPropType.ReactorControl)
|
||||||
|
return next;
|
||||||
|
|
||||||
|
return resolveLengthyAction(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LevelState InteractLeak(LevelState level, ECarrierType carrier, bool useRemedy, Func<LevelState, LevelState> resolveLengthyAction)
|
public static LevelState InteractLeak(LevelState level, ECarrierType carrier, bool useRemedy, Func<LevelState, LevelState> resolveLengthyAction)
|
||||||
|
|||||||
63
src/ReactorMaintenance.Simulation/Systems/SprinklerSystem.cs
Normal file
63
src/ReactorMaintenance.Simulation/Systems/SprinklerSystem.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
namespace ReactorMaintenance.Simulation;
|
||||||
|
|
||||||
|
internal static class SprinklerSystem
|
||||||
|
{
|
||||||
|
public static LevelState ApplyPressureDebt(LevelState level)
|
||||||
|
{
|
||||||
|
var water = level.Water.ToArray();
|
||||||
|
foreach (var valvePosition in ActiveFedValvePositions(level))
|
||||||
|
{
|
||||||
|
var index = level.Index(valvePosition);
|
||||||
|
water[index] = water[index] with {
|
||||||
|
Intensity = Balancing.Current.ClampValue(water[index].Intensity - Balancing.Current.SprinklerPressureDebt)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return level with { Water = water };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LevelState Discharge(LevelState level)
|
||||||
|
{
|
||||||
|
var surface = level.Surface.ToArray();
|
||||||
|
foreach (var valvePosition in ActiveFedValvePositions(level))
|
||||||
|
{
|
||||||
|
var valve = level.GetProp(valvePosition);
|
||||||
|
if (valve.OutletPosition is not { } outlet || !level.IsFloor(outlet))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var index = level.Index(outlet);
|
||||||
|
if (surface[index].Blocks(ECarrierType.Water))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
surface[index] = surface[index] with {
|
||||||
|
Water = Balancing.Current.ClampValue(surface[index].Water + Balancing.Current.SprinklerWaterPerStep)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return level with { Surface = surface };
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<GridPosition> ActiveFedValvePositions(LevelState level)
|
||||||
|
{
|
||||||
|
foreach (var position in LevelTraversal.AllPositions(level))
|
||||||
|
{
|
||||||
|
var valve = level.GetProp(position);
|
||||||
|
if (valve.Type != EPropType.SprinklerValve || !HasEnabledLinkedControl(level, position))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var underground = level.GetUnderground(position, ECarrierType.Water);
|
||||||
|
if (underground is { Amount: > 0, Intensity: > 0 })
|
||||||
|
yield return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool HasEnabledLinkedControl(LevelState level, GridPosition valvePosition)
|
||||||
|
{
|
||||||
|
return LevelTraversal.AllPositions(level)
|
||||||
|
.Any(position => level.GetProp(position) is {
|
||||||
|
Type: EPropType.SprinklerControl,
|
||||||
|
SwitchState: EPropSwitchState.Enabled,
|
||||||
|
LinkedPosition: var linkedPosition
|
||||||
|
} && linkedPosition == valvePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -285,7 +285,7 @@ public sealed class SimulationEngineTests
|
|||||||
var json = LevelSerializer.Serialize(level);
|
var json = LevelSerializer.Serialize(level);
|
||||||
var loaded = LevelSerializer.Deserialize(json);
|
var loaded = LevelSerializer.Deserialize(json);
|
||||||
|
|
||||||
Assert.Contains("\"Version\": 3", json);
|
Assert.Contains("\"Version\": 4", json);
|
||||||
Assert.Equal(level.Name, loaded.Name);
|
Assert.Equal(level.Name, loaded.Name);
|
||||||
Assert.Equal(EPropType.Consumer, loaded.GetProp(new(3, 3)).Type);
|
Assert.Equal(EPropType.Consumer, loaded.GetProp(new(3, 3)).Type);
|
||||||
Assert.Equal(level.RequiredFuelConsumers, loaded.RequiredFuelConsumers);
|
Assert.Equal(level.RequiredFuelConsumers, loaded.RequiredFuelConsumers);
|
||||||
@@ -323,6 +323,55 @@ public sealed class SimulationEngineTests
|
|||||||
Assert.Contains("Unsupported level file version 2", exception.Message);
|
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()
|
private static LevelState BuildReadyLevel()
|
||||||
{
|
{
|
||||||
var level = LevelState.Create("Ready", 8, 7);
|
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();
|
private readonly SimulationEngine m_Engine = new();
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user