refactor(core): derive draw_mode/is_won/move_count/is_auto_completable from session
Remove the draw_mode, move_count, is_won, and is_auto_completable fields from GameState; they are now &self methods deriving from the underlying card_game session (draw_mode from session config, move_count from history length, is_won/is_auto_completable from check_win/check_auto_complete). Tests previously fabricated these via direct field writes, which is no longer possible. Add gated test-support overrides on TestPileState (won/auto_completable/move_count) plus setters set_test_won, set_test_auto_completable, set_test_move_count, and set_test_draw_mode (re-deals the seed). All compiled out in production builds. Fix the field->method ripple across solitaire_data, solitaire_wasm, and solitaire_engine. Add a test-support dev-dependency to solitaire_data for the won-game storage test. cargo test --workspace and cargo clippy --workspace -- -D warnings pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+10
-10
@@ -194,8 +194,8 @@ impl ReplayPlayer {
|
||||
step_idx: self.step_idx,
|
||||
total_steps: self.moves.len(),
|
||||
score: self.game.score,
|
||||
move_count: self.game.move_count,
|
||||
is_won: self.game.is_won,
|
||||
move_count: self.game.move_count(),
|
||||
is_won: self.game.is_won(),
|
||||
stock: self
|
||||
.game
|
||||
.stock_cards()
|
||||
@@ -359,7 +359,7 @@ fn pile_name(pile: KlondikePile) -> String {
|
||||
}
|
||||
|
||||
fn can_stock_click(game: &GameState) -> bool {
|
||||
!(game.is_won || game.stock_cards().is_empty() && game.waste_cards().is_empty())
|
||||
!(game.is_won() || game.stock_cards().is_empty() && game.waste_cards().is_empty())
|
||||
}
|
||||
|
||||
fn legal_moves_for_game(game: &GameState) -> Vec<DebugMove> {
|
||||
@@ -450,7 +450,7 @@ fn invariant_report_for_game(game: &GameState, legal_moves: &[DebugMove]) -> Deb
|
||||
false
|
||||
});
|
||||
|
||||
let soft_lock = !game.is_won && stock.is_empty() && waste.is_empty() && legal_moves.is_empty();
|
||||
let soft_lock = !game.is_won() && stock.is_empty() && waste.is_empty() && legal_moves.is_empty();
|
||||
|
||||
let state_ok = duplicate_card_ids.is_empty()
|
||||
&& missing_card_ids.is_empty()
|
||||
@@ -496,9 +496,9 @@ impl SolitaireGame {
|
||||
};
|
||||
GameSnapshot {
|
||||
score: self.game.score,
|
||||
move_count: self.game.move_count,
|
||||
is_won: self.game.is_won,
|
||||
is_auto_completable: self.game.is_auto_completable,
|
||||
move_count: self.game.move_count(),
|
||||
is_won: self.game.is_won(),
|
||||
is_auto_completable: self.game.is_auto_completable(),
|
||||
has_moves,
|
||||
undo_count: self.game.undo_count,
|
||||
undo_stack_len: self.game.undo_stack_len(),
|
||||
@@ -582,7 +582,7 @@ impl SolitaireGame {
|
||||
|
||||
fn replay_moves_native(&self) -> Result<Vec<ReplayMove>, String> {
|
||||
let mut replay_game =
|
||||
GameState::new_with_mode(self.game.seed, self.game.draw_mode, self.game.mode);
|
||||
GameState::new_with_mode(self.game.seed, self.game.draw_mode(), self.game.mode);
|
||||
let mut replay_moves = Vec::new();
|
||||
|
||||
for instruction in self.game.instruction_history() {
|
||||
@@ -668,7 +668,7 @@ impl SolitaireGame {
|
||||
let state_json = serde_json::to_string(&self.game).unwrap_or_default();
|
||||
DebugSnapshot {
|
||||
seed: self.game.seed,
|
||||
draw_mode: self.game.draw_mode,
|
||||
draw_mode: self.game.draw_mode(),
|
||||
mode: self.game.mode,
|
||||
state: self.snap(),
|
||||
legal_moves,
|
||||
@@ -822,7 +822,7 @@ impl SolitaireGame {
|
||||
/// waste by calling `draw()` so the next step can try again. Returns the
|
||||
/// post-move snapshot, or `null` when no progress is possible.
|
||||
pub fn auto_complete_step(&mut self) -> JsValue {
|
||||
if !self.game.is_auto_completable {
|
||||
if !self.game.is_auto_completable() {
|
||||
return JsValue::NULL;
|
||||
}
|
||||
if let Some((from, to)) = self.game.next_auto_complete_move() {
|
||||
|
||||
Reference in New Issue
Block a user