Predator-Prey Simulation — Spec Review

Six expert perspectives compiled from parallel review agents.

1. Population Ecologist

The Lotka-Volterra structure is sound: trophic tiers, discrete-time energy accounting, and density-dependent reproduction all map cleanly onto the classical predator-prey framework. Several parameter choices deserve scrutiny.

Energy budget arithmetic. Each animal loses 1 energy per tick and gains 20 from eating. With a reproduction threshold of 40 and an initial energy of 20, a prey animal must eat twice before it can reproduce — reasonable. But the reproduction cost (15) leaves the parent at roughly 25+ energy, and the offspring starts at half that (~12), meaning the offspring needs only one meal to approach threshold. This makes reproduction cascades likely, which can cause prey booms that outrun plant regrowth and collapse into mass starvation. The starvation rate of 1/tick is low relative to the 20-unit energy gain; consider raising starvation to 2 or 3 per tick to create sharper boom-bust cycles that better mimic observed Lotka-Volterra oscillations.

Plant dynamics. A spread probability of 0.03 on a 100×100 grid with 500 plants gives roughly 15 new plants per tick. With 100 prey consuming plants, plant depletion is plausible but recovery may be sluggish after a prey boom. If Moore neighbourhood is chosen for plants, spread doubles relative to von Neumann; this choice alone shifts whether the system is plant-limited or not.

Super-predators at count 5. Five individuals on a 10,000-cell grid is very sparse. With a sight radius of 5, each super-predator covers a 121-cell search area. Given random initial placement and low prey/predator density, early super-predators are likely to starve before finding food consistently. Extinction is the probable outcome in most runs. To keep super-predators viable, raise their initial count to 15–20, increase their energy gain from eating, or lower their starvation rate relative to lower tiers.

Tier-order processing bias. Processing plants before prey before predators means predators always act on the prey population after prey have already moved and eaten. This creates a systematic advantage for lower tiers and can dampen oscillations. Randomising processing order across all entities, or using simultaneous-update semantics, would be more ecologically neutral.

2. Cellular Automaton / ABM Specialist

Tick-ordering bias. Processing all plants, then all prey, then all predators in strict tier sequence creates a systematic temporal advantage for higher tiers even with within-tier shuffling. Predators always act on a world-state that has already been fully updated by prey this tick — meaning a predator never misses prey that "hasn't moved yet." Conversely, prey always flee into a world where predators are still in their previous positions. This skews predator hunting efficiency upward and prey survival downward in a way that has no ecological analogue. The fix is either simultaneous update (compute next-state for all entities from a snapshot of the current state, then apply atomically) or a fully interleaved random ordering across all entities regardless of tier.

Eat-after-moving ambiguity. The spec says "after moving, if the animal occupies or is adjacent to a food target, it eats it." The "or is adjacent to" clause is the problem: it lets an animal eat without occupying the food cell, which conflicts with "each cell holds at most one entity." It also means an animal can eat on a tick where it moved away from food (if food is still a neighbour after the move). The intended mechanic is almost certainly eat-on-landing: if the destination cell contains food, consume it; otherwise, do not eat this tick. The adjacency clause should be removed.

Reproduction energy accounting. The offspring starts with "half the parent's post-reproduction energy," but post-reproduction energy is initial energy minus the reproduction cost, which at defaults is 40 − 15 = 25, giving the offspring 12 energy. The reproduction threshold is also 40, so a just-reproduced parent is immediately below starvation risk. Whether that is intended needs to be stated explicitly, as it strongly governs boom-bust cycle frequency.

Predator diet inconsistency. The entity-tier table says predators eat only prey, but the behavior section says they also eat plants (at reduced energy). The super-predator entry in the table says it eats "Prey and Predators" but the text says "only preys and predators," excluding plants. These contradictions must be resolved before implementation.

Plant neighbourhood (open question risk). Von Neumann vs. Moore is deferred, but the choice has a large quantitative effect: Moore gives twice as many candidate spread cells. With a spread probability of 0.03 and Moore neighbours, expected plant growth per plant per tick is 0.24; with von Neumann it is 0.12. At 500 initial plants this difference can determine whether the ecosystem sustains itself or collapses. This should be a fixed default, not left open.

3. Game Developer

Performance — sight radius scanning. The most expensive operation is the per-animal sight-radius scan. At radius 5, each animal inspects up to ~78 cells (Moore) per tick. With 135 animals at startup that is modest, but populations can spike into the thousands. At 10 ticks/s and 1,000 animals the scan budget is ~780,000 cell lookups per second — still fine for a flat array, but the spec gives no guidance on the data structure. Using a 2-D array indexed by [row][col] is essential; a flat typed array (Uint8Array) would be faster still. Without specifying the backing store, a developer might naively use an array of objects, causing GC pressure.

Scalability. A 100×100 grid (10,000 cells) is rendered by iterating every cell each frame. At 200×200 (40,000 cells) with fillRect per cell this will stall. The spec should mandate dirty-cell tracking or at minimum a single ImageData pixel-buffer write instead of per-cell canvas calls.

Tick-rate and rendering coupling. The spec says "10 ticks per second" but does not decouple simulation ticks from rendering frames. Using setInterval for both at 10 Hz wastes the browser's 60 Hz frame budget and produces janky charts. The implementation should use requestAnimationFrame for rendering and a separate accumulator for simulation ticks.

Missing implementation details.

4. UX / Frontend Engineer

The "single HTML file" constraint is viable for a project of this scope but creates friction at one specific point: the live chart. No charting library is named in the spec. A developer must either bundle a library (Chart.js, uPlot, Plotly — each with different CDN policies and bundle sizes), write a canvas-based chart from scratch, or pull in a CDN dependency that breaks offline use. This is the most concrete blocker in the spec and must be resolved before implementation starts.

