diff --git a/Cargo.lock b/Cargo.lock index 2515e74..a8df0b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2084,10 +2084,10 @@ dependencies = [ [[package]] name = "card_game" version = "0.4.0" -source = "sparse+https://git.aleshym.co/api/packages/Quaternions/cargo/" -checksum = "d206df6d87340019a0f5b621976cf98bc75c659a7f93ef348aaab2a9336098a9" +source = "git+https://git.aleshym.co/Quaternions/card_game#2eaa99e82dc40ab59ca0033717667fe7f66452d3" dependencies = [ "arrayvec 0.7.6 (sparse+https://git.aleshym.co/api/packages/Quaternions/cargo/)", + "serde", ] [[package]] @@ -4305,7 +4305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" dependencies = [ "byteorder-lite", - "quick-error", + "quick-error 2.0.1", ] [[package]] @@ -4600,8 +4600,7 @@ dependencies = [ [[package]] name = "klondike" version = "0.3.0" -source = "sparse+https://git.aleshym.co/api/packages/Quaternions/cargo/" -checksum = "347d55e6cf7c90b3d038262071eb2fdb0b75a713fe66c452a3400ff08fb716bc" +source = "git+https://git.aleshym.co/Quaternions/card_game#2eaa99e82dc40ab59ca0033717667fe7f66452d3" dependencies = [ "card_game", "rand 0.10.1", @@ -6059,6 +6058,25 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.11.1", + "num-traits", + "rand 0.9.4", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + [[package]] name = "prost" version = "0.14.3" @@ -6103,6 +6121,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quick-error" version = "2.0.1" @@ -6301,6 +6325,15 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.5", +] + [[package]] name = "range-alloc" version = "0.1.5" @@ -6790,6 +6823,18 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "rusty-fork" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" +dependencies = [ + "fnv", + "quick-error 1.2.3", + "tempfile", + "wait-timeout", +] + [[package]] name = "rustybuzz" version = "0.20.1" @@ -7279,6 +7324,7 @@ version = "0.1.0" dependencies = [ "card_game", "klondike", + "proptest", "serde", "thiserror 2.0.18", ] @@ -7289,7 +7335,6 @@ version = "0.1.0" dependencies = [ "async-trait", "axum", - "bevy", "chrono", "dirs", "jni 0.21.1", @@ -8846,6 +8891,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "uncased" version = "0.9.10" @@ -9052,6 +9103,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index b317d7c..2ac9f0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,8 +38,8 @@ solitaire_core = { path = "solitaire_core" } solitaire_sync = { path = "solitaire_sync" } solitaire_data = { path = "solitaire_data" } solitaire_engine = { path = "solitaire_engine" } -klondike = { version = "0.3.0", registry = "Quaternions" } -card_game = { version = "0.4.0", registry = "Quaternions" } +klondike = { git = "https://git.aleshym.co/Quaternions/card_game" } +card_game = { git = "https://git.aleshym.co/Quaternions/card_game", features = ["serde"] } # Bevy with `default-features = false` to avoid the unused # `bevy_audio → rodio + symphonia + cpal 0.15 + alsa 0.9` chain. diff --git a/solitaire_core/src/card.rs b/solitaire_core/src/card.rs index c55a7d1..67af25e 100644 --- a/solitaire_core/src/card.rs +++ b/solitaire_core/src/card.rs @@ -1,102 +1,6 @@ use serde::{Deserialize, Serialize}; -/// Card suit. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Suit { - Clubs, - Diamonds, - Hearts, - Spades, -} - -impl Suit { - /// All four suits in declaration order. - pub const SUITS: [Self; 4] = [Self::Clubs, Self::Diamonds, Self::Hearts, Self::Spades]; - - /// Returns `true` for red suits (Diamonds, Hearts). - pub fn is_red(self) -> bool { - matches!(self, Suit::Diamonds | Suit::Hearts) - } - - /// Returns `true` for black suits (Clubs, Spades). - pub fn is_black(self) -> bool { - !self.is_red() - } -} - -/// Card rank, Ace through King. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Rank { - Ace = 1, - Two = 2, - Three = 3, - Four = 4, - Five = 5, - Six = 6, - Seven = 7, - Eight = 8, - Nine = 9, - Ten = 10, - Jack = 11, - Queen = 12, - King = 13, -} - -impl Rank { - /// All thirteen ranks in ascending order. - pub const RANKS: [Self; 13] = [ - Self::Ace, - Self::Two, - Self::Three, - Self::Four, - Self::Five, - Self::Six, - Self::Seven, - Self::Eight, - Self::Nine, - Self::Ten, - Self::Jack, - Self::Queen, - Self::King, - ]; - - /// Numeric value: Ace = 1, King = 13. - pub fn value(self) -> u8 { - self as u8 - } - - const fn new(n: u8) -> Option { - match n { - 1 => Some(Self::Ace), - 2 => Some(Self::Two), - 3 => Some(Self::Three), - 4 => Some(Self::Four), - 5 => Some(Self::Five), - 6 => Some(Self::Six), - 7 => Some(Self::Seven), - 8 => Some(Self::Eight), - 9 => Some(Self::Nine), - 10 => Some(Self::Ten), - 11 => Some(Self::Jack), - 12 => Some(Self::Queen), - 13 => Some(Self::King), - _ => None, - } - } - - /// Returns the rank `n` steps above `self`, or `None` if it would exceed King. - pub const fn checked_add(self, n: u8) -> Option { - Self::new((self as u8).saturating_add(n)) - } - - /// Returns the rank `n` steps below `self`, or `None` if it would go below Ace. - pub const fn checked_sub(self, n: u8) -> Option { - match (self as u8).checked_sub(n) { - Some(v) => Self::new(v), - None => None, - } - } -} +pub use card_game::{Rank, Suit}; /// A single playing card. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] diff --git a/solitaire_core/src/klondike_adapter.rs b/solitaire_core/src/klondike_adapter.rs index 93502a0..fed263e 100644 --- a/solitaire_core/src/klondike_adapter.rs +++ b/solitaire_core/src/klondike_adapter.rs @@ -156,39 +156,6 @@ impl KlondikeAdapter { } } -// ── Type-conversion utilities ───────────────────────────────────────────── - -impl From for card::Suit { - fn from(s: card_game::Suit) -> Self { - match s { - card_game::Suit::Clubs => Self::Clubs, - card_game::Suit::Diamonds => Self::Diamonds, - card_game::Suit::Hearts => Self::Hearts, - card_game::Suit::Spades => Self::Spades, - } - } -} - -impl From for card::Rank { - fn from(r: card_game::Rank) -> Self { - match r { - card_game::Rank::Ace => Self::Ace, - card_game::Rank::Two => Self::Two, - card_game::Rank::Three => Self::Three, - card_game::Rank::Four => Self::Four, - card_game::Rank::Five => Self::Five, - card_game::Rank::Six => Self::Six, - card_game::Rank::Seven => Self::Seven, - card_game::Rank::Eight => Self::Eight, - card_game::Rank::Nine => Self::Nine, - card_game::Rank::Ten => Self::Ten, - card_game::Rank::Jack => Self::Jack, - card_game::Rank::Queen => Self::Queen, - card_game::Rank::King => Self::King, - } - } -} - /// Convert a zero-based tableau index (0..=6) into [`Tableau`]. pub fn tableau_from_index(index: usize) -> Option { match index { @@ -239,8 +206,8 @@ pub fn skip_cards_from_count(skip: usize) -> Option { /// /// The id is consistent for the same logical card across all reconstructions. pub fn card_from_kl(kl_card: &KlCard) -> card::Card { - let suit: card::Suit = kl_card.suit().into(); - let rank: card::Rank = kl_card.rank().into(); + let suit = kl_card.suit(); + let rank = kl_card.rank(); let suit_index = match suit { card::Suit::Clubs => 0, card::Suit::Diamonds => 1,