Rework simulation rules
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
namespace ReactorMaintenance.Simulation;
|
||||
|
||||
internal static class StructuralIntegritySystem
|
||||
{
|
||||
public static LevelState Resolve(LevelState level)
|
||||
{
|
||||
foreach (var carrier in Enum.GetValues<ECarrierType>())
|
||||
level = ResolveCarrier(level, carrier);
|
||||
|
||||
return level;
|
||||
}
|
||||
|
||||
private static LevelState ResolveCarrier(LevelState level, ECarrierType carrier)
|
||||
{
|
||||
var layer = level.Layer(carrier).ToArray();
|
||||
var leaks = level.Leaks.ToList();
|
||||
|
||||
foreach (var position in LevelTraversal.AllPositions(level))
|
||||
{
|
||||
var index = level.Index(position);
|
||||
var cell = layer[index];
|
||||
if (!cell.IsPresent)
|
||||
continue;
|
||||
|
||||
var integrity = DegradeIntegrity(cell, carrier);
|
||||
var state = cell.State;
|
||||
if (state != EUndergroundState.Leaking && integrity <= Balancing.Current.StructuralIntegrityLeakThreshold && cell.Intensity > 0)
|
||||
{
|
||||
state = EUndergroundState.Leaking;
|
||||
leaks = UpsertLeak(leaks, level, position, carrier);
|
||||
}
|
||||
|
||||
layer[index] = cell with { State = state, StructuralIntegrity = integrity };
|
||||
}
|
||||
|
||||
var next = carrier switch {
|
||||
ECarrierType.Fuel => level with { Fuel = layer },
|
||||
ECarrierType.Coolant => level with { Coolant = layer },
|
||||
ECarrierType.Electricity => level with { Electricity = layer },
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(carrier), carrier, "Unsupported carrier.")
|
||||
};
|
||||
|
||||
return next with { Leaks = leaks.ToArray() };
|
||||
}
|
||||
|
||||
private static int DegradeIntegrity(UndergroundCell cell, ECarrierType carrier)
|
||||
{
|
||||
if (cell.StructuralIntegrity >= Balancing.Current.MaxStructuralIntegrity && cell.Intensity <= Balancing.Current.StructuralPressureThreshold(carrier))
|
||||
return Balancing.Current.MaxStructuralIntegrity;
|
||||
|
||||
var overPressure = Math.Max(0, cell.Intensity - Balancing.Current.StructuralPressureThreshold(carrier));
|
||||
if (overPressure <= 0 || cell.StructuralIntegrity >= Balancing.Current.MaxStructuralIntegrity)
|
||||
return Math.Clamp(cell.StructuralIntegrity, 0, Balancing.Current.MaxStructuralIntegrity);
|
||||
|
||||
var damage = Math.Max(1, (int)Math.Ceiling(overPressure * Balancing.Current.StructuralIntegrityDamageScale));
|
||||
return Math.Clamp(cell.StructuralIntegrity - damage, 0, Balancing.Current.MaxStructuralIntegrity);
|
||||
}
|
||||
|
||||
private static List<LeakState> UpsertLeak(List<LeakState> leaks, LevelState level, GridPosition position, ECarrierType carrier)
|
||||
{
|
||||
var accessPosition = carrier == ECarrierType.Electricity
|
||||
? position.Neighbors().FirstOrDefault(level.IsFloor)
|
||||
: position;
|
||||
if (accessPosition is null || !level.IsFloor(accessPosition))
|
||||
return leaks;
|
||||
|
||||
var index = leaks.FindIndex(leak => leak.UndergroundPosition == position && leak.Carrier == carrier);
|
||||
var leakState = new LeakState {
|
||||
Carrier = carrier,
|
||||
UndergroundPosition = position,
|
||||
AccessPosition = accessPosition,
|
||||
Repaired = false
|
||||
};
|
||||
|
||||
if (index >= 0)
|
||||
leaks[index] = leakState;
|
||||
else
|
||||
leaks.Add(leakState);
|
||||
|
||||
return leaks;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user