Explore tragedy-of-the-commons dynamics with AI coding agents
Fish Banks Sandbox is an offline, single-player port of the classic commons-collapse fishing simulation, built for an AI coding agent to extend.
1.0.0Add to Favorites
Why it matters
Teach systems thinking and policy design by providing an interactive, agent-ready simulation of shared-resource collapse that developers can run locally, break open with AI coding assistants, and extend to model their own domains.
Outcomes
What it gets done
Run headless simulations to find collapse thresholds and test policy interventions
Extend the model with new policy levers like taxes, quotas, or dynamic pricing
Let AI agents play as fishing companies to observe emergent goal-misalignment
Re-skin the fishery dynamics to model your domain's shared-resource problems
Source
Get it from source
Spark does not host a copy of it.
Open sourceReports
Agent outcome reports
No reports yet
Overview
Fishbanks Sandbox
A single-player, offline browser sandbox that reproduces a classic Fish Banks tragedy-of-the-commons simulation with a pure-function engine, meant to be run, inspected, and extended by an AI coding agent. Reach for it when teaching or exploring commons-collapse dynamics, or when you want an AI agent to prototype and compare policy levers like pricing, taxes, or quotas against a small, transparent simulation.
What it does
Fish Banks Policy Sandbox is a single-player, fully offline, browser-based port of the classic Dennis Meadows "Fish Banks" tragedy-of-the-commons simulation, originally played live as a multiplayer classroom exercise (AI + Systems Thinking course, Workshop 5). Each fishing company chases its own cash; the sandbox reproduces the same verified engine so you can explore why a shared ocean stock collapses even when no single player intends harm. It's fully self-contained - open index.html directly, no server or install required - and ships a pure-function simulation core (fishbanks.js) plus a headless CLI explorer (explore.mjs) for scripted experiments.
When to use - and when NOT to
Use it to explore or teach the mechanics of commons collapse - how a shared stock, a build delay on new fishing capacity, and a "maximize my own cash" objective combine to drive overshoot - and to let an AI coding agent extend the model with new policy levers (pricing, taxes, quotas, subsidies) or reskin it for another domain (groundwater, API rate limits, shared tech debt). It is not the multiplayer game itself: the live classroom version's multiplayer architecture is only documented as a spec (FISHBANKS-SPEC.md Part 2), not shipped as running code in this repo, and its tuned constants are built for a classroom exercise, not as a validated real-world fishery forecasting model.
Inputs and outputs
import { fishBanksParams, fbNewState, stepRound } from './fishbanks.js';
const P = fishBanksParams(); // tuned constants (K=6000, costs, regen curve)
let state = fbNewState(P, 4); // 4 teams, 4800 fish to start
// one round = 3 simulated years; a decision per team:
const decisions = state.teams.map(() => ({ buy: 5, toSea: 99, sendNewToSea: true }));
const result = stepRound(state, decisions, P); // mutates `state`, returns this round's outcome
// result.fish, result.catchPerShip, result.teams[i].roundCatch
// state.fish, state.teams[i].cash / shipsSea / shipsPort / bankrupt
Input is a per-round decision per team: buy (ships ordered, costing $25k and arriving the following round - the build delay that drives overshoot) and toSea (ships moved from port to the water, 99 sends them all). Output is each round's result (remaining fish, catch per ship, each team's catch) and the mutated simulation state (cash, ships at sea/in port, bankruptcy status per team). Engine constants fixed by fishBanksParams() include a carrying capacity of 6,000, a maximum sustainable yield of about 8,688 fish/round (regeneration peaks at 70% density), a commons-collapse cliff around 75 ships at sea, and a sea ship break-even point of 25 t/yr; with 3 teams the fishery collapses once any team buys 3+ ships/round, and with 4 teams at 3-4.
Integrations
Runs as a static, dependency-free web page (index.html, with sliders, presets, and live charts) or headless via node explore.mjs, which prints the collapse threshold and policy comparisons straight from the engine. A no-install hosted copy runs on GitHub Pages. The repo ships CLAUDE.md/AGENTS.md files so an AI coding agent opening the folder (Claude Code, Codex) already understands the engine and can be asked to run experiments, add policy levers, or wire the per-team decision function to an LLM player that only sees what a real player would see (its own cash and catch, not the stock).
Who it's for
Instructors and learners of systems-thinking or commons-management courses, and anyone using an AI coding agent to prototype policy interventions - pricing, taxes, quotas, subsidies - against a small, inspectable simulation before reasoning about a real shared-resource problem.
Source README
๐ Fish Banks - Policy Sandbox
The simulation you played in the workshop, packaged so you can play with it and break it open with your AI coding agent. Same verified engine, no login, runs fully offline.
It's a tragedy-of-the-commons model: each fishing company chases cash; collectively they can overfish a shared ocean to collapse. The lesson isn't "be nice" - it's that the structure (a shared stock + a build delay + a "maximize my cash" goal) drives the collapse, and only the right rule prevents it.
The debrief reveal from the live workshop game: the hidden ocean (cyan) and catch-per-ship (orange) that no team could see while playing. Catch-per-ship was already sliding while cash still looked great - the early warning a real fishery actually gets. The single-player sandbox in this repo reproduces the same engine.
Want the detailed step-by-step (running locally, reading the charts, troubleshooting, extending)? See
MANUAL.md.Want the full model + multiplayer-architecture spec (parameters, equations, the Meadows leverage map, the 3 escapes, and how the live classroom game is built)? See
FISHBANKS-SPEC.md.
Your cohort never collapsed it (room 8305: ocean survived, +$23.6M). But that was low fishing pressure + luck, not safety. You averaged ~1 ship bought/team/round - below the threshold. If any one team had floored it to buy-5, the shared ocean dies and everyone goes bankrupt. Your restraint was only as good as the least restrained player. This package lets you prove that to yourself in 10 seconds.

What a team saw on its own phone during the live game: its cash, its fleet, its last haul - but never the ocean stock. Players had to infer the shared commons from catch-per-ship alone. That hidden-state chokepoint is the whole lesson; the multiplayer architecture that enforces it is documented in FISHBANKS-SPEC.md Part 2.
Play it now (no setup)
Live (GitHub Pages): https://bayramannakov.github.io/fishbanks-sandbox/
Hit the โถ Your cohort preset, then flip ๐ โฆnow one of you defects.
Run it locally
Just open index.html - double-click it (or drag it into a browser tab). It's fully self-contained, so it works straight from your disk with no server and no install.
Explore headless (the fun part)
node explore.mjs
Prints the collapse threshold, your real game vs. one defector, and the enforced-quota cure - straight from the engine. Then go edit it.
The model in 30 seconds
Three functions, all pure, in fishbanks.js:
import { fishBanksParams, fbNewState, stepRound } from './fishbanks.js';
const P = fishBanksParams(); // tuned constants (K=6000, costs, regen curve)
let state = fbNewState(P, 4); // 4 teams, 4800 fish to start
// one round = 3 simulated years; a decision per team:
const decisions = state.teams.map(() => ({ buy: 5, toSea: 99, sendNewToSea: true }));
const result = stepRound(state, decisions, P); // mutates `state`, returns this round's outcome
// result.fish, result.catchPerShip, result.teams[i].roundCatch
// state.fish, state.teams[i].cash / shipsSea / shipsPort / bankrupt
A decision is { buy, toSea, sendNewToSea }:
buy- ships ordered this round (they cost $25k and arrive next round - the build delay that causes overshoot).toSea- move ships from port to sea (99= send them all). Ships at sea earn; ships in port idle cheaply.
Key numbers (engine-verified): carrying capacity 6,000, max sustainable yield ~8,688/round (regen peaks at 70% density), the commons cliff is ~75 ships at sea, a sea ship breaks even at 25 t/yr. With 3 teams it collapses at buy โฅ 3/team; with 4 teams at buy โฅ 3-4.
Explore with your agent (Claude Code / Codex)
This folder ships a CLAUDE.md / AGENTS.md so your agent already knows the engine. Open the folder in Claude Code or Codex and try:
Warm-ups
- "Run
explore.mjsand explain why buy-2 survives but buy-3 collapses." - "Find the exact MSY by sweeping a constant total catch per round."
- "Plot the fish stock for buy-4 as ASCII in the terminal."
Add a policy lever
- "Add supply-demand pricing: make fish sell for more as they get scarcer. Does collapse happen sooner or later? Why?" (it speeds up - scarcity rewards fishing harder)
- "Add a ship tax and a cap-and-trade quota. Which one sustains the fishery with the least lost profit?"
- "Add a subsidy on ship purchases and show it guarantees collapse."
Make it agentic
- "Replace the
decisionfunction with a call to an LLM - let Claude play one fishing company each round, given only what a real player sees (its own cash + catch, not the stock). Watch it strip-mine the ocean." - "Now change only the goal you give the LLM from 'maximize my cash' to 'maximize total catch over 50 years without collapse.' Does it self-restrain? This is the whole point: the optimizer obeys the goal, not your intent."
Make it yours
- "Re-skin this as [your domain] - groundwater / API rate limits / ad-auction CAC / shared codebase tech-debt. Keep the same dynamics, rename the variables."
Files
| File | What |
|---|---|
index.html |
the sandbox UI (sliders, presets, live charts) |
fishbanks.js |
the simulation engine - pure functions, the source of truth |
FISHBANKS-SPEC.md |
full model + multiplayer-architecture spec (Part 1 ships; Part 2 is the buildable pattern) |
explore.mjs |
headless policy explorer + your starting point for extensions |
MANUAL.md |
full step-by-step instruction manual (run, read, extend, troubleshoot) |
CLAUDE.md / AGENTS.md |
context for your AI coding agent |
From the AI + Systems Thinking course, Workshop 5 (Fish Banks). Model ported & tuned from Dennis Meadows' classic; engine validated round-by-round. Have fun breaking it.
FAQ
Common questions
Discussion
Questions & comments ยท 0
Sign In Sign in to leave a comment.