Rework simulation rules

This commit is contained in:
2026-05-11 22:18:43 +02:00
parent 3d406179bf
commit e1ac56d201
30 changed files with 554 additions and 848 deletions

View File

@@ -13,7 +13,7 @@ public static class LevelEditor
EEditorTool.Wall => level.SetTerrain(position, ECellTerrain.Wall),
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.Consumer => SetFloorProp(level, position, new() { Type = EPropType.Consumer, SwitchState = EPropSwitchState.Enabled }),
EEditorTool.Junction => SetFloorProp(level, position, new() { Type = EPropType.Junction }),
EEditorTool.Door => SetFloorProp(level, position, new() { Type = EPropType.Door }),
EEditorTool.AllSeeingEyeTerminal => SetFloorProp(level, position, new() { Type = EPropType.AllSeeingEyeTerminal }),
@@ -27,19 +27,6 @@ public static class LevelEditor
};
}
public static LevelState SetDoorEdge(LevelState level, GridPosition a, GridPosition b)
{
if (!level.IsFloor(a) || !level.IsFloor(b) || a.ManhattanDistance(b) != 1)
return level;
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))
@@ -51,7 +38,10 @@ public static class LevelEditor
if (carrier == ECarrierType.Electricity && undergroundPosition.ManhattanDistance(accessPosition) != 1)
return level;
var next = level.SetUnderground(undergroundPosition, carrier, new() { State = EUndergroundState.Leaking });
var next = level.SetUnderground(undergroundPosition, carrier, new() {
State = EUndergroundState.Leaking,
StructuralIntegrity = Balancing.Current.StructuralIntegrityLeakThreshold
});
return next with {
Leaks = [
.. next.Leaks.Where(leak => leak.UndergroundPosition != undergroundPosition || leak.Carrier != carrier),
@@ -64,32 +54,12 @@ public static class LevelEditor
};
}
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 });
return level.SetUnderground(position, carrier, new() {
State = EUndergroundState.Intact,
StructuralIntegrity = Balancing.Current.MaxStructuralIntegrity
});
}
private static LevelState SetCarrierProp(LevelState level, GridPosition position, EPropType type, ECarrierType carrier)
@@ -125,10 +95,7 @@ public static class LevelEditor
.. level.Reactors,
new() {
ReactorId = id,
ControlPosition = position,
FuelConsumerPosition = position,
CoolantConsumerPosition = position,
ElectricityConsumerPosition = position
ControlPosition = position
}
]
};
@@ -141,28 +108,4 @@ public static class LevelEditor
return SetLeak(level, position, position, carrier);
}
private static bool SameDoorEdge(DoorState door, GridPosition a, GridPosition b)
{
return (door.A == a && door.B == b) || (door.A == b && door.B == a);
}
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}";
}
}