Contradictions and ambiguities. The spec says the predator "eats prey and plants" in the Entity Behaviors section, but the Entity Tiers table says predators eat only prey. The eating mechanic is ambiguous: "occupies or is adjacent to" conflates movement and eating into an unclear sequence.

Missing UI specifics. The layout says the chart appears "below or beside" the canvas — this needs to be decided. At 100×100 cells even with small cell sizes the canvas will be large; a side-by-side layout breaks on narrow viewports. No minimum canvas cell size is given, so the renderer has no basis for clipping or scaling decisions.

Accessibility. No keyboard controls are specified for Start/Pause/Step/ Reset. Color alone distinguishes the four tiers (green/yellow/orange/red), with no mention of patterns, labels, or ARIA live regions for the population counts.

Minor gaps. The "Energy gained by eating" parameter is a single value shared across all tiers and food types, but the spec also states plants give predators less energy than prey do — a second configurable parameter that is absent from the defaults table.

5. Technical Writer

Three contradictory color systems.

  1. The Entity Tiers table: Plant=Green, Prey=Yellow, Predator=Orange, Super-predator=Red.
  2. The "Colors" bullet list under Animal Behaviors: Prey=Red, Predator=Blue, Super-predator=Yellow.
  3. The UI section restates the canvas scheme as "green / yellow / orange / red" — consistent with the table but not the bullet list.

The bullet list under Animal Behaviors must be removed or corrected to match the table.

Behavioral contradictions. The Tiers table states predators eat "Prey" only. The prose under Animals says "Predators eat preys and plants." These conflict; the specification must pick one. The super-predator text "eats animals only preys and predators" is ungrammatical; rewrite as "Super-predators eat prey and predators only."

Incomplete and ambiguous sentences. The eating rule says the animal eats if it "occupies or is adjacent to a food target." Movement already moved the animal one cell toward the target, so "adjacent" after movement is an edge case that should be defined explicitly.

Missing definitions.

Open Questions section conflicts with defaults. "Idle movement: random walk or stay put?" is listed as unresolved, but the Movement section already specifies both behaviors. "Sight radius: short (3), medium (5), or long (10)?" is listed as unresolved, but the configuration table already sets the default to 5. Both open questions should be closed or removed.

6. Dynamical Systems Mathematician

Uniform energy gain across tiers. A single "energy gained by eating = 20" value applied identically to prey eating plants, predators eating prey, and super-predators eating prey or predators ignores the energetic cost of pursuit and the size differential between prey and predator. In classical Lotka-Volterra extensions, higher-tier predators require more energy per tick to sustain themselves precisely because prey is harder to locate. With identical gain values but higher initial energies and thresholds at each tier, super-predators will simply crash the predator population before it can recover, because each kill is proportionally more valuable relative to starvation cost for smaller animals than for larger ones.

Reproduction threshold and offspring energy create a ratchet. The threshold is 40, cost is 15, offspring receive half of post-reproduction energy. A parent at exactly 40 drops to 25 and the offspring starts at 12 (integer arithmetic). That offspring must reach 40 again — needing roughly 28 more energy units from eating — before it can reproduce. With starvation of 1 per tick and eating restoring 20, a prey animal needs to eat roughly every 20 ticks just to survive, and must eat twice more to reproduce. On a 100×100 grid with 500 plants (5% coverage) and a spread probability of 0.03, plant regrowth is slow enough that prey will locally exhaust patches, triggering boom-bust rather than stable oscillation.

Carrying capacity mismatch. 500 plants on 10,000 cells is 5% initial coverage. Plant spread probability 0.03 per tick means each plant produces roughly 0.03 × (empty neighbours) new plants per tick. Once prey reduce coverage below ~2–3%, plant recovery is slower than prey consumption at even modest prey densities (~50 animals), pushing the system toward prey extinction and then predator extinction in cascade.

Tier-order processing bias. Processing all plants, then all prey, then all predators each tick means predators always act on a prey population that has already moved and eaten this tick. This dampens predator efficiency inconsistently and makes the dynamics harder to reason about analytically.

Recommendations. Differentiate energy gain by tier (e.g., 10 for plant-eating, 20 for prey-eating, 30 for predator-eating). Increase plant spread probability to 0.05–0.08 or raise initial plant count to ~1500 for a 100×100 grid. Consider simultaneous (not sequential) tick resolution, or at minimum randomise processing order across all tiers rather than enforcing tier priority.

Cross-cutting Issues

The following issues were flagged independently by multiple reviewers and should be treated as highest priority:

Issue Reviewers
Color definitions conflict between the tier table and the prose body ABM, Technical
Predator diet contradicts between the tier table (prey only) and the prose (prey + plants) ABM, Game Dev, UX, Technical Writer
"Occupies or is adjacent to" eating rule is ambiguous — likely should be eat-on-landing only Ecology, ABM, Game Dev, UX, Technical Writer
Single energy-gain value for all food types contradicts the prose stating plants give less energy UX, Technical Writer, Mathematician
Tier-order processing creates systematic bias Ecology, ABM, Mathematician
Super-predators at count 5 will almost certainly go extinct Ecology, Mathematician
No charting library specified Game Dev, UX
Open Questions section contains items already resolved in the body Technical Writer
  1. Three conflicting color systems — the tier table, the prose body, and the UI section disagree.
  2. Predator diet contradiction — tier table says prey only; prose says prey + plants.
  3. Ambiguous eating rule — "occupies or is adjacent to" should almost certainly be eat-on-landing.
  4. Single energy-gain value — conflicts with the prose stating plants give less energy.
  5. Super-predators will likely go extinct at count 5 — raise to 15–20.
  6. No charting library named — a concrete blocker for implementation.