Table of Contents
Bio-Dynamics is an educational 3D lab, not a clinical simulator. That constraint shaped every decision in the simulation layer: reproducible ticks, scalar tissue state, capped agent counts, and inflammation that emerges from pressure instead of jumping on every button press.
This post walks through the engine design. Start with the anchor case study if you want the project context first.
Why deterministic?
Interactive demos fail the educational test when the same button sequence produces different outcomes on refresh. Readers cannot build intuition from noise.
SimEngine fixes that with three choices:
- Fixed timestep —
FIXED_DT = 1/30seconds; the frame loop may render faster, but simulation advances in capped substeps. - Seeded PRNG — default seed
42for spawn positions and vitality jitter via a linear congruential generator. - Golden snapshot tests — scripted action sequences are compared against checked-in JSON fixtures so refactors cannot silently drift behavior.
Full model overview: simulation/model-overview.md
Agents plus scalars, not a full ABM framework
The engine keeps two parallel representations:
MicrobeNodeagents (max 400) — probiotics, pathogens, allergens, commensals, and prebiotic substrate particles with vitality and positions in a unit box.BiomeStatescalars — pH, moisture, barrier integrity, biofilm, immune activity, postbiotic level, and region-specific fields like cerumen or oxygen tension.
User actions apply immediate biome mutations and spawns. Continuous dynamics run each tick: growth, competition, prebiotic conversion, sugar decay, and emergent inflammation.
Population counts shown in the dashboard are multiplied by POPULATION_SCALE (1000) for readable numbers — another explicit simplification documented in assumptions-and-limits.md.
Emergent inflammation instead of flat deltas
Early prototypes bumped inflammation directly on every stressor click. That felt game-like and wrong for teaching barrier defense.
The current model in inflammationDynamics.ts computes a target from pathogen pressure, allergen load, low integrity, biofilm, and immune signaling, then eases inflammation toward that target each tick. Stressors like histamine spikes raise immuneActivity first; inflammation follows.
Dynamics reference: simulation/dynamics.md
Gut-brain as an educational proxy
On gut tissue, gutBrainDynamics.ts maintains tryptophanSupport — a scalar proxy linked to calm mucosa and SCFA output, not mood prediction. The lifecycle preset surfaces it in the dashboard with article links on key strains.
The point is narrative coherence for the pre → pro → postbiotic chain, not serotonin pharmacokinetics.
Golden tests as a contract
engine.golden.test.ts replays two scripted sequences:
- Allergy / nose — allergen spike, histamine, L. rhamnosus, saline mist
- Lifecycle / gut — prebiotic apply, probiotic conversion, postbiotic rise
Each checkpoint records tick, biome scalars, and population counts. npm test in labs/microbiome-sandbox fails if behavior drifts.
| |
Fixture: src/sim/fixtures/engine-golden.json
What I deliberately did not model
The assumptions doc is part of the product. Non-goals include:
- Pharmacokinetics and dosing timelines
- Metagenomic profiles or strain-level genomics
- Anatomically accurate spatial niches
- Postbiotics as individual agents (they stay a scalar
postbioticLevel)
Saying “educational abstraction” in the UI disclaimer is not modesty — it is architecture.
Omid Farhang