The Ecosystem — Plants, Herbivores, Predators, Mutating Genomes
A 2D world with sunlight, plants, herbivores, and carnivores. Each individual carries a 12-trait genome that mutates with reproduction. Run for an hour. Watch arms races emerge that you never coded.
What this is
An 800×600 toroidal world. Plants grow on sunlight. Herbivores (colored circles) chase plants and flee carnivores. Carnivores (oriented triangles) chase herbivores. Every individual has a 12-trait genome that mutates each reproduction — including the mutation rate itself. The simulation runs at 100+ ticks per second on a spatial-hash neighbor index. Within 30 seconds, classic Lotka-Volterra population waves emerge on the bottom graph. After 30 minutes, herbivores have evolved higher sense range to detect carnivores from further away; carnivores have evolved higher aggression and sense range in response. None of this is scripted.
Why this is mind-blowing
You wrote one paragraph. The model produced a real ecology. Watch it long enough and you'll see selection pressure invent strategies you didn't anticipate — herd behavior, ambush, plant defenses (encoded in toxicity-equivalent traits). This is what evolutionary biologists mean by "emergent." Sit with it for an afternoon.
Build a single-file ecosystem simulator. A 2D toroidal world with
sunlight as a renewable resource. Three classes: plants, herbivores,
carnivores. Each individual has a 12-trait genome (size, speed, sense
range, metabolism, reproduction threshold, color, etc.). Genomes mutate
on reproduction. Energy flows: plants ← sunlight, herbivores ← plants,
carnivores ← herbivores. Run at 100+ generations/second. No scripted
behaviors — just selection pressure. After an hour I want to see
emergent arms races that I never coded.
Paste this into Claude, Cursor, or Copilot. Change one thing that matters to you.
What I learned shipping it
- Letting the mutation rate itself evolve as a genome trait is the move. Lineages that need more diversity raise their own mutation rate; stable ones lower it.
- Spatial hash grids for O(1) neighbor queries are what makes 1500+ agents at 100+ ticks/sec feasible in single-threaded JavaScript. Don't iterate all-pairs.
- Population graphs always show Lotka-Volterra waves within 30 seconds. The math forces this — predator-prey systems can't help oscillating.