summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2022-12-23 21:29:46 -0500
committerKjetil Orbekk <kj@orbekk.com>2022-12-23 21:33:50 -0500
commit0f3c580176ee50795908bf16b4abf9f6faa0565c (patch)
tree92a5d80e7c4bf24753a2710698d0e1824722c009
parent8f72f1dcdf2309484b1c5e933984bb6215c14999 (diff)
Fix winning trick implementation
-rw-r--r--protocol/src/bridge_engine.rs52
1 files 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<Suit> {
+ 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<Suit>) -> 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<Suit>,
tricks_played: Vec<Trick>,
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<Suit>,
+ 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);
}
}