//! Adapter bridging `solitaire_core` types to the upstream `klondike` crate. //! //! [`KlondikeAdapter`] is a pure helper namespace for: //! - building [`KlondikeConfig`] from Ferrous settings //! - translating between local and upstream types //! //! Ferrous-specific scoring policy (the win-time bonus) lives in //! [`crate::scoring`], not here. //! //! All `From` / `TryFrom` conversions between `solitaire_core` product types and //! upstream `card_game` / `klondike` types live here so that the product modules //! (`card`, `pile`, etc.) remain free of upstream dependencies. use klondike::{ DrawStockConfig, Foundation, KlondikeConfig, MoveFromFoundationConfig, ScoringConfig, SkipCards, Tableau, }; /// Bridges `solitaire_core` game config to the upstream `klondike` crate. /// /// This type is intentionally zero-sized: it does not carry mutable runtime /// state, and exists only as a namespace for configuration and conversion /// helpers. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] pub struct KlondikeAdapter; impl KlondikeAdapter { /// Build a [`KlondikeConfig`] from draw mode and foundation house-rule setting. pub fn config_for(draw_mode: DrawStockConfig, take_from_foundation: bool) -> KlondikeConfig { KlondikeConfig { draw_stock: draw_mode, move_from_foundation: if take_from_foundation { MoveFromFoundationConfig::Allowed } else { MoveFromFoundationConfig::Disallowed }, scoring: ScoringConfig::DEFAULT, } } } /// Convert a zero-based tableau index (0..=6) into [`Tableau`]. pub fn tableau_from_index(index: usize) -> Option { match index { 0 => Some(Tableau::Tableau1), 1 => Some(Tableau::Tableau2), 2 => Some(Tableau::Tableau3), 3 => Some(Tableau::Tableau4), 4 => Some(Tableau::Tableau5), 5 => Some(Tableau::Tableau6), 6 => Some(Tableau::Tableau7), _ => None, } } /// Convert a zero-based foundation slot (0..=3) into [`Foundation`]. pub fn foundation_from_slot(slot: u8) -> Option { match slot { 0 => Some(Foundation::Foundation1), 1 => Some(Foundation::Foundation2), 2 => Some(Foundation::Foundation3), 3 => Some(Foundation::Foundation4), _ => None, } } /// Convert a tableau skip count (0..=12) into [`SkipCards`]. pub fn skip_cards_from_count(skip: usize) -> Option { match skip { 0 => Some(SkipCards::Skip0), 1 => Some(SkipCards::Skip1), 2 => Some(SkipCards::Skip2), 3 => Some(SkipCards::Skip3), 4 => Some(SkipCards::Skip4), 5 => Some(SkipCards::Skip5), 6 => Some(SkipCards::Skip6), 7 => Some(SkipCards::Skip7), 8 => Some(SkipCards::Skip8), 9 => Some(SkipCards::Skip9), 10 => Some(SkipCards::Skip10), 11 => Some(SkipCards::Skip11), 12 => Some(SkipCards::Skip12), _ => None, } }