Loading repository data…
Loading repository data…
nilsgollub / repository
Emergent ant-colony simulation in TypeScript: pheromone foraging, a rival colony at war, GPU (Pixi.js) + Canvas rendering, fully deterministic. Runs in-browser and on a Raspberry Pi.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
▶ Try it live in your browser — no install needed.
An agent-based ant-colony simulation in TypeScript: a deterministic, emergent little world where workers forage along pheromone trails, a queen lays brood, soldiers mob predators, and — optionally — a rival colony wages war next door (border skirmishes, resource theft and brood raids). It renders on the GPU via Pixi.js (with a pure Canvas-2D fallback) and is light enough to run as a screensaver on a Raspberry Pi 4.
Everything random flows through a seeded PRNG, so any run is fully reproducible and the colony's emergent behaviour is regression-tested headlessly.
git clone https://github.com/nilsgollub/AntSim_V2.git
cd AntSim_V2
npm install
npm run dev # dev server (hot reload) → http://localhost:5173
npm run dev uses vite --host, so the server is also reachable from other devices on
your LAN (handy for testing on a tablet/phone or the Pi). Other scripts:
npm run build # type-check (tsc) + production build → dist/
npm run preview # serve the production build locally
npm run test # run the test suite once (Vitest)
npm run test:watch # tests in watch mode
To serve the production build yourself, npm run build then host the dist/ folder with
any static file server.
Camera — drag to pan, mouse wheel to zoom (zoom-to-cursor). On a touchscreen: one finger pans, two fingers pinch-zoom, a tap acts as a click.
| Button | Action |
|---|---|
− 1× + | Simulation speed (0 / 0.5 / 1 / 2 / 4 / 8×) |
| ⏸ / ▶ | Pause / resume (also Space) |
| ⏭ | Single step (while paused) |
| ➕ ➖ ⌖ | Zoom in / out / reset camera |
| 📷 | Screenshot the world view to a PNG download |
| 🔍 | Inspect tool — click an ant or insect for live stats |
| 🍬 / 🥩 | Place sugar / protein |
| ☠ | Spawn a predator |
| 🎨 Grafik | Graphics panel (renderer, quality, bloom, pheromone overlay + intensity slider, day/night, cinematic camera) |
| Restart | Rebuild the world from a fresh seed |
| Rivalenkolonie | Toggle the second (rival) colony on/off |
| 📈 Stats / 🎛 Params / ⚙ Analyse | History graphs / live parameter sliders / tuner advisor |
Append to the URL to preconfigure a run without touching the UI:
| Param | Example | Effect |
|---|---|---|
seed | ?seed=12345 | Reproduce an exact run (otherwise seeded from the clock) |
colonies | ?colonies=2 | 1 = solo, 2 = rival colony + war |
quality | ?quality=LOW | Pin render quality (ULTRA_LOW…ULTRA), overrides saved/auto |
Example: index.html?colonies=2&quality=LOW — the exact URL the kiosk screensaver uses.
UI choices (quality, speed, pheromone overlay, rival toggle, …) persist in
localStorage; a URL parameter always wins over the saved value.
The 🎨 Grafik panel exposes the renderer (WebGL/Canvas), a quality preset
(Ultra Low → Ultra), bloom, the pheromone overlay + an intensity slider, the day/night
tint, and the cinematic-camera toggle. The auto-downgrade floors at LOW (never the
barren Ultra Low) so a struggling Pi keeps its grass and trades only frames.
On a Raspberry Pi 4, pick Low (the kiosk pins ?quality=LOW, ~30 fps). At low presets
pheromone diffusion is off (decay-only), the canvas renders at 0.4× resolution, the ant
cap drops, and particles/shadows/animation are trimmed. The camera, inspector and tuner
stay fully functional at every quality level.
An auto-downgrade triggers after 60 consecutive frames below 20 FPS (10 s cooldown
between steps), so the sim self-tunes on first launch. Crucially, simulation fidelity is
decoupled from quality — pheromone grid resolution / diffusion / update cadence live in
CONFIG, not the preset — so the colony behaves identically at every graphics level (a
test proves it).
All simulation randomness flows through a seeded PRNG (src/rng.ts, mulberry32) instead
of Math.random(), so a run is fully reproducible from its seed. Rendering-only
randomness (background texture, grass) stays on Math.random() and never affects sim
state.
runHeadless(seed, ticks) (src/simulation/headless.ts) runs the whole simulation with
no DOM and returns aggregate metrics. The tests use it to assert on emergent outcomes:
npm run test
Tests run in a node environment (no DOM); config.ts guards every window.* read so it
imports safely from tests. Test files live beside their modules as *.test.ts.
src/
├── main.ts Entry point: render loop, input (mouse + touch), HUD, panels,
│ screenshot, URL params, screensaver auto-restart
├── config.ts All tunable simulation constants (grouped sub-objects)
├── configStore.ts Runtime CONFIG overrides (live sliders / tuner)
├── rng.ts Seeded PRNG (mulberry32) — the determinism backbone
├── PerformanceManager.ts Quality presets + FPS auto-downgrade
├── graphics/
│ ├── Camera.ts Pan/zoom with screen↔world mapping (mouse + touch)
│ ├── Renderer.ts Canvas-2D rendering (world fallback + nest interior view)
│ └── PixiBackdrop.ts WebGL (Pixi.js v8) world renderer: baked textures, bloom
└── simulation/
├── World.ts Central controller; owns colonies[] + shared environment
├── Colony.ts One colony's state (queen, nest, brood, stockpiles, raids)
├── Ant.ts Agent data + low-level movement/sensing/steering
├── antStates.ts The FSM state handlers (forage/return/nurse/combat/raid/…)
├── Queen.ts Egg laying + mortality
├── Brood.ts Egg → larva → pupa → ant; nutrition-driven caste
├── Insect.ts Prey & predators (spider, beetle, ladybug, aphid, …)
├── Food.ts Sugar / protein / corpse sources
├── PheromoneGrid.ts Float32 fields with decay + separable-blur diffusion
├── Terrain.ts Obstacles + circle–circle collision
├── SpatialGrid.ts Ant proximity queries
├── Nest.ts Node-graph underground structure + greedy routing
├── headless.ts runHeadless(seed, ticks) → metrics (no DOM)
└── SimObserver.ts Metric sampling + the parameter-tuner advisor
See ROADMAP.md for the running status/changelog and ARCHITECTURE_AND_MECHANICS.md for deeper design notes.
Every tunable constant lives in src/config.ts, grouped under e.g.
CONFIG.ant.* (detection ranges, energy thresholds), CONFIG.pheromone.* (decay,
diffusion, deposits), CONFIG.brood.* (lifecycle, caste threshold), `CONFI