diff --git a/docs/design.md b/docs/design.md index 57a8092..4a4bac3 100644 --- a/docs/design.md +++ b/docs/design.md @@ -6,20 +6,20 @@ The player controls a maintenance robot inside a failing reactor facility. The game is a deterministic, turn-based systems puzzle. The player studies a visible machine, predicts its failures, and chooses which systems to stabilize first. -The revised simulation model is intentionally narrow: +The simulation model is intentionally narrow: - a surface grid - an underground fuel network - an underground coolant network - an underground electricity network - surface props that connect vertically into exactly one underground network -- a reactor that must be supplied and kept cool +- a reactor that must receive fuel, cooling, and electricity support before activation - a diagnostic UI that exposes the current state and the next predicted changes Each turn has three phases: 1. Player phase: the player spends a limited number of actions. -2. Simulation phase: local network, leak, and heat rules are resolved deterministically. +2. Simulation phase: network flow, leaks, local hazards, consumers, and level state are resolved deterministically. 3. Event phase: scheduled failures or scripted level events advance. The main fantasy is: @@ -47,12 +47,13 @@ The reactor starts offline. To win a level, the player must: -- restore electricity delivery to the required consumers -- restore coolant delivery to the reactor path - restore fuel delivery to the required fuel consumer -- reach a stable enough state to activate the reactor +- restore coolant delivery to the required coolant consumer +- restore electricity delivery to the required electricity consumer +- keep the reactor area below terminal heat +- reach the reactor control site and activate the core -When all required systems are ready, the game shows: +When all required consumers are enabled, supplied, and producing service, and no terminal reactor condition is active, the level shows: > REACTOR READY @@ -64,9 +65,11 @@ The player loses if the level reaches a clearly predicted terminal state. Primary loss conditions: -- reactor overheating reaches terminal heat -- required consumers remain starved long enough to force shutdown -- cascading heat makes the level irrecoverable +- reactor overheating reaches the terminal heat threshold +- a scripted terminal event resolves +- cascading hazards make the level explicitly unrecoverable according to level-authored rules + +Required consumer starvation does not directly cause loss. A starved or disabled required consumer prevents `Ready`, but failure still comes from terminal heat, scripted loss events, or other explicit terminal rules. Failure should not be instant unless the player knowingly allows a predicted critical state to mature. @@ -74,28 +77,32 @@ Failure should not be instant unless the player knowingly allows a predicted cri ### 1. Player Phase -The player has a fixed number of actions per turn, usually 3. +The player has a fixed number of actions per turn, defined by balancing. Possible actions: - move -- interact with a flow prop -- interact with a consumer prop -- repair a leaking network cell - inspect a cell or prop +- enable or disable a flow prop +- enable or disable a consumer prop +- adjust a junction prop +- repair a leaking network cell - activate the reactor +Each non-inspection action costs one action unless balancing or a level rule explicitly says otherwise. Inspection is intended to be free or cheap enough that it does not punish understanding the system. + ### 2. Simulation Phase The facility updates all active systems. Examples: -- outside connections feed enabled networks -- enabled consumers draw from their bound network -- leaking underground cells emit their element into the surface cell above them -- neighboring surface cells exchange leaked matter or heat through deterministic lookup rules -- coolant reduces heat +- enabled flow props inject pressure or voltage into connected underground networks +- junctions throttle or boost pressure or voltage along branches +- enabled consumers draw from their bound network and produce service if supplied +- leaking underground cells emit their carrier into the surface cell above them +- neighboring surface cells exchange leaked matter, charge, or heat through deterministic numeric rules +- coolant lowers heat - electricity interacting with coolant or fuel raises heat ### 3. Event Phase @@ -104,9 +111,10 @@ Predicted events advance by one turn. Examples: -- a leak worsens -- a consumer disables itself after starvation +- a scripted leak starts +- an existing leak worsens - a scripted level event adds heat or disables a prop +- a scripted cell block appears or clears Events are not hidden. The player sees upcoming failures before they happen. @@ -116,21 +124,26 @@ All relevant information is visible and predictable. The player can see: -- the state of each underground network cell: absent, intact, or leaking -- the local amount band of leaked fuel, coolant, and electricity -- the local heat band +- the structural state of each underground network cell: absent, intact, or leaking +- the current numeric local amount of leaked fuel, coolant, electricity, and heat +- the UI label for each numeric value: safe, caution, or critical +- the pressure value for fuel and coolant network cells +- the voltage value for electricity network cells - whether each surface prop is enabled or disabled -- which consumer is currently starved +- the current mode of each junction +- whether each consumer is supplied, starved, disabled, or producing service - the current global level state - scheduled upcoming events +Safe, caution, and critical labels are UI and forecast labels only. They are derived from balance constants and are not authoritative simulation state. Exact numeric values and balance predicates drive simulation. + The question is not: > "What is behind the corner?" It is: -> "What happens if I let this pair of cells interact for one more turn?" +> "What happens if I let this pair of values interact for one more turn?" ## Simulation Model @@ -149,87 +162,104 @@ The three underground networks are disjunct. They do not share edges and do not Each network has: -- its own outside-of-level connection -- exactly one flow prop type on the surface -- exactly one consumer prop type on the surface +- its own outside-of-level source connection +- one flow prop type on the surface +- one consumer prop type on the surface +- optional junction props on the surface The surface prop is an abstract vertical connection to one underground cell. ### Network Semantics -The three network families are intentionally symmetric. +The three network families are intentionally symmetric in structure but differ by carrier behavior. -- Fuel: used by its consumer, dangerous when leaked next to electricity or high heat. -- Coolant: used by its consumer, safe by itself, lowers heat, dangerous when leaked next to electricity. -- Electricity: used by its consumer, safe by itself, dangerous when leaked next to coolant or fuel. +- Fuel: liquid carrier, uses pressure, required by the fuel consumer, dangerous when leaked near electricity or high heat. +- Coolant: liquid carrier, uses pressure, required by the coolant consumer, lowers heat, dangerous when leaked near electricity. +- Electricity: electrical carrier, uses voltage, required by the electricity consumer, dangerous when leaked near coolant or fuel. -Each underground network cell has only three structural states: +Each underground network cell has one structural state: - `Absent` - `Intact` - `Leaking` -Each element amount uses the same three thresholds: +Each underground network cell stores exact numeric values: -- `Safe` = `0-9` -- `Caution` = `10-19` -- `Critical` = `20-29` +- local carrier amount +- local pressure for fuel and coolant +- local voltage for electricity -Heat uses the same thresholds: +Each surface cell stores exact numeric values: -- `HeatSafe` = `0-9` -- `HeatCaution` = `10-19` -- `HeatCritical` = `20-29` +- leaked fuel amount +- leaked coolant amount +- leaked electricity amount +- heat amount + +All numeric values use balance-defined minimum and maximum clamps. The design intentionally does not fix numeric thresholds in this document. Balancing defines source strength, consumer requirements, leak rates, junction deltas, display bands, terminal thresholds, and event magnitudes. ### Why This Formalization -This model keeps the simulation small enough for a table lookup: +This model keeps the simulation small enough to forecast while still creating tactical decisions: - network topology is stored underground -- leaked matter and heat are projected onto the surface -- only the projected surface bands participate in the lookup matrix -- props, robot, and global level state modify or consume those projected bands before or after the matrix pass +- pressure and voltage determine whether consumers are satisfied and how severe leaks are +- leaked matter, charge, and heat are projected onto the surface +- local surface interactions use deterministic numeric predicates +- props, robot, and global level state modify or consume values before or after the local interaction pass ## State Inventory ### Cell State -Surface cell states: +Surface cell terrain states: - `Open` - `Blocked` -- `HeatSafe` -- `HeatCaution` -- `HeatCritical` -Underground network states, repeated for fuel, coolant, and electricity: +Surface hazard values: + +- `Fuel` +- `Coolant` +- `Electricity` +- `Heat` + +Underground network state, repeated for fuel, coolant, and electricity: - `Absent` - `Intact` - `Leaking` -- `Safe` -- `Caution` -- `Critical` +- local carrier amount +- local pressure for fuel and coolant +- local voltage for electricity Notes: - `Absent` / `Intact` / `Leaking` describe the underground cell itself. -- `Safe` / `Caution` / `Critical` describe the local amount currently present in that layer or leaked onto the surface. -- A leaking underground cell injects its element into the surface cell above it during simulation. +- Numeric values describe the current simulation state. +- Safe/caution/critical labels are derived from numeric values for UI and forecasts only. +- A leaking underground cell injects its carrier into the surface cell above it during simulation. ### Prop State -Each network has exactly two prop types on the surface: +Each network has three surface prop categories: - flow prop - consumer prop +- junction prop -Each prop has exactly two states: +Flow and consumer props have two states: - `Enabled` - `Disabled` -Concrete prop states: +Junction props have three mode families: + +- `Neutral`: no pressure or voltage adjustment +- `Throttle`: reduces downstream pressure or voltage by a balanceable amount +- `Boost`: increases downstream pressure or voltage by a balanceable amount + +Concrete flow and consumer states: - `FuelFlowEnabled` - `FuelFlowDisabled` @@ -244,9 +274,38 @@ Concrete prop states: - `ElectricityConsumerEnabled` - `ElectricityConsumerDisabled` +Concrete junction modes: + +- `FuelJunctionNeutral` +- `FuelJunctionThrottle` +- `FuelJunctionBoost` +- `CoolantJunctionNeutral` +- `CoolantJunctionThrottle` +- `CoolantJunctionBoost` +- `ElectricityJunctionNeutral` +- `ElectricityJunctionThrottle` +- `ElectricityJunctionBoost` + +### Consumer State + +Each consumer derives one current service state: + +- `Disabled`: the prop is off, consumes nothing, produces no service, and does not starve. +- `Supplied`: the prop is enabled and receives enough carrier amount plus pressure or voltage. +- `Starved`: the prop is enabled but receives too little carrier amount, pressure, or voltage. +- `Producing`: the prop is supplied this simulation step and its required service is active. + +`Supplied` is the input condition. `Producing` is the output condition used by readiness. + +Required consumer mapping: + +- Fuel consumer: required for reactor fuel path. +- Coolant consumer: required for reactor cooling path. +- Electricity consumer: required for reactor activation path. + ### Level State -The whole level has exactly five states: +The whole level has five states: - `Stable` - `Caution` @@ -256,15 +315,17 @@ The whole level has exactly five states: Meaning: -- `Stable`: all required consumers are fed and no terminal heat path is active. -- `Caution`: one or more required systems are degrading but recovery remains straightforward. +- `Stable`: no terminal path is active and no urgent predicted intervention is required. +- `Caution`: one or more required services are unavailable, a hazard is growing, or reactor heat is concerning but not terminal. - `Critical`: the simulation predicts a loss without near-term intervention. -- `Ready`: the reactor activation prerequisites are met. +- `Ready`: all reactor activation prerequisites are met. - `Lost`: terminal failure has already occurred. +Level state is derived. It is not diffused spatially. + ### Robot State -The robot has exactly four states: +The robot has four states: - `Ready` - `Interacting` @@ -274,64 +335,162 @@ The robot has exactly four states: Meaning: - `Ready`: free to move and act. -- `Interacting`: currently spending an action on a prop or repair. -- `Blocked`: the target move is refused because the destination is blocked or too hazardous. +- `Interacting`: currently spending an action on a prop, repair, or reactor activation. +- `Blocked`: the target move or action was refused because the destination or target is invalid. - `Damaged`: the robot entered or remained in an unresolved hazardous cell. +## Flow Mechanic + +### Sources + +An enabled flow prop is the source for its bound network. + +During the network flow step: + +- `FeedFromOutside[Fuel]` injects fuel amount and fuel pressure. +- `FeedFromOutside[Coolant]` injects coolant amount and coolant pressure. +- `FeedFromOutside[Electricity]` injects electricity amount and voltage. + +The injected source amount and source pressure or voltage are balance constants. A disabled flow prop injects nothing and isolates its bound source cell from outside supply. + +### Propagation + +Carrier amount, pressure, and voltage propagate through connected intact underground cells using deterministic distance falloff. + +For each carrier network: + +- start from every enabled flow prop connected to that carrier +- walk through connected `Intact` and `Leaking` cells of that carrier +- stop at `Absent` cells and blocked or disabled source boundaries +- assign each reached cell the best available incoming carrier amount plus pressure or voltage +- subtract the balance-defined amount falloff and pressure or voltage falloff for each network step from the source +- apply junction modifications when a path crosses a junction +- clamp final values to the balance-defined numeric range + +If multiple sources or paths reach the same cell, the cell uses the best resulting carrier amount and the best resulting pressure or voltage unless a level-specific rule states otherwise. This keeps routing predictable and prevents order-dependent results. + +### Junctions + +A junction is a player-toggleable local modifier for one carrier network. + +Junction modes: + +- `Neutral`: passes pressure or voltage without modification. +- `Throttle`: reduces downstream pressure or voltage by a balanceable amount. +- `Boost`: increases downstream pressure or voltage by a balanceable amount. + +The adjusted value affects downstream cells according to deterministic path traversal. The document intentionally does not define fixed delta numbers; balancing owns those constants. + +Strategic uses: + +- throttle a leaking branch so the leak injects less dangerous material +- boost a long branch so a required consumer becomes supplied +- shift risk from one network area to another when action economy is tight +- temporarily disable a consumer to stop demand while repairing or rerouting + +### Consumers + +An enabled consumer evaluates after network propagation. + +The consumer is supplied if all required balance predicates pass: + +- enough carrier amount reaches the bound underground cell +- enough pressure reaches a fuel or coolant consumer +- enough voltage reaches an electricity consumer +- the bound network path is not isolated by a disabled source or invalid topology + +If supplied, the consumer emits `ConsumeFromNetwork[n]`, removes or reserves the balance-defined demand amount, and produces its required service for this turn. + +If enabled but not supplied, the consumer emits `StarveConsumer[n]`. Starvation blocks readiness and contributes to `Caution` or forecast warnings, but it does not directly cause loss. + +If disabled, the consumer consumes nothing, produces nothing, does not starve, and cannot satisfy readiness. + +### Leaks And Flow Values + +Pressure and voltage make leaks strategically meaningful. + +A leaking underground cell: + +- remains part of network propagation unless a future implementation explicitly introduces broken pipe states +- emits its carrier into the surface cell above during `InjectLeak[n]` +- uses balance-defined leak predicates that can depend on carrier amount, pressure, or voltage +- may inject more severe hazards when pressure or voltage is high + +Repairing a leak changes the underground cell from `Leaking` to `Intact` and stops future injection. It does not clean existing leaked surface fuel, coolant, electricity, or heat. + ## Events That Modify State +`[n]` means one of the three carriers: fuel, coolant, or electricity. + +### Player Actions + +- `Move`: spends one action to move the robot to an adjacent open surface cell. Invalid destinations emit `BlockRobot`. +- `Inspect`: reveals or focuses already-known local state without changing simulation values. +- `InteractFlow[n]`: spends one action to toggle a flow prop between enabled and disabled. +- `InteractConsumer[n]`: spends one action to toggle a consumer prop between enabled and disabled. +- `AdjustJunction[n]`: spends one action to cycle or set a junction between neutral, throttle, and boost. +- `RepairLeak[n]`: spends one action at a reachable leaking network cell to restore it to `Intact`. +- `ActivateReactor`: spends one action at the reactor control site. It wins only if the level is `Ready`; otherwise it reports that the reactor is not ready. + ### Cell And Network Events -- `CreateCellBlock`: changes a surface cell from `Open` to `Blocked`. +- `CreateCellBlock`: changes a surface cell from `Open` to `Blocked`. If the robot occupies the cell, the event must also emit `BlockRobot`, `DamageRobot`, or a scripted displacement event. - `ClearCellBlock`: changes a surface cell from `Blocked` to `Open`. -- `StartLeak[n]`: changes an underground network cell from `Intact` to `Leaking`. -- `RepairLeak[n]`: changes an underground network cell from `Leaking` to `Intact`. -- `InjectLeak[n]`: adds one band of leaked element from a leaking underground cell into the surface cell above. -- `Equalize[n]`: transfers one band of the same element from the higher local band to the lower local band between neighboring cells. -- `HeatTransfer`: transfers one heat band from the hotter cell to the cooler cell. -- `HeatUp[1]`: increases local heat by 1 band-equivalent. -- `HeatUp[2]`: increases local heat by 2 band-equivalents. -- `CoolDown[1]`: decreases local heat by 1 band-equivalent. -- `CoolDown[2]`: decreases local heat by 2 band-equivalents. -- `Short[1]`: electricity and coolant interact, raising heat and discharging electricity. -- `Short[2]`: a stronger version of `Short[1]`. -- `Ignite[1]`: fuel and electricity or fuel and heat interact, raising heat in both participating cells. -- `Ignite[2]`: a stronger version of `Ignite[1]`. -- `ClampBand`: clamps all element and heat values back into `0-29`. - -`[n]` means one of the three carriers: fuel, coolant, or electricity. +- `StartLeak[n]`: changes an underground network cell from `Intact` to `Leaking`. It does not immediately add surface hazard unless the event explicitly also emits `InjectLeak[n]`. +- `RepairLeak[n]`: changes an underground network cell from `Leaking` to `Intact`. Existing surface hazards remain. +- `FeedFromOutside[n]`: writes source carrier amount and pressure or voltage into the connected network according to propagation rules. +- `Equalize[n]`: moves a balance-defined amount of the same leaked surface carrier from a higher-value open cell to a lower-value adjacent open cell. It never crosses blocked edges. +- `InjectLeak[n]`: adds a balance-defined leaked carrier amount from a leaking underground cell into the surface cell above. The amount may depend on local carrier amount, pressure, or voltage. +- `HeatTransfer`: moves a balance-defined heat amount from a hotter open cell to a cooler adjacent open cell. It never crosses blocked edges. +- `HeatUp[1]`: increases local heat by a small balance-defined amount. +- `HeatUp[2]`: increases local heat by a larger balance-defined amount. +- `CoolDown[1]`: decreases local heat by a small balance-defined amount. +- `CoolDown[2]`: decreases local heat by a larger balance-defined amount. +- `Short[1]`: resolves electricity and coolant interaction by raising heat, reducing leaked electricity, and optionally reducing leaked coolant by balance-defined amounts. +- `Short[2]`: stronger short event with larger balance-defined heat and discharge effects. +- `Ignite[1]`: resolves fuel with electricity or fuel with high heat by raising heat and consuming or transforming leaked fuel by balance-defined amounts. +- `Ignite[2]`: stronger ignition event with larger balance-defined heat and fuel effects. +- `ClampValues`: clamps all carrier, pressure, voltage, leaked surface, and heat values to balance-defined ranges. ### Prop Events -- `EnableFlow[n]`: changes a flow prop from `Disabled` to `Enabled`. -- `DisableFlow[n]`: changes a flow prop from `Enabled` to `Disabled`. -- `EnableConsumer[n]`: changes a consumer prop from `Disabled` to `Enabled`. -- `DisableConsumer[n]`: changes a consumer prop from `Enabled` to `Disabled`. -- `FeedFromOutside[n]`: an enabled flow prop pulls supply from the level boundary into its bound network. -- `ConsumeFromNetwork[n]`: an enabled consumer removes one band from its bound network and emits its intended service. -- `StarveConsumer[n]`: a consumer receives too little supply and degrades the level state. +- `EnableFlow[n]`: changes a flow prop from `Disabled` to `Enabled`. Its source participates in the next network propagation step. +- `DisableFlow[n]`: changes a flow prop from `Enabled` to `Disabled`. Its source does not feed the next network propagation step. +- `EnableConsumer[n]`: changes a consumer prop from `Disabled` to `Enabled`. It can consume, starve, and satisfy readiness during the next simulation step. +- `DisableConsumer[n]`: changes a consumer prop from `Enabled` to `Disabled`. It stops consuming and starving, but also stops satisfying readiness. +- `SetJunctionNeutral[n]`: sets a junction to pass pressure or voltage unchanged. +- `SetJunctionThrottle[n]`: sets a junction to reduce downstream pressure or voltage by a balance-defined amount. +- `SetJunctionBoost[n]`: sets a junction to increase downstream pressure or voltage by a balance-defined amount. +- `ConsumeFromNetwork[n]`: an enabled and supplied consumer removes or reserves demand and emits service for the turn. +- `StarveConsumer[n]`: an enabled but unsupplied consumer emits a visible warning and blocks readiness. It does not directly emit `LoseLevel`. ### Level Events -- `EscalateLevel`: `Stable -> Caution -> Critical`, and `Ready -> Caution` if readiness is lost. -- `RecoverLevel`: `Critical -> Caution -> Stable`. -- `MarkReady`: `Stable` or `Caution` becomes `Ready` when all activation prerequisites are satisfied. -- `LoseLevel`: `Critical` or `Ready` becomes `Lost` when a terminal rule fires. +- `EscalateLevel`: derives a worse non-terminal state when required service is missing, heat is rising, a terminal forecast is near, or a scripted level condition says the situation is deteriorating. +- `RecoverLevel`: derives a better non-terminal state when required services are restored and terminal forecasts are no longer near. +- `MarkReady`: changes the derived level state to `Ready` when all required consumers are producing service and the reactor area is below terminal conditions. +- `ClearReady`: changes `Ready` back to `Stable`, `Caution`, or `Critical` when any readiness prerequisite is lost before activation. +- `LoseLevel`: changes the level to `Lost` when terminal heat, scripted terminal failure, or explicit unrecoverable conditions fire. +- `ActivateCore`: changes the level to the win state after `ActivateReactor` succeeds while the level is `Ready`. ### Robot Events - `MoveRobot`: moves the robot into a valid neighboring open cell. -- `StartInteraction`: changes `Ready -> Interacting`. -- `FinishInteraction`: changes `Interacting -> Ready`. -- `BlockRobot`: changes `Ready -> Blocked` for the attempted move or action. -- `DamageRobot`: changes `Ready` or `Blocked -> Damaged`. -- `RecoverRobot`: changes `Blocked -> Ready` after the blocking condition is removed. +- `StartInteraction`: changes `Ready` to `Interacting` for the duration of an action. +- `FinishInteraction`: changes `Interacting` to `Ready` after the action resolves. +- `BlockRobot`: changes `Ready` to `Blocked` for the attempted move or action, then returns to `Ready` once the refusal is reported. +- `DamageRobot`: changes `Ready` or `Blocked` to `Damaged` when the robot occupies a cell whose final hazard values exceed robot safety predicates. +- `RecoverRobot`: changes `Damaged` or `Blocked` to `Ready` when recovery rules are satisfied. -## Projection Into The Lookup Matrix +## Condition Table -Not every stored state belongs in the pairwise neighbor table. +The table is a design summary for pair interactions. It is not the authoritative simulation algorithm. -The pairwise table only operates on projected surface fields: +Authoritative logic is defined by numeric predicates and balance constants. The UI may label values as safe, caution, or critical, and those labels may be used to explain forecasts, but implementation must evaluate the underlying numeric values. + +### Projection For Readability + +Projected labels: - `FuelSafe` - `FuelCaution` @@ -348,42 +507,45 @@ The pairwise table only operates on projected surface fields: Projection rules: -- within a single cell, unordered pairs of projected field states use the same lookup table as neighboring cells -- `Blocked` cells do not participate in neighbor lookup across that edge. -- `Leaking` underground cells first emit their carrier into the surface cell above them through `InjectLeak[n]`. -- flow props and consumers act before the neighbor lookup, because they modify underground supply -- level state is derived after the lookup, because it is global rather than local -- robot state is resolved after the lookup, because it reacts to the final local hazard state of its cell - -This keeps the spatial interaction system small while still identifying the full set of cell, prop, level, and robot states. +- labels are derived from balance-defined UI thresholds +- labels do not change stored simulation values +- blocked cells do not participate in neighbor interaction across blocked edges +- leaking underground cells first emit their carrier into the surface cell above them through `InjectLeak[n]` +- flow props, junctions, and consumers act before the local surface interaction pass +- level state is derived after local interactions +- robot state is resolved after local interactions, using final local hazard values ## Simulation Order -The revised simulation loop for one turn is: +The simulation loop for one turn is: 1. Resolve player actions. -2. Apply `FeedFromOutside[n]` for every enabled flow prop. -3. Apply `ConsumeFromNetwork[n]` or `StarveConsumer[n]` for every enabled consumer. -4. Apply `InjectLeak[n]` for every leaking underground cell. -5. For every open cell, evaluate every unordered pair of projected field states inside that same cell. -6. For every open cell, evaluate the current cell against its right neighbor and bottom neighbor. -7. For each pair, read the projected field-state table below and emit the listed event. -8. Apply all emitted deltas. -9. Clamp all values with `ClampBand`. -10. Update robot state from the final local surface cell it occupies. -11. Derive level state from required consumers, reactor prerequisites, and terminal heat conditions. -12. Advance scheduled turn events. +2. Apply scheduled start-of-turn events that explicitly occur before flow. +3. Apply `FeedFromOutside[n]` for every enabled flow prop. +4. Propagate carrier amount plus pressure or voltage through each underground network using distance falloff and junction modifiers. +5. Apply `ConsumeFromNetwork[n]` or `StarveConsumer[n]` for every enabled consumer. +6. Apply `InjectLeak[n]` for every leaking underground cell. +7. For every open cell, evaluate local numeric predicates between leaked surface values and heat. +8. For every open cell, evaluate numeric predicates against its right neighbor and bottom neighbor. +9. Emit the corresponding interaction events from the condition table summary. +10. Apply all emitted deltas in a deterministic order. +11. Clamp all values with `ClampValues`. +12. Update robot state from the final local surface cell it occupies. +13. Derive level state from required services, reactor prerequisites, forecasts, and terminal conditions. +14. Advance scheduled turn events. -## Pair Lookup Event Legend +If multiple events modify the same value in one step, their deltas are accumulated before clamping unless a specific event states that it consumes or reserves a value earlier in the order. -The symmetric lookup matrix uses the following event names: +## Pair Event Legend + +The symmetric condition table uses the following event names: - `Hold`: no direct change. - `FuelFlow`: apply `Equalize[Fuel]`. - `CoolFlow`: apply `Equalize[Coolant]`. - `ChargeFlow`: apply `Equalize[Electricity]`. -- `HeatFlow`: apply `HeatTransfer` by 1 band. -- `HeatFlow2`: apply `HeatTransfer` by 2 bands. +- `HeatFlow`: apply `HeatTransfer` with normal magnitude. +- `HeatFlow2`: apply `HeatTransfer` with stronger magnitude. - `Warm1`: apply `HeatUp[1]` to the fuel-owning side. - `Warm2`: apply `HeatUp[2]` to the fuel-owning side. - `Quench1`: apply `CoolDown[1]` to the heat-owning side. @@ -399,11 +561,11 @@ Design intent: - coolant only becomes dangerous through electricity - coolant opposes heat - heat equalizes between neighboring cells -- same-carrier amounts equalize between neighboring cells +- same-carrier leaked surface amounts equalize between neighboring cells -## Symmetric Pair Lookup Table +## Symmetric Pair Condition Table -Rows and columns are identical projected field states. Only the upper-right triangle is filled. The lower-left triangle is intentionally empty because the table is symmetric. +Rows and columns are identical projected UI labels. Only the upper-right triangle is filled. The lower-left triangle is intentionally empty because the table is symmetric. | Row\Col | FuelSafe | FuelCaution | FuelCritical | CoolantSafe | CoolantCaution | CoolantCritical | ElectricitySafe | ElectricityCaution | ElectricityCritical | HeatSafe | HeatCaution | HeatCritical | | ------- | -------- | ----------- | ------------ | ----------- | -------------- | --------------- | --------------- | ------------------ | ------------------- | -------- | ----------- | ------------ | @@ -422,24 +584,26 @@ Rows and columns are identical projected field states. Only the upper-right tria ## Prop Rules -Props do not appear in the neighbor table. They are local vertical controls on top of the underground layers. +Props do not appear as participants in the pair condition table. They are local vertical controls on top of the underground layers. Flow prop rule: -- if enabled, the prop allows `FeedFromOutside[n]` or onward transport through its bound network -- if disabled, its bound network path is isolated at that cell +- if enabled, the prop allows `FeedFromOutside[n]` +- if disabled, its bound source does not inject supply + +Junction prop rule: + +- if neutral, the prop does not change pressure or voltage +- if throttling, it reduces downstream pressure or voltage +- if boosting, it increases downstream pressure or voltage +- the adjustment amount is a balance constant Consumer prop rule: -- if enabled and supplied, it consumes one band and produces its service +- if enabled and supplied, it consumes demand and produces service - if enabled and unsupplied, it triggers `StarveConsumer[n]` -- if disabled, it neither consumes nor produces - -Required consumer mapping: - -- Fuel consumer: required for reactor fuel path -- Coolant consumer: required for reactor cooling path -- Electricity consumer: required for reactor activation path +- if disabled, it neither consumes, produces, nor starves +- a disabled required consumer blocks readiness ## Robot Rules @@ -447,21 +611,36 @@ The robot is intentionally simple. - The robot moves only on the surface. - The robot can occupy only `Open` cells. -- A move into a cell that resolves to `HeatCritical` changes the robot to `Damaged`. - A move into a blocked or forbidden cell changes the robot to `Blocked`. -- Interacting with a prop or repairing a leak changes the robot to `Interacting` until the action resolves. +- A move into or continued presence in a cell whose final hazard values exceed robot safety predicates changes the robot to `Damaged`. +- Interacting with a prop, repairing a leak, or activating the reactor changes the robot to `Interacting` until the action resolves. +- Robot safety predicates are balance data. The design does not require them to match UI band thresholds exactly. ## Level Rules -Level state is derived, not spatially diffused. +Level state is derived after each simulation step. -Suggested derivation: +Derivation: -- `Stable`: all required consumers supplied and no reactor-adjacent `HeatCritical` -- `Caution`: at least one required consumer is unstable or one reactor-adjacent cell is `HeatCaution` -- `Critical`: any required consumer is starved for too long or any reactor-adjacent cell is `HeatCritical` -- `Ready`: all required consumers supplied and the reactor area is not `HeatCritical` -- `Lost`: a scripted terminal rule or unrecoverable reactor heat condition fires +- `Stable`: no terminal forecast is near, reactor heat is controlled, and the facility is not actively degrading. +- `Caution`: at least one required service is missing, a required consumer is starved or disabled, a hazard is growing, or reactor-adjacent heat is concerning. +- `Critical`: forecasts predict terminal loss without near-term intervention, or reactor heat is close to terminal. +- `Ready`: all required consumers are producing service and the reactor area is below terminal conditions. +- `Lost`: a scripted terminal rule, terminal reactor heat condition, or explicit unrecoverable state fires. + +`Ready` is reversible before activation. If a required consumer is disabled, starved, disconnected, or no longer producing service, `ClearReady` derives the appropriate non-ready state. + +## Strategic Interactions + +The flow mechanic should create tactical decisions without hidden information. + +Examples: + +- A fuel leak on a high-pressure branch may be made safer by throttling the branch, but throttling may starve the fuel consumer and block readiness. +- A distant coolant consumer may need boosted pressure, but boosting that path can make an unrepaired coolant leak produce more surface coolant. +- An electricity boost can satisfy activation requirements while increasing the danger of nearby coolant leaks. +- Disabling a consumer can stop demand while the player repairs or reroutes, but it also prevents the level from becoming `Ready`. +- Repairing a leak stops future injection, but existing leaked material remains a local problem until simulation effects disperse, cool, ignite, discharge, or otherwise resolve it. ## Design Pillars @@ -471,7 +650,7 @@ The same actions in the same state always produce the same result. ### Visible Consequences -The player sees both the local field bands and the global state they imply. +The player sees exact local values, UI labels, global state, and forecasted consequences. ### Meaningful Tradeoffs @@ -481,23 +660,44 @@ Turning one network on may feed a required consumer while making a leak more dan The simulation should be explainable as: -- underground network structure +- underground network topology +- numeric pressure and voltage flow - surface leaks -- one shared threshold system -- one pairwise lookup table +- deterministic local interaction predicates +- derived global level state ### Extensible Later -The current code and earlier design are treated as a prototype. This reduced model is the new formal core. More mechanics can be added later only if they preserve table-driven readability. +The current code and earlier design are treated as a prototype. This reduced model is the new formal core. More mechanics can be added later only if they preserve deterministic readability and forecastability. + +## Remaining Design Gaps + +No implementation-blocking design gaps are intentionally left open. + +The following values are deliberately assigned to balancing rather than fixed in this document: + +- source strengths +- pressure and voltage falloff +- junction throttle and boost deltas +- consumer demand predicates +- leak injection magnitudes +- local interaction magnitudes +- UI safe/caution/critical thresholds +- robot safety thresholds +- terminal heat thresholds +- action costs beyond the default one-action rule + +Implementation should expose these as balance data and tests should assert behavior against configured constants rather than hardcoded design numbers. ## Summary -The revised design reduces the simulation to a small layered system: +The design reduces the simulation to a small layered system: - three disjunct underground networks -- two prop types per network -- one shared threshold model -- one projected surface interaction table +- exact numeric carrier, pressure, voltage, leak, and heat values +- flow, consumer, and junction props +- UI bands as labels rather than simulation truth +- one deterministic condition table summary backed by numeric predicates - one derived global level state -That gives a solid basis for a deterministic simulation that can be visualized, forecast, and extended without reintroducing hidden complexity. +That gives a solid basis for a deterministic simulation that can be visualized, forecast, balanced, and extended without reintroducing hidden complexity.