Finish rewrite task list
This commit is contained in:
@@ -1,91 +1,92 @@
|
||||
namespace ReactorMaintenance.Simulation;
|
||||
|
||||
public enum EEditorTool
|
||||
{
|
||||
Cursor,
|
||||
Floor,
|
||||
Wall,
|
||||
FuelUnderground,
|
||||
CoolantUnderground,
|
||||
ElectricityUnderground,
|
||||
FuelFlow,
|
||||
CoolantFlow,
|
||||
ElectricityFlow,
|
||||
FuelConsumer,
|
||||
CoolantConsumer,
|
||||
ElectricityConsumer,
|
||||
Junction,
|
||||
Door,
|
||||
AllSeeingEyeTerminal,
|
||||
FuelRemedySupply,
|
||||
CoolantRemedySupply,
|
||||
ElectricityRemedySupply,
|
||||
HeatRemedySupply,
|
||||
ReactorControl,
|
||||
FuelLeak,
|
||||
CoolantLeak,
|
||||
ElectricityLeak,
|
||||
FuelHazard,
|
||||
CoolantHazard,
|
||||
ElectricityHazard,
|
||||
Heat,
|
||||
Robot
|
||||
}
|
||||
|
||||
public static class LevelEditor
|
||||
{
|
||||
public static LevelState Apply(LevelState level, GridPosition position, EEditorTool tool)
|
||||
public static LevelState Apply(LevelState level, GridPosition position, EditorToolCommand command)
|
||||
{
|
||||
if (!level.InBounds(position))
|
||||
return level;
|
||||
|
||||
return tool switch {
|
||||
return command.Tool switch {
|
||||
EEditorTool.Cursor => level,
|
||||
EEditorTool.Floor => level.SetTerrain(position, ECellTerrain.Floor),
|
||||
EEditorTool.Wall => level.SetTerrain(position, ECellTerrain.Wall),
|
||||
EEditorTool.FuelUnderground => SetUnderground(level, position, ECarrierType.Fuel),
|
||||
EEditorTool.CoolantUnderground => SetUnderground(level, position, ECarrierType.Coolant),
|
||||
EEditorTool.ElectricityUnderground => SetUnderground(level, position, ECarrierType.Electricity),
|
||||
EEditorTool.FuelFlow => SetCarrierProp(level, position, EPropType.Flow, ECarrierType.Fuel),
|
||||
EEditorTool.CoolantFlow => SetCarrierProp(level, position, EPropType.Flow, ECarrierType.Coolant),
|
||||
EEditorTool.ElectricityFlow => SetCarrierProp(level, position, EPropType.Flow, ECarrierType.Electricity),
|
||||
EEditorTool.FuelConsumer => SetCarrierProp(level, position, EPropType.Consumer, ECarrierType.Fuel),
|
||||
EEditorTool.CoolantConsumer => SetCarrierProp(level, position, EPropType.Consumer, ECarrierType.Coolant),
|
||||
EEditorTool.ElectricityConsumer => SetCarrierProp(level, position, EPropType.Consumer, ECarrierType.Electricity),
|
||||
EEditorTool.Underground => SetUnderground(level, position, command.Carrier),
|
||||
EEditorTool.Flow => SetCarrierProp(level, position, EPropType.Flow, command.Carrier),
|
||||
EEditorTool.Consumer => SetCarrierProp(level, position, EPropType.Consumer, command.Carrier),
|
||||
EEditorTool.Junction => SetFloorProp(level, position, new() { Type = EPropType.Junction }),
|
||||
EEditorTool.Door => SetDoor(level, position),
|
||||
EEditorTool.Door => SetFloorProp(level, position, new() { Type = EPropType.Door }),
|
||||
EEditorTool.AllSeeingEyeTerminal => SetFloorProp(level, position, new() { Type = EPropType.AllSeeingEyeTerminal }),
|
||||
EEditorTool.FuelRemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.FuelNeutralizer }),
|
||||
EEditorTool.CoolantRemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.CoolantNeutralizer }),
|
||||
EEditorTool.ElectricityRemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.ElectricityNeutralizer }),
|
||||
EEditorTool.HeatRemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = ERemedyType.HeatShield }),
|
||||
EEditorTool.RemedySupply => SetFloorProp(level, position, new() { Type = EPropType.RemedySupply, RemedyType = command.RemedyType }),
|
||||
EEditorTool.ReactorControl => SetReactorControl(level, position),
|
||||
EEditorTool.FuelLeak => SetLeak(level, position, ECarrierType.Fuel),
|
||||
EEditorTool.CoolantLeak => SetLeak(level, position, ECarrierType.Coolant),
|
||||
EEditorTool.ElectricityLeak => SetLeak(level, position, ECarrierType.Electricity),
|
||||
EEditorTool.FuelHazard => level.SetSurface(position, level.GetSurface(position) with { Fuel = level.GetSurface(position).Fuel + 1 }),
|
||||
EEditorTool.CoolantHazard => level.SetSurface(position, level.GetSurface(position) with { Coolant = level.GetSurface(position).Coolant + 1 }),
|
||||
EEditorTool.ElectricityHazard => level.SetSurface(position, level.GetSurface(position) with { Electricity = level.GetSurface(position).Electricity + 1 }),
|
||||
EEditorTool.Leak => SetLeak(level, position, command.Carrier),
|
||||
EEditorTool.SurfaceHazard => AddSurfaceHazard(level, position, command.Carrier),
|
||||
EEditorTool.Heat => level.SetSurface(position, level.GetSurface(position) with { Heat = level.GetSurface(position).Heat + 1 }),
|
||||
EEditorTool.Robot => level.IsFloor(position) ? level with { Robot = level.Robot with { Position = position } } : level,
|
||||
_ => level
|
||||
};
|
||||
}
|
||||
|
||||
public static LevelState BindFirstReactorToConsumers(LevelState level, GridPosition fuelConsumer, GridPosition coolantConsumer, GridPosition electricityConsumer)
|
||||
public static LevelState SetDoorEdge(LevelState level, GridPosition a, GridPosition b)
|
||||
{
|
||||
if (level.Reactors.Count == 0)
|
||||
if (!level.IsFloor(a) || !level.IsFloor(b) || a.ManhattanDistance(b) != 1)
|
||||
return level;
|
||||
|
||||
var reactors = level.Reactors.ToArray();
|
||||
reactors[0] = reactors[0] with {
|
||||
FuelConsumerPosition = fuelConsumer,
|
||||
CoolantConsumerPosition = coolantConsumer,
|
||||
ElectricityConsumerPosition = electricityConsumer
|
||||
return level.SetProp(a, new() { Type = EPropType.Door }) with {
|
||||
Doors = [
|
||||
.. level.Doors.Where(door => !SameDoorEdge(door, a, b)),
|
||||
new() { A = a, B = b, State = EDoorState.Closed }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
public static LevelState SetLeak(LevelState level, GridPosition undergroundPosition, GridPosition accessPosition, ECarrierType carrier)
|
||||
{
|
||||
if (!level.InBounds(undergroundPosition) || !level.IsFloor(accessPosition))
|
||||
return level;
|
||||
|
||||
if (carrier is ECarrierType.Fuel or ECarrierType.Coolant && undergroundPosition != accessPosition)
|
||||
return level;
|
||||
|
||||
if (carrier == ECarrierType.Electricity && undergroundPosition.ManhattanDistance(accessPosition) != 1)
|
||||
return level;
|
||||
|
||||
var next = level.SetUnderground(undergroundPosition, carrier, new() { State = EUndergroundState.Leaking });
|
||||
return next with {
|
||||
Leaks = [
|
||||
.. next.Leaks.Where(leak => leak.UndergroundPosition != undergroundPosition || leak.Carrier != carrier),
|
||||
new() {
|
||||
Carrier = carrier,
|
||||
UndergroundPosition = undergroundPosition,
|
||||
AccessPosition = accessPosition
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
public static LevelState BindReactorConsumer(LevelState level, int reactorId, ECarrierType carrier, GridPosition consumerPosition)
|
||||
{
|
||||
if (!level.InBounds(consumerPosition) || level.GetProp(consumerPosition) is not { Type: EPropType.Consumer } prop || prop.Carrier != carrier)
|
||||
return level;
|
||||
|
||||
var reactors = level.Reactors.Select(reactor => reactor.ReactorId == reactorId ? BindConsumer(reactor, carrier, consumerPosition) : reactor).ToArray();
|
||||
return level with { Reactors = reactors };
|
||||
}
|
||||
|
||||
public static LevelState AddRuleEvent(LevelState level, RuleEventState ruleEvent)
|
||||
{
|
||||
var id = string.IsNullOrWhiteSpace(ruleEvent.Id) ? NextRuleEventId(level) : ruleEvent.Id;
|
||||
var authoredEvent = ruleEvent with { Id = id };
|
||||
return level with {
|
||||
RuleEvents = [.. level.RuleEvents.Where(existing => existing.Id != id), authoredEvent]
|
||||
};
|
||||
}
|
||||
|
||||
public static LevelState RemoveRuleEvent(LevelState level, string id)
|
||||
{
|
||||
return level with { RuleEvents = level.RuleEvents.Where(ruleEvent => ruleEvent.Id != id).ToArray() };
|
||||
}
|
||||
|
||||
private static LevelState SetUnderground(LevelState level, GridPosition position, ECarrierType carrier)
|
||||
{
|
||||
return level.SetUnderground(position, carrier, new() { State = EUndergroundState.Intact });
|
||||
@@ -96,25 +97,22 @@ public static class LevelEditor
|
||||
return SetFloorProp(level, position, new() { Type = type, Carrier = carrier, SwitchState = EPropSwitchState.Enabled });
|
||||
}
|
||||
|
||||
private static LevelState AddSurfaceHazard(LevelState level, GridPosition position, ECarrierType carrier)
|
||||
{
|
||||
var surface = level.GetSurface(position);
|
||||
return carrier switch {
|
||||
ECarrierType.Fuel => level.SetSurface(position, surface with { Fuel = surface.Fuel + 1 }),
|
||||
ECarrierType.Coolant => level.SetSurface(position, surface with { Coolant = surface.Coolant + 1 }),
|
||||
ECarrierType.Electricity => level.SetSurface(position, surface with { Electricity = surface.Electricity + 1 }),
|
||||
_ => level
|
||||
};
|
||||
}
|
||||
|
||||
private static LevelState SetFloorProp(LevelState level, GridPosition position, PropState prop)
|
||||
{
|
||||
return level.IsFloor(position) ? level.SetProp(position, prop) : level;
|
||||
}
|
||||
|
||||
private static LevelState SetDoor(LevelState level, GridPosition position)
|
||||
{
|
||||
if (!level.IsFloor(position))
|
||||
return level;
|
||||
|
||||
var neighbor = position.Neighbors().FirstOrDefault(level.IsFloor);
|
||||
if (neighbor is null)
|
||||
return SetFloorProp(level, position, new() { Type = EPropType.Door });
|
||||
|
||||
return SetFloorProp(level, position, new() { Type = EPropType.Door }) with {
|
||||
Doors = [.. level.Doors, new() { A = position, B = neighbor }]
|
||||
};
|
||||
}
|
||||
|
||||
private static LevelState SetReactorControl(LevelState level, GridPosition position)
|
||||
{
|
||||
if (!level.IsFloor(position))
|
||||
@@ -141,23 +139,30 @@ public static class LevelEditor
|
||||
if (!level.InBounds(position))
|
||||
return level;
|
||||
|
||||
var accessPosition = carrier == ECarrierType.Electricity && level.GetTerrain(position) == ECellTerrain.Wall
|
||||
? position.Neighbors().FirstOrDefault(level.IsFloor)
|
||||
: position;
|
||||
return SetLeak(level, position, position, carrier);
|
||||
}
|
||||
|
||||
if (accessPosition is null || !level.IsFloor(accessPosition))
|
||||
return level;
|
||||
private static bool SameDoorEdge(DoorState door, GridPosition a, GridPosition b)
|
||||
{
|
||||
return door.A == a && door.B == b || door.A == b && door.B == a;
|
||||
}
|
||||
|
||||
var next = level.SetUnderground(position, carrier, new() { State = EUndergroundState.Leaking });
|
||||
return next with {
|
||||
Leaks = [
|
||||
.. next.Leaks,
|
||||
new() {
|
||||
Carrier = carrier,
|
||||
UndergroundPosition = position,
|
||||
AccessPosition = accessPosition
|
||||
}
|
||||
]
|
||||
private static ReactorBinding BindConsumer(ReactorBinding reactor, ECarrierType carrier, GridPosition consumerPosition)
|
||||
{
|
||||
return carrier switch {
|
||||
ECarrierType.Fuel => reactor with { FuelConsumerPosition = consumerPosition },
|
||||
ECarrierType.Coolant => reactor with { CoolantConsumerPosition = consumerPosition },
|
||||
ECarrierType.Electricity => reactor with { ElectricityConsumerPosition = consumerPosition },
|
||||
_ => reactor
|
||||
};
|
||||
}
|
||||
|
||||
private static string NextRuleEventId(LevelState level)
|
||||
{
|
||||
var next = level.RuleEvents.Count + 1;
|
||||
while (level.RuleEvents.Any(ruleEvent => ruleEvent.Id == $"rule-{next}"))
|
||||
next++;
|
||||
|
||||
return $"rule-{next}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user