summaryrefslogtreecommitdiff
path: root/protocol/src/core.rs
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2023-01-01 20:34:09 -0500
committerKjetil Orbekk <kj@orbekk.com>2023-01-01 20:34:09 -0500
commitd3fbefad9cf25786fb5f28f96eeceb65d0a8b35b (patch)
tree156a23b5c04b93d746ecf592971aefbcc127cfd2 /protocol/src/core.rs
parentbb2ed3a2926384df063e476d10613fa310cd7ffa (diff)
Split bridge_engine into a few separate modules
Diffstat (limited to 'protocol/src/core.rs')
-rw-r--r--protocol/src/core.rs116
1 files changed, 116 insertions, 0 deletions
diff --git a/protocol/src/core.rs b/protocol/src/core.rs
new file mode 100644
index 0000000..7939fb2
--- /dev/null
+++ b/protocol/src/core.rs
@@ -0,0 +1,116 @@
+use rand::{prelude::Distribution, distributions::Standard, seq::SliceRandom};
+use strum::EnumCount;
+use strum_macros::{EnumCount, FromRepr, EnumIter};
+use serde::{Serialize, Deserialize};
+
+use crate::card::{Card, Suit, RankOrder, sort_cards, make_deck};
+
+#[derive(
+ PartialEq,
+ Eq,
+ Clone,
+ Copy,
+ Debug,
+ FromRepr,
+ EnumCount,
+ Serialize,
+ Deserialize,
+ EnumIter,
+)]
+#[repr(u8)]
+pub enum Player {
+ West = 0,
+ North,
+ East,
+ South,
+}
+
+impl Player {
+ pub fn next(&self) -> Self {
+ self.many_next(1)
+ }
+
+ pub fn many_next(self, i: usize) -> Self {
+ Player::from_repr(((self as usize + i) % Player::COUNT) as u8).unwrap()
+ }
+
+ pub fn short_str(&self) -> &str {
+ match self {
+ Self::West => "W",
+ Self::North => "N",
+ Self::East => "E",
+ Self::South => "W",
+ }
+ }
+
+ pub fn get_cards<'a>(&self, deal: &'a Deal) -> &'a Vec<Card> {
+ match self {
+ Self::West => &deal.west,
+ Self::North => &deal.north,
+ Self::East => &deal.east,
+ Self::South => &deal.south,
+ }
+ }
+
+ pub fn get_cards_mut<'a>(&self, deal: &'a mut Deal) -> &'a mut Vec<Card> {
+ match self {
+ Self::West => &mut deal.west,
+ Self::North => &mut deal.north,
+ Self::East => &mut deal.east,
+ Self::South => &mut deal.south,
+ }
+ }
+}
+
+impl Distribution<Player> for Standard {
+ fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Player {
+ let min = Player::West as u8;
+ let max = Player::South as u8;
+ let v = rng.gen_range(min..=max);
+ Player::from_repr(v).unwrap()
+ }
+}
+
+#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
+pub struct Deal {
+ pub north: Vec<Card>,
+ pub west: Vec<Card>,
+ pub south: Vec<Card>,
+ pub east: Vec<Card>,
+}
+
+impl Deal {
+ pub fn empty() -> Self {
+ Self {
+ north: Vec::with_capacity(13),
+ west: Vec::with_capacity(13),
+ south: Vec::with_capacity(13),
+ east: Vec::with_capacity(13),
+ }
+ }
+
+ pub fn sort(&mut self, suits: &[Suit; 4], ord: RankOrder) {
+ sort_cards(suits, ord, self.north.as_mut_slice());
+ sort_cards(suits, ord, self.west.as_mut_slice());
+ sort_cards(suits, ord, self.south.as_mut_slice());
+ sort_cards(suits, ord, self.east.as_mut_slice());
+ }
+}
+
+impl Distribution<Deal> for Standard {
+ fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Deal {
+ let mut deck = make_deck();
+ deck.shuffle(rng);
+ let mut deck = deck.iter();
+ let north = deck.by_ref().take(13).cloned().collect();
+ let west = deck.by_ref().take(13).cloned().collect();
+ let south = deck.by_ref().take(13).cloned().collect();
+ let east = deck.by_ref().take(13).cloned().collect();
+ Deal {
+ north,
+ west,
+ south,
+ east,
+ }
+ }
+}