Expand rule event coverage
This commit is contained in:
@@ -447,6 +447,24 @@ public sealed class SimulationEngine
|
||||
return level.InBounds(position) && level.GetProp(position) is { Type: EPropType.Consumer, Carrier: var consumerCarrier, ServiceState: EConsumerServiceState.Producing } && consumerCarrier == carrier;
|
||||
}
|
||||
|
||||
private static bool ReactorMatches(LevelState level, RulePredicate predicate, Func<ReactorBinding, bool> selector)
|
||||
{
|
||||
return level.Reactors.Any(reactor => MatchesReactorId(reactor, predicate.ReactorId) && selector(reactor)) == predicate.BoolValue;
|
||||
}
|
||||
|
||||
private static bool MatchesReactorId(ReactorBinding reactor, int reactorId)
|
||||
{
|
||||
return reactorId <= 0 || reactor.ReactorId == reactorId;
|
||||
}
|
||||
|
||||
private static bool ReactorWonMatches(LevelState level, RulePredicate predicate)
|
||||
{
|
||||
var won = predicate.ReactorId > 0
|
||||
? level.Reactors.Any(reactor => reactor.ReactorId == predicate.ReactorId && reactor.Activated)
|
||||
: level.Global.LevelState == ELevelState.Won || level.Reactors.Any(reactor => reactor.Activated);
|
||||
return won == predicate.BoolValue;
|
||||
}
|
||||
|
||||
private LevelState ApplyRuleEvents(LevelState level, ERuleEventPhase phase)
|
||||
{
|
||||
var next = level;
|
||||
@@ -472,10 +490,15 @@ public sealed class SimulationEngine
|
||||
return predicate.Kind switch {
|
||||
ERulePredicateKind.TurnAtLeast => level.Global.Turn >= predicate.Turn,
|
||||
ERulePredicateKind.LevelStateIs => level.Global.LevelState == predicate.LevelState,
|
||||
ERulePredicateKind.ReactorReadyIs => ReactorMatches(level, predicate, reactor => reactor.Ready),
|
||||
ERulePredicateKind.ReactorLostIs => (level.Global.LevelState == ELevelState.Lost) == predicate.BoolValue,
|
||||
ERulePredicateKind.ReactorWonIs => ReactorWonMatches(level, predicate),
|
||||
ERulePredicateKind.PropStateAt => level.InBounds(predicate.Position) && level.GetProp(predicate.Position).SwitchState == predicate.PropSwitchState,
|
||||
ERulePredicateKind.ConsumerStateAt => level.InBounds(predicate.Position) && level.GetProp(predicate.Position).ServiceState == predicate.ConsumerServiceState,
|
||||
ERulePredicateKind.NetworkBandAt => level.InBounds(predicate.Position) && NetworkBand(level.GetUnderground(predicate.Position, predicate.Carrier), predicate.Carrier, predicate.NetworkValue) >= predicate.Band,
|
||||
ERulePredicateKind.SurfaceBandAt => level.InBounds(predicate.Position) && SurfaceBand(level.GetSurface(predicate.Position), predicate.Carrier) >= predicate.Band,
|
||||
ERulePredicateKind.RobotAt => level.Robot.Position == predicate.Position,
|
||||
ERulePredicateKind.RobotInventoryAtLeast => level.Robot.Count(predicate.Remedy) >= predicate.InventoryCount,
|
||||
ERulePredicateKind.AllSeeingEyeUnlocked => level.Global.AllSeeingEyeUnlocked == predicate.BoolValue,
|
||||
_ => false
|
||||
};
|
||||
@@ -490,8 +513,11 @@ public sealed class SimulationEngine
|
||||
ERuleEffectKind.DisableNetworkCell => level.SetUnderground(effect.Position, effect.Carrier, new()),
|
||||
ERuleEffectKind.SetPropEnabled => level.SetProp(effect.Position, level.GetProp(effect.Position) with { SwitchState = effect.PropSwitchState }),
|
||||
ERuleEffectKind.AddSurfaceHazard => level.SetSurface(effect.Position, AddSurfaceCarrier(level.GetSurface(effect.Position), effect.Carrier, effect.Amount)),
|
||||
ERuleEffectKind.RemoveSurfaceHazard => level.SetSurface(effect.Position, AddSurfaceCarrier(level.GetSurface(effect.Position), effect.Carrier, -effect.Amount)),
|
||||
ERuleEffectKind.AddHeat => level.SetSurface(effect.Position, level.GetSurface(effect.Position) with { Heat = level.GetSurface(effect.Position).Heat + effect.Amount }),
|
||||
ERuleEffectKind.RemoveHeat => level.SetSurface(effect.Position, level.GetSurface(effect.Position) with { Heat = level.GetSurface(effect.Position).Heat - effect.Amount }),
|
||||
ERuleEffectKind.AddInventory => level with { Robot = level.Robot.Add(effect.Remedy, (int)effect.Amount) },
|
||||
ERuleEffectKind.RemoveInventory => level with { Robot = level.Robot.Add(effect.Remedy, -(int)effect.Amount) },
|
||||
ERuleEffectKind.MarkTerminalLoss => level with { Global = level.Global with { LevelState = ELevelState.Lost, TerminalLoss = true, Status = string.IsNullOrWhiteSpace(effect.Message) ? "TERMINAL FAILURE" : effect.Message } },
|
||||
ERuleEffectKind.EmitWarning => level with { Global = level.Global with { Warnings = [.. level.Global.Warnings, effect.Message] } },
|
||||
_ => level
|
||||
@@ -503,7 +529,7 @@ public sealed class SimulationEngine
|
||||
var leak = new LeakState {
|
||||
Carrier = effect.Carrier,
|
||||
UndergroundPosition = effect.Position,
|
||||
AccessPosition = effect.Position
|
||||
AccessPosition = effect.AccessPosition ?? effect.Position
|
||||
};
|
||||
return level.SetUnderground(effect.Position, effect.Carrier, level.GetUnderground(effect.Position, effect.Carrier) with { State = EUndergroundState.Leaking }) with { Leaks = [.. level.Leaks, leak] };
|
||||
}
|
||||
@@ -625,6 +651,17 @@ public sealed class SimulationEngine
|
||||
};
|
||||
}
|
||||
|
||||
private static EBand NetworkBand(UndergroundCell underground, ECarrierType carrier, ENetworkValueKind valueKind)
|
||||
{
|
||||
var value = valueKind == ENetworkValueKind.Amount ? underground.Amount : underground.Intensity;
|
||||
return carrier switch {
|
||||
ECarrierType.Fuel => BandFuel(value),
|
||||
ECarrierType.Coolant => BandCoolant(value),
|
||||
ECarrierType.Electricity => BandElectricity(value),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(carrier), carrier, "Unsupported carrier.")
|
||||
};
|
||||
}
|
||||
|
||||
private static EBand BandFuel(float value)
|
||||
{
|
||||
return Balancing.Current.Band(value, Balancing.Current.FuelCaution, Balancing.Current.FuelCritical);
|
||||
|
||||
Reference in New Issue
Block a user