summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2022-12-22 11:35:14 -0500
committerKjetil Orbekk <kj@orbekk.com>2022-12-22 11:35:14 -0500
commit0ba28546b94a794d56c56bba35f035200fd0a434 (patch)
tree3baa019b135043f46587b968e5d5e41478e33778
parent42f6ef6d44e893b47e5e2a49496b5dd2122df232 (diff)
Support bidding→playing transition in GameState
Introduce a generic type to represent result of playing moves
-rw-r--r--protocol/src/bridge_engine.rs92
-rw-r--r--protocol/src/lib.rs1
-rw-r--r--protocol/src/play_result.rs20
3 files changed, 55 insertions, 58 deletions
diff --git a/protocol/src/bridge_engine.rs b/protocol/src/bridge_engine.rs
index 35eb90f..a2766f0 100644
--- a/protocol/src/bridge_engine.rs
+++ b/protocol/src/bridge_engine.rs
@@ -1,4 +1,7 @@
-use crate::card::{make_deck, sort_cards, Card, RankOrder, Suit};
+use crate::{
+ card::{make_deck, sort_cards, Card, RankOrder, Suit},
+ play_result::MoveResult,
+};
use anyhow::{anyhow, bail};
use log::{error, info};
use rand::{
@@ -628,7 +631,7 @@ impl PlayState {
}
pub fn play(
- mut self,
+ self,
card: Card,
) -> Result<PlayStateResult, anyhow::Error> {
Ok(match self.playing_deal.play(card)? {
@@ -658,11 +661,6 @@ pub enum PlayStateResult {
pub enum GameState {
Bidding(BiddingState),
Play(PlayState),
- PassedOut {
- dealer: Player,
- deal: Deal,
- bidding: Bidding,
- },
}
impl GameState {
@@ -677,7 +675,6 @@ impl GameState {
pub fn deal(&self) -> &Deal {
match self {
Self::Bidding(BiddingState { deal, .. }) => deal,
- Self::PassedOut { deal, .. } => deal,
Self::Play(PlayState { playing_deal, .. }) => &playing_deal.deal(),
}
}
@@ -685,22 +682,14 @@ impl GameState {
pub fn dealer(&self) -> Player {
match self {
Self::Bidding(BiddingState { dealer, .. }) => *dealer,
- Self::PassedOut { dealer, .. } => *dealer,
Self::Play(play_state) => play_state.dealer(),
}
}
- pub fn current_player(&self) -> Option<Player> {
+ pub fn current_player(&self) -> Player {
match self {
- GameState::Bidding(bidding) => {
- Some(bidding.bidding.current_bidder())
- }
- GameState::Play(_) => todo!(),
- GameState::PassedOut {
- dealer,
- deal,
- bidding,
- } => None,
+ GameState::Bidding(bidding) => bidding.bidding.current_bidder(),
+ GameState::Play(play) => play.current_player(),
}
}
@@ -720,7 +709,10 @@ impl GameState {
}
}
- pub fn bid(self, bid: Bid) -> Result<Self, anyhow::Error> {
+ pub fn bid(
+ self,
+ bid: Bid,
+ ) -> Result<MoveResult<GameState, GameResult>, anyhow::Error> {
let (dealer, deal, bidding) = match self {
GameState::Bidding(BiddingState {
dealer,
@@ -731,24 +723,27 @@ impl GameState {
};
Ok(match bidding.bid(bid)? {
BiddingResult::InProgress(bidding) => {
- GameState::Bidding(BiddingState {
+ MoveResult::Stay(GameState::Bidding(BiddingState {
dealer,
deal,
bidding,
- })
+ }))
+ }
+ BiddingResult::Contract(None, _bidding) => {
+ MoveResult::Go(GameResult)
}
- BiddingResult::Contract(None, bidding) => GameState::PassedOut {
- dealer,
- deal,
- bidding,
- },
BiddingResult::Contract(Some(contract), bidding) => {
- GameState::Play(PlayState::new(deal, contract, bidding))
+ MoveResult::Stay(GameState::Play(PlayState::new(
+ deal, contract, bidding,
+ )))
}
})
}
}
+#[derive(Debug)]
+pub struct GameResult;
+
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct Deal {
pub north: Vec<Card>,
@@ -829,26 +824,7 @@ impl PlayStatePlayerView {
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
pub enum GameStatePlayerView {
Bidding(BiddingStatePlayerView),
- PassedOut {
- dealer: Player,
- player_position: Player,
- deal: Deal,
- bidding: Bidding,
- },
- Lead {
- dealer: Player,
- player_position: Player,
- contract: Contract,
- hand: Vec<Card>,
- },
- Play {
- dealer: Player,
- player_position: Player,
- contract: Contract,
- trick: Trick,
- dummy: Vec<Card>,
- hand: Vec<Card>,
- },
+ Playing(PlayStatePlayerView),
}
impl GameStatePlayerView {
@@ -863,7 +839,6 @@ impl GameStatePlayerView {
player_position,
),
),
- GameState::PassedOut { .. } => todo!(),
GameState::Play { .. } => todo!(),
}
}
@@ -874,13 +849,9 @@ impl GameStatePlayerView {
hand,
..
}) => hand,
- GameStatePlayerView::PassedOut {
- deal,
- player_position,
- ..
- } => player_position.get_cards(deal),
- GameStatePlayerView::Lead { hand, .. } => hand,
- GameStatePlayerView::Play { hand, .. } => hand,
+ GameStatePlayerView::Playing(PlayStatePlayerView {
+ hand, ..
+ }) => hand,
}
}
}
@@ -1128,14 +1099,19 @@ mod tests {
info!("Start bidding with game state {game_state:#?}");
let raise = |s| Bid::Raise(Raise::from_str(s).unwrap());
- let game_state = game_state.bid(raise("1H")).unwrap();
- assert_eq!(game_state.is_bidding(), true);
+ let game_state = game_state.bid(raise("1H")).unwrap().stay().unwrap();
let game_state = game_state
.bid(Bid::Pass)
.unwrap()
+ .stay()
+ .unwrap()
.bid(Bid::Pass)
.unwrap()
+ .stay()
+ .unwrap()
.bid(Bid::Pass)
+ .unwrap()
+ .stay()
.unwrap();
info!("Start playing with game state {game_state:#?}");
assert_eq!(game_state.is_bidding(), false);
diff --git a/protocol/src/lib.rs b/protocol/src/lib.rs
index 8b48fec..3fbf1e0 100644
--- a/protocol/src/lib.rs
+++ b/protocol/src/lib.rs
@@ -4,6 +4,7 @@ pub mod card;
pub mod bridge_engine;
pub mod bot;
pub mod simple_bots;
+pub mod play_result;
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
pub struct UserInfo {
diff --git a/protocol/src/play_result.rs b/protocol/src/play_result.rs
new file mode 100644
index 0000000..21961ee
--- /dev/null
+++ b/protocol/src/play_result.rs
@@ -0,0 +1,20 @@
+pub enum MoveResult<Stay, Go> {
+ Stay(Stay),
+ Go(Go),
+}
+
+impl<Stay, Go> MoveResult<Stay, Go> {
+ pub fn stay(self) -> Result<Stay, anyhow::Error> {
+ match self {
+ MoveResult::Stay(o) => Ok(o),
+ MoveResult::Go(_) => Err(anyhow::anyhow!("Not in stay state")),
+ }
+ }
+
+ pub fn go(self) -> Result<Go, anyhow::Error> {
+ match self {
+ MoveResult::Go(f) => Ok(f),
+ MoveResult::Stay(_) => Err(anyhow::anyhow!("Not in go state")),
+ }
+ }
+}