diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2022-12-30 10:27:10 -0500 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2022-12-30 10:27:10 -0500 |
commit | dbe316d8b337eadff5518585dfc163f2724d0810 (patch) | |
tree | 6e2d772c7e4db77671cadb7ae240b6a44105b883 | |
parent | 83ffcc667999879197508aba0d1f910ca7cb000b (diff) |
Utility method to reconstruct Deal from tricks played
-rw-r--r-- | protocol/src/bridge_engine.rs | 45 | ||||
-rw-r--r-- | protocol/src/simple_bots.rs | 14 |
2 files changed, 56 insertions, 3 deletions
diff --git a/protocol/src/bridge_engine.rs b/protocol/src/bridge_engine.rs index 708d9ae..75a51ba 100644 --- a/protocol/src/bridge_engine.rs +++ b/protocol/src/bridge_engine.rs @@ -10,7 +10,7 @@ use rand::{ }; use regex::Regex; use serde::{Deserialize, Serialize}; -use std::cmp::Ordering; +use std::{cmp::Ordering, borrow::Cow}; use std::fmt; use std::str::FromStr; use strum::{EnumCount, IntoEnumIterator}; @@ -682,6 +682,7 @@ impl PlayState { MoveResult::Next(tricks) => { MoveResult::Next(PlayResult::Played(PlayedResult { bidding: self.bidding, + contract: self.contract, tricks, })) } @@ -695,18 +696,51 @@ pub struct PassedOutResult { pub bidding: Bidding, } +impl PassedOutResult { + pub fn deal(&self) -> Cow<Deal> { + Cow::Borrowed(&self.deal) + } +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct PlayedResult { pub bidding: Bidding, + pub contract: Contract, pub tricks: Vec<Trick>, } +impl PlayedResult { + pub fn deal(&self) -> Cow<Deal> { + let mut deal = Deal::empty(); + let mut leader = self.contract.leader(); + let trump_suit = self.contract.highest_bid.suit; + for trick in &self.tricks { + let mut player = leader; + for card in &trick.cards_played { + player.get_cards_mut(&mut deal).push(*card); + player = player.next(); + } + leader = trick.winner(trump_suit); + } + Cow::Owned(deal) + } +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum PlayResult { PassedOut(PassedOutResult), Played(PlayedResult), } +impl PlayResult { + pub fn deal(&self) -> Cow<Deal> { + match self { + PlayResult::PassedOut(r) => r.deal(), + PlayResult::Played(r) => r.deal(), + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub enum GameState { Bidding(BiddingState), @@ -824,6 +858,15 @@ pub struct Deal { } 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()); diff --git a/protocol/src/simple_bots.rs b/protocol/src/simple_bots.rs index 45d1a5b..182229f 100644 --- a/protocol/src/simple_bots.rs +++ b/protocol/src/simple_bots.rs @@ -46,7 +46,7 @@ impl PlayingBot for RandomPlayingBot { #[cfg(test)] mod tests { use std::str::FromStr; - use crate::move_result::MoveResult; + use crate::{move_result::MoveResult, bridge_engine::SUIT_DISPLAY_ORDER, card::RankOrder}; use super::*; use crate::{ @@ -159,7 +159,9 @@ mod tests { async fn play_until_completion() { crate::tests::test_setup(); let bot = RandomPlayingBot {}; - let mut result = MoveResult::Current(example_play_state()); + let play_state = example_play_state(); + let mut deal = play_state.deal.clone(); + let mut result = MoveResult::Current(play_state); while let MoveResult::Current(play_state) = result { info!("Play state: {play_state:#?}"); let player_state = PlayStatePlayerView::from_play_state( @@ -169,5 +171,13 @@ mod tests { let card = bot.play(&player_state).await; result = play_state.play(card).unwrap(); } + let play_result = result.next().unwrap(); + + // Verify that the deal is intact. + deal.sort(&SUIT_DISPLAY_ORDER, RankOrder::Descending); + let mut result_deal = play_result.deal().into_owned(); + result_deal.sort(&SUIT_DISPLAY_ORDER, RankOrder::Descending); + + assert_eq!(result_deal, deal); } } |