Skip to content

Environment and Economy

denfry edited this page Oct 13, 2026 · 1 revision

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.

Conventions

  • 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.

Emissions ledger

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.

Flue gas cleaning

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.

Chunk-based pollution

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).

Effects of pollution

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.

Oil spills (M10)

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.

Commodity exchange

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).

Contracts

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).

CO₂ quotas and environmental fees

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.

Currency, anti-exploit and modes

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).

Cross-industry links

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

See also

Clone this wiki locally