refactor: slim solver to card_game-native types
Per Rhys: card_game's solver is the real engine, so drop the redundant
adapter types in solitaire_data::solver rather than maintain a parallel
verdict/config/move vocabulary.
- Delete SolverResult, SolverConfig, SolverMove, and snapshot_to_solver_move.
The verdict now reads straight off card_game's return:
Ok(Some(instr)) = winnable (first move on the path)
Ok(None) = provably unwinnable
Err(_) = inconclusive (budget exceeded)
- SolveOutcome is now Result<Option<KlondikeInstruction>, SolveError>.
- try_solve / try_solve_from_state take plain (moves_budget, states_budget)
u64s; add DEFAULT_SOLVE_{MOVES,STATES}_BUDGET consts.
- snapshot_to_solver_move duplicated core's GameState::instruction_to_move,
so make that pub and have the hint convert the first-move instruction to
highlighted (from, to) piles through it. Re-export KlondikeInstruction
from solitaire_core.
- HintSolverConfig now holds { moves_budget, states_budget } instead of
wrapping the deleted SolverConfig.
- Update consumers: pending_hint, play_by_seed (verdict badge), game_plugin
(choose_winnable_seed), input_plugin, hud_plugin, and the gen_seeds /
gen_difficulty_seeds asset tools.
solver.rs drops 274 -> 140 lines. cargo test --workspace and
cargo clippy --workspace --all-targets -- -D warnings pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -79,13 +79,25 @@ fn dragged_card_z(index: usize) -> f32 {
|
||||
|
||||
/// Solver budgets used by the H-key hint system.
|
||||
///
|
||||
/// Wraps `solitaire_data::solver::SolverConfig` as a Bevy resource so
|
||||
/// tests can inject tighter budgets to exercise the heuristic-fallback
|
||||
/// path. Production initialises this to `SolverConfig::default()` (100k
|
||||
/// move / 200k state budgets, the same numbers the new-game retry loop
|
||||
/// uses).
|
||||
#[derive(Resource, Debug, Clone, Default)]
|
||||
pub struct HintSolverConfig(pub solitaire_data::solver::SolverConfig);
|
||||
/// A Bevy resource so tests can inject tighter budgets to exercise the
|
||||
/// heuristic-fallback path. Production initialises this to the same default
|
||||
/// 100k move / 200k state budgets the new-game retry loop uses.
|
||||
#[derive(Resource, Debug, Clone, Copy)]
|
||||
pub struct HintSolverConfig {
|
||||
/// Maximum solver moves before giving up (inconclusive).
|
||||
pub moves_budget: u64,
|
||||
/// Maximum unique solver states before giving up (inconclusive).
|
||||
pub states_budget: u64,
|
||||
}
|
||||
|
||||
impl Default for HintSolverConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
moves_budget: solitaire_data::solver::DEFAULT_SOLVE_MOVES_BUDGET,
|
||||
states_budget: solitaire_data::solver::DEFAULT_SOLVE_STATES_BUDGET,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers keyboard, mouse, and touch input systems.
|
||||
///
|
||||
@@ -277,7 +289,7 @@ fn handle_keyboard_core(
|
||||
/// turns into hint visuals one frame later.
|
||||
///
|
||||
/// Median solve time is ~2 ms but pathological positions can hit the
|
||||
/// `SolverConfig::default()` cap at ~120 ms; running synchronously
|
||||
/// default solve budget at ~120 ms; running synchronously
|
||||
/// (the v0.17.0 behaviour) blocked the main thread on the same frame
|
||||
/// the player pressed H. Cancel-on-replace lives in
|
||||
/// `PendingHintTask::spawn` — a fresh H press while a previous task
|
||||
@@ -314,7 +326,11 @@ fn handle_keyboard_hint(
|
||||
|
||||
let Some(_layout_res) = layout else { return };
|
||||
|
||||
pending_hint.spawn(g.0.clone(), solver_config.0);
|
||||
pending_hint.spawn(
|
||||
g.0.clone(),
|
||||
solver_config.moves_budget,
|
||||
solver_config.states_budget,
|
||||
);
|
||||
}
|
||||
|
||||
/// Heuristic hint helper used by `pending_hint::poll_pending_hint_task`
|
||||
|
||||
Reference in New Issue
Block a user