Skip to content

Plants

Each plant is a specimen with a size, a condition and a bank. Light drives everything it earns — the photosynthetic rate and every benefit channel run through the same saturating PAR curve — while upkeep is charged in all twenty-four hours. What income and damage leave banks, and the bank is spent on repair first and new tissue second.

Mechanic Status Why
Photosynthesis on PAR settled Jassby–Platt tanh(PAR/Ik), evaluated per plant against its own saturating irradiance.
Carbon–oxygen exchange settled One yield, run both ways. Respiration releases the carbon photosynthesis fixed, and the oxygen derives from it at the molar mass ratio rather than from a second constant.
Respiration settled Runs 24/7 on Q10 × Monod, so a plant in suffocating water respires slower and releases proportionally less carbon.
The two ledgers settled Energy deficits are paid in tissue, environmental damage in condition. A starving plant shrinks and survives.
The surplus bank settled One bank, two claims, in an order: upkeep spends it to the last unit, damage and growth only what stands above the survival ration.
Shedding settled A rate reading a rate — the share of the upkeep bill left standing, with no threshold in it.
Nutrition scaffolding The weakest thing in the engine. Sufficiency is min(1, ppm/required) against a per-tier required/booster split, so a low-demand species is completely indifferent to potassium and iron, and the maintenance share of uptake is a magic number inline in the photosynthesis module.
Carbon limitation scaffolding co2Factor is a hard linear ramp to optimalCo2, so a low-tech tank runs the rate at a fifth. It reaches photosynthesis and uptake only — plant health reads carbon through the tolerance band instead, which is why low-tech plantings thrive anyway.
Tolerance-band benefits scaffolding A step. Crossing an edge on CO₂, temperature or pH loses the whole channel at once and starts damage.
Photoperiod gates scaffolding Three switches on light > 0: the light-low stressor, the CO₂-low stressor, and surplus accrual. A carbon-starved plant swings between 0 and full damage as the lamp flips while its benefits ramp smoothly.
Size against maxSize scaffolding The ceiling is 600–1100 across the roster and the asymptotic factor stays above 0.9 through any calibration window, so it does not bind. Trimming validates a target in [0, 100] against it.
Propagation missing A plant with nowhere left to grow banks its whole income and nothing spends it. No runners, no daughter plants — the only way a plant enters the tank is the keeper putting one there.
General hardness missing Ca/Mg is absent from the engine, so a species’ nutrition reads four nutrients and never the water’s hardness.
Species Tolerable PAR Saturates at Nutrient demand Hardiness Substrate
Anubias 8–70 16 low 0.75 attaches
Java Fern 10–90 20 low 0.7 attaches
Amazon Sword 20–120 40 medium 0.5 sand
Dwarf Hairgrass 25–200 50 high 0.3 aqua soil
Monte Carlo 30–200 60 high 0.3 aqua soil

Saturating irradiance is derived, not declared: saturationIrradianceFactor × tolerableLight[0]. One number therefore carries both light channels, and a plant sitting at the bottom of its band runs at 46 % of its rate while the light-insufficient stressor charges it.

lightResponse_i = tanh(PAR / Ik_i)
potential_i = (size_i / 100) × co2Factor × lightResponse_i
actual_i = potential_i × sufficiency_i

Actual — the Liebig-gated rate — drives the gases and the bulk of nutrient uptake; potential adds the maintenance draw underneath it. Both are summed across the planting and multiplied by basePhotosynthesisRate to give the tank’s rate in rate units, where one unit is an hour of 100 % plant size at full carbon and saturating light.

Photosynthesis emits resource effects only. It never adds size directly: growth flows through the bank, so nutrient health reaches biomass once, through the deficiency stressor, and is never counted twice.

Direction Carbon Oxygen
Photosynthesis actual × co2PerRateUnit, clamped to the dissolved mass derived from the carbon fixed, at CO2_TO_O2_MASS_RATIO
Respiration baseRespirationRate × (size/100) × warmth × air, then × co2PerRateUnit derived from the carbon released, same ratio

