Skip to content

Enhancement/update points to win with 3 and 4 kings, create new and u… - #207

Merged
itsalaidbacklife merged 2 commits into
cuttle-cards:mainfrom
TommySchmid:buff_kings
Nov 9, 2022
Merged

Enhancement/update points to win with 3 and 4 kings, create new and u…#207
itsalaidbacklife merged 2 commits into
cuttle-cards:mainfrom
TommySchmid:buff_kings

Conversation

@TommySchmid

@TommySchmid TommySchmid commented Nov 8, 2022

Copy link
Copy Markdown
Contributor

…pdate existing test case

Please check the following

  • Do the tests still pass? (see Run the Tests)
  • Is the code formatted properly? (see Linting (Formatting))
  • For New Features:
    • Have tests been added to cover any new features or fixes?
    • Has the documentation been updated accordingly?

Please describe additional details for testing this change

Comment thread api/services/userService.js Outdated
Comment thread client/js/components/RulesDialog.vue Outdated
Comment thread tests/e2e/specs/in-game/oneOffs.spec.js Outdated

@itsalaidbacklife itsalaidbacklife left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good. My change requests are in the comments, and then we're ready to merge

@itsalaidbacklife
itsalaidbacklife merged commit af25121 into cuttle-cards:main Nov 9, 2022
@TommySchmid
TommySchmid deleted the buff_kings branch December 7, 2022 20:23
@itsalaidbacklife itsalaidbacklife added backend Requires changes to the (node) backend webserver frontend Requires changes to the frontend (vue) client rules change Adjustment to the rules of the game labels Aug 4, 2026
itsalaidbacklife added a commit that referenced this pull request Aug 4, 2026
…dates

