From 0f3c580176ee50795908bf16b4abf9f6faa0565c Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Fri, 23 Dec 2022 21:29:46 -0500 Subject: Fix winning trick implementation --- protocol/src/bridge_engine.rs | 52 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/protocol/src/bridge_engine.rs b/protocol/src/bridge_engine.rs index 70dcda4..fb4efa7 100644 --- a/protocol/src/bridge_engine.rs +++ b/protocol/src/bridge_engine.rs @@ -92,9 +92,28 @@ pub struct Trick { } impl Trick { - pub fn winner(&self) -> Player { - error!("XXX: Returning incorrect result for winner"); - self.leader + pub fn suit(&self) -> Option { + self.cards_played.iter().next().map(|&Card(suit, _)| suit) + } + + // TODO: This should be moved somewhere we can guarantee that cards are non-empty. + pub fn winner(&self, trump_suit: Option) -> Player { + let suit = self.suit(); + let value = |c: &Card| { + if Some(c.suit()) == trump_suit { + 14 + c.rank() as i8 + } else if Some(c.suit()) == suit { + c.rank() as i8 + } else { + 0 + } + }; + + let (i, _) = self.cards_played + .iter() + .enumerate() + .max_by(|&(_, c1), &(_, c2)| value(c1).cmp(&value(c2))).unwrap(); + self.leader.many_next(i) } } @@ -151,6 +170,7 @@ impl TurnInPlay { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct DealInPlay { deal: Deal, + trump_suit: Option, tricks_played: Vec, in_progress: TurnInPlay, } @@ -162,9 +182,14 @@ pub enum DealInPlayResult { } impl DealInPlay { - pub fn new(leader: Player, deal: Deal) -> DealInPlay { + pub fn new( + leader: Player, + trump_suit: Option, + deal: Deal, + ) -> DealInPlay { DealInPlay { deal, + trump_suit, tricks_played: Vec::with_capacity(13), in_progress: TurnInPlay::new(leader), } @@ -199,7 +224,9 @@ impl DealInPlay { let player_cards = player.get_cards_mut(&mut self.deal); if let Some(suit) = self.in_progress.suit() { - if card.suit() != suit && player_cards.iter().find(|c| c.suit() == suit).is_some() { + if card.suit() != suit + && player_cards.iter().find(|c| c.suit() == suit).is_some() + { return Err(anyhow!("Must follow {suit} suit")); } } @@ -223,7 +250,7 @@ impl DealInPlay { }) } TurnInPlayResult::Trick(trick) => { - let trick_winner = trick.winner(); + let trick_winner = trick.winner(self.trump_suit); let mut tricks = self.tricks_played; tricks.push(trick); @@ -231,6 +258,7 @@ impl DealInPlay { DealInPlayResult::PlayFinished(tricks) } else { DealInPlayResult::InProgress(Self { + trump_suit: self.trump_suit, in_progress: TurnInPlay::new(trick_winner), tricks_played: tricks, deal: self.deal, @@ -636,8 +664,11 @@ pub struct PlayState { impl PlayState { pub fn new(deal: Deal, contract: Contract, bidding: Bidding) -> Self { - let playing_deal = - DealInPlay::new(contract.declarer.many_next(3), deal.clone()); + let playing_deal = DealInPlay::new( + contract.declarer.many_next(3), + contract.highest_bid.suit, + deal.clone(), + ); Self { deal, contract, @@ -1329,7 +1360,7 @@ mod tests { #[test] fn play_hand() { - let deal = DealInPlay::new(Player::West, mini_deal()); + let deal = DealInPlay::new(Player::West, None, mini_deal()); assert_eq!(deal.tricks_played, vec!()); { let err = deal.clone().play(mkcard("♥9")).unwrap_err().to_string(); @@ -1354,5 +1385,8 @@ mod tests { cards_played: mkcards("♢A ♢Q ♢7 ♡10"), }) ); + let trick = &deal.tricks_played[0]; + assert_eq!(trick.winner(None), Player::West); + assert_eq!(trick.winner(Some(Suit::Heart)), Player::South); } } -- cgit v1.2.3