refactor(core): card_game redundancy cleanup + derive scoring from upstream stats #88

Open
funman300 wants to merge 4 commits from refactor/strip-card_game-redundancies into master
Owner

Summary

This branch carries two related strands of the card_game/klondike migration:

  1. Leftover redundancy cleanup — a workspace audit found four small remaining redundancies after the migration (the rest of GameState/klondike_adapter is load-bearing boundary code).
  2. Scoring migration (issues #84, #86, #87)GameState's hand-rolled WXP scoring state is replaced by values derived from the upstream session stats. This became possible after upstream card_game 0.4.1 / klondike 0.4.0, which now track undos and recycle_count and default undo_penalty to −15.

Changes

Redundancy cleanup

  • core: delete dead GameState::compute_time_bonus (zero callers; engine uses the klondike_adapter free fn)
  • data: drop dead public re-exports load_latest_replay_from/save_latest_replay_to (no callers outside replay.rs); keep latest_replay_path (engine legacy migration uses it)
  • data+engine: lift win-XP scoring into a shared XpBreakdown so the win-summary modal and xp_for_win share one source of truth
  • engine: replace feedback_anim_plugin's private foundation_from_slot copy with the canonical klondike_adapter::foundation_from_slot

Scoring migration — commit 372b642 (closes #84, #86, #87)

  • core (#87): remove GameState fields score, undo_count, recycle_count
  • core (#86): remove the score_history + is_recycle_history undo journal
  • core (#84): remove KlondikeAdapter::apply_undo_score, the score_for_* helpers, and pre_instruction_score_delta / will_flip_tableau_source
  • core: add derived accessors score() / undo_count() / recycle_count() reading session.stats(); the −15 undo penalty is now SessionConfig::undo_penalty, applied by the upstream score formula
  • core: save schema bumped v4 → v5 — the three counters are no longer persisted; they are rebuilt by replaying the forward instruction history on load (v3/v4 saves still load, extra keys ignored)
  • engine/wasm/data: convert the field-access sites to the derived method calls; test helpers drive real play instead of assigning the now-derived values

Intentional behavior changes: the escalating recycle penalty and per-step score floor are gone (upstream linear scoring, floored once at 0); recycle_count is now cumulative (upstream does not roll it back on undo); undo_count resets across save/load (only the forward history is persisted).

Verification

cargo test --workspace (core 52, data 134, engine 897, + others — all green) and cargo clippy --workspace --all-targets -- -D warnings clean.

🤖 Generated with Claude Code

## Summary This branch carries two related strands of the `card_game`/`klondike` migration: 1. **Leftover redundancy cleanup** — a workspace audit found four small remaining redundancies after the migration (the rest of `GameState`/`klondike_adapter` is load-bearing boundary code). 2. **Scoring migration (issues #84, #86, #87)** — `GameState`'s hand-rolled WXP scoring state is replaced by values **derived** from the upstream session stats. This became possible after upstream `card_game 0.4.1` / `klondike 0.4.0`, which now track `undos` and `recycle_count` and default `undo_penalty` to −15. ## Changes ### Redundancy cleanup - **core:** delete dead `GameState::compute_time_bonus` (zero callers; engine uses the `klondike_adapter` free fn) - **data:** drop dead public re-exports `load_latest_replay_from`/`save_latest_replay_to` (no callers outside `replay.rs`); keep `latest_replay_path` (engine legacy migration uses it) - **data+engine:** lift win-XP scoring into a shared `XpBreakdown` so the win-summary modal and `xp_for_win` share one source of truth - **engine:** replace `feedback_anim_plugin`'s private `foundation_from_slot` copy with the canonical `klondike_adapter::foundation_from_slot` ### Scoring migration — commit `372b642` (closes #84, #86, #87) - **core (#87):** remove `GameState` fields `score`, `undo_count`, `recycle_count` - **core (#86):** remove the `score_history` + `is_recycle_history` undo journal - **core (#84):** remove `KlondikeAdapter::apply_undo_score`, the `score_for_*` helpers, and `pre_instruction_score_delta` / `will_flip_tableau_source` - **core:** add derived accessors `score()` / `undo_count()` / `recycle_count()` reading `session.stats()`; the −15 undo penalty is now `SessionConfig::undo_penalty`, applied by the upstream score formula - **core:** save schema bumped **v4 → v5** — the three counters are no longer persisted; they are rebuilt by replaying the forward instruction history on load (v3/v4 saves still load, extra keys ignored) - **engine/wasm/data:** convert the field-access sites to the derived method calls; test helpers drive real play instead of assigning the now-derived values **Intentional behavior changes:** the escalating recycle penalty and per-step score floor are gone (upstream linear scoring, floored once at 0); `recycle_count` is now cumulative (upstream does not roll it back on undo); `undo_count` resets across save/load (only the forward history is persisted). ## Verification `cargo test --workspace` (core 52, data 134, engine 897, + others — all green) and `cargo clippy --workspace --all-targets -- -D warnings` clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
funman300 added 1 commit 2026-06-11 04:12:14 +00:00
Post-migration audit found the card_game/klondike migration essentially
complete; these are the four small redundancies that remained:

- core: delete dead GameState::compute_time_bonus (zero callers; engine
  uses the klondike_adapter free fn directly)
- data: drop dead public re-exports load_latest_replay_from /
  save_latest_replay_to (no callers outside replay.rs); keep
  latest_replay_path (engine legacy migration still uses it)
- data+engine: lift win-XP scoring into a shared XpBreakdown so the
  win-summary modal breakdown and xp_for_win share one source of truth
  instead of duplicating the speed/no-undo constants
- engine: replace feedback_anim_plugin's private foundation_from_slot
  copy with the canonical klondike_adapter::foundation_from_slot

cargo test --workspace + clippy -D warnings green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
funman300 added 1 commit 2026-06-11 04:17:06 +00:00
Keep Codex / claude-flow scaffolding (.agents/, .codex/, AGENTS.md) out
of the repo — these are locally generated and not project sources.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
funman300 added 1 commit 2026-06-11 17:49:22 +00:00
Replace the bespoke WXP scoring engine with the upstream
card_game/klondike session stats, eliminating duplicated state that
could drift from the single source of truth.

score()/undo_count()/recycle_count() now read session.stats(); the -15
undo penalty is configured as SessionConfig::undo_penalty and applied by
the upstream score formula. Save schema bumped v4 -> v5 (the three
counters are no longer persisted -- they are rebuilt by replaying the
forward instruction history on load).

- Remove GameState fields score, undo_count, recycle_count (#87)
- Remove score_history / is_recycle_history undo journal (#86)
- Remove KlondikeAdapter::apply_undo_score and the score_for_* helpers,
  plus pre_instruction_score_delta / will_flip_tableau_source (#84)

These three issues are a single atomic change: each removed field/helper
is consumed by the same draw/apply_instruction/undo/serde/PartialEq
paths, so they cannot compile or pass tests in isolation.

Behaviour changes (intentional): the escalating recycle penalty and
per-step score floor are gone (upstream linear scoring, floored once at
0); recycle_count is now cumulative; undo_count resets across save/load.

Refs #84, #86, #87

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
funman300 changed title from refactor: remove leftover redundancies after card_game migration to refactor(core): card_game redundancy cleanup + derive scoring from upstream stats 2026-06-11 17:53:46 +00:00
funman300 added 1 commit 2026-06-11 18:06:32 +00:00
Replace O(n) `Query::iter().find()` card scans with O(1) `CardEntityIndex`
lookups in the mouse and touch drag pipelines (`follow_drag`, `end_drag`,
`touch_follow_drag`, `touch_end_drag`) and `update_drag_shadow` — 7 sites
across 5 systems. Each ran per dragged card per frame during a drag.

`InputPlugin` now defensively `init_resource::<CardEntityIndex>()` (idempotent;
`CardPlugin` still owns and rebuilds it) so the plugin is self-sufficient in
tests. The lone remaining card-keyed `.find` is a `#[cfg(test)]` world-query
helper, which is the correct pattern there.

Completes the CardEntityIndex migration started in ef1efdc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin refactor/strip-card_game-redundancies:refactor/strip-card_game-redundancies
git checkout refactor/strip-card_game-redundancies
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: funman300/Ferrous-Solitaire#88