One reaction run both ways, so one yield. The day/night asymmetry lives entirely in baseRespirationRate, and the oxygen partner is not a second knob. A carbon-starved tank stops producing oxygen because there was no carbon to pay for it.

Respiration is quoted against the light-saturated rate at ambient carbon, which is a fifth of the rate at optimalCo2. A planting under a fixture too dim to clear that respires more than it fixes and draws oxygen with the lamps on.

Stock Fills it Drains it Unit
size Surplus converted to tissue, scaled by species growth rate and the asymptotic factor Shedding against an unpaid upkeep bill; trimming %, where 100 is a full specimen
condition Repair, withdrawn from the bank during the photoperiod Stressor damage the bank could not buffer %
surplus Income left after upkeep and damage, while the lights are on Unpaid upkeep, buffered damage, repair, growth bank units, capped at surplusCap
oxygen Photosynthesis Respiration mg/L
co2 Respiration Photosynthesis, clamped to what is dissolved mg/L
nitrate · phosphate · potassium · iron Dosing; nitrification for NO₃ and decay for PO₄, elsewhere Uptake at the gated rate plus the maintenance fraction of potential, split by the fertilizer ratio mg
waste Shed tissue and plant death Mineralization, elsewhere g

A bank unit is a condition point — the bank accrues out of the same %/h the condition deficit is measured in, which is what lets one number pay for both.

Sufficiency is a Liebig floor over the nutrients a species actually requires, and the tier decides which those are.

Demand tier Required Boosters Threshold
Low NO₃ PO₄, K, Fe 30 % of optimal
Medium NO₃, PO₄ K, Fe 60 % of optimal
High NO₃, PO₄, K, Fe 100 % of optimal

A missing required nutrient caps sufficiency. A booster reads 1.0 whether it is there or not, so it has no effect in either direction — a low-demand species is entirely indifferent to potassium and iron.

Uptake is Liebig-gated with a floor under it. A plant draws (actual + 0.2 × potential) × nutrientsPerPhotosynthesis and splits it across the four nutrients by the fertilizer formula’s own ratio. Since actual is potential already multiplied by sufficiency, a starved potassium drops the draw on nitrogen and phosphate to the 0.2 maintenance fraction — a sixth of what the same planting takes at full sufficiency — rather than ending it, so the water column keeps falling while growth is capped. The consequence to know: because uptake reads the same ratio the doser meters by, dosing cannot correct an imbalance it did not create.

Every benefit channel is realised through photosynthesis, so all four are multiplied by the same light term rather than standing beside it. Good water is worth nothing at midnight.

Channel Earns when At saturating light
CO₂ inside tolerableCO2 co2BenefitPeak
Temperature inside tolerableTemp temperatureBenefitPeak
pH inside tolerablePH phBenefitPeak
Nutrients scales linearly with sufficiency nutrientBenefitPeak × sufficiency

Against that income sits upkeep, charged every hour at upkeepCost × q10(temperature) — the same Q10 the gas layer’s respiration runs on, so a warm blackout kills faster than a cool one. The two together set a compensation point: a hardiness-0.3 species breaks even at 10.5 % of its own Ik, which is where the macrophyte literature puts it.

Below that PAR a plant runs a deficit however perfect the water is. Night and a week-long blackout cost exactly the same per hour; what tells them apart is whether the bank ever refills.

Claim Depth it may reach Where the shortfall lands
Upkeep the last unit starved — a share of the bill, spent as tissue
Stressor damage down to upkeepRate × upkeepReserveHours condition
Repair, then growth the same reserved line, during the photoperiod only nothing — what the ladder cannot use stays banked

The reserved line is what lets one bank serve two claims. Damage outweighs upkeep by an order of magnitude, so a bank damage may empty is a bank the next dark hour finds empty, which turns any nagging channel into starvation.

Each lit hour a plant mobilises growthDrawRate of its bank and spends it on condition first and size second. Only what repaired or became tissue leaves the bank, so a plant at its ceiling in perfect water converts nothing, pays nothing, and banks everything it earns. Repair is a withdrawal, which means a damaged plant does not heal at night.

