Repository navigation
Environment and Economy
Note
Design stage. This page describes planned mechanics from the design document. Not implemented yet — see Roadmap (milestone M13 for ecology and economy; oil spills and spill response arrive with M10).
Industries are linked by products; this page links them by consequences and price. A coal plant in era I1 is cheap but dirty: haze, yellowing leaves, coughing, acid rain, faster corrosion of tanks. Electrostatic precipitators, flue-gas desulfurization and SCR fix that, but cost grid power, reagents and spare parts. From era I2, CO₂ quotas make nuclear power economically attractive. A commodity exchange sets prices but is not a money printer: with elastic demand, revenue grows slower than volume.
This section owns the sim.environment and sim.economy packages (EmissionLedger, Market, Contract) and the pc_market peripheral.
-
Units: masses in kg, rates in kg/s, concentrations in kg/m³ (HMI shows µg/m³ in air, mg/Nm³ at reference O₂ in the stack). Currency is the credit
CR, stored as integer hundredths. - Time: accounting, pollution, market and contracts run in SLOW (×72). A "day" is a game day = physical day = 20 real minutes.
-
CO₂ equivalent:
m_CO2e = m_CO2 + 28 · m_CH4(IPCC AR5 GWP-100,env.gwp_ch4). N₂O and refrigerants are not modelled. - Point of oxidation: carbon is counted where it oxidizes to CO₂ — blast furnace gas burnt in a boiler is the boiler's emission, not the furnace's.
| Substance | Sources | Local effect | Global accounting |
|---|---|---|---|
SO2 |
combustion, Claus tail gas, flares with H₂S | health, plants, acid rain, corrosion | fee |
NOX (as NO₂) |
combustion, engines, gas turbines | plants, acid rain | fee |
PM (PM₁₀) |
ash after cleaning, coke plant, blast furnace, diesel soot | haze, health | fee |
CO2 |
combustion, flares, FGD, converter | none (well mixed) | quotas |
CH4 |
flare unburnt, oil and gas leaks, mine ventilation | none | quotas ×28 |
CO, H2S
|
incomplete combustion, vents, leaks | none (emergencies are Operations and Safety) | log |
VOC |
spill evaporation, tank breathing | smog (backlog) | fee |
Source categories: BOILER, GAS_TURBINE, ENGINE, FLARE (98 % combustion efficiency, 90 % in high wind), COKE_OVEN, BLAST_FURNACE, REFINERY, FUGITIVE, SPILL, PROCESS (CO₂ from FGD and calcination).
Each organized source is the outlet of a chimney with stack height, diameter, exit velocity and temperature. Plume rise uses the Briggs formulas. Example: 2 m stack diameter, 10 m/s, 423 K exit, 293 K air, 5 m/s wind → 55.1 m rise, effective height 85.1 m on a 30 m stack. Wet FGD cools the gas to ≈ 325 K, cutting buoyancy threefold and plume rise in half — so stacks after FGD are built taller (gas reheating is backlog). Fugitive and spill sources emit at ground level.
Emission factors for sources without a combustion model (datapack data/promptcritical/emission_factors/*.json):
| Source | PM | SO₂ | NOx | CO₂ / CH₄ |
|---|---|---|---|---|
| Coke battery, per t coke | 0.5 kg | 1.0 kg (no coke-oven gas desulfurization) | 0.4 kg | counted at the gas consumer |
| Blast furnace and cast house, per t iron | 0.3 kg | 0.1 kg | 0.05 kg | BF gas through a bleeder: CO + CO₂ |
| Converter, per t steel | 0.15 kg (after gas cleaning) | — | — | CO₂ from converter gas combustion |
| Open coal stockpile, per t·day | 0.01 kg when wind > 5 m/s | — | — | — |
| Mine ventilation | — | — | — | CH₄ = airflow × concentration |
Reporting method multiplies quotas and fees (not physical pollution):
| Method | Condition | Multiplier |
|---|---|---|
MEASURED |
working, calibrated cems_analyzer on the stack |
1.0 |
CALCULATED |
no analyzer; mass from the model | 1.2 (env.calculated_method_factor) |
SUBSTITUTED |
analyzer faulty or uncalibrated for more than a day | 1.5 |
As in real reporting, an unmeasured source reports conservatively — so stack monitoring pays for itself.
furnace → [SCR 593–673 K] → air heater → [ESP | baghouse] → ID fan → [wet FGD] → chimney
The duct is built from flue_duct blocks: a chain of devices sharing the gas flow, each changing the flue-gas state and adding resistance for the induced_draft_fan. A wrong order (SCR after FGD at 325 K) is not blocked — the device simply does nothing, visible on the stack monitor. All cleaning devices draw grid power or Create rotation. Without power, cleaning stops but the boiler keeps running: an environmental failure, not a process trip, with a P3 "CLEANING NOT RUNNING" alarm and a log entry.
| Device | Model | Key numbers |
|---|---|---|
electrostatic_precipitator |
Deutsch–Anderson: η = 1 − exp(−wA/Q) | migration velocity 0.10 m/s (halved for low-sulfur, high-resistivity ash); 5000 m² at 100 m³/s → 99.33 %; ≈ 0.2 kWh per 1000 m³; collected fly_ash goes to cement and concrete |
baghouse_filter |
η 0.997 (0.999 with PTFE bags) almost regardless of ash | pressure drop grows with dust cake; a compressed-air pulse at 1.5 kPa cleans it; filter_bag polyester up to 408 K, PTFE up to 533 K; overheated bags burn through (η → 0.5, maintenance panel "burnt bags") |
fgd_absorber |
limestone slurry: CaCO₃ + SO₂ + ½O₂ + 2H₂O → CaSO₄·2H₂O + CO₂ | per kg SO₂: 1.562 kg limestone × Ca/S 1.05, 2.687 kg fgd_gypsum, 0.687 kg CO₂. At L/G 15 L/m³ and pH 5.6 → 95 %. You control pH by limestone dosing on a PLC; below 4.5 removal drops, above 6.2 nozzles scale. Pumps and oxidation air ≈ 1 % of boiler output |
scr_reactor |
catalyst_denox (V₂O₅–WO₃/TiO₂) + ammonia injection |
η = 0.90 × activity × min(1, NH₃/NOx) × temperature window (593–673 K); activity −1 % per 10 physical days; slip below 573 K with SO₃ forms ammonium bisulfate in the air heater. Ammonia comes from chemistry (I3) — before that only low-NOx burners |
cems_analyzer |
stack monitor: SO₂, NOx, CO, O₂, dust, flow | noise, drift and calibration like any analyzer |
Limestone is create:limestone or vanilla calcite (tag c:limestone), milled in Create to limestone_powder. Gypsum goes to cement (5 % set retarder) and decor.
Emission limit values (order of EU Directive 2010/75 for large boilers, env.elv.*):
| Fuel | SO₂ | NOx | Dust, mg/Nm³ |
|---|---|---|---|
| Solid (6 % O₂) | 400 | 300 | 30 |
| Liquid (3 % O₂) | 350 | 300 | 30 |
| Gas (3 % O₂) | 35 | 150 | 5 |
An uncleaned gas-coal boiler emits ≈ 3490 mg/Nm³ SO₂ and ≈ 800 mg/Nm³ NOx — 9× and 2.7× the limits.
Pollution accumulation in chunks is borrowed from GregTech: New Horizons, made more physical. Two layers with different lifetimes:
| Layer | What | Physics | Lifetime | Drives |
|---|---|---|---|---|
| A. Ground concentration | air at ground level per chunk for SO₂, NOx, PM | Gaussian plume from current emissions, quasi-steady | seconds (wind flushes a chunk in 16/u s) | haze, coughing, rain pH |
| B. Accumulated load | deposited sulfur, nitrogen, dust on leaves, soil, roofs | dry and wet deposition from layer A, spread to neighbours, cleanup | hours to days | withering, block damage, corrosion |
CO₂ and CH₄ have no local layers — only quotas.
Layer A uses the Pasquill–Gifford plume with ground reflection and neutral (class D) stability. Distances are compressed: x_phys = x_game / 0.05 (env.plume_distance_scale), so the concentration maximum of an 85 m effective stack moves from ≈ 2 km to ≈ 100 m (≈ 6 chunks), while concentration values are unchanged. The kernel covers 17×17 chunks around the stack (radius 8) and is recomputed when wind turns more than 22.5° or changes more than 20 %. Example: 55.74 g/s SO₂ at 5 m/s and 85 m effective height gives a 148 µg/m³ peak — 3.7× the WHO daily guideline, typical near an uncleaned coal plant.
Layer B balances deposition, cleanup and spreading per chunk:
| Parameter | Value |
|---|---|
| Dry deposition velocity | SO₂ 0.008, NO₂ 0.003, PM₁₀ 0.010 m/s |
| Rain washout | SO₂ 5·10⁻⁵, NO₂ 2·10⁻⁵, PM 1·10⁻⁴ s⁻¹ |
| Mixing height | 500 m |
| Background cleanup | 1/(24 h) |
| Rain cleanup | 1/(6 h) |
| Vegetation cleanup | 1/(12 h) × fraction of live leaves and grass |
| Spread to 4 neighbours | 1/(4 h), biased ±50 % with the wind |
withered_leaves do not count as vegetation — a dead forest stops cleaning the air and the load climbs faster. Far from sources, load falls to 2/3 per chunk (halves every 1.7 chunks). Calibration target: a 50 MW(th) gas-coal boiler (1.5 % S), 30 m stack, no cleaning → acid load index Φ ≈ 2.5 in the peak chunk after one game day; with ESP and FGD Φ < 0.3.
The field is a sparse grid in pc-sim (not a chunk data attachment), because plumes fall on unloaded chunks too. It is saved as dimension SavedData promptcritical:pollution, updated every 10 real seconds (720 s physical), at most 4096 cells per dimension (weakest cells merge into 8×8-chunk regions that only decay). When a chunk reloads, missed effects are caught up in at most 6 steps. Deposition passes through the territory ContaminationPolicy: the disallowed share is redirected so the "dirt" stays with the polluter (Multiplayer).
Acid load index: Φ = (2·D_S/64 + D_N/46) / 0.1 meq/m². Rain pH comes from the 6-hour average of layer A: clean rain is pH 5.6; 100 µg/m³ SO₂ gives pH 4.2.
| Level | Enters at (exits at 0.8×) | Effect |
|---|---|---|
| L1 Haze | PM ≥ 45 µg/m³ (WHO 2021, 24 h) | client fog with Koschmieder visibility (not below 24 m), greyish sky, particles |
| L1+ Smog | PM ≥ 150 or SO₂ ≥ 350 µg/m³ | yellow-grey fog, dim sun |
| L2 Withering | Φ ≥ 1 or daily SO₂ ≥ 30 µg/m³ | crop and sapling growth slowed by 1/(1+Φ); leaves turn to withered_leaves
|
| L3 Coughing | SO₂ ≥ 500 (WHO 10 min) or PM ≥ 150 µg/m³ |
smog_cough: cough sound, −15 % speed for 1 s every 20–40 s |
| L3+ Weakness | SO₂ ≥ 2620 (1 ppm) or PM ≥ 500 µg/m³ |
smog_cough + Weakness I, sprinting interrupted |
| L4 Acid rain | raining and pH ≤ 4.5 | leaf damage ×3; crops lose a growth stage (5 % per check); copper blocks oxidize faster |
Protection: the radiological respirator against particles, gas_mask with an E filter against SO₂ and NOx, scba against everything.
| Effect | realistic |
contained |
creative_safe |
|---|---|---|---|
| Fields, monitoring, accounting, quotas | yes | yes | yes |
| Haze and smog (client) | yes | yes | yes |
| Coughing and weakness | yes | only from sources allowed in that chunk | no |
| Leaf and crop withering, acid rain on blocks | yes, via DamageBudget
|
only on the source team's territory | no |
| Equipment corrosion | yes | yes, own equipment only | no |
| Compensation to affected teams | yes | — | — |
Block changes go through DamageBudget as cosmetic CORROSION requests, with a cap of 64 block effects per chunk per day (env.max_block_effects_per_chunk_per_day) and the #promptcritical:damage_immune tag. withered_leaves recover after a day at Φ < 0.2.
Atmospheric corrosion. Outdoor steel (tanks, pipelines, towers) gets extra corrosion from the ISO 9223 dose–response function: 20 mg/(m²·day) SO₂ deposition at 75 % RH and 15 °C → 28.7 µm/year (category C3). Near the reference boiler stack (≈ 100 mg/(m²·day)) it is ≈ 66 µm/year, +25 % on the base 0.25 mm/year used for thickness surveys. Coastal biomes add chloride. Vanilla copper blocks get extra oxidation attempts.
Up to 64 oil blocks on land and up to 256 oil_slick blocks on water are placed in the world; the rest of the spill is tracked as a SpillRecord with real area, thickness and mass. Shoreline oil is stored in a ShoreOilMap (4×4×4 cells).
-
Spreading on water follows Fay's three regimes (gravity-inertia, gravity-viscous, surface tension), with maximum area
A_max = 10⁵·V^(3/4)m². Wind drifts the slick at 3 % of wind speed; rivers carry it at 0.5 m/s. Example: 10 m³ of 850 kg/m³ oil on fresh water after 1 h → radius 81.7 m, area 2.1·10⁴ m², thickness 0.48 mm. - Evaporation and weathering (Fingas): evaporated percent grows with ln(t) depending on the fraction boiling below 180 °C from the crude assay; 30 % light fraction at 15 °C → 36 % evaporated in 24 h. Evaporated mass is counted as VOC. The residue emulsifies into "chocolate mousse" with up to 70 % water after a day, so skimmers recover more water than oil.
| Response tool | Model | Limits |
|---|---|---|
oil_boom + boom_anchor
|
floating barrier: slick blocks cannot cross the boom line | holds while normal current speed ≤ 0.35 m/s; on a 0.5 m/s river set the boom at ≤ 44.4° or oil escapes under the skirt |
oil_skimmer (oleophilic drum on a Create shaft) |
efficiency = h/(h + 2 mm) | thin slicks recover poorly (0.48 mm → 19 %), so boom first to thicken; recovered oil goes to a recovered_oil tank and back to the refinery |
sorbent_pad (polypropylene) |
15 kg oil per kg sorbent | becomes oiled_sorbent waste, burnt in a boiler (emissions counted) |
| Shoreline cleanup | shovel + sorbent on oiled_sand / oiled_gravel; hot-water shore_washer is backlog |
natural weathering half-life 30 days |
Sand and gravel above 0.5 kg/m² become oiled_sand / oiled_gravel through DamageBudget. The spill fee is charged on unrecovered oil after one physical day, so fast response pays off.
Tailings and reclamation (backlog, M15). tailings_dam holds drilling mud, mill tailings and uranium tailings; slope failure (factor of safety < 1) breaches through DamageBudget; without a polyethylene pond_liner the pond contaminates nearby water. Reclamation refunds 50 % of waste fees. Trees give no CO₂ credits (no sapling farms), but they do raise the vegetation cleanup of layer B.
Commodities are whitelisted IDs or c: tags with a unit (t, m³, Nm³, MWh, TBq, t CO₂), defined in data/promptcritical/market/commodities/*.json. Vanilla blocks and farmable goods (cobblestone, mob drops) are not accepted.
| Field | Meaning |
|---|---|
id, unit, basePrice
|
identifier, unit, starting price in CR |
minEpoch |
NPCs sell to a team only after it reached this era — no skipping eras through NPCs; player-to-player trade is allowed |
npcBuy, npcSell
|
NPC buys / sells |
depth, elasticity
|
market depth (units/day at base price) and demand elasticity |
volatility, reversion, trend
|
price process parameters |
perishable |
NONE or DECAY(nuclide) — value proportional to current activity |
restricted |
fissile material and category 1–2 sources: NPCs never trade them |
Price is a trend times seasonal factor times a mean-reverting (Ornstein–Uhlenbeck) log deviation (Schwartz one-factor model): reversion 1/(3 days), stationary deviation 10 %, seasonality for fuel oil, coal and gas. The random generator is seeded from the world. Electricity is priced separately.
Elastic demand. NPC markets remember your recent sales volume (decaying over 2 days). The marginal price falls as p(V) = p·(1 + V/D)^(−1/ε). With ε < 1, revenue from an arbitrarily large batch is capped at p·D·ε/(1−ε). Isotopes, RTG fuel and rare products have ε = 0.5; bulk raw materials and fuels ε = 2–4 with large depth. Example: price 100, depth 10, ε = 0.5, selling 10 units earns 500, not 1000 (cap 1000); at ε = 2 it earns 828.4. Buying from NPCs mirrors this plus a 4 % spread, so buy-and-resell always loses.
Perishable goods. For decaying isotopes the price is proportional to activity at delivery; below 25 % of spec the batch is refused. A Mo-99 tc99m_generator (half-life 65.94 physical hours = 55 real minutes) is worth 0.220 of its starting price after 2 real hours — Create logistics (trains) becomes part of the economy.
Electricity is settled from energy_meter readings at the station boundary per game hour, at an hourly price following the dispatcher load forecast (market.power_peak_factor = 1.5). Unserved energy and quality penalties are detected by the grid and charged here (Energy Grid).
| Type | Parties | Security | Penalty |
|---|---|---|---|
SPOT |
player ↔ NPC | — | — |
SUPPLY (forward) |
player ↔ NPC at a price fixed at signing; player ↔ player | supplier deposit 20 % of the period value (market.contract_margin), buyer's money in escrow |
0.2 × price × shortfall per period + 1 %/day late fee, capped at the deposit |
POWER_BLOCK |
player ↔ NPC grid, player ↔ player (connected islands) | as SUPPLY
|
imbalance price ±25 % (shortfall costs more, surplus pays less) |
ALLOWANCE_SWAP |
player ↔ player | escrowed allowances | — |
Delivery is physical: items and fluids go into a trade_depot (inventory, fluid port, Create funnels and trains); energy by meter. Contract states: PROPOSED → ACTIVE → CLOSED, CANCELLED, or DEFAULTED after three consecutive periods below 50 % (deposit goes to the buyer). Contracts within your own team are refused (E_SAME_TEAM). If the owner is offline and the station frozen, obligations pause (market.offline_force_majeure).
Cap and trade starts when a team reaches era I2 (env.co2_quota_start_epoch); eras I0–I1 teach engineering, not bookkeeping. A period is 7 game days. Free allocation starts at the first full period's emissions and shrinks 5 % per period. At period end you surrender allowances for CO₂e × reporting multiplier. Surplus carries over and can be sold as co2_allowance; a deficit costs 100 CR/t (modelled on EU ETS €100/t) and is added to next period's obligation.
Example: 1000 t allocated, 1150 t CO₂ + 2 t CH₄ emitted, method CALCULATED → (1150 + 56) × 1.2 = 1447.2 t; deficit 447.2 t → 44,720 CR fine plus 447.2 t carried over.
Nuclear, hydro and renewables use no allowances. Moving to nuclear in era I4 pays twice: no allowances to buy, and surplus to sell — the intended economic incentive.
| Fee | Base | Rate | Surcharge |
|---|---|---|---|
| SO₂, NOx, PM, VOC | kg per period × reporting multiplier | 0.5, 0.5, 1.0, 0.3 CR/kg | ×5 on mass emitted above the stack limit |
| Oil spill | t unrecovered after a day | 500 CR/t | +20 CR per m² of oiled shore |
| Thermal discharge | water body ΔT exceedance | 10 CR/(K·day) | — |
Compensation (realistic) |
blocks on another team's territory changed by pollution | 20 CR per block, paid to the affected team | — |
All rates are visible in pc_market.getFees() and the period report. In creative_safe fees are computed and shown but not charged.
The credit CR is a team account record (SavedData promptcritical:market), with no coin item and no link to real money. Optional exchange to Create: Numismatics coins through a market_terminal is backlog.
| Threat | Countermeasure |
|---|---|
| infinite sale of one good | elastic demand; daily revenue cap 50,000 CR per team |
| buy-from-NPC, sell-to-NPC arbitrage | 4 % spread and mirrored price impact |
| price manipulation through own trades | player-to-player deals do not move NPC prices |
| contracts with an alt account |
E_SAME_TEAM; teams younger than a day cannot sign SUPPLY
|
| skipping eras by buying |
minEpoch, restricted
|
| Lua spam | call cost tokens; trade calls cost 8–16 |
| duping and farms | commodity whitelist |
| sapling credits | no offsets |
Trades, contracts, fees and compensation go into the station log (MARKET_TRADE, CONTRACT_STATE, ENV_FEE). market.mode is OFF, NPC_ONLY or FULL (default). TRAINING: prices without noise, fees not charged. HARDCORE: volatility ×1.5, penalties ×2.
Money is a separate balance axis: it never changes physics (energy per kg of uranium, SWU, W_PER_SU) and never sells what the design makes expensive through time and risk. NPC markets do not sell fuel, fuel assemblies, enriched uranium or high-activity sources.
A5 automation task: blending at market prices. The refinery gasoline blending LP becomes a plant-level (A5) optimization: once per game hour a Lua program reads pc_market.getQuote("gasoline:ai95").bid and component opportunity values, plus pc_tank.getBlendData(), solves the simplex and changes the blend recipe. If naphtha gets more expensive, the optimum shifts from reformate to alkylate — real-time optimization (Automation Platform).
| Into this system | Out of it |
|---|---|
| combustion results, stack parameters, flue gas, power for cleaning devices, meters and load forecast (Energy Grid) |
fly_ash and fgd_gypsum → portland cement, concrete, plaster |
| coke plant, blast furnace, mine methane; limestone from Create and vanilla (Coal and Metallurgy) |
recovered_oil → refinery dehydration |
| spills, evaporation, flares, leaks (Oil and Gas, Operations and Safety) | extra corrosion rate for thickness surveys |
ammonia, catalyst_denox, PTFE bags, polypropylene sorbents, polyethylene liners (Petrochemistry) |
energy trading and contracts for the dispatcher |
| isotope activity for perishable pricing (Isotopes and RTG) | A5 blending task |
| team era, station log, roles, territories (Multiplayer) | prices and contracts for every product in the complex |
- Energy Grid — combustion model, consumers, dispatcher
- Oil and Gas — flaring, tanks, spills
- Operations and Safety — flare system, PPE, thickness surveys
-
Multiplayer — server modes,
DamageBudget, territory policy, economy balance - Radiation Safety — the radioactive contamination map this design mirrors
Prompt Critical · © 2026 denfry · Repository · Report an issue
Start here
Design
Nuclear
Industries
Control and automation
World and server
Development