namespace ReactorMaintenance.Simulation; internal static class StructuralIntegritySystem { public static LevelState Resolve(LevelState level) { foreach (var carrier in Enum.GetValues()) 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.Water => level with { Water = 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 UpsertLeak(List 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; } }