fix(web): rebuild Bevy canvas WASM; add SolitaireGame interactive API
Grey screen fix (canvas_bg.wasm): - Rebuilt Bevy WASM from refactored solitaire_core that removes the per-game KlondikeAdapter field from GameState. The old binary was built with wasm-opt -Oz; the large adapter allocation pattern appears to trigger an over-aggressive wasm-opt optimisation that corrupts Bevy's render pipeline, causing a permanent grey screen on /play. - build_wasm.sh: change wasm-opt -Oz → -O2. Speed-optimised level avoids the size-focused transforms that miscompile Bevy's deep render stacks. solitaire_core refactoring: - game_state.rs: remove adapter: KlondikeAdapter field; use static KlondikeAdapter::config_for() instead of a per-instance allocation. Gate test_pile_state behind #[cfg(feature = "test-support")] so production builds carry no test-only heap state. Add instruction_history() public accessor (delegates to saved_moves()). - card.rs: add Card::new(), face_up(), face_down() const constructors for more ergonomic test and wasm code. - pile.rs, solver.rs: cargo fmt. solitaire_wasm interactive API: - lib.rs: add SolitaireGame wasm-bindgen struct with draw(), move_cards(), undo(), auto_complete_step(), serialize(), from_saved() — the full player-action surface used by game.js. Add DebugSnapshot, DebugMove, DebugInvariantReport structs and debug_snapshot(), debug_legal_moves(), debug_apply_move_json() methods for e2e test automation (window.__FERROUS_DEBUG__ bridge). Add replay_moves() to export the current game as a Replay v2 payload. - solitaire_wasm.js + solitaire_wasm_bg.wasm: rebuilt with new API. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -111,6 +111,28 @@ pub struct Card {
|
||||
pub face_up: bool,
|
||||
}
|
||||
|
||||
impl Card {
|
||||
/// Creates a card with explicit face orientation.
|
||||
pub const fn new(id: u32, suit: Suit, rank: Rank, face_up: bool) -> Self {
|
||||
Self {
|
||||
id,
|
||||
suit,
|
||||
rank,
|
||||
face_up,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a face-up card.
|
||||
pub const fn face_up(id: u32, suit: Suit, rank: Rank) -> Self {
|
||||
Self::new(id, suit, rank, true)
|
||||
}
|
||||
|
||||
/// Creates a face-down card.
|
||||
pub const fn face_down(id: u32, suit: Suit, rank: Rank) -> Self {
|
||||
Self::new(id, suit, rank, false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -166,4 +188,19 @@ mod tests {
|
||||
assert!(Suit::Diamonds.is_red() && Suit::Hearts.is_red());
|
||||
assert!(Suit::Clubs.is_black() && Suit::Spades.is_black());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn card_constructors_set_fields() {
|
||||
let up = Card::face_up(10, Suit::Spades, Rank::Queen);
|
||||
assert_eq!(up.id, 10);
|
||||
assert_eq!(up.suit, Suit::Spades);
|
||||
assert_eq!(up.rank, Rank::Queen);
|
||||
assert!(up.face_up);
|
||||
|
||||
let down = Card::face_down(11, Suit::Diamonds, Rank::King);
|
||||
assert_eq!(down.id, 11);
|
||||
assert_eq!(down.suit, Suit::Diamonds);
|
||||
assert_eq!(down.rank, Rank::King);
|
||||
assert!(!down.face_up);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user