Skip to content

Lock early rage quits and let the winner finish their card - #127

Open
ejsmith wants to merge 2 commits into
mainfrom
rage-quit-lockout
Open

ejsmith wants to merge 2 commits into
mainfrom
rage-quit-lockout

Conversation

@ejsmith

@ejsmith ejsmith commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

A rage quit throws the winner's score off the high-score boards. That let a losing player wipe out someone's best game just by quitting late. This PR closes that gap and keeps rage quit fun:

  • Too soon to quit. Rage Quit stays in the menu and the taps still insult you. Until the quitter has filled 3 boxes, the tenth fast tap refuses instead ("Denied.", "Nice try, crybaby.") and says they can't quit until they've played 3 turns. The cancel button reads "Fine, I'll play." game-action refuses an early quit too. The rule lives in rageQuitUnlockTurns / isRageQuitUnlocked in shared/game.ts.
  • Finish your card. After a rage quit, the winner can keep playing their own open boxes alone, from the game-over screen or from the completed game's score card.
    • The result, rating, and streaks stay as they were at the quit.
    • Every turn is theirs, with the usual rolls, Extra Rolls, Mulligans, and Sucker Deals. Nobody is left to punch, so there are no response windows, punches, or taunts, and the quitter is not notified.
    • The game stays in the winner's active list ("Tap to keep finishing your card.") until the card is full, even if newer games push it out of the latest 25 finished games. The quitter keeps seeing the flipped table.
    • A winner whose card was already full when the opponent quit has nothing left to play, so the quit credits that card right away.
    • On the last box, game-action upserts the winner's result with played_out_at, raises their matchup high score, and awards their instant and card feats (buildPlayOutFeats: 400/500 Club, Spotless, the Sucker tiers, and so on). It never awards feats about the forfeit or the quitter's frozen card.
  • The weekly (by played_out_at) and all-time high score boards count a finished card. Punch % still never counts a forfeit.
  • Spec, docs/multiplayer.md, and docs/community-leaderboards.md are updated.

The game stays status = 'complete' throughout, and state.rageQuit.playOut is 'playing' and then 'finished'. Ratings and the completion trigger never run again.

Stacked on #122, because the play-out's card feats (400/500 Club, Spotless) come from it. Merge #122 first.

Needs migration 20261029130000_let_rage_quit_winners_finish.sql (supabase db push), then a game-action deploy, then the client. Older binaries let an early quit through locally, and it fails with the server's "Too soon" error. They can't play a card in progress.

Testing

  • npm run typecheck, npm run lint, npm run check:expo, npm run typecheck:edge, npm run test:edge (65), npm run test (228).
  • npm run test:integration:supabase (49 passed) on an isolated local stack:
    • The existing rage quit test now checks the "Too soon" refusal before quitting with 3 boxes.
    • A new test finishes a card: only the winner can start it, the quitter can't roll or punch, the game stays complete, the score posts with played_out_at, the rating and completion time stay unchanged, the matchup high and both boards update, the play-out feats are awarded, and the quitter gains none.
    • Another new test quits while the winner's card is already full: the card counts at once with played_out_at, reaches the board, and earns its feats, and finish_card reports nothing left to finish.
  • Checked the lobby's state->rageQuit->>playOut filter against the local stack: it returns only the card in progress.
  • Web E2E on the same isolated stack: the two rage quit tests pass. The UI test now covers the refusal, a real quit after 3 boxes, the winner's Finish button (the quitter has none), finishing from the score card, rolling, and the active-list hint.
  • Checked screenshots at 393×852: the refusal dialog, the winner's overlay with the insult grid and the Finish button, the score card button, and the play-out board.

🤖 Generated with Claude Code

Rage Quit stays in the menu, but until the quitter has filled 3 boxes the
tenth fast tap refuses ("Denied.") and tells them to finish what they
started. game-action refuses an early quit too.

After a Rage Quit, the winner can finish their own card alone from the
game-over screen or the completed score card. The result, rating, and
streaks stay as they were at the quit. Every turn is theirs, with no
response windows, punches, or taunts, and the quitter is not notified. The
game stays in their active list until the card is full. Their last box sets
game_player_results.played_out_at, posts the final score to the weekly and
all-time boards and their matchup high, and awards instant and card feats
(buildPlayOutFeats), never ones about the forfeit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T20:13:42.203260Z 44c706c New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a3a5421d0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/multiplayer/MultiplayerLobby.tsx Resolved
Comment thread shared/game.ts Resolved
A winner whose card was already full when the opponent rage quit had no box
left to play out, so the quit still wiped their score. The quit now credits
that card at once: played_out_at, the matchup high, and the card's feats.

The game list only loads the latest 25 finished games, so an unfinished
card could drop out after newer games. listMyGames now also loads every
card still being finished.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from instant-feats to main October 29, 2026 20:14

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant