A browser game about keeping a make-believe jungle network alive through one on-call shift. Routers are temples, firewalls are vine gates, the database lives in a lake, and the outages are real ones in costume.
It is 09:00. You are on call. A stampede of bison is about to hit the Banana Cache, a worm is reaching across the vines, and the certificate on the Auth Gate expires in fifty seconds. The Watchtower can see some of it coming. Not all of it.
- ๐ฎ How to play
- ๐ง What it teaches
- โ๏ธ How the game code works
- ๐ ๏ธ Build and run it yourself
- โ๏ธ Change the game without recompiling
- ๐ Documentation
- ๐ Credits and licences
You run a small crew through an 8-minute shift (09:00 โ 17:00 on the game clock). Things break. You read the symptoms, send someone, pick the response, and race the โณ Time to Loss.
| Key | Mode | |
|---|---|---|
| T | ๐บ๏ธ Tour | Island by island through all 28 nodes: what each one is, its lore, what it links to, and how many services lose their path if it goes down |
| P | ๐งช Practice | One problem at a time, timers ร3, nothing spreads, no game over |
| B | ๐ Field guide | Every concept you've met, with the example where you met it |
| Faster at | Can't | ||
|---|---|---|---|
| ๐ต | Mango the monkey | good at everything | |
| ๐ฆ | Pip the parrot | diagnosis | heavy work |
| ๐ฆฅ | Moss the sloth | maintenance: certs, patches, canaries | |
| ๐ธ | Fern the tree frog | hardware: cables, vents, power | |
| ๐ | Tusk the elephant | heavy work: rollbacks, hotfixes, replicas |
Pick a response and a crew member runs it straight away, in about 2.5 s. They still travel to the node on the map, but nothing waits for them. Each runs one thing at a time, so the whole crew can work five problems at once.
Every problem starts somewhere for a reason ("A botnet of a million bison found the Banana Cache on the open internet") and, left alone, spreads along its links as its timer runs down.
- ๐ก Warning: nothing is broken yet. Prevent it (renew the cert, canary the deploy) for bonus points.
- ๐ด Incident: the origin. It's degraded and counting down; at 0 it goes down.
- ๐ Symptom: a neighbour suffering from it. Nothing to fix there: O jumps to the origin, and fixing the origin clears every symptom at once.
- ๐ Worms are contagious: they infect neighbours for real.
- ๐ฉถ Unreachable: fine, but cut off because the only path runs through a down node.
Pick one of four responses. The terminal types the real command, streams its output, runs a health check, and then says โ CORRECT, ๐ฉน PARTLY (it bought time) or โ NOT THE FIX, with the reason. Not sure? ๐ H spends a banana on a hint, or ๐ I diagnoses every option.
Network health is the network right now. Shift SLA is its average over the
shift, and you need 95% to pass and unlock the next level. At the end you get
your score, โ
what went right,
Enter start ยท Space most urgent ยท Tab cycle problems ยท 1-4 respond ยท I diagnose ยท
H ๐ hint ยท O go to the origin ยท Z X C V N pick a crew member ยท G send ยท
arrows hop nodes ยท Q/E islands ยท WASD/drag pan ยท wheel/pinch zoom ยท F follow
๐ฑ On a phone: drag, pinch, tap a node, tap a response. Off-screen nodes become pins on the screen edge. Tap one to fly there.
โถ Jump straight into a situation: DDoS on the Banana Cache ยท a deploy that migrated the database ยท a certificate about to expire ยท DNS down
Full rules: docs/gameplay.md
Under the jungle paint, every fault is a real production failure and every right answer is the first move an experienced operator would make. All 18 fault types โ
| In the jungle | In real life |
|---|---|
| ๐ฅ Service crashed โ ๐ restart | a process can die while the machine still answers ping |
| ๐ Names don't resolve, IPs work โ fix DNS | the classic "it's always DNS" |
| ๐ท๏ธ New devices get no address โ expand the DHCP pool | address exhaustion |
| ๐ฆฌ Stampede on one endpoint โ block with an ACL (rate-limit only buys time) | DDoS: mitigation vs remediation |
| ๐ Neighbours failing because of one broken node โ fix the origin, not the symptoms | root cause and blast radius |
| ๐ Worm โ patch (quarantine only buys time) | containment vs eradication |
| ๐ฆ Bad deploy โ roll back; with a schema migration โ fall forward | when rollback is and isn't safe |
| โ๏ธ Replicas disagree โ resync from the primary | replication lag and split brain |
| ๐ Routing loop, ๐ข broadcast storm (โ Spanning Tree), ๐๏ธ wrong VLAN | layer 2 and 3 failure modes |
| ๐ Expiring certificate โ renew it. "Disable TLS" is refused, with the reason | security isn't optional under pressure |
| ๐ฉถ Router down โ 27 services unreachable | root cause vs dependency impact, blast radius |
| ๐ ๐งฌ ๐พ warnings | proactive vs reactive work: prevention is cheaper |
| โณ Time to Loss | prioritising by consequence, not by noise |
It also teaches the shape of on-call: triage, delegating to people with different strengths, not burning out your crew, and reading the symptom before grabbing a tool. "Time to Loss" is the game's own term, and the field guide is explicit that it is not IP TTL or DNS TTL.
game/data/*.json โโโถ data.rs โโโถ sim.rs (the rules: no Bevy, fully testable)
tuning ยท islands ยท โฒ โ health, faults, crew, director, log
nodes ยท world ยท npcs โ โผ
keys/clicks โ ops.rs (HUD, Time to Loss, overlays, pins, input โ orders)
โ
world.rs ยท water.rs ยท clouds.rs ยท npc.rs ยท view.rs ยท ui.rs (Bevy ECS: drawing)
- Bevy 0.20, Rust โ WebAssembly โ WebGL2. One isometric projection function, one terrain mesh per diagonal row so depth sorting is exact, a texture atlas for the tiles. โ docs/engine.md, docs/world.md
sim.rsis the whole game model, with no engine. Each frame the screen callsSim::step(dt)and draws the result. A separate native crate,game/simtest/, compiles the same file and runs 14 rule tests plus a balancing harness with bot players (Idle / Novice / Beginner / Expert ร 4 levels ร 20 seeds). โ docs/simulation.md- Health is a graph walk. After every change a breadth-first search from the core router marks what's reachable. Anything cut off is Unreachable, so root causes and impacts never get mixed up.
- An incident director deals new trouble only after a grace period, under a per-level budget, and never while the network is already on its knees.
- Workers route over the links with Dijkstra (flyers go straight). The game picks whoever would finish first unless you choose.
- One event log groups related events ("27 services unreachable" is one line, not 27).
- The map is data.
tools/gen-world.pyturnsislands.json+nodes.jsoninto the archipelago: one river from void to void, canyons where islands rise above it, vine bridges, free-floating islands, hanging pixel vines.
| File | What |
|---|---|
game/src/sim.rs |
rules: faults, responses, director, crew, routing, health, SLA, scoring, event log |
game/src/ops.rs |
the game screen: HUD, Time to Loss, roster, alerts, log, rope links, edge pins, tour, summary, input |
game/src/ui.rs |
welcome gate, node panel |
game/src/world.rs |
terrain meshes, vines, decorations, node cards |
game/src/water.rs ยท clouds.rs ยท npc.rs |
waterfall, bubbles, data frames ยท clouds, rain, lightning ยท wandering critters |
game/src/view.rs ยท link.rs |
camera, touch, picking ยท deep links (#node=โฆ&incident=โฆ) |
game/src/data.rs |
loads live JSON, merges over built-in copies, never crashes on a bad file |
game/simtest/ |
native tests + balancing bots |
tools/ |
world generator, doc generator, texture packer, font subsetter, build scripts |
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.129 --locked # must match game/Cargo.lock
tools/build-web.sh # builds into web/game
python3 -m http.server -d web 8080 # open http://localhost:8080Run the rules tests and the balancing table (native, no browser needed):
cd game/simtest
cargo test --release
cargo run --release --bin balanceA release build needs a few GB of disk and takes a while the first time (Bevy is
big). The live site also runs inside a small Next.js host page (app/page.tsx).
tools/deploy.sh is the author's own deploy to their server.
Everything worth tuning is JSON in game/data/, fetched when the page loads:
| File | Holds |
|---|---|
tuning.json |
every fault, response, action, crew member, level, the training script, concepts, numbers |
islands.json |
the archipelago: islands, heights, hills, river, bridges |
nodes.json |
the 33 nodes: names, emoji, connections, lore |
world.json |
generated from the two above by tools/gen-world.py |
Edit, run python3 tools/gen-world.py (if you touched the map), copy into
web/game/data/, and reload. A broken file falls back to the built-in copy, so a
typo can't take the game down. Add a fault in JSON and it's in the game, in the
docs (tools/gen-docs.py), and in the deep links.
| ๐ฎ How to play | rules, crew, levels, keys |
| ๐ฅ Failure types | all 18 faults: symptom, fix, mitigation, why (generated from the data) |
| ๐๏ธ Nodes and lore | the legend, every island and node, its role and story (generated) |
| ๐งฎ The simulation | the model, director, workers, tests and balancing numbers |
| ๐ฏ On-call design | why the loop works the way it does |
| ๐ฅ๏ธ Interface | layout, phone layout, camera, deep links, Bevy UI traps |
| ๐ The world | isometric maths, terrain, the archipelago, water, clouds |
| ๐ฆ The engine | Bevy and ECS, explained for this project |
| ๐ง Build, deploy and test ยท Extending | |
| ๐ผ๏ธ A tour in pictures ยท Overview and history ยท Decisions ยท Glossary | |
| ๐ฆ Outside assets and licences ยท Isometric engine extraction report |
- Engine: Bevy (MIT/Apache-2.0) and the Rust crates listed in docs/assets.md.
- Emoji: Twemoji graphics ยฉ Twitter / X Corp. and contributors, CC-BY 4.0, in the Twemoji Mozilla colour font build.
- Fonts: DejaVu Sans Mono (Bitstream Vera licence) and Noto Sans Mono CJK JP subset (SIL OFL 1.1).
- Tile sprites and grid background: from the project's original v0.dev prototype. Their provenance wasn't recorded; see docs/assets.md.
Made by LuckyMonkey ๐๐











