feat(difficulty): add difficulty-tier game mode with seed catalogs and home UI

Adds DifficultyLevel (Easy/Medium/Hard/Expert/Grandmaster/Random) to
solitaire_core::game_state alongside GameMode::Difficulty(DifficultyLevel).
Five seed catalogs (40 seeds each) are pre-verified by the new
gen_difficulty_seeds binary using tiered solver budgets (1K–200K moves).
DifficultyPlugin resolves StartDifficultyRequestEvent → catalog seed →
NewGameRequestEvent; Random uses a system-time seed and bypasses the
winnable-only filter. The home overlay gets an expandable Difficulty section
between Draw Mode and the mode grid; last-played tier persists in Settings.
Difficulty wins pool into Classic stats. 5 unit tests in difficulty_plugin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-08 21:07:49 -07:00
parent 4df962ee07
commit 4303ef3f5b
14 changed files with 1074 additions and 29 deletions
+24 -15
View File
@@ -6,21 +6,28 @@ project follows [Semantic Versioning](https://semver.org/).
## [Unreleased]
**`395a322`** — double-tap auto-move (2026-05-08).
**`0cb1587`** — Play-by-Seed dialog (2026-05-08).
**`2062bd0`** — 75 new challenge seeds + gen_seeds binary (2026-05-08).
**`45436d0`** — gate handle_fullscreen to non-Android (2026-05-08).
**`2c822ba`** — JNI clipboard bridge for Android Stats share-link (2026-05-08).
**`f281425`** — Android Keystore AES-GCM token storage via JNI (2026-05-08).
See [0.21.9] for the committed detail once cut.
## [0.22.0] — 2026-05-08
## [0.21.9] — pending cut
Closes the "Prev/Next selector chips spawn site" punch-list item from
v0.19.0.
Adds difficulty-tier game selection, Android JNI bridges for keystore and
clipboard, Play-by-Seed dialog, and double-tap auto-move on touch screens.
Also closes the Prev/Next replay-selector spawn-site item carried since v0.19.0.
### Added
- **Difficulty-tier game mode** (this release).
`DifficultyLevel` enum (`Easy / Medium / Hard / Expert / Grandmaster /
Random`) added to `solitaire_core::game_state` alongside a new
`GameMode::Difficulty(DifficultyLevel)` variant. Five pre-verified seed
catalogs (40 seeds each, 200 total) are generated by the new
`gen_difficulty_seeds` binary in `solitaire_assetgen`; each catalog
contains seeds proven winnable at progressively larger solver budgets
(1 K → 200 K moves). `DifficultyPlugin` resolves `StartDifficultyRequestEvent`
→ catalog seed → `NewGameRequestEvent`; the `Random` tier uses a
system-time seed and intentionally bypasses the winnable-only filter.
The home overlay gains an expandable `▶ Difficulty` section between the
Draw Mode row and the mode-card grid; the last-played tier is persisted
in `Settings::last_difficulty` and pre-expands/highlights on re-open.
Difficulty wins pool into Classic stats (no separate buckets).
- **Prev/Next replay selector in the Stats overlay** (`a449f60`).
`ReplayPrevButton`, `ReplayNextButton`, `ReplaySelectorCaption`, and
`ReplaySelectorDetail` nodes now spawn inside `spawn_stats_screen`
@@ -116,11 +123,13 @@ confirmed end-to-end device run.
### Stats
- Tests: **1292 passing** / 0 failing (+10 from double-tap + Play-by-Seed tests)
- Tests: **1300+ passing** / 0 failing
- Clippy: clean
- Crates touched: `solitaire_engine` (input_plugin, events, home_plugin,
play_by_seed_plugin, lib), `solitaire_app` (lib.rs), `solitaire_data`
(challenge.rs), `solitaire_assetgen` (gen_seeds binary, Cargo.toml)
- Crates touched: `solitaire_core` (game_state), `solitaire_data`
(settings, stats, difficulty_seeds, challenge), `solitaire_engine`
(events, difficulty_plugin, home_plugin, hud_plugin, win_summary_plugin,
input_plugin, play_by_seed_plugin, lib), `solitaire_app` (lib.rs),
`solitaire_assetgen` (gen_difficulty_seeds + gen_seeds binaries)
## [0.21.8] — 2026-05-08