A growing plant never settles at surplusCap. A day’s withdrawal there exceeds a day’s income, so the bank settles proportional to what the plant clears — 9 to 26 units across the roster for a young specimen, a shade species holding more than a carpet because the same PAR sits nearer its saturation.

starved = share of upkeep neither income nor the bank could pay // 0..1
sizeLost = size × starved × maxSheddingRate
waste += sizeLost × wastePerShedSize

Nothing shrinks a plant for being damaged, only for being unfed. The tissue leaves as waste rather than as fuel — a starving plant abscises its oldest leaves rather than digesting them, which is why melting plants foul the water.

A plant dies when condition or size falls below its threshold, and the two name different deaths. Condition takes the plant that was poisoned, cooked or shaded; size takes the one that starved, holding condition 100 the whole way down until there is nothing left of it. Either way the remaining size becomes waste and the plant leaves the array.

Tunable Meaning Unit
basePhotosynthesisRate Rate units per hour per 100 % plant size at full carbon and saturating light 1.0 /hr
saturationIrradianceFactor Multiple of a species’ band low at which it saturates — the Ik of the light curve 2.0 × band low
optimalCo2 Carbon at which co2Factor reaches 1 20 mg/L
co2PerRateUnit Carbon one rate unit moves, in either direction 30 mg
nutrientsPerPhotosynthesis Total nutrient draw per rate unit the uptake term resolves to 4.0 mg
baseRespirationRate Dark respiration as a share of the light-saturated rate 0.03 /hr
respirationQ10 Factor respiration and upkeep multiply by per 10 °C 2.0
respirationOxygenHalfSaturation O₂ at which respiration runs at half rate 0.5 mg/L
upkeepCost Cost of being alive, quoted at the reference temperature 0.075 %/hr
upkeepReserveHours Hours of upkeep the bank keeps back from every junior claim 100 hr
surplusCap Saturation ceiling for the bank 50 units
growthDrawRate Share of the bank mobilised each lit hour 0.02 /hr
sizePerSurplus Size gained per converted unit, before the species growth rate 0.4 %
maxSheddingRate Share of itself a plant drops per hour when it pays none of its bill 0.02 /hr
nutrientDeficiencySeverity Damage per point of Liebig shortfall — pinned from both ends, at 28 days for a starved carpet and 180 for an undosed beginner planting 0.3 %/hr
co2InsufficientSeverity Damage per mg/L below the species’ carbon band 1.5 %/hr
Benefit peaks (×4) Recovery per channel in band, before the light term. Four at 0.125 sum to the 0.5 %/h budget the recovery curves were pinned against 0.125 %/hr
deathConditionThreshold · deathSizeThreshold The two floors a plant leaves the tank through 10 % each
Neighbour Read Written
Light light — PAR at the substrate, which multiplies the photosynthetic rate and every benefit channel, and gates accrual
Water & gases co2 for the rate and the band, oxygen for the respiration Monod oxygen and co2, both directions, on one carbon yield
Nitrogen cycle nitrate — the one nutrient every tier requires nitrate drained on uptake; waste from shedding and death
Environment temperature for the Q10 on respiration and upkeep, water for every ppm
Equipment substrate.type — which species may be planted at all
Algae algae.mass — the shading stressor, one tick behind Plant power, which drives algae’s suppression stressor and its low-plant-power benefit
Livestock Plant power again, saturating the fish shelter benefit at three full-grown healthy plants
Actions Planting, removal and trimming write size and the array directly; dosing fills the four nutrient pools
Alerts & logging A plant-died log entry per plant lost
State & persistence Receives seeded plantings, at a named size and the same half-bank a stocked plant gets

src/simulation/plants/ — the roster, construction and the per-tick pipeline; src/simulation/systems/ — photosynthesis, respiration, nutrition, vitality and lifecycle; src/simulation/config/ — the tunables above and their declared ranges.