From 0b4b0723b38c607c1484f5429a3c54a8d98d5a24 Mon Sep 17 00:00:00 2001 From: bel Date: Tue, 5 May 2020 22:00:58 -0600 Subject: [PATCH] game setup lookin good, need main game loop and win conditions and exceptions tho --- secert-hitler/src/config.rs | 13 ++ .../src/controller/gamemaster/gamemaster.rs | 138 ++++++++++++++++-- .../src/controller/gamemaster/lobby.rs | 3 + .../src/controller/gamemaster/player.rs | 4 + 4 files changed, 145 insertions(+), 13 deletions(-) diff --git a/secert-hitler/src/config.rs b/secert-hitler/src/config.rs index 9354b85..a0330dd 100644 --- a/secert-hitler/src/config.rs +++ b/secert-hitler/src/config.rs @@ -1,2 +1,15 @@ pub static PORT:&str = ":8080"; pub static MIN_PLAYERS:usize = 5; +pub static MAX_PLAYERS:usize = 10; + +pub fn players_to_facists(n: usize) -> Result { + match n { + 5 => Ok(2), + 6 => Ok(2), + 7 => Ok(3), + 8 => Ok(3), + 9 => Ok(4), + 10 => Ok(4), + _ => Err("unsupported number of players".to_string()), + } +} diff --git a/secert-hitler/src/controller/gamemaster/gamemaster.rs b/secert-hitler/src/controller/gamemaster/gamemaster.rs index d902893..b24642f 100644 --- a/secert-hitler/src/controller/gamemaster/gamemaster.rs +++ b/secert-hitler/src/controller/gamemaster/gamemaster.rs @@ -4,6 +4,7 @@ use super::lobby::Lobby; use super::player::Player; use super::gameevent::GameEvent; use super::gameevent::GameEventType; +use super::role::Role; use std::thread; use std::time; @@ -68,16 +69,13 @@ impl GameMaster { } fn run_game_setup(&mut self) -> Result { - for player in self.players() { - if self.player(player.clone()).is_none() { - return Err(format!("missing player {}", player)); - } - self.candidate_presidents.push(player.clone()); - debug!("player = {}", player); - } - debug!("/players"); - debug!("should shuffle candidate_presidents to set game order"); - Err("not impl".to_string()) + self.setup_gather_candidates()?; + debug!("players: {:?}", self.candidate_presidents); + self.setup_set_roles()?; + debug!("/players: {:?}", self.candidate_presidents); + self.setup_order_candidates()?; + debug!("/players: {:?}", self.candidate_presidents); + Ok("ok".to_string()) } fn run_game(&mut self) -> Result { @@ -95,6 +93,54 @@ impl GameMaster { fn player(&mut self, id: String) -> Option<&mut Player> { self.lobby.players.get_mut(&id) } + + fn setup_gather_candidates(&mut self) -> Result { + for player in self.players() { + let p = self.player(player.clone()); + if p.is_none() { + return Err(format!("missing player {}", player)); + } + self.candidate_presidents.push(player.clone()); + debug!("player = {}", player); + } + Ok("ok".to_string()) + } + + fn setup_set_roles(&mut self) -> Result { + for player in self.players() { + self.player(player.clone()).unwrap().set_role(Role::Liberal); + } + let n = config::players_to_facists(self.players().len())?; + for i in 0..n { + debug!("picking facist {}/{} for {} players", i, n, self.players().len()); + loop { + let j = rand_usize(self.players().len()); + let id = self.candidate_presidents[j].clone(); + let player = self.player(id.clone()).unwrap(); + if player.get_role() != Role::Liberal { + continue; + } + let role = match i { + 0 => Role::Hitler, + _ => Role::Facist, + }; + player.set_role(role); + break; + } + } + Ok("ok".to_string()) + } + + fn setup_order_candidates(&mut self) -> Result { + shuffle(&mut self.candidate_presidents); + let n = self.candidate_presidents.len(); + for _ in 0..5 { + for i in 0..n { + self.candidate_presidents.push(self.candidate_presidents[i].clone()); + } + } + Ok("ok".to_string()) + } } fn shuffle(v: &mut Vec) { @@ -209,19 +255,85 @@ mod tests { init(); let mut mrs = MockRooms::new(); let r1 = mrs.create(); - let room_id = r1.room_id(); let mut gm = GameMaster::new(r1); let r = gm.run_game_setup(); assert!(!r.is_ok()); - for _ in 0..config::MIN_PLAYERS-1 { - mrs.join(room_id.clone()).unwrap(); + for i in 0..config::MIN_PLAYERS { + let id = format!("{}", i); + gm.lobby.players.insert(id.clone(), Player::new(id.clone())); } let r = gm.run_game_setup(); assert!(r.is_ok(), "failed to start game after sufficient players joined: {:?}", r); + assert!(gm.candidate_presidents.len() > gm.lobby.players.len()); } #[test] fn run_game_fail() { assert!(false, "not impl"); } + + #[test] + fn setup_gather_candidates() { + init(); + let mut mrs = MockRooms::new(); + let r1 = mrs.create(); + let mut gm = GameMaster::new(r1); + assert!(gm.setup_gather_candidates().is_ok()); + for i in 0..config::MIN_PLAYERS { + let id = format!("{}", i); + gm.lobby.players.insert(id.clone(), Player::new(id.clone())); + } + assert!(gm.setup_gather_candidates().is_ok()); + for i in config::MIN_PLAYERS..config::MAX_PLAYERS+1 { + let id = format!("{}", i); + gm.lobby.players.insert(id.clone(), Player::new(id.clone())); + } + assert!(gm.setup_gather_candidates().is_ok()); + } + + #[test] + fn setup_set_roles() { + init(); + let mut mrs = MockRooms::new(); + let r1 = mrs.create(); + let mut gm = GameMaster::new(r1); + assert!(gm.setup_set_roles().is_err()); + for i in 0..config::MIN_PLAYERS { + let id = format!("{}", i); + gm.lobby.players.insert(id.clone(), Player::new(id.clone())); + gm.candidate_presidents.push(id.clone()); + } + assert!(gm.setup_set_roles().is_ok()); + for i in config::MIN_PLAYERS..config::MAX_PLAYERS+1 { + let id = format!("{}", i); + gm.lobby.players.insert(id.clone(), Player::new(id.clone())); + gm.candidate_presidents.push(id.clone()); + } + assert!(gm.setup_set_roles().is_err()); + } + + #[test] + fn setup_order_candidates() { + init(); + let mut mrs = MockRooms::new(); + let r1 = mrs.create(); + let mut gm = GameMaster::new(r1); + assert!(gm.setup_order_candidates().is_ok()); + gm.candidate_presidents = ["1".to_string()].to_vec(); + assert!(gm.setup_order_candidates().is_ok()); + assert!(gm.candidate_presidents.len() > 1); + gm.candidate_presidents = [].to_vec(); + for i in 0..50 { + gm.candidate_presidents.push(format!("{}", i)); + } + let was = format!("{:?}", gm.candidate_presidents); + assert!(gm.setup_order_candidates().is_ok()); + assert!(gm.candidate_presidents.len() > 50); + assert!(was != format!("{:?}", gm.candidate_presidents)); + let mut found = false; + for i in 1..gm.candidate_presidents.len() { + found = found || gm.candidate_presidents[i] < gm.candidate_presidents[i-1]; + } + assert!(found); + } } diff --git a/secert-hitler/src/controller/gamemaster/lobby.rs b/secert-hitler/src/controller/gamemaster/lobby.rs index 296b5a4..1b028e0 100644 --- a/secert-hitler/src/controller/gamemaster/lobby.rs +++ b/secert-hitler/src/controller/gamemaster/lobby.rs @@ -42,6 +42,9 @@ impl Lobby { if n < config::MIN_PLAYERS { return Err("not enough players".to_string()); } + if n > config::MAX_PLAYERS { + return Err("too many players".to_string()); + } Ok(n) } } diff --git a/secert-hitler/src/controller/gamemaster/player.rs b/secert-hitler/src/controller/gamemaster/player.rs index bbb0b15..63c8f68 100644 --- a/secert-hitler/src/controller/gamemaster/player.rs +++ b/secert-hitler/src/controller/gamemaster/player.rs @@ -14,6 +14,10 @@ impl Player { } } + pub fn get_role(&self) -> Role { + self.role.clone() + } + pub fn set_role(&mut self, role: Role) { self.role.set(role); }