Skip to content

Difficulty tuning: slower grace ramp + harder default strategy (tangled)#46

Merged
riethmayer merged 1 commit into
masterfrom
grace-tile-scaling
May 25, 2026
Merged

Difficulty tuning: slower grace ramp + harder default strategy (tangled)#46
riethmayer merged 1 commit into
masterfrom
grace-tile-scaling

Conversation

@riethmayer

@riethmayer riethmayer commented May 25, 2026

Copy link
Copy Markdown
Owner

Follows up on production feedback that the game got easier as you climbed levels. Measured root cause: every per-level lever reduced difficulty — grace tiles grew as level − 1 (7 by level 8) and the only board strategy (scatter) is the most forgiving one we have.

Changes

1. Grace tiles ramp slowly (init-gameboard.ts)
Was level − 1. Now a slow step schedule:

level grace tiles
1 0
2–4 1
5–14 2
15+ 3

Grace only adds selectability, so solvability is unaffected.

2. New default strategy tangled (order-strategies.ts)
scatter (current default) is the most forgiving strategy; the harder existing ones (topDownRandom, bottomUpRandom) carry the "ready-made" top-cluster artifact. tangled peels low tiles first (fewer matches open at once → harder) but pulls each exposed upper tile down into the base, so the top never clusters.

Measured (branching = simultaneous legal moves; lower = harder; top-cluster = the artifact):

strategy branching forced-move % top-cluster
scatter (was default) 9.4 3% 0%
bottomUpRandom 4.4 34% 100% ❌
tangled (new default) 7.6 3% 0%

So tangled restores roughly the pre-scatter difficulty without the artifact. scatter and the others stay selectable (dev switcher / env override).

Notes

  • Strategy is still recorded per game; new games will record tangled. Production stays locked to the default (no player override).
  • yarn lint / type-check / vitest (106) / build all green.
  • Not merged — opening for review; say the word to ship.

Summary by CodeRabbit

  • New Features

    • Added "tangled" board peel-order strategy
  • Enhancements

    • Default board generation strategy changed from "scatter" to "tangled"
    • Updated grace tiles difficulty scaling: 1 tile for levels 2-4, 2 for levels 5-14, 3+ for level 15+

Review Change Stack

Higher levels were getting easier, not harder: grace tiles grew as level-1
(7 by level 8) and the only strategy (scatter) is the most forgiving. Two
changes give an upward curve:

- Grace tiles ramp slowly: 1 from level 2, 2 from level 5, 3 from level 15+
  (was level - 1). Grace only adds selectability, so solvability is unaffected.

- New default strategy `tangled`: peels low tiles first (fewer matches open at
  once → harder) but disperses each exposed upper tile into the base, so the
  top never forms a "ready-made" cluster. Measured ~20% fewer simultaneous
  matches than scatter (branching 7.6 vs 9.4) with 0% top-cluster — restoring
  the old default's difficulty without its artifact. scatter and the others
  remain selectable.
@vercel

vercel Bot commented May 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
eureka Ready Ready Preview, Comment May 25, 2026 4:55pm

@supabase

supabase Bot commented May 25, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project lthqyqlislwikgoxmttn because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e33ee65d-b0be-45b5-88d0-650b73e50a18

📥 Commits

Reviewing files that changed from the base of the PR and between 426cb0c and 82c0464.

📒 Files selected for processing (6)
  • CLAUDE.md
  • src/utils/init-gameboard.test.ts
  • src/utils/init-gameboard.ts
  • src/utils/order-strategies.test.ts
  • src/utils/order-strategies.ts
  • src/utils/solvable-board.test.ts

📝 Walkthrough

Walkthrough

Introduces a new tangled board peel strategy as the production default, which disperses upper-layer tiles by pairing them with base tiles. Restructures grace-tile difficulty scaling to use fixed level-based thresholds (0, 1, 2, 3) instead of linear level - 1 calculation. Updates all related tests and documentation accordingly.

Changes

Tangled Strategy and Grace-Tiles Ramp