Replace the flat '1.0.0' backfill with a CASE over each game's createdAt, mapping
to the rule set live at that time using the UTC merge timestamps of the PRs that
shipped each change: #207 (0.0.1), #855 (0.1.1), #1197 (1.0.0), #1320 (1.0.1).
Still idempotent (ADD COLUMN IF NOT EXISTS + WHERE rulesVersion IS NULL). New
games get 1.0.2 from the model default and are left untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
itsalaidbacklife added a commit that referenced this pull request Aug 4, 2026
Annotate the VERSION HISTORY with the PR that shipped each rule change (#207,
#855, #1197, #1320, #1359) after the initial version.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
itsalaidbacklife added a commit that referenced this pull request Aug 4, 2026
* feat: replace eager hand-limit enforcement with discard-to-hand-limit phase

Introduces a new DISCARDING_TO_HAND_LIMIT game phase (value 6) so players
can always draw or resolve moves that overflow the 8-card hand limit, then
discard down immediately rather than being blocked upfront.

- Draw: removed the block-at-8 validation; drawing a 9th card enters the
  new phase instead of incrementing turn
- Five: always draws 3 cards (removed the spaceInHand cap); overflows
  trigger the discard phase
- Nine: if the returned card pushes the targeted player over 8, they enter
  the discard phase before getting their turn
- New discard-to-hand-limit validate/execute helpers; supports discarding
  1 card (hand=9) or 2 cards (hand=10) in a single move
- Frontend: DiscardToHandLimitDialog, game store computed/action wiring,
  socket event handler, and i18n strings
- AI: generates all valid discard combinations for the new move type
- Tests: updated basicMoves, 5_fives, and 9_nines specs; new handLimit.spec.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(game-state-api.md): init

* refactor: switch to disardedCard in api for discarding to hand limit

* test: fix which player is p0 and handling of empty deck in hand limit tests

* fix(translations): match en.json for hand limit

* test(9_nines.spec.js): fix it('Nine returns card to player hand at hand limit, triggering discard dialog for player'

* fix(translations): add game.snackbar.oneOffs.discardToHandLimit key to each file

* refactor(DiscardToHandLimitDialog): switch to script setup

* docs(AGENTS.md): describe pinia and script setup

* refactor(inGameEvents): move discard to hand limit block into main handler

* fix(discard-to-hand-limit/validate): add turn check

* docs(translations/CLAUDE.md): init file to instruct maintaining lang file parity

* docs(translations/CLAUDE.md): revise copy

* fix: set phase and increment turn based on hand limit

* chore(.gitignore): allow AI config files

* docs(.clause/rules/translation-parity.md) pull into .claude/rules with paths spec

* test(9_nines.spec.js): adjusted hand limit cases to avoid dialog on same turn

* refactor(handLimit.spec.js): reorganize by move type

* fix(resolve/execute): set discard based on active player not playedBy

* test(handLimit.spec.js): add 'Forces player to discard down to hand limit after opponent nines and player draws'

* test(handLimit.spec.js): implement Skips discarding when opponent nines player at the hand limit and player then plays points

* chore(handLimit.spec): remove .only()

* test(handLimit.spec.js): add Discards down to hand limit after playing a 4 on opponent when player has 10 cards in hand

* fix(resolve-four/execute.js): make it the four-player to discard down to hand limit after four resolution

* chore(handLimit.spec.js): remove .only()

* fix(get-active-player-p-num): use turn/active player for DISCARDING_TO_HAND_LIMIT case

* fix(get-log.js): update log for discard to hand limit to accommodate multiple cards

* docs(game-state-api.md): fix typo

* fix(game.js): set waitingForOpponentToDiscard based on turn for discarding to hand limit case

* fix(game.js): set showDiscardToHandLimit based on turn + phase

* chore(translations): remove unused draw.handLimit keypair

* docs(game-state-api.md): Remove project-proposal/RFC language

* docs(game-state-api.md): document discarding to hand limit phase

* docs(game-state-api.md): remove 'can be null' since it's in the type def

* docs(game-state-api.md): format code blocks

* docs(game-state-api.md): doc the hand limit phase + move types

* docs(game-state-api.md): fix capitalization

* docs(game-state-api.md): doc game phase

* docs(game-state-api.md): pull docs for MoveType into own section

* docs(game-state-api.md): replace numbered lists with bulleted lists

* docs(game-state-api.md): update draw/execute example

* docs(game-state-api.md): Apply code review revisions

Co-authored-by: Ryan Emberling <itsalaidbacklife@gmail.com>

* fix(draw/validate): set activePlayer based on turn

Co-authored-by: Ryan Emberling <itsalaidbacklife@gmail.com>

* chore(basicMoves.spec.js): rename test case

* test(handLimit.spec.js): assert gameState more specifically

* refactor(discard-to-hand-limit/execute): simplify discard loop, keep presence guard

Address review feedback: splice once and push the removed card to both
discardedCards and scrap (dropping the double-read). Keep a lightweight
cardIndex === -1 guard so a validate bypass can never splice(-1) and silently
remove the wrong card.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(get-move-bodies-for-move-type): document discard combination bound

Address review feedback about the discard combination recursion. Document that
C(hand, overflow) is bounded by game rules (hand <= ~10, overflow 1-2), so there
is no blow-up risk. No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(handLimit.spec.js): add pass-over-hand-limit discard test

Add a Passing and Hand Limit case: with an empty deck and a 9-card hand, the
player passes (clicking the deck) and is forced into the discard-to-hand-limit
dialog, with the turn only advancing after discarding down to 8.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(rules): update hand limit text for end-of-turn discard

Reflect the reworked hand limit in the How To Play rules across all five
locales: the Play section now describes performing one action then discarding
down to 8, and the Draw and Five descriptions no longer claim you cannot exceed
the 8-card hand limit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(Game): track rulesVersion of the rule set used per game

Add a canonical CURRENT_RULES_VERSION constant (utils/rulesVersion.js) and stamp
it onto each Game via a defaulted rulesVersion column, so any game can be
disambiguated back to the rules it was played under. The hand-limit rework is
version 1.0.0. Orthogonal rule mods (e.g. jokers) are intentionally deferred to
a future ruleVariants column.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(skills/announcement): add skill to author home-page announcements

Add an /announcement skill that gathers announcement copy, timing, and optional
image/cards, then produces the announcementData object and the flat announcement
i18n block across all five translation files, following the pattern of prior
announcement PRs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(announcement): announce the hand limit rework

Replace the site announcement with the hand-limit-rework notice: activator
"Hand Limit Rework", dialog title "Hand Limit", and copy explaining the
simplified single rule (discard down to 8 at end of turn) that replaces the
separate draw/Five/Nine hand-limit interactions. Open-ended (no time bounds) and
shown to all users; drops the now-unused twitchLink key across all five locales.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(e2e): suppress always-on announcement dialog before app load

The hand-limit announcement has no date window, so its dialog is always active
and its overlay scrim covered UI elements, failing many e2e specs. Seed
LS_ANNOUNCEMENT in the global window:before:load handler so the flag is present
before the app mounts (AnnouncementDialog reads localStorage synchronously at
mount, so dismissIntroPopups() after cy.visit is too late). Keeps the
announcement always-on in production while suppressing it in tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(migrations): add idempotent game.rulesVersion column migration

Production/staging run Waterline with migrate: 'safe', so the new Game.rulesVersion
column (PR #1359) is not auto-created and must be applied by hand. Add an idempotent
SQL migration that ADD COLUMN IF NOT EXISTS "rulesVersion" on "game" and backfills
existing rows to '1.0.0'. New rows get '1.0.0' from the model's defaultsTo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(rulesVersion): bump to 1.0.2

* chore(rulesVersion): renumber and add 5 rework

* docs(rulesVersion): add rule set version history, bump current to 1.0.2

Document the full VERSION HISTORY (0.0.0 -> 1.0.2) and set CURRENT_RULES_VERSION
to 1.0.2 for the hand-limit rework, so new games are stamped 1.0.2 via the Game
model default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(migrations): backfill rulesVersion by createdAt using PR merge dates

Replace the flat '1.0.0' backfill with a CASE over each game's createdAt, mapping
to the rule set live at that time using the UTC merge timestamps of the PRs that
shipped each change: #207 (0.0.1), #855 (0.1.1), #1197 (1.0.0), #1320 (1.0.1).
Still idempotent (ADD COLUMN IF NOT EXISTS + WHERE rulesVersion IS NULL). New
games get 1.0.2 from the model default and are left untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(translations): translate discardToHandLimit dialog + snackbar keys

The game.dialogs.discardToHandLimit (title/body/discard) and
game.snackbar.oneOffs.discardToHandLimit (notDiscardingPhase/handNotOverLimit/
mustSelectCards) values were left as English placeholders in de/es/fr/ukr when
the keys were first added. Translate all six into each language, consistent with
each file's existing hand-limit terminology.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(translation-parity): require translated values, add placeholder self-check

Add a 'Values must be in the file's language' section forbidding English
placeholders in non-English files (the failure mode that left discardToHandLimit
untranslated), covering key *additions* not just value changes, plus a self-check
comparing non-English values against en.json. Cross-reference it from the
announcement skill.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(rulesVersion): reference the PR behind each version

Annotate the VERSION HISTORY with the PR that shipped each rule change (#207,
#855, #1197, #1320, #1359) after the initial version.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(skills): add game-state-api skill routing to the move-lifecycle doc

Add a skill that instructs when to read docs/game-state-api.md — before working
on game-move processing (MoveType changes, validate/execute helpers, the
move.js request lifecycle, GameState/GameStateRow packing, the card string
format, GamePhase/MoveType enums, models, or the socket payload).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(rules): replace cheatsheet PDF with v6, update cheatsheet link

Remove public/img/cuttle_rules.pdf, add public/img/cuttle_rules_v6.pdf (the _v6
suffix busts caches), and point the Cuttle Cheatsheet link in RulesView.vue at
the new path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(rules): update cuttle_rules_v6 cheatsheet PDF

Replace public/img/cuttle_rules_v6.pdf with the revised version.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(skills/announcement): glob translation files instead of hardcoding the list

Reference src/translations/*.json (and 'every translation file') instead of the
explicit {en,de,es,fr,ukr} list / 'all five' phrasing, so adding a new locale
doesn't leave the skill stale.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: remove migrations/ folder

Drop the standalone SQL migration for game.rulesVersion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(e2e): seed play-time flag pre-load and remove dismissIntroPopups

The global window:before:load hook now seeds both LS_ANNOUNCEMENT and
LS_PLAY_TIME_DIALOG_DISMISSED before app load, suppressing both intro dialogs
uniformly. Delete the now-redundant dismissIntroPopups command (its LS_ANNOUNCEMENT
write ran after cy.visit, too late; its play-time write was inert since that
dialog only shows after 60s in a lobby) and all 19 call sites. The 'Lobby - Play
Time Dialog' block opts back in by clearing the play-time flag in its beforeEach
(enterLobby uses SPA nav, so no reload re-seeds it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(rules): update cuttle_rules_v6 cheatsheet PDF

Replace public/img/cuttle_rules_v6.pdf with the latest cheatsheet iteration.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(DiscardToHandLimitDialog): select cards by id directly

Pass card.id from the template to selectCard instead of the hand index and
looking the id back up; drop the now-unused v-for index. No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Requires changes to the (node) backend webserver frontend Requires changes to the frontend (vue) client rules change Adjustment to the rules of the game

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants