Skip to content

Watershed

Watershed is the pure CRDT showcase: a real-time territory game with no turns, no hidden information, and no authoritative game server. Players place, merge, and split tokens concurrently. The board is derived from active token records, so two valid writes to one cell remain a contested cell rather than a last-write-wins replacement.

Run it

npm run relay
# in another terminal
npm run watershed:web

The web script builds the bundle and serves it on http://localhost:8080. The browser client defaults to the relay URL documented by the example; adjust the client configuration when the relay is elsewhere.

Rules and sync tests are available directly:

npm run test:watershed:rules
npm run test:watershed:sync

State model

doc.watershed.tokens is a token map. Parent tokens are never deleted: actions record tombstones in consumed and create children with _mergedFrom or _splitFrom provenance. deriveBoard() and scoring materialize a plain clone before inspecting state, avoiding Automerge proxy pitfalls. Energy is partly derived from stored energy and elapsed time; lobby presets select energy and duration.

The action surface is watershed:init, register, start, place, merge, split, and end, dispatched through the TypeScript ActionRegistry. Handlers validate phase, bounds, registration, energy, adjacency, and strength before field-level writes. ConsensusCore exchanges sync blobs through the relay; peers converge, but the relay does not decide which placement is legal.

Caveats

Watershed intentionally has no secrecy and no global turn arbitration. A modified client can attempt invalid writes, and concurrent valid actions may produce contested state that the game must score explicitly. The example is a good fit for collaborative, merge-friendly play—not for games requiring a trusted referee, private decks, or strict serial transactions.