diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2022-12-22 08:31:35 -0500 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2022-12-22 08:31:35 -0500 |
commit | 42f6ef6d44e893b47e5e2a49496b5dd2122df232 (patch) | |
tree | dff2f84bbc41295b27deb2397071cb16bb742058 /protocol/src/bridge_engine.rs | |
parent | 10ecb9e30568bf20287b053a620252d7a80dbd6b (diff) |
Add a simple bot that plays random (legal) cards
- Leads random cards
- Follows suit if possible
Diffstat (limited to 'protocol/src/bridge_engine.rs')
-rw-r--r-- | protocol/src/bridge_engine.rs | 97 |
1 files changed, 73 insertions, 24 deletions
diff --git a/protocol/src/bridge_engine.rs b/protocol/src/bridge_engine.rs index 50f619b..35eb90f 100644 --- a/protocol/src/bridge_engine.rs +++ b/protocol/src/bridge_engine.rs @@ -3,7 +3,8 @@ use anyhow::{anyhow, bail}; use log::{error, info}; use rand::{ distributions::Standard, - prelude::{Distribution, SliceRandom}, random, + prelude::{Distribution, SliceRandom}, + random, }; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -140,7 +141,7 @@ impl TurnInPlay { TurnInPlayResult::InProgress(self) } - pub fn next_player(&self) -> Player { + pub fn current_player(&self) -> Player { self.trick.leader.many_next(self.trick.cards_played.len()) } } @@ -179,11 +180,15 @@ impl DealInPlay { &self.deal } + pub fn current_player(&self) -> Player { + self.in_progress.current_player() + } + pub fn play( mut self: Self, card: Card, ) -> Result<DealInPlayResult, anyhow::Error> { - let player = self.in_progress.next_player(); + let player = self.current_player(); let player_cards = player.get_cards_mut(&mut self.deal); info!( @@ -604,8 +609,8 @@ 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), deal.clone()); Self { deal, contract, @@ -617,6 +622,36 @@ impl PlayState { pub fn dealer(&self) -> Player { self.bidding.dealer } + + pub fn current_player(&self) -> Player { + self.playing_deal.current_player() + } + + pub fn play( + mut self, + card: Card, + ) -> Result<PlayStateResult, anyhow::Error> { + Ok(match self.playing_deal.play(card)? { + DealInPlayResult::InProgress(playing_deal) => { + PlayStateResult::InProgress(Self { + playing_deal, + ..self + }) + } + DealInPlayResult::PlayFinished(_) => { + PlayStateResult::PlayFinished(PlayResult) + } + }) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct PlayResult; + +#[derive(Debug)] +pub enum PlayStateResult { + InProgress(PlayState), + PlayFinished(PlayResult), } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] @@ -708,8 +743,7 @@ impl GameState { bidding, }, BiddingResult::Contract(Some(contract), bidding) => { - GameState::Play( - PlayState::new(deal, contract, bidding)) + GameState::Play(PlayState::new(deal, contract, bidding)) } }) } @@ -752,15 +786,15 @@ impl Distribution<Deal> for Standard { #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] pub struct PlayStatePlayerView { - player_position: Player, - bidding: Bidding, - contract: Contract, + pub player_position: Player, + pub bidding: Bidding, + pub contract: Contract, // If None, the lead has not been played. - dummy: Option<Vec<Card>>, - declarer_tricks: u8, - hand: Vec<Card>, - previous_trick: Trick, - current_trick: TurnInPlay, + pub dummy: Option<Vec<Card>>, + pub declarer_tricks: u8, + pub hand: Vec<Card>, + pub previous_trick: Trick, + pub current_trick: TurnInPlay, } impl PlayStatePlayerView { @@ -774,11 +808,22 @@ impl PlayStatePlayerView { contract: play_state.contract, dummy: None, declarer_tricks: 0, - hand: vec!(), - previous_trick: Trick { leader: random(), cards_played: vec!() }, - current_trick: TurnInPlay::new(random()), + hand: player_position.get_cards(&play_state.deal).clone(), + previous_trick: Trick { + leader: random(), + cards_played: vec![], + }, + current_trick: play_state.playing_deal.in_progress.clone(), } } + + pub fn dealer(&self) -> Player { + self.bidding.dealer + } + + pub fn current_player(&self) -> Player { + self.current_trick.current_player() + } } #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] @@ -1001,13 +1046,13 @@ mod tests { #[test] fn play_turn() { let turn = TurnInPlay::new(Player::South); - assert_eq!(turn.next_player(), Player::South); + assert_eq!(turn.current_player(), Player::South); let turn = as_turn(turn.play("♣4".parse().unwrap())); - assert_eq!(turn.next_player(), Player::West); + assert_eq!(turn.current_player(), Player::West); let turn = as_turn(turn.play("♥A".parse().unwrap())); - assert_eq!(turn.next_player(), Player::North); + assert_eq!(turn.current_player(), Player::North); let turn = as_turn(turn.play("♣4".parse().unwrap())); - assert_eq!(turn.next_player(), Player::East); + assert_eq!(turn.current_player(), Player::East); let trick = as_trick(turn.play("♣A".parse().unwrap())); assert_eq!( trick, @@ -1147,8 +1192,12 @@ mod tests { fn play_state_player_view() { crate::tests::test_setup(); let play_state = some_play_state(); - let player_deal = - PlayStatePlayerView::from_play_state(&play_state, random()); + let player = random(); + let player_state = + PlayStatePlayerView::from_play_state(&play_state, player); + assert_eq!(play_state.dealer(), player_state.dealer()); + assert_eq!(player_state.player_position, player); + assert_eq!(player_state.current_player(), play_state.current_player()); } fn as_playing_hand(result: DealInPlayResult) -> DealInPlay { |