From d3fbefad9cf25786fb5f28f96eeceb65d0a8b35b Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Sun, 1 Jan 2023 20:34:09 -0500 Subject: Split bridge_engine into a few separate modules --- protocol/src/actions.rs | 66 +++++++ protocol/src/bot.rs | 4 +- protocol/src/bridge_engine.rs | 406 ++---------------------------------------- protocol/src/contract.rs | 210 ++++++++++++++++++++++ protocol/src/core.rs | 116 ++++++++++++ protocol/src/lib.rs | 3 + protocol/src/simple_bots.rs | 16 +- 7 files changed, 425 insertions(+), 396 deletions(-) create mode 100644 protocol/src/actions.rs create mode 100644 protocol/src/contract.rs create mode 100644 protocol/src/core.rs (limited to 'protocol') diff --git a/protocol/src/actions.rs b/protocol/src/actions.rs new file mode 100644 index 0000000..defe1f9 --- /dev/null +++ b/protocol/src/actions.rs @@ -0,0 +1,66 @@ +use core::fmt; +use std::str::FromStr; + +use serde::{Deserialize, Serialize}; + +use crate::contract::LevelAndSuit; + +#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] +pub enum Bid { + Pass, + Double, + Redouble, + Raise(LevelAndSuit), +} + +impl Bid { + pub fn as_raise(&self) -> Option { + match self { + Bid::Raise(raise) => Some(*raise), + _ => None, + } + } +} + +impl fmt::Display for Bid { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::result::Result<(), std::fmt::Error> { + match self { + Bid::Pass => write!(f, "Pass"), + Bid::Double => write!(f, "Double"), + Bid::Redouble => write!(f, "Redouble"), + Bid::Raise(x) => write!(f, "{}", x), + } + } +} + +impl fmt::Debug for Bid { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::result::Result<(), std::fmt::Error> { + match self { + Bid::Pass => write!(f, "Pass"), + Bid::Double => write!(f, "Double"), + Bid::Redouble => write!(f, "Redouble"), + Bid::Raise(x) => write!(f, "Raise({})", x), + } + } +} + +impl FromStr for Bid { + type Err = anyhow::Error; + fn from_str( + s: &str, + ) -> std::result::Result::Err> { + match s.trim().to_ascii_lowercase().as_str() { + "pass" => Ok(Bid::Pass), + "double" => Ok(Bid::Double), + "redouble" => Ok(Bid::Redouble), + x => Ok(Bid::Raise(x.parse()?)), + } + } +} + diff --git a/protocol/src/bot.rs b/protocol/src/bot.rs index a85fda0..24495c8 100644 --- a/protocol/src/bot.rs +++ b/protocol/src/bot.rs @@ -1,8 +1,8 @@ use async_trait::async_trait; use crate::{ - bridge_engine::{Bid, BiddingStatePlayerView, PlayStatePlayerView}, - card::Card, + bridge_engine::{BiddingStatePlayerView, PlayStatePlayerView}, + card::Card, actions::Bid, }; #[async_trait] diff --git a/protocol/src/bridge_engine.rs b/protocol/src/bridge_engine.rs index d04bdf0..74a8262 100644 --- a/protocol/src/bridge_engine.rs +++ b/protocol/src/bridge_engine.rs @@ -1,90 +1,16 @@ use crate::{ - card::{make_deck, sort_cards, Card, RankOrder, Suit}, + card::{Card, Suit}, move_result::MoveResult, + core::{Player, Deal}, actions::Bid, contract::{LevelAndSuit, Contract, ContractModifier} }; use anyhow::{anyhow, bail}; use log::info; -use rand::{ - distributions::Standard, - prelude::{Distribution, SliceRandom}, -}; -use regex::Regex; use serde::{Deserialize, Serialize}; -use std::{cmp::Ordering, borrow::Cow}; -use std::fmt; -use std::str::FromStr; -use strum::{EnumCount, IntoEnumIterator}; -use strum_macros::{EnumCount as EnumCountMacro, EnumIter, FromRepr}; +use std::borrow::Cow; pub const SUIT_DISPLAY_ORDER: [Suit; 4] = [Suit::Diamond, Suit::Club, Suit::Heart, Suit::Spade]; -#[derive( - PartialEq, - Eq, - Clone, - Copy, - Debug, - FromRepr, - EnumCountMacro, - 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 { - 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 { - match self { - Self::West => &mut deal.west, - Self::North => &mut deal.north, - Self::East => &mut deal.east, - Self::South => &mut deal.south, - } - } -} - -impl Distribution for Standard { - fn sample(&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(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] pub struct Trick { pub leader: Player, @@ -255,266 +181,6 @@ impl DealInPlay { } } -#[derive( - PartialEq, - Eq, - PartialOrd, - Ord, - Clone, - Copy, - EnumIter, - Serialize, - Deserialize, -)] -pub enum ContractLevel { - One = 1, - Two, - Three, - Four, - Five, - Six, - Seven, -} - -impl fmt::Display for ContractLevel { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> std::result::Result<(), std::fmt::Error> { - write!(f, "{}", *self as u8) - } -} - -impl fmt::Debug for ContractLevel { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> std::result::Result<(), std::fmt::Error> { - write!(f, "{}", self) - } -} - -impl FromStr for ContractLevel { - type Err = anyhow::Error; - - fn from_str( - s: &str, - ) -> std::result::Result::Err> { - match s { - "1" => Ok(ContractLevel::One), - "2" => Ok(ContractLevel::Two), - "3" => Ok(ContractLevel::Three), - "4" => Ok(ContractLevel::Four), - "5" => Ok(ContractLevel::Five), - "6" => Ok(ContractLevel::Six), - "7" => Ok(ContractLevel::Seven), - _ => Err(anyhow!("invalid string: {}", s)), - } - } -} - -#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] -pub enum Bid { - Pass, - Double, - Redouble, - Raise(Raise), -} - -impl Bid { - pub fn as_raise(&self) -> Option { - match self { - Bid::Raise(raise) => Some(*raise), - _ => None, - } - } -} - -impl fmt::Display for Bid { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> std::result::Result<(), std::fmt::Error> { - match self { - Bid::Pass => write!(f, "Pass"), - Bid::Double => write!(f, "Double"), - Bid::Redouble => write!(f, "Redouble"), - Bid::Raise(x) => write!(f, "{}", x), - } - } -} - -impl fmt::Debug for Bid { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> std::result::Result<(), std::fmt::Error> { - match self { - Bid::Pass => write!(f, "Pass"), - Bid::Double => write!(f, "Double"), - Bid::Redouble => write!(f, "Redouble"), - Bid::Raise(x) => write!(f, "Raise({})", x), - } - } -} - -impl FromStr for Bid { - type Err = anyhow::Error; - fn from_str( - s: &str, - ) -> std::result::Result::Err> { - match s.trim().to_ascii_lowercase().as_str() { - "pass" => Ok(Bid::Pass), - "double" => Ok(Bid::Double), - "redouble" => Ok(Bid::Redouble), - x => Ok(Bid::Raise(x.parse()?)), - } - } -} - -#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] -pub struct Raise { - pub level: ContractLevel, - pub suit: Option, -} - -impl Raise { - pub fn all_raises() -> Vec { - let mut result = Vec::with_capacity(7 * 5); - for level in ContractLevel::iter() { - for suit in Suit::iter() { - result.push(Raise { - level, - suit: Some(suit), - }); - } - result.push(Raise { level, suit: None }); - } - result - } -} - -impl PartialOrd for Raise { - fn partial_cmp(&self, o: &Self) -> Option { - if self.level != o.level { - return self.level.partial_cmp(&o.level); - } - if self.suit != o.suit { - if self.suit.is_none() { - return Some(Ordering::Greater); - } - if o.suit.is_none() { - return Some(Ordering::Less); - } - return self.suit.partial_cmp(&o.suit); - } - Some(Ordering::Equal) - } -} - -impl Ord for Raise { - fn cmp(&self, o: &Self) -> std::cmp::Ordering { - self.partial_cmp(o).unwrap() - } -} - -impl fmt::Display for Raise { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> std::result::Result<(), std::fmt::Error> { - write!( - f, - "{}{}", - self.level, - self.suit - .map_or("NT".to_string(), |suit| format!("{}", suit)) - ) - } -} - -impl fmt::Debug for Raise { - fn fmt( - &self, - f: &mut std::fmt::Formatter<'_>, - ) -> std::result::Result<(), std::fmt::Error> { - write!(f, "{}", self) - } -} - -impl FromStr for Raise { - type Err = anyhow::Error; - fn from_str( - s: &str, - ) -> std::result::Result::Err> { - lazy_static::lazy_static! { - static ref RE: Regex = Regex::new(r#"\s*(.[0-9]*)\s*(.*)"#).unwrap(); - }; - let caps = RE - .captures(s) - .ok_or_else(|| anyhow!("invalid raise: {}", s))?; - info!("caps: {:?}", caps); - let level = caps[1].parse()?; - let suit = match caps[2].to_ascii_uppercase().as_str() { - "NT" => None, - x => Some(x.parse()?), - }; - Ok(Raise { level, suit }) - } -} - -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] -pub enum ContractModifier { - None, - Doubled, - Redoubled, -} - -impl fmt::Display for ContractModifier { - fn fmt( - &self, - f: &mut fmt::Formatter, - ) -> std::result::Result<(), std::fmt::Error> { - match self { - ContractModifier::None => Ok(()), - ContractModifier::Doubled => write!(f, "x"), - ContractModifier::Redoubled => write!(f, "xx"), - } - } -} - -#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] -pub struct Contract { - pub declarer: Player, - pub highest_bid: Raise, - pub modifier: ContractModifier, -} - -impl Contract { - pub fn dummy(&self) -> Player { - self.declarer.many_next(2) - } - - pub fn leader(&self) -> Player { - self.declarer.many_next(3) - } -} - -impl fmt::Display for Contract { - fn fmt( - &self, - f: &mut fmt::Formatter<'_>, - ) -> std::result::Result<(), fmt::Error> { - write!( - f, - "{}{}{}", - self.highest_bid, - self.declarer.short_str(), - self.modifier - ) - } -} - #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct Bidding { pub dealer: Player, @@ -538,7 +204,7 @@ impl Bidding { self.dealer.many_next(self.bids.len()) } - pub fn highest_bid(&self) -> Option { + pub fn highest_bid(&self) -> Option { for bid in self.bids.iter().rev() { if let Some(raise) = bid.as_raise() { return Some(raise); @@ -856,49 +522,6 @@ impl GameState { } } -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct Deal { - pub north: Vec, - pub west: Vec, - pub south: Vec, - pub east: Vec, -} - -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 for Standard { - fn sample(&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, - } - } -} #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] pub struct PlayStatePlayerView { @@ -1059,9 +682,14 @@ impl TableStatePlayerView { #[cfg(test)] mod tests { + use std::str::FromStr; + + use crate::{contract::ContractLevel, card::RankOrder}; + use super::*; use log::info; use rand::random; + use strum::IntoEnumIterator; fn as_bidding(r: BiddingResult) -> Bidding { match r { @@ -1105,21 +733,21 @@ mod tests { #[test] fn bid_conversion() { crate::tests::test_setup(); - let bid1d = Raise { + let bid1d = LevelAndSuit { level: ContractLevel::One, suit: Some(Suit::Diamond), }; assert_eq!("1♢", format!("{}", bid1d)); assert_eq!("1♢", format!("{:?}", bid1d)); - assert_eq!(bid1d, Raise::from_str("1D").unwrap()); + assert_eq!(bid1d, LevelAndSuit::from_str("1D").unwrap()); assert_eq!(Bid::Pass, Bid::from_str("pass").unwrap()); let mut checked_raises = 0; - for bid in Raise::all_raises() { + for bid in LevelAndSuit::all_raises() { assert_eq!( bid, - Raise::from_str(format!("{}", bid).as_str()).unwrap() + LevelAndSuit::from_str(format!("{}", bid).as_str()).unwrap() ); assert_eq!( Bid::Raise(bid), @@ -1159,12 +787,12 @@ mod tests { #[test] fn bid_ord() { - let bid = |s| Raise::from_str(s).unwrap(); + let bid = |s| LevelAndSuit::from_str(s).unwrap(); assert!(bid("2♦") < bid("3♦")); assert!(bid("3♦") < bid("3♥")); assert!(bid("1♠") < bid("2♣")); assert!(bid("1♠") < bid("1NT")); - for bid in Raise::all_raises() { + for bid in LevelAndSuit::all_raises() { assert_eq!(bid, bid); } } @@ -1283,7 +911,7 @@ mod tests { assert!(game_state.is_bidding()); info!("Start bidding with game state {game_state:#?}"); - let raise = |s| Bid::Raise(Raise::from_str(s).unwrap()); + let raise = |s| Bid::Raise(LevelAndSuit::from_str(s).unwrap()); let game_state = game_state.bid(raise("1H")).unwrap().current().unwrap(); let game_state = game_state @@ -1329,7 +957,7 @@ mod tests { fn some_play_state() -> PlayState { crate::tests::test_setup(); let deal = random(); - let raise1c = Raise { + let raise1c = LevelAndSuit { level: ContractLevel::One, suit: Some(Suit::Club), }; diff --git a/protocol/src/contract.rs b/protocol/src/contract.rs new file mode 100644 index 0000000..4c1d2f3 --- /dev/null +++ b/protocol/src/contract.rs @@ -0,0 +1,210 @@ +use core::fmt; +use std::{str::FromStr, cmp::Ordering}; + +use anyhow::anyhow; +use regex::Regex; +use serde::{Serialize, Deserialize}; +use strum::IntoEnumIterator; +use strum_macros::EnumIter; + +use crate::{core::Player, card::Suit}; + +#[derive( + PartialEq, + Eq, + PartialOrd, + Ord, + Clone, + Copy, + EnumIter, + Serialize, + Deserialize, +)] +pub enum ContractLevel { + One = 1, + Two, + Three, + Four, + Five, + Six, + Seven, +} + +impl fmt::Display for ContractLevel { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::result::Result<(), std::fmt::Error> { + write!(f, "{}", *self as u8) + } +} + +impl fmt::Debug for ContractLevel { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::result::Result<(), std::fmt::Error> { + write!(f, "{}", self) + } +} + +impl FromStr for ContractLevel { + type Err = anyhow::Error; + + fn from_str( + s: &str, + ) -> std::result::Result::Err> { + match s { + "1" => Ok(ContractLevel::One), + "2" => Ok(ContractLevel::Two), + "3" => Ok(ContractLevel::Three), + "4" => Ok(ContractLevel::Four), + "5" => Ok(ContractLevel::Five), + "6" => Ok(ContractLevel::Six), + "7" => Ok(ContractLevel::Seven), + _ => Err(anyhow!("invalid string: {}", s)), + } + } +} + +#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +pub enum ContractModifier { + None, + Doubled, + Redoubled, +} + +impl fmt::Display for ContractModifier { + fn fmt( + &self, + f: &mut fmt::Formatter, + ) -> std::result::Result<(), std::fmt::Error> { + match self { + ContractModifier::None => Ok(()), + ContractModifier::Doubled => write!(f, "x"), + ContractModifier::Redoubled => write!(f, "xx"), + } + } +} + +#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)] +pub struct Contract { + pub declarer: Player, + pub highest_bid: LevelAndSuit, + pub modifier: ContractModifier, +} + +impl Contract { + pub fn dummy(&self) -> Player { + self.declarer.many_next(2) + } + + pub fn leader(&self) -> Player { + self.declarer.many_next(3) + } +} + +impl fmt::Display for Contract { + fn fmt( + &self, + f: &mut fmt::Formatter<'_>, + ) -> std::result::Result<(), fmt::Error> { + write!( + f, + "{}{}{}", + self.highest_bid, + self.declarer.short_str(), + self.modifier + ) + } +} + +#[derive(PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] +pub struct LevelAndSuit { + pub level: ContractLevel, + pub suit: Option, +} + +impl LevelAndSuit { + pub fn all_raises() -> Vec { + let mut result = Vec::with_capacity(7 * 5); + for level in ContractLevel::iter() { + for suit in Suit::iter() { + result.push(LevelAndSuit { + level, + suit: Some(suit), + }); + } + result.push(LevelAndSuit { level, suit: None }); + } + result + } +} + +impl PartialOrd for LevelAndSuit { + fn partial_cmp(&self, o: &Self) -> Option { + if self.level != o.level { + return self.level.partial_cmp(&o.level); + } + if self.suit != o.suit { + if self.suit.is_none() { + return Some(Ordering::Greater); + } + if o.suit.is_none() { + return Some(Ordering::Less); + } + return self.suit.partial_cmp(&o.suit); + } + Some(Ordering::Equal) + } +} + +impl Ord for LevelAndSuit { + fn cmp(&self, o: &Self) -> std::cmp::Ordering { + self.partial_cmp(o).unwrap() + } +} + +impl fmt::Display for LevelAndSuit { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::result::Result<(), std::fmt::Error> { + write!( + f, + "{}{}", + self.level, + self.suit + .map_or("NT".to_string(), |suit| format!("{}", suit)) + ) + } +} + +impl fmt::Debug for LevelAndSuit { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> std::result::Result<(), std::fmt::Error> { + write!(f, "{}", self) + } +} + +impl FromStr for LevelAndSuit { + type Err = anyhow::Error; + fn from_str( + s: &str, + ) -> std::result::Result::Err> { + lazy_static::lazy_static! { + static ref RE: Regex = Regex::new(r#"\s*(.[0-9]*)\s*(.*)"#).unwrap(); + }; + let caps = RE + .captures(s) + .ok_or_else(|| anyhow!("invalid raise: {}", s))?; + let level = caps[1].parse()?; + let suit = match caps[2].to_ascii_uppercase().as_str() { + "NT" => None, + x => Some(x.parse()?), + }; + Ok(LevelAndSuit { level, suit }) + } +} 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 { + 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 { + match self { + Self::West => &mut deal.west, + Self::North => &mut deal.north, + Self::East => &mut deal.east, + Self::South => &mut deal.south, + } + } +} + +impl Distribution for Standard { + fn sample(&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, + pub west: Vec, + pub south: Vec, + pub east: Vec, +} + +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 for Standard { + fn sample(&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, + } + } +} diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs index f828be5..088802f 100644 --- a/protocol/src/lib.rs +++ b/protocol/src/lib.rs @@ -5,6 +5,9 @@ pub mod bridge_engine; pub mod card; pub mod move_result; pub mod simple_bots; +pub mod contract; +pub mod actions; +pub mod core; #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] pub struct UserInfo { diff --git a/protocol/src/simple_bots.rs b/protocol/src/simple_bots.rs index 182229f..3df50fb 100644 --- a/protocol/src/simple_bots.rs +++ b/protocol/src/simple_bots.rs @@ -5,8 +5,9 @@ use rand::{ }; use crate::{ + actions::Bid, bot::{BiddingBot, PlayingBot}, - bridge_engine::{Bid, BiddingStatePlayerView, PlayStatePlayerView}, + bridge_engine::{BiddingStatePlayerView, PlayStatePlayerView}, card::Card, }; @@ -45,14 +46,19 @@ impl PlayingBot for RandomPlayingBot { #[cfg(test)] mod tests { + use crate::{ + bridge_engine::SUIT_DISPLAY_ORDER, + card::RankOrder, + contract::{Contract, ContractLevel, ContractModifier, LevelAndSuit}, + core::{Deal, Player}, + move_result::MoveResult, + }; use std::str::FromStr; - use crate::{move_result::MoveResult, bridge_engine::SUIT_DISPLAY_ORDER, card::RankOrder}; use super::*; use crate::{ bridge_engine::{ - Bidding, BiddingState, BiddingStatePlayerView, Contract, - ContractLevel, ContractModifier, Deal, PlayState, Player, Raise, + Bidding, BiddingState, BiddingStatePlayerView, PlayState, }, card::Suit, }; @@ -118,7 +124,7 @@ mod tests { fn example_play_state() -> PlayState { let deal = example_deal(); - let raise1c = Raise { + let raise1c = LevelAndSuit { level: ContractLevel::One, suit: Some(Suit::Club), }; -- cgit v1.2.3