What this teaches
Battleship is useful because the privacy failure is obvious. A hidden-board game should not require the service, spectators, support tools, or analytics jobs to see every unshot ship location. The tutorial isolates this product shape:Privacy boundary
The tutorial’s core lesson is recipient specificity. “Reveal hit/miss” is incomplete until the product says who receives it and when.
Reveal policies
The tutorial compares three policies:-
Public combat log
- Everyone sees the coordinate and result.
- The board still stays hidden unless the game explicitly allows review.
-
Private result
- Attacker and target see the detailed hit/miss result.
- Bystanders may see only that a turn happened.
-
Delayed reveal
- Details stay hidden during live play.
- Selected logs may open after elimination or game end.
Code map
normal/battleship.rs: see the omniscient-referee backend.private/battleship.rs: see recipient-specific authorized views.src/client.rs: see the attacker and target-board payloads.src/app.rs: see the Rust service generate the local run, attach inputs, and decode the shot result.src/main.stfl: see oblivious lookup, private hit-mask update, private remaining-health update, and opened output fields.tests/: see reveal-policy behavior and hidden-state expectations.
Run it
From the tutorial repository root:What not to copy
Do not copy Battleship as a claim that every game needs MPC. Copy the hidden-state design habit:- Separate public liveness state from private app state.
- Define the recipient-specific view before coding.
- Update private state without turning it into a backend-readable board.
- Open only the facts named by the reveal policy.
- Treat logs, support tools, analytics, and spectators as product surfaces with explicit access rules.