Watch the whole game from the deal

The seed + command log has been the whole game all along; now it can
be watched. Finished games offer "⟲ Watch the whole game" beside the
face-up hands: the server replays every command from seq 0 through
the same redacted catch-up pipeline (the 200-step window remains a
live-game courtesy; full replays wait for the game to finish), and
the reel plays it titled "The whole tale, from the deal" with new
1×/2×/4× speed controls for the long tellings. Each viewer rewatches
from their own seat — hidden information stays hidden in the retelling
exactly as it was at the table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 13:38:24 -04:00
co-authored by Claude Fable 5
parent 37c38d5c1a
commit cdcd1de71a
5 changed files with 30 additions and 6 deletions
+3 -2
View File
@@ -268,11 +268,12 @@ export interface CatchUpStep {
* Rebuild the game and capture a redacted view after each command from
* `sinceSeq` on — the "what happened while you were away" reel.
*/
export function catchUpSteps(room: Room, playerId: PlayerId, sinceSeq: number): CatchUpStep[] | { error: string } {
export function catchUpSteps(room: Room, playerId: PlayerId, sinceSeq: number, full = false): CatchUpStep[] | { error: string } {
if (!room.state) return { error: "game not started" };
if (!room.players.includes(playerId)) return { error: "you hold no seat in this room" };
if (full && room.state.phase !== "finished") return { error: "full replays wait for the game to finish" };
const MAX_STEPS = 200;
const from = Math.max(sinceSeq, room.log.length - MAX_STEPS);
const from = full ? 0 : Math.max(sinceSeq, room.log.length - MAX_STEPS);
const { state: fresh } = createGame(room.state.config);
let current = fresh;
const steps: CatchUpStep[] = [];