cellSize
number
The pixel width/height of a single soil grid cell; determines grid resolution.
const cellSize = 10;
soilHeight
number
How many pixels tall the soil strip at the bottom of the canvas is.
const soilHeight = 150;
rows
number
Number of rows in the soil grid, computed from soilHeight and cellSize.
let rows;
cols
number
Number of columns in the soil grid, computed from canvas width and cellSize.
let cols;
soilGrid
array
2D array storing each cell's nutrient value from 0-100; the core data structure of the simulation.
let soilGrid;
noiseOffset
number
A slowly-incrementing offset fed into Perlin noise to make the soil's noise pattern drift over time.
let noiseOffset = 0;
noiseScale
number
Controls how 'chunky' or fine the Perlin noise pattern looks across the grid.
const noiseScale = 0.05;
noiseDriftRate
number
How fast noiseOffset increases each frame, controlling the speed of the soil's 'breathing' effect.
const noiseDriftRate = 0.0005;
noiseNutrientInfluence
number
The maximum amount noise can nudge a cell's nutrient value up or down each frame.
const noiseNutrientInfluence = 2;
nutrientWells
array
List of well objects ({x, radius}) that continually regenerate nearby soil fertility.
let nutrientWells = [];
minWells
number
The minimum number of nutrient wells created at setup/resize.
const minWells = 5;
maxWells
number
The maximum number of nutrient wells created at setup/resize.
const maxWells = 8;
wellRadius
number
How far (in pixels) each well's fertility boost reaches.
const wellRadius = 70;
wellRegenRate
number
How much nutrient a well adds per frame at its very center.
const wellRegenRate = 0.15;
diffusionRate
number
The fraction of a cell's nutrient value that blends with its neighbors' average each frame.
const diffusionRate = 0.03;
seeds
array
List of all active Seed objects currently falling, dormant, or about to germinate.
let seeds = [];
seedSpawnTimer
number
Countdown of frames until the next normal (non-rain) seed spawns.
let seedSpawnTimer = 0;
seedSpawnIntervalMin
number
The shortest possible wait time between normal seed spawns.
const seedSpawnIntervalMin = 60;
seedSpawnIntervalMax
number
The longest possible wait time between normal seed spawns.
const seedSpawnIntervalMax = 120;
seedSize
number
The pixel size used to draw each seed shape.
const seedSize = 8;
seedGravity
number
Downward acceleration applied to falling seeds each frame.
const seedGravity = 0.1;
seedWindForce
number
The maximum random horizontal push applied to falling seeds, simulating wind.
const seedWindForce = 0.05;
germinationNutrientThreshold
number
The minimum soil nutrient level required for a seed to germinate.
const germinationNutrientThreshold = 40;
nutrientConsumptionOnGermination
number
How many nutrients are subtracted from the soil the moment a seed germinates.
const nutrientConsumptionOnGermination = 30;
dormantRecheckInterval
number
How many frames a dormant seed waits before rechecking whether the soil has become fertile enough.
const dormantRecheckInterval = 60;
nutrientParticles
array
List of active NutrientParticle objects visualizing nutrients returning to the soil.
let nutrientParticles = [];
particleSizeMin
number
Smallest possible size for a nutrient particle.
const particleSizeMin = 2;
particleSizeMax
number
Largest possible size for a nutrient particle.
const particleSizeMax = 4;
particleGravity
number
Downward acceleration applied to falling nutrient particles.
const particleGravity = 0.05;
particleLifeSpan
number
How many frames a dissolving particle stays visible before disappearing entirely.
const particleLifeSpan = 120;
seedRainActive
boolean
Whether a seed rain event is currently in progress.
let seedRainActive = false;
seedRainTimer
number
Countdown of remaining seeds to drop during the current seed rain event.
let seedRainTimer = 0;
seedRainCount
number
How many seeds a single seed rain event spawns.
const seedRainCount = 20;
seedRainInterval
number
How many frames pass between the start of each seed rain event.
const seedRainInterval = 1000;
droughtActive
boolean
Whether a drought event is currently suppressing well regeneration and other events.
let droughtActive = false;
droughtTimer
number
Countdown of remaining frames in the current drought.
let droughtTimer = 0;
droughtDuration
number
How long, in frames, a drought event lasts.
const droughtDuration = 300;
bloomActive
boolean
Whether a bloom (flowering) event is currently active.
let bloomActive = false;
bloomTimer
number
Countdown of remaining frames in the current bloom event.
let bloomTimer = 0;
bloomDuration
number
How long, in frames, a bloom event (and each plant's flowering) lasts.
const bloomDuration = 180;
bloomInterval
number
How many frames pass between the start of each bloom event.
const bloomInterval = 2000;
plants
array
List of all active Plant objects, alive or currently decaying.
let plants = [];
plantIDMap
object
A Map from plant ID to Plant instance, used to quickly look up parents/offspring for genealogy.
let plantIDMap = new Map();
totalPlantsAlive
number
Current count of living plants, recalculated every frame and fed into the timeline.
let totalPlantsAlive = 0;
totalPlantsDead
number
Cumulative count of plants that have fully decayed since the sketch started.
let totalPlantsDead = 0;
plantGrowthInterval
number
Base number of frames between a plant's L-system growth iterations.
const plantGrowthInterval = 30;
plantMaxIterations
number
The maximum number of L-system rewrite generations a plant can reach.
const plantMaxIterations = 4;
plantBaseLength
number
The starting branch segment length before decay is applied.
const plantBaseLength = 10;
plantLengthDecay
number
Multiplier applied to branch length each growth iteration, shrinking later branches.
const plantLengthDecay = 0.7;
plantBranchThickness
number
The stroke weight used when drawing plant branch lines.
const plantBranchThickness = 1.5;
plantNutrientConsumptionBase
number
The base amount of nutrients a plant consumes per frame before scaling by complexity.
const plantNutrientConsumptionBase = 0.05;
plantNutrientConsumptionMultiplier
number
Multiplier that increases nutrient consumption as a plant grows more complex.
const plantNutrientConsumptionMultiplier = 0.5;
plantDecayTime
number
How many frames a dead plant takes to fully decay and disappear.
const plantDecayTime = 200;
plantCompostBonus
number
Multiplier applied to nutrients returned to the soil when a plant decays, rewarding decomposition.
const plantCompostBonus = 1.5;
lightNoiseOffset
number
A slowly-incrementing offset used to drift the light band pattern over time.
let lightNoiseOffset = 0;
lightNoiseScale
number
Controls the width/pattern of the drifting light bands.
const lightNoiseScale = 0.005;
lightDriftRate
number
How fast the light bands drift across the scene each frame.
const lightDriftRate = 0.0001;
lightBrightnessMin
number
The minimum transparency/brightness value used for light bands.
const lightBrightnessMin = 0;
lightBrightnessMax
number
The maximum transparency/brightness value used for light bands.
const lightBrightnessMax = 10;
shadowThreshold
number
The light exposure level below which plants start growing more slowly.
const shadowThreshold = 0.6;
shadowDeathThreshold
number
The light exposure level below which plants stop growing entirely and begin risking death.
const shadowDeathThreshold = 0.3;
shadowDeathTimerMax
number
How many consecutive frames a plant can survive below shadowDeathThreshold before dying.
const shadowDeathTimerMax = 180;
aliveHistory
array
Rolling history of totalPlantsAlive values used to draw the timeline's green line.
let aliveHistory = [];
deadHistory
array
Rolling history of totalPlantsDead values used to draw the timeline's gray line.
let deadHistory = [];
fertilityHistory
array
Rolling history of average soil fertility used to draw the timeline's amber line.
let fertilityHistory = [];
historyLength
number
The maximum number of frames of history kept for the timeline charts.
const historyLength = 200;
timelineHeight
number
The pixel height of the timeline bar drawn at the bottom of the canvas.
const timelineHeight = 60;
showGenealogyWeb
boolean
Toggle (via the 'G' key) for whether parent-offspring lines are drawn between plants.
let showGenealogyWeb = false;
fastForward
boolean
Toggle (via the 'F' key) that runs the simulation update multiple times per rendered frame.
let fastForward = false;
depletedHue
number
The HSB hue used for the most nutrient-depleted soil color.
const depletedHue = 30;
depletedSat
number
The HSB saturation used for the most nutrient-depleted soil color.
const depletedSat = 20;
depletedBright
number
The HSB brightness used for the most nutrient-depleted soil color.
const depletedBright = 10;
richHue
number
The HSB hue used for the most nutrient-rich soil color.
const richHue = 15;
richSat
number
The HSB saturation used for the most nutrient-rich soil color.
const richSat = 95;
richBright
number
The HSB brightness used for the most nutrient-rich soil color.
const richBright = 85;
plantColorMap
object
Lookup table mapping each seed shape to its base plant color (hue/saturation/brightness).
const plantColorMap = { triangle: { hue: 20, sat: 80, bright: 60 }, ... };