diff --git a/src/game.rs b/src/game.rs index bda3288..44a3f4f 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,12 +1,15 @@ +use crate::game::bid_round::BidRound; use crate::user::User; use crate::game::lobby::Lobby; +use crate::game::table::Table; -mod lobby; -mod table; +pub mod lobby; +pub mod table; +pub mod bid_round; #[derive(Debug, PartialEq, Eq, Clone, Copy)] -struct Settings { - to_win: u8, +pub struct Settings { + pub to_win: u8, } #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -41,39 +44,50 @@ impl<'a> Player<'a> { } #[derive(Debug, PartialEq, Eq, Clone, Copy)] -struct Game { +pub struct Game<'a> { settings: Settings, + table: Table<'a>, } -impl Game { - fn new(settings: Settings) -> Lobby<'static> { - Lobby { settings, players: Vec::new() } +impl Game<'_> { + pub fn new(settings: Settings, table: Table) -> Game { + Game { settings, table } } -} - -#[derive(Debug, PartialEq, Eq)] -struct BidRound { - settings: Settings, - players: Vec>, -} -impl BidRound { - fn new(settings: Settings) -> BidRound { - // TODO(2024-05-25 mollemoll): move players - BidRound { settings, players: Vec::new() } + pub fn start_round(&self) -> BidRound { + BidRound::new(0) } } #[cfg(test)] mod tests { + use crate::game::bid_round::BidRound; use super::*; + fn setup_users() -> Vec { + vec![ + User::new("A"), + User::new("B"), + User::new("C"), + User::new("D"), + ] + } + + fn setup_lobby() -> Lobby<'static> { + let settings = Settings { to_win: 13 }; + Lobby::new(settings) + } + #[test] - fn new_game_returns_a_lobby() { + fn new_game() { let settings = Settings { to_win: 13 }; - let game = Game::new(settings); + let users = setup_users(); + let mut lobby = setup_lobby(); + users.iter().for_each(|u| lobby.add_user(u)); + let table = Table::new(&lobby); + let game = Game::new(settings, table); - assert_eq!(game, Lobby { settings, players: Vec::new() }); + assert_eq!(game, Game { settings, table }); } #[test] @@ -84,4 +98,21 @@ mod tests { assert_eq!(player.user().name(), "John Doe"); assert_eq!(player.team(), Team::Lajvarna); } + + #[test] + fn start_round() { + let settings = Settings { to_win: 13 }; + let users = setup_users(); + let mut lobby = setup_lobby(); + users.iter().for_each(|u| lobby.add_user(u)); + let table = Table::new(&lobby); + let game = Game::new(settings, table); + + let bid_round = game.start_round(); + + assert_eq!( + bid_round.bids().len(), + 0, + ); + } } diff --git a/src/game/bid_round.rs b/src/game/bid_round.rs new file mode 100644 index 0000000..5adddc6 --- /dev/null +++ b/src/game/bid_round.rs @@ -0,0 +1,89 @@ +use crate::deck::Deck; +use crate::hand::Hand; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Bid { + Pass, + Play, +} + +type WinningBid = Bid; + +#[derive(Debug, PartialEq, Clone)] +pub struct BidRound { + hands: Vec, + dealer: usize, + bids: Vec, +} + +impl BidRound { + pub fn new(dealer: usize) -> BidRound { + let mut deck = Deck::new(); + deck.shuffle(); + let hands = deck.deal_hands(); + + BidRound { + hands, + dealer, + bids: Vec::with_capacity(4), + } + } + + pub fn bids(&self) -> &[Bid] { + &self.bids + } + + pub fn register_bid(&mut self, bid: Bid) -> Option { + self.bids.push(bid); + + if bid == Bid::Play { + return Some(Bid::Play); + } + + if self.bids.len() == 4 { + return Some(Bid::Pass); + } + + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn new_bid_round() { + let bid_round = BidRound::new(0); + + assert_eq!(bid_round.hands.len(), 4); + assert_eq!(bid_round.dealer, 0); + assert_eq!(bid_round.bids().len(), 0); + } + + #[test] + fn register_a_play_bid_triggers_play() { + let mut bid_round = BidRound::new(0); + + assert_eq!(bid_round.register_bid(Bid::Play), Some(Bid::Play)); + } + + #[test] + fn register_four_pass_bids_triggers_pass() { + let mut bid_round = BidRound::new(0); + + assert_eq!(bid_round.register_bid(Bid::Pass), None); + assert_eq!(bid_round.register_bid(Bid::Pass), None); + assert_eq!(bid_round.register_bid(Bid::Pass), None); + assert_eq!(bid_round.register_bid(Bid::Pass), Some(Bid::Pass)); + } + + #[test] + fn register_three_pass_bids_does_not_trigger_pass() { + let mut bid_round = BidRound::new(0); + + assert_eq!(bid_round.register_bid(Bid::Pass), None); + assert_eq!(bid_round.register_bid(Bid::Pass), None); + assert_eq!(bid_round.register_bid(Bid::Pass), None); + } +} diff --git a/src/game/lobby.rs b/src/game/lobby.rs index 0c10c30..e4e4ee5 100644 --- a/src/game/lobby.rs +++ b/src/game/lobby.rs @@ -1,15 +1,23 @@ use crate::errors::GameError; -use crate::game::{BidRound, Player, Settings, Team}; +use crate::game::{Game, Player, Settings, Team}; use crate::user::User; +use crate::game::table::Table; #[derive(Debug, PartialEq, Clone)] -pub(crate) struct Lobby<'a> { +pub struct Lobby<'a> { pub(crate) settings: Settings, pub(crate) players: Vec>, } impl<'a> Lobby<'a> { - pub(crate) fn add_user(&mut self, user: &'a User) { + pub fn new(settings: Settings) -> Lobby<'a> { + Lobby { + settings, + players: Vec::new(), + } + } + + pub fn add_user(&mut self, user: &'a User) { // Create player let player = Player::build( &user, @@ -42,7 +50,7 @@ impl<'a> Lobby<'a> { } } - fn ready_up(&mut self, user: &'a User) { + pub fn ready_up(&mut self, user: &'a User) { if let Some(player) = self.players .iter_mut() .find(|p| p.user() == user) { @@ -89,7 +97,7 @@ impl<'a> Lobby<'a> { } } - fn start_game(&self) -> Result { + pub fn start_game(&self) -> Result { if self.ready_count() != 4 { return Err(GameError::RequiresFourReadyPlayers); } @@ -98,7 +106,14 @@ impl<'a> Lobby<'a> { return Err(GameError::UnbalancedTeams); } - Ok(BidRound::new(self.settings)) + let table = Table::new(self); + + Ok( + Game::new( + self.settings, + table, + ) + ) } } @@ -106,17 +121,17 @@ impl<'a> Lobby<'a> { #[cfg(test)] mod tests { - use crate::game::{Game, Settings, Team}; + use crate::game::{Settings, Team}; use super::*; - fn setup_game() -> Lobby<'static> { + fn setup_lobby() -> Lobby<'static> { let settings = Settings { to_win: 13 }; - Game::new(settings) + Lobby::new(settings) } #[test] fn accepts_user_joining() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); game_lobby.add_user(&user); @@ -126,7 +141,7 @@ mod tests { #[test] fn denies_player_joining_twice() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); game_lobby.add_user(&user); @@ -137,7 +152,7 @@ mod tests { #[test] fn accepts_user_leaving() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); let user2 = User::new("Jane Doe"); @@ -151,7 +166,7 @@ mod tests { #[test] fn denies_user_leaving_twice() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); let user2 = User::new("Jane Doe"); @@ -165,7 +180,7 @@ mod tests { #[test] fn assigning_users_evenly_between_teams() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); let user2 = User::new("Jane Doe"); let user3 = User::new("Dolly"); @@ -181,7 +196,7 @@ mod tests { #[test] fn denies_5th_player() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); let user2 = User::new("Jane Doe"); let user3 = User::new("Dolly"); @@ -201,7 +216,7 @@ mod tests { #[test] fn allowing_players_to_change_team() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); game_lobby.add_user(&user); @@ -216,7 +231,7 @@ mod tests { #[test] fn player_can_ready_up() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); game_lobby.add_user(&user); @@ -227,7 +242,7 @@ mod tests { #[test] fn readying_up_twice_doesnt_change_anything() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); game_lobby.add_user(&user); @@ -239,7 +254,7 @@ mod tests { #[test] fn player_can_unready() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); let user2 = User::new("Jane Doe"); @@ -254,7 +269,7 @@ mod tests { #[test] fn starting_requires_four_ready_players() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); let user2 = User::new("Jane Doe"); let user3 = User::new("Dolly"); @@ -271,7 +286,7 @@ mod tests { #[test] fn cant_start_with_unbalanced_teams() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); let user2 = User::new("Jane Doe"); let user3 = User::new("Dolly"); @@ -295,7 +310,7 @@ mod tests { #[test] fn can_start_with_four_ready_players() { - let mut game_lobby = setup_game(); + let mut game_lobby = setup_lobby(); let user = User::new("John Doe"); let user2 = User::new("Jane Doe"); let user3 = User::new("Dolly"); @@ -310,13 +325,8 @@ mod tests { game_lobby.ready_up(&user3); game_lobby.ready_up(&user4); - assert_eq!( - game_lobby.start_game().unwrap(), - BidRound { - settings: Settings { to_win: 13 }, - // TODO(2024-05-25 mollemoll): fix move players - players: vec![] - } - ); + let result = game_lobby.start_game(); + + assert!(result.is_ok()); } } diff --git a/src/game/table.rs b/src/game/table.rs index daea6be..e26050f 100644 --- a/src/game/table.rs +++ b/src/game/table.rs @@ -3,8 +3,8 @@ use crate::game::lobby::Lobby; use crate::game::Player; use crate::deck::Deck; -#[derive(Debug, PartialEq, Eq, Clone)] -struct Table<'a> { +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct Table<'a> { north: Player<'a>, east: Player<'a>, south: Player<'a>, @@ -12,7 +12,7 @@ struct Table<'a> { } impl<'a> Table<'a> { - pub fn new(lobby: Lobby<'a>) -> Table { + pub fn new(lobby: &Lobby<'a>) -> Table<'a> { // Each player draws a card let high_card_draws = Self::high_card_for_dealer_button(lobby); let highest_card_team = high_card_draws[0].0.team(); @@ -39,7 +39,7 @@ impl<'a> Table<'a> { } } - fn high_card_for_dealer_button(lobby: Lobby<'a>) -> Vec<(Player, Card)> { + fn high_card_for_dealer_button(lobby: &Lobby<'a>) -> Vec<(Player<'a>, Card)> { let mut deck = Deck::new(); deck.shuffle(); @@ -60,7 +60,7 @@ impl<'a> Table<'a> { mod tests { use super::*; use crate::game::lobby::Lobby; - use crate::game::{Game, Settings}; + use crate::game::{Settings}; use crate::user::User; fn setup_users() -> Vec { @@ -74,7 +74,7 @@ mod tests { fn setup_lobby() -> Lobby<'static> { let settings = Settings { to_win: 13 }; - Game::new(settings) + Lobby::new(settings) } #[test] @@ -83,7 +83,7 @@ mod tests { let mut lobby = setup_lobby(); users.iter().for_each(|u| lobby.add_user(u)); - let high_card_draws = Table::high_card_for_dealer_button(lobby); + let high_card_draws = Table::high_card_for_dealer_button(&lobby); let cards = high_card_draws.iter() .map(|(_, c)| c.clone()) @@ -104,7 +104,7 @@ mod tests { let mut lobby = setup_lobby(); users.iter().for_each(|u| lobby.add_user(u)); - let table = Table::new(lobby); + let table = Table::new(&lobby); assert_eq!(table.north.team(), table.south.team()); assert_eq!(table.east.team(), table.west.team()); diff --git a/src/lib.rs b/src/lib.rs index 700026e..9264d4e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ pub mod user; -mod game; +pub mod game; mod errors; mod card; mod deck;