impl game over
parent
2b8581952e
commit
0347d613df
|
|
@ -1,46 +1,67 @@
|
|||
use super::gamemaster::GameMaster;
|
||||
use super::super::gameevent::GameEvent;
|
||||
use super::super::gameevent::GameEventType;
|
||||
use super::super::policy::Policy;
|
||||
|
||||
use log::{LevelFilter};
|
||||
use super::super::role::Role;
|
||||
use super::super::player::Player;
|
||||
|
||||
impl GameMaster {
|
||||
pub fn game_is_over(&mut self) -> Result<GameEvent, String> {
|
||||
Err("not impl".to_string())
|
||||
pub fn game_is_over(&mut self) -> Result<GameEvent, Role> {
|
||||
if self.policies[&Policy::Facist] >= 3 {
|
||||
let chancellor = self.chancellor.clone();
|
||||
if chancellor.is_some() {
|
||||
let player = self.player(chancellor.unwrap());
|
||||
if player.is_some() && player.unwrap().get_role() == Role::Hitler {
|
||||
return Err(Role::Facist);
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.policies[&Policy::Facist] > 5 {
|
||||
return Err(Role::Facist);
|
||||
}
|
||||
if self.policies[&Policy::Liberal] > 5 {
|
||||
return Err(Role::Liberal);
|
||||
}
|
||||
Ok(GameEventType::Null.build())
|
||||
}
|
||||
|
||||
pub fn game_election(&mut self) -> Result<GameEvent, String> {
|
||||
Err("not impl".to_string())
|
||||
pub fn game_election(&mut self) -> Result<GameEvent, Role> {
|
||||
Err(Role::Null)
|
||||
}
|
||||
|
||||
pub fn game_election_vote(&mut self) -> Result<GameEvent, String> {
|
||||
Err("not impl".to_string())
|
||||
pub fn game_election_vote(&mut self) -> Result<GameEvent, Role> {
|
||||
Err(Role::Null)
|
||||
}
|
||||
|
||||
pub fn game_policy_select_random(&mut self) -> Result<Policy, String> {
|
||||
Err("not impl".to_string())
|
||||
pub fn game_policy_select_random(&mut self) -> Result<GameEvent, Role> {
|
||||
Err(Role::Null)
|
||||
}
|
||||
|
||||
pub fn game_policy_select(&mut self) -> Result<Policy, String> {
|
||||
Err("not impl".to_string())
|
||||
pub fn game_policy_select(&mut self) -> Result<GameEvent, Role> {
|
||||
Err(Role::Null)
|
||||
}
|
||||
|
||||
pub fn game_policy_veto(&mut self, _p: Policy) -> Result<GameEvent, String> {
|
||||
Err("not impl".to_string())
|
||||
pub fn game_policy_veto(&mut self, _p: Policy) -> Result<GameEvent, Role> {
|
||||
Err(Role::Null)
|
||||
}
|
||||
|
||||
pub fn game_ends_with(&mut self, _p: Policy) -> Result<GameEvent, String> {
|
||||
Err("not impl".to_string())
|
||||
pub fn game_ends_with(&mut self, _p: Policy) -> Result<GameEvent, Role> {
|
||||
Err(Role::Null)
|
||||
}
|
||||
|
||||
pub fn game_policy_enact(&mut self, _p: Policy) -> Result<GameEvent, String> {
|
||||
Err("not impl".to_string())
|
||||
pub fn game_policy_enact(&mut self, _p: Policy) -> Result<GameEvent, Role> {
|
||||
Err(Role::Null)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::super::super::super::super::model::state::mockrooms::MockRooms;
|
||||
use super::super::super::super::super::model::state::rooms::Rooms;
|
||||
use super::super::super::super::super::config;
|
||||
|
||||
use log::{debug, LevelFilter};
|
||||
|
||||
fn init() {
|
||||
let _ = env_logger::builder()
|
||||
|
|
@ -49,8 +70,83 @@ mod tests {
|
|||
.try_init();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn game() {
|
||||
fn dummy() -> GameMaster {
|
||||
init();
|
||||
let mut mrs = MockRooms::new();
|
||||
let r = mrs.create();
|
||||
let room_id = r.room_id().clone();
|
||||
let mut gm = GameMaster::new(r);
|
||||
for _ in 0..config::MIN_PLAYERS-2 {
|
||||
assert!(mrs.join(room_id.clone()).is_ok());
|
||||
}
|
||||
mrs.join(room_id).unwrap().send(format!(r#"{{
|
||||
"msgtype": "m.text",
|
||||
"body": "{{\"GameEventType\": \"GameStart\"}}"
|
||||
}}"#)).unwrap();
|
||||
assert!(gm.run_lobby().is_ok());
|
||||
assert!(gm.run_game_setup().is_ok());
|
||||
gm
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dummy() {
|
||||
let gm = dummy();
|
||||
assert!(gm.players().len() == config::MIN_PLAYERS);
|
||||
assert!(config::players_to_policies_facist(gm.players().len()) + config::players_to_policies_liberal(gm.players().len()) == gm.deck.len());
|
||||
assert!(gm.players().len() < gm.candidate_presidents.len());
|
||||
assert!(gm.policies[&Policy::Facist] == 0);
|
||||
assert!(gm.policies[&Policy::Liberal] == 0);
|
||||
let mut found = false;
|
||||
for i in 1..gm.candidate_presidents.len() {
|
||||
found = found || gm.candidate_presidents[i-1] > gm.candidate_presidents[i];
|
||||
}
|
||||
assert!(found);
|
||||
debug!("gamemaster dummy: {:?}", gm);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn game_is_over() {
|
||||
let mut gm = dummy();
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
|
||||
let mut gm = dummy();
|
||||
gm.policies.insert(Policy::Facist, 10);
|
||||
assert!(gm.game_is_over().is_err());
|
||||
assert!(gm.game_is_over().err().unwrap() == Role::Facist);
|
||||
|
||||
let mut gm = dummy();
|
||||
gm.policies.insert(Policy::Liberal, 10);
|
||||
assert!(gm.game_is_over().err().unwrap() == Role::Liberal);
|
||||
|
||||
let mut gm = dummy();
|
||||
gm.policies.insert(Policy::Facist, 3);
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
gm.chancellor = Some("123".to_string());
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
let mut p = Player::new("123".to_string());
|
||||
p.set_role(Role::Liberal);
|
||||
gm.lobby.players.insert("123".to_string(), p);
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
|
||||
let mut gm = dummy();
|
||||
gm.policies.insert(Policy::Facist, 3);
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
gm.chancellor = Some("123".to_string());
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
let mut p = Player::new("123".to_string());
|
||||
p.set_role(Role::Facist);
|
||||
gm.lobby.players.insert("123".to_string(), p);
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
|
||||
let mut gm = dummy();
|
||||
gm.policies.insert(Policy::Facist, 3);
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
gm.chancellor = Some("123".to_string());
|
||||
assert!(gm.game_is_over().is_ok());
|
||||
let mut p = Player::new("123".to_string());
|
||||
p.set_role(Role::Hitler);
|
||||
gm.lobby.players.insert("123".to_string(), p);
|
||||
assert!(gm.game_is_over().is_err());
|
||||
assert!(gm.game_is_over().err().unwrap() == Role::Facist);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,19 +2,25 @@ use super::super::super::super::model::state::room::Room;
|
|||
use super::super::lobby::Lobby;
|
||||
use super::super::player::Player;
|
||||
use super::super::policy::Policy;
|
||||
use super::super::role::Role;
|
||||
use super::super::gameevent::GameEventType;
|
||||
use super::super::gameevent::GameEvent;
|
||||
|
||||
use log::{info, error};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GameMaster {
|
||||
pub room: Box<dyn Room>,
|
||||
pub lobby: Lobby,
|
||||
pub candidate_presidents: Vec<String>,
|
||||
pub deck: Vec<Policy>,
|
||||
pub policies: HashMap<Policy, usize>,
|
||||
pub president: Option<String>,
|
||||
pub chancellor: Option<String>,
|
||||
}
|
||||
|
||||
impl GameMaster {
|
||||
|
||||
pub fn new(room: Box<dyn Room>) -> GameMaster {
|
||||
info!("created for room {}", room.room_id());
|
||||
GameMaster{
|
||||
|
|
@ -22,10 +28,13 @@ impl GameMaster {
|
|||
lobby: Lobby::new(),
|
||||
candidate_presidents: vec![],
|
||||
deck: vec![],
|
||||
policies: HashMap::new(),
|
||||
president: None,
|
||||
chancellor: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&mut self) -> Result<String, String> {
|
||||
pub fn run(&mut self) -> Result<GameEvent, Role> {
|
||||
loop {
|
||||
let r = self.run_lobby();
|
||||
if r.is_ok() {
|
||||
|
|
@ -37,19 +46,31 @@ impl GameMaster {
|
|||
self.run_game()
|
||||
}
|
||||
|
||||
pub fn run_game(&mut self) -> Result<String, String> {
|
||||
pub fn run_game(&mut self) -> Result<GameEvent, Role> {
|
||||
loop {
|
||||
self.game_is_over()?;
|
||||
self.game_election()?;
|
||||
self.game_is_over()?;
|
||||
let p = match self.game_election_vote().unwrap_or(GameEventType::GameStop.build()).mode() {
|
||||
GameEventType::VoteFailed => self.game_policy_select_random(),
|
||||
GameEventType::GameStop => Err("game ended".to_string()),
|
||||
GameEventType::GameStop => self.game_is_over(),
|
||||
_ => self.game_policy_select(),
|
||||
}?;
|
||||
self.game_policy_veto(p.clone())?;
|
||||
self.game_ends_with(p.clone())?;
|
||||
self.game_policy_enact(p.clone())?; // todo facist policies special
|
||||
if p.mode() != GameEventType::PolicySet {
|
||||
error!("unexpected game event type after election vote followup: {:?}", p);
|
||||
return Err(Role::Null);
|
||||
}
|
||||
let params = p.params();
|
||||
let param = params.first();
|
||||
if param.is_none() {
|
||||
error!("unexpected missing param on {:?}: {:?}", p, param);
|
||||
return Err(Role::Null);
|
||||
}
|
||||
let param = param.unwrap();
|
||||
let policy = Policy::from_string(param.to_string());
|
||||
self.game_policy_veto(policy.clone())?;
|
||||
self.game_ends_with(policy.clone())?;
|
||||
self.game_policy_enact(policy.clone())?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ use super::super::policy::Policy;
|
|||
use super::super::rand::rand_usize;
|
||||
use super::super::rand::shuffle;
|
||||
|
||||
use log::{debug, LevelFilter};
|
||||
use log::{debug, error, LevelFilter};
|
||||
|
||||
impl GameMaster {
|
||||
pub fn run_game_setup(&mut self) -> Result<String, String> {
|
||||
pub fn run_game_setup(&mut self) -> Result<String, Role> {
|
||||
self.setup_gather_candidates()?;
|
||||
debug!("players: {:?}", self.candidate_presidents);
|
||||
self.setup_set_roles()?;
|
||||
|
|
@ -20,11 +20,12 @@ impl GameMaster {
|
|||
Ok("ok".to_string())
|
||||
}
|
||||
|
||||
pub fn setup_gather_candidates(&mut self) -> Result<String, String> {
|
||||
pub fn setup_gather_candidates(&mut self) -> Result<String, Role> {
|
||||
for player in self.players() {
|
||||
let p = self.player(player.clone());
|
||||
if p.is_none() {
|
||||
return Err(format!("missing player {}", player));
|
||||
error!("missing player {}", player);
|
||||
return Err(Role::Null);
|
||||
}
|
||||
self.candidate_presidents.push(player.clone());
|
||||
debug!("player = {}", player);
|
||||
|
|
@ -32,11 +33,15 @@ impl GameMaster {
|
|||
Ok("ok".to_string())
|
||||
}
|
||||
|
||||
pub fn setup_set_roles(&mut self) -> Result<String, String> {
|
||||
pub fn setup_set_roles(&mut self) -> Result<String, Role> {
|
||||
for player in self.players() {
|
||||
self.player(player.clone()).unwrap().set_role(Role::Liberal);
|
||||
}
|
||||
let n = config::players_to_facists(self.players().len())?;
|
||||
let n = config::players_to_facists(self.players().len());
|
||||
if n.is_err() {
|
||||
return Err(Role::Null);
|
||||
}
|
||||
let n = n.unwrap();
|
||||
for i in 0..n {
|
||||
debug!("picking facist {}/{} for {} players", i, n, self.players().len());
|
||||
loop {
|
||||
|
|
@ -54,10 +59,12 @@ impl GameMaster {
|
|||
break;
|
||||
}
|
||||
}
|
||||
self.president = None;
|
||||
self.chancellor = None;
|
||||
Ok("ok".to_string())
|
||||
}
|
||||
|
||||
pub fn setup_order_candidates(&mut self) -> Result<String, String> {
|
||||
pub fn setup_order_candidates(&mut self) -> Result<String, Role> {
|
||||
shuffle(&mut self.candidate_presidents);
|
||||
let n = self.candidate_presidents.len();
|
||||
for _ in 0..5 {
|
||||
|
|
@ -68,7 +75,7 @@ impl GameMaster {
|
|||
Ok("ok".to_string())
|
||||
}
|
||||
|
||||
pub fn setup_deck(&mut self) -> Result<String, String> {
|
||||
pub fn setup_deck(&mut self) -> Result<String, Role> {
|
||||
for _ in 0..config::players_to_policies_facist(self.players().len()) {
|
||||
self.deck.push(Policy::Facist);
|
||||
}
|
||||
|
|
@ -79,6 +86,9 @@ impl GameMaster {
|
|||
|
||||
shuffle(&mut self.deck);
|
||||
|
||||
self.policies.insert(Policy::Facist, 0); // todo start iwth 1 if 5 players?
|
||||
self.policies.insert(Policy::Liberal, 0); // todo start iwth 1 if 5 players?
|
||||
|
||||
Ok("deck is loaded".to_string())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Policy {
|
||||
Null,
|
||||
Facist,
|
||||
|
|
@ -6,6 +6,20 @@ pub enum Policy {
|
|||
}
|
||||
|
||||
impl Policy {
|
||||
pub fn from_string(s: String) -> Policy {
|
||||
let cases = [
|
||||
Policy::Null,
|
||||
Policy::Facist,
|
||||
Policy::Liberal,
|
||||
];
|
||||
for c in &cases {
|
||||
if format!("{:?}", c) == s {
|
||||
return c.clone();
|
||||
}
|
||||
}
|
||||
Policy::Null
|
||||
}
|
||||
|
||||
pub fn new() -> Policy {
|
||||
Policy::Null
|
||||
}
|
||||
|
|
@ -34,4 +48,10 @@ mod tests {
|
|||
r.set(Policy::Liberal);
|
||||
assert!(r == Policy::Liberal);
|
||||
}
|
||||
|
||||
fn from_string() {
|
||||
assert!(Policy::from_string("".to_string()) == Policy::Null);
|
||||
assert!(Policy::from_string("Liberal".to_string()) == Policy::Liberal);
|
||||
assert!(Policy::from_string("Facist".to_string()) == Policy::Facist);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use super::event;
|
||||
|
||||
pub trait Room {
|
||||
use std::fmt;
|
||||
|
||||
pub trait Room: fmt::Debug {
|
||||
fn rollback(&mut self, since: String);
|
||||
fn sync(&mut self) -> Vec<event::Event>;
|
||||
fn send(&mut self, message: String) -> Result<String, &str>;
|
||||
|
|
|
|||
Loading…
Reference in New Issue