Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jkh2/Primordial-Sim/llms.txt

Use this file to discover all available pages before exploring further.

Primordial runs a continuous-space ecosystem where every colored dot is a living organism with position, velocity, energy, age, a species identity, and four genetic traits. No behavior is scripted — territories, predator-prey cycles, and migration patterns all emerge from five simple behavioral drives and the physics of survival.

Simulation Loop

Every animation frame executes a fixed sequence of steps:
1

Spawn Food

New food pellets appear at the configured spawn rate. When food oases are active, 60% of new pellets are placed near an oasis center (randomly within its radius), and 40% appear at fully random map positions.
2

Build Spatial Grids

All alive organisms and food pellets are bucketed into their respective spatial hash grid cells (40 px per cell). This happens fresh every frame so the grids always reflect current positions.
3

Per-Organism Behavioral Step

For each alive organism, the engine scans the surrounding 3×3 neighborhood of grid cells (5×5 in Food Chain mode). Five force vectors are accumulated: hunt, flee, flock, food attraction, and separation. Eat/collision events are resolved here. A small wander noise term is also added for organic movement.
4

Integrate Physics

Accumulated forces are scaled by the organism’s genetic speed multiplier and a size-based speed penalty (larger organisms move slightly slower). Velocity is clamped, position is updated, and edges wrap toroidally.
5

Metabolism

Energy is deducted each frame based on the organism’s efficiency gene: metaCost = 0.3 * (1.2 - gEfficiency * 0.5). Size is recalculated from energy as size = sqrt(energy) * 1.5. Death is checked here (starvation or old age) and reproduction is triggered when thresholds are met.
6

Reproduce with Mutation

Any organism that reached the reproduction threshold this frame spawns offspring. Each offspring inherits the parent’s exact gene values, then each gene independently mutates with probability equal to the mutation rate, shifting by a random amount within ±mutation strength.
7

Update Death Particles

Active kill and death particle effects are advanced: positions updated, velocities damped, lifetimes decremented. Expired particles are recycled.
8

Check Experiments

If an AI-designed experiment is running, elapsed simulation time is compared against the experiment duration. When complete, the end-state snapshot is captured and sent to the AI for analysis.
9

Render

The previous frame is either cleared or faded (trail mode). The GL attribute arrays are rebuilt in order — food pellets first, then death particles, then organisms — uploaded to the GPU as dynamic buffers, and drawn as point sprites in a single gl.drawArrays call.

Behavioral Forces

Each organism accumulates five independent force vectors every frame. The vectors are summed and applied to velocity.
ForceDirectionDriverNotes
HuntToward smaller preyhunt * (0.5 + gAggro)Only toward organisms of other species that the hunter is large enough to eat. Scales with the organism’s aggression gene.
FleeAway from larger predatorsflee * 1.2Triggered when a nearby organism of another species is large enough to eat the current one. Flee force is stronger per unit distance than hunt.
FlockToward same-species center of massflock * 0.15Organisms within 1.5 grid cells of a same-species neighbor contribute to a running center-of-mass average. The force pulls toward that average direction.
Food AttractionToward nearest food pelletfoodDrive * 0.3The nearest alive food pellet within the food scan radius (1–3 cells, scaled by perception gene) provides a constant pull.
SeparationAway from overlapping neighborsseparation * 2 / (distance + 1)Both same-species and other-species organisms trigger separation when very close. Prevents pileups and creates natural spacing.

Predation Mechanics

An organism can eat another organism of a different species when:
  1. The predator’s size exceeds the prey’s size multiplied by the size advantage ratio (default 1.3×, configurable 1.05×–2.0×).
  2. The prey is within the predator’s perception range.
  3. Same-species protection is enabled (default on) — organisms never eat members of their own species regardless of size.
When a kill occurs:
  • The prey’s oalive flag is cleared immediately.
  • The predator gains prey.size * eatGain energy (default eatGain = 0.5).
  • The predator’s kill counter increments.
  • A burst of death particles emits in the prey’s species color.
  • An audio thud plays (if sound is on), with pitch proportional to prey size.
Rock-Paper-Scissors Food Chain mode replaces the size-ratio check with circular predation: species 0 hunts species 1, species 1 hunts species 2, species 2 hunts species 0, and so on. No species can dominate because every predator is also prey to another species. This produces classic Lotka-Volterra population oscillations visible in the real-time population graph — populations rise and fall in out-of-phase waves as the cycle propagates.

Food Mechanics

Food pellets are scattered across the map and provide a base energy source for all organisms.
  • Eating: When an organism moves within organism.size + 3 pixels of a food pellet, the pellet is consumed and the organism gains 3 energy.
  • Spawn rate: Configurable pellets-per-second. New pellets reuse slots from previously consumed pellets, keeping the live food count near the configured maximum.
  • Oases: Up to 8 configurable fertile zones can be placed on the map. Each oasis has a center point and a radius (80–200 px). When oases are active, 60% of spawned food appears near an oasis and 40% appears randomly. This creates geographic resource concentration that drives territorial behavior and migration.

Reproduction

Reproduction is triggered when an organism meets both thresholds in the same frame:
  • Size threshold: osize >= reproSize (default 12)
  • Energy threshold: oenergy > reproSize * 2.5
When triggered:
  1. The parent’s energy is reduced to 40% of its pre-reproduction value.
  2. Parent size is recalculated from the new energy.
  3. Offspring count (default 2, configurable 1–5) new organisms are spawned near the parent.
  4. Each offspring starts at the configured starting size with energy = startSize * 2.
  5. Offspring inherit the parent’s genes, then mutation is applied per gene.
The energy cost of reproduction is steep — parents shrink significantly after giving birth, making them temporarily vulnerable to predation.

Death

Organisms die from two causes:
CauseConditionEffect
Starvationenergy <= 0Small death particle burst emitted at the organism’s position in its species color.
Old ageage > lifespanOrganism simply disappears; no death particles for age-related death by default.
Dead organisms free their array slots for reuse by newborns, keeping memory usage bounded.

Spatial Hash Grid

The spatial hash grid is the core performance enabler. The map is divided into 40 px cells, each holding up to 64 organism references. Every frame:
  1. All alive organisms are inserted into their cell (floor(x / 40) + floor(y / 40) * gridWidth).
  2. Behavioral scans check only the immediate 3×3 neighborhood of cells (9 cells × 64 entries = 576 candidates maximum per organism).
  3. In practice each organism checks ~30–50 neighbors — compared to O(n²) = millions of checks without the grid.
A separate food grid uses the same cell size but stores up to 32 food references per cell, with a configurable scan radius of 1–3 cells (widened for organisms with high perception genes).

Build docs developers (and LLMs) love