feat(core): card/pile conversion utils and GameMode-aware scoring (steps 2-prep, 5)
Build and Deploy / build-and-push (push) Failing after 55s

Step 2 prep — card_game dep + type-conversion utilities:
- Add card_game = "0.3.0" (registry Quaternions) to workspace + core
- suit_to_kl / suit_from_kl, rank_to_kl / rank_from_kl
- card_to_kl (drops id, Deck1), card_from_kl (reconstructs stable id
  from Clubs-first suit×13+rank ordering matching deck.rs)
- Ready to wire into KlondikeState pile projection once upstream
  adds KlondikeState::from_piles()

Step 5 — GameMode-aware scoring in the adapter:
- score_for_move_with_mode, score_for_flip_with_mode (return 0 in Zen)
- apply_undo_score (static, handles Zen + −15 penalty + clamp)
- score_for_recycle_with_mode (return 0 in Zen)
- game_state.rs: all inline GameMode::Zen checks replaced with
  adapter calls; adapter is now the single source of truth for
  "what score does this action give in this mode"

192 tests pass; clippy -D warnings clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-29 14:38:41 -07:00
parent f1914b4398
commit 57c4b5aacf
5 changed files with 121 additions and 18 deletions
+10 -17
View File
@@ -275,11 +275,12 @@ impl GameState {
stock.cards.push(card);
}
self.recycle_count = self.recycle_count.saturating_add(1);
if self.mode != GameMode::Zen {
let penalty =
KlondikeAdapter::score_for_recycle(self.recycle_count, self.draw_mode == DrawMode::DrawThree);
self.score = (self.score + penalty).max(0);
}
let penalty = KlondikeAdapter::score_for_recycle_with_mode(
self.recycle_count,
self.draw_mode == DrawMode::DrawThree,
self.mode,
);
self.score = (self.score + penalty).max(0);
self.move_count = self.move_count.saturating_add(1);
return Ok(());
}
@@ -411,11 +412,7 @@ impl GameState {
start
};
let score_delta = if self.mode == GameMode::Zen {
0
} else {
self.adapter.score_for_move(&from, &to)
};
let score_delta = self.adapter.score_for_move_with_mode(&from, &to, self.mode);
self.push_snapshot();
// Execute move
@@ -446,8 +443,8 @@ impl GameState {
.cards
.append(&mut moved);
let flip_bonus = if flipped && self.mode != GameMode::Zen {
self.adapter.score_for_flip()
let flip_bonus = if flipped {
self.adapter.score_for_flip_with_mode(self.mode)
} else {
0
};
@@ -478,11 +475,7 @@ impl GameState {
.pop_back()
.ok_or(MoveError::UndoStackEmpty)?;
self.piles = snapshot.piles;
self.score = if self.mode == GameMode::Zen {
0
} else {
(snapshot.score + KlondikeAdapter::score_for_undo()).max(0)
};
self.score = KlondikeAdapter::apply_undo_score(snapshot.score, self.mode);
self.move_count = snapshot.move_count;
self.is_won = false;
self.is_auto_completable = false;