🤖
3562 in / 1994 out / 5556 total tokens
Changed the entire identity of Bridge Cross. It used to be a "pick a color and watch" game — now every player directly chooses top or bottom each column, like a dice game where user input determines the outcome.
The biggest structural change is the phase system. The entire betting stage is gone. bettingReady became roundReady. Phase enum cleaned up to idle | ready-wait | playing | finished. The old 5-step phase dance was meaningless in a user-driven model, so it all got deleted. Dead constants like BRIDGE_BETTING_SEC removed, only BRIDGE_WAVE_SEC=3 remains.
Core loop: ready → character spawn (max 6, color auto-assigned by i % 6 ready order) → per-column 3-second countdown with top/bottom buttons → no click means server Math.random 50/50 forced decision → all players decided = simultaneous jump (wave gating) → survive the last column = winner. 0 to N winners allowed.
Server authority is the real centerpiece of this commit. safeRows never reaches the client. Not in gameStart, waveResult, gameEnd — none of them. currentRoomInfo returns bridgeCross: undefined to block leaks on reconnection. Even console.log of safeRows is gated behind NODE_ENV !== 'production'. Client-side Math.random handles visual effects only (jitter, camera shake) — never game outcomes.
Socket events trimmed hard. Client→Server bridge-cross:choice (top/bottom pick), Server→Client bridge-cross:waveStart / bridge-cross:waveResult. Old bridge-cross:select, selectionConfirm, selectionCount all scrapped. Event count dropped by more than half.
Redefined mulberry32 seed as participants.length + waveIndex + colorSum — deterministic per-wave but unpredictable. Cascade guard changed from winner guard to success guard for correct multi-winner handling.
Wrote AutoTest/bridge-cross-user-driven-payload.js — spins up two real socket.io-client connections, plays through a game, validates safeRows leakage, fairness, mode toggle rejection. 14 PASS / 0 FAIL.
CSS: killed bettingSection, built new waveChoicePanel. Visible during play, hidden 700ms after result. Added 480px mobile responsive layout.
Also killed auto/manual mode toggle as follow-up. Wave gating makes it redundant — the 3-second no-click auto-forced decision handles deadlock prevention alone.
Total: +1617 -938 across 8 files. Removed all betting code, implanted user-driven rules. Major surgery.
"A game where players make outcomes and a game where players just watch need fundamentally different server architectures. That's why changing one rule meant ripping open 8 files."