refactor(core,engine,wasm): canonical FOUNDATIONS/TABLEAUS consts; adopt upstream SUITS/RANKS

Review findings 1+2 (Quat-underuse lens, 2026-07-06):

- solitaire_core gains pub const FOUNDATIONS / TABLEAUS — the canonical
  iteration source for the upstream pile enums (upstream klondike has no
  Foundation::ALL, and inherent impls cannot be added to foreign types).
  Deletes three identical private const-fn copies (radial_menu,
  table_plugin, input_plugin) and the hand-enumerated variants in
  card_plugin::sync::all_cards and solitaire_wasm.

- Hand-rolled [Suit; 4] / [Rank; 13] arrays replaced with upstream
  Suit::SUITS / Rank::RANKS. The order-sensitive CardImageSet indexing
  is re-keyed through canonical card_plugin::{suit_index, rank_index}
  helpers that match upstream order, with regression tests asserting
  the correspondence — one ordering everywhere instead of three
  divergent local ones.

Net -177 lines. No behaviour change; all consumers go through the
canonical helpers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-07-06 19:58:33 -07:00
parent 15bb136c79
commit 7a5f03987d
11 changed files with 120 additions and 297 deletions
+9 -27
View File
@@ -28,6 +28,7 @@ use bevy::window::PrimaryWindow;
#[cfg(not(target_os = "android"))]
use bevy::window::{MonitorSelection, WindowMode};
use solitaire_core::{Foundation, KlondikeInstruction, KlondikePile, Tableau};
use solitaire_core::{FOUNDATIONS, TABLEAUS};
use solitaire_core::{Card, Suit};
use solitaire_core::game_state::GameState;
@@ -1329,13 +1330,13 @@ const DOUBLE_TAP_FLASH_SECS: f32 = 0.35;
pub fn best_destination(card: &Card, game: &GameState) -> Option<KlondikePile> {
let source = game.pile_containing_card(card.clone())?;
for foundation in foundations() {
for foundation in FOUNDATIONS {
let dest = KlondikePile::Foundation(foundation);
if game.can_move_cards(&source, &dest, 1) {
return Some(dest);
}
}
for tableau in tableaus() {
for tableau in TABLEAUS {
let dest = KlondikePile::Tableau(tableau);
if game.can_move_cards(&source, &dest, 1) {
return Some(dest);
@@ -1356,7 +1357,7 @@ pub fn best_tableau_destination_for_stack(
game: &GameState,
stack_count: usize,
) -> Option<(KlondikePile, usize)> {
for tableau in tableaus() {
for tableau in TABLEAUS {
let dest = KlondikePile::Tableau(tableau);
if game.can_move_cards(from, &dest, stack_count) {
return Some((dest, stack_count));
@@ -1692,7 +1693,7 @@ pub(crate) fn hint_piles(
fn legacy_all_hints(game: &GameState) -> Vec<(KlondikePile, KlondikePile)> {
let sources: Vec<KlondikePile> = {
let mut s = vec![KlondikePile::Stock];
for tableau in tableaus() {
for tableau in TABLEAUS {
s.push(KlondikePile::Tableau(tableau));
}
s
@@ -1706,7 +1707,7 @@ fn legacy_all_hints(game: &GameState) -> Vec<(KlondikePile, KlondikePile)> {
let Some(_card) = from_pile.last().filter(|(_, face_up)| *face_up) else {
continue;
};
for foundation in foundations() {
for foundation in FOUNDATIONS {
let dest = KlondikePile::Foundation(foundation);
if game.can_move_cards(from, &dest, 1) {
hints.push((*from, dest));
@@ -1728,7 +1729,7 @@ fn legacy_all_hints(game: &GameState) -> Vec<(KlondikePile, KlondikePile)> {
if already_has_foundation_hint {
continue;
}
for tableau in tableaus() {
for tableau in TABLEAUS {
let dest = KlondikePile::Tableau(tableau);
if game.can_move_cards(from, &dest, 1) {
hints.push((*from, dest));
@@ -1742,13 +1743,13 @@ fn legacy_all_hints(game: &GameState) -> Vec<(KlondikePile, KlondikePile)> {
// should never hint Foundation→Foundation. Here we handle the return path
// separately so the guarded `take_from_foundation` rule is respected.
if game.take_from_foundation {
for foundation in foundations() {
for foundation in FOUNDATIONS {
let from = KlondikePile::Foundation(foundation);
let from_pile = pile_cards(game, &from);
let Some(_card) = from_pile.last().filter(|(_, face_up)| *face_up) else {
continue;
};
for tableau in tableaus() {
for tableau in TABLEAUS {
let dest = KlondikePile::Tableau(tableau);
if game.can_move_cards(&from, &dest, 1) {
hints.push((from, dest));
@@ -1782,26 +1783,7 @@ fn pile_cards(game: &GameState, pile: &KlondikePile) -> Vec<(Card, bool)> {
}
}
const fn foundations() -> [Foundation; 4] {
[
Foundation::Foundation1,
Foundation::Foundation2,
Foundation::Foundation3,
Foundation::Foundation4,
]
}
const fn tableaus() -> [Tableau; 7] {
[
Tableau::Tableau1,
Tableau::Tableau2,
Tableau::Tableau3,
Tableau::Tableau4,
Tableau::Tableau5,
Tableau::Tableau6,
Tableau::Tableau7,
]
}
const fn tableau_number(tableau: Tableau) -> u8 {
match tableau {