diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2023-01-07 16:23:56 -0500 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2023-01-07 16:23:56 -0500 |
commit | 1f52e2e448b464e95530cab9e1b7d9177ada3279 (patch) | |
tree | 9290facc77bfb77b078e973e325f2e3d62216464 | |
parent | 0f7dacea15d6e22123c3290c52515a772fc7ee92 (diff) |
Add dealer and vulnerability to the Deal struct
-rw-r--r-- | protocol/src/bridge_engine.rs | 36 | ||||
-rw-r--r-- | protocol/src/core.rs | 45 | ||||
-rw-r--r-- | protocol/src/simple_bots.rs | 12 |
3 files changed, 65 insertions, 28 deletions
diff --git a/protocol/src/bridge_engine.rs b/protocol/src/bridge_engine.rs index 73a8bf4..4b3d889 100644 --- a/protocol/src/bridge_engine.rs +++ b/protocol/src/bridge_engine.rs @@ -1,7 +1,7 @@ use crate::{ card::{Card, Suit}, move_result::MoveResult, - core::{Player, Deal}, actions::Bid, contract::{LevelAndSuit, Contract, ContractModifier} + core::{Player, Deal, Vulnerability}, actions::Bid, contract::{LevelAndSuit, Contract, ContractModifier} }; use anyhow::{anyhow, bail}; use log::info; @@ -273,14 +273,12 @@ impl BiddingResult { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct BiddingState { - pub dealer: Player, pub deal: Deal, pub bidding: Bidding, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct BiddingStatePlayerView { - pub dealer: Player, pub player_position: Player, pub hand: Vec<Card>, pub bidding: Bidding, @@ -292,12 +290,10 @@ impl BiddingStatePlayerView { player_position: Player, ) -> Self { let BiddingState { - dealer, deal, bidding, } = bidding_state; Self { - dealer: *dealer, player_position, hand: player_position.get_cards(deal).clone(), bidding: bidding.clone(), @@ -329,7 +325,7 @@ impl PlayState { } pub fn dealer(&self) -> Player { - self.bidding.dealer + self.deal.dealer } pub fn current_player(&self) -> Player { @@ -347,6 +343,7 @@ impl PlayState { }), MoveResult::Next(tricks) => { MoveResult::Next(PlayResult::Played(PlayedResult { + vulnerability: self.deal.vulnerability, bidding: self.bidding, contract: self.contract, tricks, @@ -370,6 +367,7 @@ impl PassedOutResult { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct PlayedResult { + pub vulnerability: Vulnerability, pub bidding: Bidding, pub contract: Contract, pub tricks: Vec<Trick>, @@ -377,7 +375,7 @@ pub struct PlayedResult { impl PlayedResult { pub fn deal(&self) -> Cow<Deal> { - let mut deal = Deal::empty(); + let mut deal = Deal::empty(self.bidding.dealer, self.vulnerability); let mut leader = self.contract.leader(); let trump_suit = self.contract.highest_bid.suit; for trick in &self.tricks { @@ -427,9 +425,9 @@ impl From<PlayState> for GameState { } impl GameState { - pub fn new(deal: Deal, dealer: Player) -> Self { + pub fn new(deal: Deal) -> Self { + let dealer = deal.dealer; Self::Bidding(BiddingState { - dealer, deal, bidding: Bidding::new(dealer), }) @@ -444,7 +442,7 @@ impl GameState { pub fn dealer(&self) -> Player { match self { - Self::Bidding(BiddingState { dealer, .. }) => *dealer, + Self::Bidding(BiddingState { deal, .. }) => deal.dealer, Self::Play(play_state) => play_state.dealer(), } } @@ -483,14 +481,12 @@ impl GameState { bid: Bid, ) -> Result<MoveResult<GameState, PlayResult>, anyhow::Error> { let BiddingState { - dealer, deal, bidding, } = self.bidding()?.clone(); Ok(match bidding.bid(bid)? { BiddingResult::InProgress(bidding) => { MoveResult::Current(GameState::Bidding(BiddingState { - dealer, deal, bidding, })) @@ -868,6 +864,8 @@ mod tests { fn example_deal() -> Deal { Deal { + dealer: Player::North, + vulnerability: Vulnerability::None, west: mkcards("♠Q ♠9 ♠5 ♠2 ♥K ♥J ♥4 ♣5 ♣4 ♣2 ♦10 ♦5 ♦3"), north: mkcards("♠A ♠8 ♠7 ♠6 ♥A ♥9 ♥5 ♥3 ♣9 ♣3 ♦Q ♦J ♦9"), east: mkcards("♠K ♠3 ♥Q ♥10 ♥8 ♥7 ♣K ♣Q ♣J ♣10 ♣6 ♦A ♦4"), @@ -877,6 +875,8 @@ mod tests { fn mini_deal() -> Deal { Deal { + dealer: Player::North, + vulnerability: Vulnerability::None, west: mkcards("♢A ♡Q"), north: mkcards("♢Q ♡9"), east: mkcards("♢7 ♡K"), @@ -905,7 +905,7 @@ mod tests { #[test] fn game_state() { crate::tests::test_setup(); - let game_state = GameState::new(mini_deal(), Player::North); + let game_state = GameState::new(mini_deal()); assert_eq!(game_state.deal(), &mini_deal()); assert_eq!(game_state.dealer(), Player::North); assert!(game_state.is_bidding()); @@ -935,18 +935,18 @@ mod tests { #[test] fn table_view() { crate::tests::test_setup(); - let game_state = GameState::new(mini_deal(), Player::East); + let game_state = GameState::new(mini_deal()); info!("Game state: {game_state:?}"); for p in Player::iter() { info!("Testing view for {p:?}"); let view = GameStatePlayerView::from_game_state(&game_state, p); match view { GameStatePlayerView::Bidding(BiddingStatePlayerView { - dealer, + bidding, hand, .. }) => { - assert_eq!(dealer, Player::East); + assert_eq!(bidding.dealer, Player::North); assert_eq!(&hand, p.get_cards(&mini_deal())); } _ => panic!("expected bidding: {view:#?}"), @@ -956,7 +956,7 @@ mod tests { fn some_play_state() -> PlayState { crate::tests::test_setup(); - let deal = random(); + let deal: Deal = random(); let raise1c = LevelAndSuit { level: ContractLevel::One, suit: Some(Suit::Club), @@ -967,7 +967,7 @@ mod tests { modifier: ContractModifier::Doubled, }; let bidding = Bidding { - dealer: random(), + dealer: deal.dealer, bids: vec![Bid::Raise(raise1c), Bid::Pass, Bid::Pass, Bid::Pass], }; PlayState::new(deal, contract, bidding) diff --git a/protocol/src/core.rs b/protocol/src/core.rs index 7939fb2..7d055ac 100644 --- a/protocol/src/core.rs +++ b/protocol/src/core.rs @@ -1,9 +1,9 @@ -use rand::{prelude::Distribution, distributions::Standard, seq::SliceRandom}; +use rand::{distributions::Standard, prelude::Distribution, seq::SliceRandom, random}; +use serde::{Deserialize, Serialize}; use strum::EnumCount; -use strum_macros::{EnumCount, FromRepr, EnumIter}; -use serde::{Serialize, Deserialize}; +use strum_macros::{EnumCount, EnumIter, FromRepr}; -use crate::card::{Card, Suit, RankOrder, sort_cards, make_deck}; +use crate::card::{make_deck, sort_cards, Card, RankOrder, Suit}; #[derive( PartialEq, @@ -71,8 +71,39 @@ impl Distribution<Player> for Standard { } } +#[derive( + PartialEq, + Eq, + Clone, + Copy, + Debug, + FromRepr, + EnumCount, + Serialize, + Deserialize, + EnumIter, +)] +#[repr(u8)] +pub enum Vulnerability { + None, + NorthSouth, + EastWest, + All, +} + +impl Distribution<Vulnerability> for Standard { + fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Vulnerability { + let min = Vulnerability::None as u8; + let max = Vulnerability::All as u8; + let v = rng.gen_range(min..=max); + Vulnerability::from_repr(v).unwrap() + } +} + #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct Deal { + pub dealer: Player, + pub vulnerability: Vulnerability, pub north: Vec<Card>, pub west: Vec<Card>, pub south: Vec<Card>, @@ -80,8 +111,10 @@ pub struct Deal { } impl Deal { - pub fn empty() -> Self { + pub fn empty(dealer: Player, vulnerability: Vulnerability) -> Self { Self { + dealer, + vulnerability, north: Vec::with_capacity(13), west: Vec::with_capacity(13), south: Vec::with_capacity(13), @@ -107,6 +140,8 @@ impl Distribution<Deal> for Standard { let south = deck.by_ref().take(13).cloned().collect(); let east = deck.by_ref().take(13).cloned().collect(); Deal { + dealer: random(), + vulnerability: random(), north, west, south, diff --git a/protocol/src/simple_bots.rs b/protocol/src/simple_bots.rs index 3df50fb..ce2fdec 100644 --- a/protocol/src/simple_bots.rs +++ b/protocol/src/simple_bots.rs @@ -50,7 +50,7 @@ mod tests { bridge_engine::SUIT_DISPLAY_ORDER, card::RankOrder, contract::{Contract, ContractLevel, ContractModifier, LevelAndSuit}, - core::{Deal, Player}, + core::{Deal, Player, Vulnerability}, move_result::MoveResult, }; use std::str::FromStr; @@ -115,6 +115,8 @@ mod tests { fn example_deal() -> Deal { Deal { + dealer: Player::North, + vulnerability: Vulnerability::None, west: mkcards("♠Q ♠9 ♠5 ♠2 ♥K ♥J ♥4 ♣5 ♣4 ♣2 ♦10 ♦5 ♦3"), north: mkcards("♠A ♠8 ♠7 ♠6 ♥A ♥9 ♥5 ♥3 ♣9 ♣3 ♦Q ♦J ♦9"), east: mkcards("♠K ♠3 ♥Q ♥10 ♥8 ♥7 ♣K ♣Q ♣J ♣10 ♣6 ♦A ♦4"), @@ -134,7 +136,7 @@ mod tests { modifier: ContractModifier::Doubled, }; let bidding = Bidding { - dealer: random(), + dealer: deal.dealer, bids: vec![Bid::Raise(raise1c), Bid::Pass, Bid::Pass, Bid::Pass], }; PlayState::new(deal, contract, bidding) @@ -143,11 +145,11 @@ mod tests { #[tokio::test] async fn always_passing_bot_passes() { crate::tests::test_setup(); - let dealer = random(); + let deal: Deal = random(); + let dealer = deal.dealer; let player_position = random(); let bidding_state = BiddingState { - dealer, - deal: random(), + deal, bidding: Bidding::new(dealer), }; let player_view = BiddingStatePlayerView::from_bidding_state( |