From 72d5fe6f2bc51d186dccae8ef46e17dd7d6226a3 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Thu, 7 May 2020 08:57:04 -0600 Subject: [PATCH] impl game policy select and rando select --- .../controller/gamemaster/gamemaster/game.rs | 214 +++++++++++++++++- .../gamemaster/gamemaster/gamemaster.rs | 2 + 2 files changed, 211 insertions(+), 5 deletions(-) diff --git a/secert-hitler/src/controller/gamemaster/gamemaster/game.rs b/secert-hitler/src/controller/gamemaster/gamemaster/game.rs index 2d119d7..f6d945b 100644 --- a/secert-hitler/src/controller/gamemaster/gamemaster/game.rs +++ b/secert-hitler/src/controller/gamemaster/gamemaster/game.rs @@ -23,7 +23,9 @@ impl GameMaster { _ => self.game_policy_select(), }?; self.room.send(p.serialize()); - if p.mode() != GameEventType::PolicySet { + if p.mode() == GameEventType::Null { + continue; + } else if p.mode() != GameEventType::PolicySet { error!("unexpected game event type after election vote followup: {:?}", p); return Err(Role::Null); } @@ -115,7 +117,7 @@ impl GameMaster { let mut ge = GameEventType::VoteSet.build(); ge.d["sources"] = json::array!["__gm__"]; let mut yays = 0; - for (player, vote) in &votes { + for (_, vote) in &votes { if *vote { yays += 1; } @@ -141,18 +143,126 @@ impl GameMaster { } pub fn game_policy_select_random(&mut self) -> Result { + self.failed_votes += 1; + if self.failed_votes < 3 { + return Ok(GameEventType::Null.build()); + } let policy = self.deck.pop().unwrap().clone(); + self.discard.push(policy.clone()); let mut ge = GameEventType::PolicySet.build(); ge.d["params"] = json::array![format!("{:?}", policy)]; - self.room.send(ge.serialize()).unwrap(); + Ok(ge) } pub fn game_policy_select(&mut self) -> Result { - let draw = vec![]; + let mut draw = vec![]; + let mut to_discard = vec![]; for _ in 0..3 { draw.push(self.deck.pop().unwrap().clone()); + to_discard.push(self.deck.pop().unwrap().clone()); } - Err(Role::Null) + + let mut ge = GameEventType::CardPend.build(); + if self.president.is_none() { + return Err(Role::Null); + } + ge.d["targets"] = json::array![self.president.clone().unwrap().clone()]; + ge.d["params"] = json::array![]; + for policy in &draw { + ge.d["params"].push(format!("{:?}", policy)); + } + self.room.send(ge.serialize()).unwrap(); + + draw.clear(); + loop { + let events = self.scrape_until_gameeventtype(GameEventType::CardPick); + if events.is_err() { + return Err(Role::Null); + } + let events = events.unwrap(); + if events.len() == 0 { + return Err(Role::Null); + } + let card_pick_event = GameEvent::new(events.last().unwrap().clone()); + let sources = card_pick_event.sources(); + if sources.len() == 0 || sources.first().unwrap().clone() != self.president.clone().unwrap() { + continue + } + let params = card_pick_event.params(); + if params.len() != 2 { + continue + } + for param in ¶ms { + let policy = Policy::from_string(param.clone()); + if policy != Policy::Null { + draw.push(policy); + } + } + if draw.len() != params.len() { + continue; + } + break; + } + + let mut ge = GameEventType::CardPend.build(); + if self.chancellor.is_none() { + return Err(Role::Null); + } + ge.d["targets"] = json::array![self.chancellor.clone().unwrap().clone()]; + ge.d["params"] = json::array![]; + for policy in &draw { + ge.d["params"].push(format!("{:?}", policy)); + } + self.room.send(ge.serialize()).unwrap(); + + draw.clear(); + loop { + let events = self.scrape_until_gameeventtype(GameEventType::CardPick); + if events.is_err() { + return Err(Role::Null); + } + let events = events.unwrap(); + if events.len() == 0 { + return Err(Role::Null); + } + let card_pick_event = GameEvent::new(events.last().unwrap().clone()); + let sources = card_pick_event.sources(); + if sources.len() == 0 || sources.first().unwrap().clone() != self.chancellor.clone().unwrap() { + continue + } + let params = card_pick_event.params(); + if params.len() != 1 { + continue + } + for param in ¶ms { + let policy = Policy::from_string(param.clone()); + if policy != Policy::Null { + draw.push(policy); + } + } + if draw.len() != params.len() { + continue; + } + break; + } + + let policy = draw[0].clone(); + for i in 0..to_discard.len() { + if policy == to_discard[i] { + to_discard.remove(i); + break; + } + } + if to_discard.len() == 3 { + return Err(Role::Null); + } + for i in &to_discard { + self.discard.push(i.clone()); + } + + let mut ge = GameEventType::PolicySet.build(); + ge.d["params"] = json::array!(format!("{:?}", policy)); + Ok(ge) } pub fn game_policy_veto(&mut self, _p: Policy) -> Result { @@ -388,9 +498,103 @@ mod tests { #[test] fn game_policy_select() { + let mut gm = dummy(); + gm.president = Some("president".to_string()); + gm.chancellor = Some("chancellor".to_string()); + + debug!("sending an irrelevant event to pres picking a policy"); + let mut ge = GameEventType::Null.build(); + assert!(ge.mode() == GameEventType::Null); + ge.d["sources"] = json::array!["2"]; + ge.d["params"] = json::array!["y"]; + assert!(gm.room.send(ge.serialize()).is_ok()); + debug!("sent: {}", ge.serialize()); + + debug!("sending a invalid president card pick"); + let mut ge = GameEventType::CardPick.build(); + assert!(ge.mode() == GameEventType::CardPick); + ge.d["sources"] = json::array!["president"]; + ge.d["params"] = json::array!["abc"]; + assert!(gm.room.send(ge.serialize()).is_ok()); + debug!("sent: {}", ge.serialize()); + + debug!("sending a short president card pick"); + let mut ge = GameEventType::CardPick.build(); + assert!(ge.mode() == GameEventType::CardPick); + ge.d["sources"] = json::array!["president"]; + ge.d["params"] = json::array!["Facist"]; + assert!(gm.room.send(ge.serialize()).is_ok()); + debug!("sent: {}", ge.serialize()); + + debug!("sending a valid president card pick"); + let mut ge = GameEventType::CardPick.build(); + assert!(ge.mode() == GameEventType::CardPick); + ge.d["sources"] = json::array!["president"]; + ge.d["params"] = json::array!["Facist", "Liberal"]; + assert!(gm.room.send(ge.serialize()).is_ok()); + debug!("sent: {}", ge.serialize()); + + debug!("sending an irrelevant event to chan picking a policy"); + let mut ge = GameEventType::Null.build(); + assert!(ge.mode() == GameEventType::Null); + ge.d["sources"] = json::array!["2"]; + ge.d["params"] = json::array!["y"]; + assert!(gm.room.send(ge.serialize()).is_ok()); + debug!("sent: {}", ge.serialize()); + + debug!("sending a invalid chan card pick"); + let mut ge = GameEventType::CardPick.build(); + assert!(ge.mode() == GameEventType::CardPick); + ge.d["sources"] = json::array!["chancellor"]; + ge.d["params"] = json::array!["abc"]; + assert!(gm.room.send(ge.serialize()).is_ok()); + debug!("sent: {}", ge.serialize()); + + debug!("sending a short chan card pick"); + let mut ge = GameEventType::CardPick.build(); + assert!(ge.mode() == GameEventType::CardPick); + ge.d["sources"] = json::array!["chancellor"]; + ge.d["params"] = json::array![]; + assert!(gm.room.send(ge.serialize()).is_ok()); + debug!("sent: {}", ge.serialize()); + + debug!("sending a valid chan card pick"); + let mut ge = GameEventType::CardPick.build(); + assert!(ge.mode() == GameEventType::CardPick); + ge.d["sources"] = json::array!["chancellor"]; + ge.d["params"] = json::array!["Facist"]; + assert!(gm.room.send(ge.serialize()).is_ok()); + debug!("sent: {}", ge.serialize()); + + let ge = gm.game_policy_select(); + assert!(ge.is_ok()); + let ge = ge.unwrap(); + assert!(ge.mode() == GameEventType::PolicySet); + assert!(ge.params().len() == 1); + assert!(ge.params().first().unwrap() == "Facist"); + assert!(gm.discard.len() == 2); + // todo assert cards picked were viable } #[test] fn game_policy_select_random() { + let mut gm = dummy(); + gm.failed_votes = 0; + let ge = gm.game_policy_select_random(); + assert!(ge.is_ok()); + assert!(ge.unwrap().mode() == GameEventType::Null); + assert!(gm.discard.len() == 0); + + let mut gm = dummy(); + gm.failed_votes = 2; + let ge = gm.game_policy_select_random(); + assert!(ge.is_ok()); + let ge = ge.unwrap(); + assert!(ge.clone().mode() == GameEventType::PolicySet); + assert!(ge.clone().params().len() == 1); + let policy = Policy::from_string(ge.clone().params().first().clone().unwrap().clone()); + assert!(policy != Policy::Null); + assert!(gm.discard.len() == 1); + assert!(gm.discard.first().unwrap().clone() == policy); } } diff --git a/secert-hitler/src/controller/gamemaster/gamemaster/gamemaster.rs b/secert-hitler/src/controller/gamemaster/gamemaster/gamemaster.rs index 242280d..ab14c8c 100644 --- a/secert-hitler/src/controller/gamemaster/gamemaster/gamemaster.rs +++ b/secert-hitler/src/controller/gamemaster/gamemaster/gamemaster.rs @@ -22,6 +22,7 @@ pub struct GameMaster { pub policies: HashMap, pub president: Option, pub chancellor: Option, + pub failed_votes: usize, } impl GameMaster { @@ -36,6 +37,7 @@ impl GameMaster { policies: HashMap::new(), president: None, chancellor: None, + failed_votes: 0, } }