Layer / File(s) Summary
Tangled Peeling Strategy
src/utils/order-strategies.ts, src/utils/order-strategies.test.ts
Implements new tangled strategy that peels low-layer tiles and pairs exposed upper-layer tiles with base tiles to avoid top clustering. Updates registry and marks tangled as DEFAULT_STRATEGY. Test asserts new default.
Grace-Tiles Level-Based Ramp
src/utils/init-gameboard.ts, src/utils/init-gameboard.test.ts, src/utils/solvable-board.test.ts
Replaces linear level - 1 grace-tile logic with threshold-based counts: 0 (L1), 1 (L2–L4), 2 (L5–L14), 3 (L15+). Updates core logic, comments, and grace-tile expectations across test suites.
Strategy and Difficulty Documentation
CLAUDE.md
Documents tangled as production default, clarifies adapter seam with selectable strategies, explains level-based grace-tile ramp and internal canonical fallback.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • riethmayer/eureka#45: Both PRs modify src/utils/order-strategies.ts and its strategy setup—this PR adds the new tangled strategy and changes DEFAULT_STRATEGY to "tangled", building directly on the existing order-strategy adapter seam and prior "scatter" default.

Poem

🐰 A tangled web we weave with tile,
Low layers peeled with upper-tile guile,
Grace tiles scale in thresholds neat,
From level's ramp to harder beat,
New defaults set, the board's complete! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main changes: a slower grace tile ramp and the adoption of a harder default strategy (tangled), which directly correspond to the primary objectives of this difficulty-tuning pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch grace-tile-scaling

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/utils/init-gameboard.test.ts

Oops! Something went wrong! :(

ESLint: 9.39.4

TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'configs' -> object with constructor 'Object'
| property 'flat' -> object with constructor 'Object'
| ...
| property 'plugins' -> object with constructor 'Object'
--- property 'react' closes the circle
Referenced from: /.eslintrc.json
at JSON.stringify ()
at /node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2255:45
at Array.map ()
at ConfigValidator.formatErrors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2246:23)
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2277:84)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3123:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3088:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3393:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3261:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3199:25)
(node:2) ESLintRCWarning: You are using an eslintrc configuration file, which is deprecated and support will be removed in v10.0.0. Please migrate to an eslint.config.js file. See https://eslint.org/docs/latest/use/configure/migration-guide for details. An eslintrc configuration file is used because you have the ESLINT_USE_FLAT_CONFIG environment variable set to false. If you want to use an eslint.config.js file, remove the environment variable. If you want to find the location of the eslintrc configuration file, use the --debug flag.
(Use node --trace-warnings ... to show where the warning was created)

src/utils/init-gameboard.ts

Oops! Something went wrong! :(

ESLint: 9.39.4

TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'configs' -> object with constructor 'Object'
| property 'flat' -> object with constructor 'Object'
| ...
| property 'plugins' -> object with constructor 'Object'
--- property 'react' closes the circle
Referenced from: /.eslintrc.json
at JSON.stringify ()
at /node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2255:45
at Array.map ()
at ConfigValidator.formatErrors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2246:23)
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2277:84)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3123:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3088:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3393:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3261:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3199:25)
(node:2) ESLintRCWarning: You are using an eslintrc configuration file, which is deprecated and support will be removed in v10.0.0. Please migrate to an eslint.config.js file. See https://eslint.org/docs/latest/use/configure/migration-guide for details. An eslintrc configuration file is used because you have the ESLINT_USE_FLAT_CONFIG environment variable set to false. If you want to use an eslint.config.js file, remove the environment variable. If you want to find the location of the eslintrc configuration file, use the --debug flag.
(Use node --trace-warnings ... to show where the warning was created)

src/utils/order-strategies.test.ts

Oops! Something went wrong! :(

ESLint: 9.39.4

TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Object'
| property 'configs' -> object with constructor 'Object'
| property 'flat' -> object with constructor 'Object'
| ...
| property 'plugins' -> object with constructor 'Object'
--- property 'react' closes the circle
Referenced from: /.eslintrc.json
at JSON.stringify ()
at /node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2255:45
at Array.map ()
at ConfigValidator.formatErrors (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2246:23)
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2277:84)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3123:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3088:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3393:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3261:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3199:25)
(node:2) ESLintRCWarning: You are using an eslintrc configuration file, which is deprecated and support will be removed in v10.0.0. Please migrate to an eslint.config.js file. See https://eslint.org/docs/latest/use/configure/migration-guide for details. An eslintrc configuration file is used because you have the ESLINT_USE_FLAT_CONFIG environment variable set to false. If you want to use an eslint.config.js file, remove the environment variable. If you want to find the location of the eslintrc configuration file, use the --debug flag.
(Use node --trace-warnings ... to show where the warning was created)

  • 2 others

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@riethmayer riethmayer merged commit bc93a38 into master May 25, 2026
6 checks passed
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