This commit is contained in:
ntr 2019-04-29 18:42:03 +10:00
parent b2bfe8cf2a
commit 18aef974b6
4 changed files with 60 additions and 17 deletions

View File

@ -278,6 +278,11 @@ impl Cryp {
self.green_life.value == 0 self.green_life.value == 0
} }
pub fn force_ko(&mut self) -> &mut Cryp {
self.green_life.value = 0;
self
}
pub fn immune(&self, skill: Skill) -> Option<Immunity> { pub fn immune(&self, skill: Skill) -> Option<Immunity> {
// also checked in resolve stage so shouldn't happen really // also checked in resolve stage so shouldn't happen really
if self.is_ko() { if self.is_ko() {

View File

@ -22,7 +22,6 @@ use instance::{instance_game_finished, global_game_finished};
pub enum Phase { pub enum Phase {
Start, Start,
Skill, Skill,
Target,
Resolve, Resolve,
Finish, Finish,
} }
@ -568,19 +567,29 @@ impl Game {
} }
fn phase_timed_out(&self) -> bool { fn phase_timed_out(&self) -> bool {
Utc::now().signed_duration_since(self.phase_start).num_seconds() > 30 Utc::now().signed_duration_since(self.phase_start).num_seconds() > 60
} }
pub fn upkeep(mut self) -> Game { pub fn upkeep(mut self) -> Game {
// give players a ready status if self.phase != Phase::Skill {
// on time out if not enough skills selected panic!("{:?} game not in skill phase during upkeep", self);
// add a warning
// on 3 warnings forfeit
if self.phase == Phase::Skill && self.phase_timed_out() {
self = self.resolve_phase_start();
} }
if !self.phase_timed_out() {
return self;
}
for player in self.players.iter_mut() {
if !player.ready {
player.set_ready(true);
player.add_warning();
if player.warnings >= 3 {
player.forfeit();
}
}
}
self = self.resolve_phase_start();
self self
} }
} }
@ -998,12 +1007,12 @@ mod tests {
let i_player_id = Uuid::new_v4(); let i_player_id = Uuid::new_v4();
i.account = i_player_id; i.account = i_player_id;
j.account = i_player_id; j.account = i_player_id;
let mut i_player = Player::new(i_player_id, &"ntr".to_string(), vec![i, j]); let i_player = Player::new(i_player_id, &"ntr".to_string(), vec![i, j]);
let x_player_id = Uuid::new_v4(); let x_player_id = Uuid::new_v4();
x.account = x_player_id; x.account = x_player_id;
y.account = x_player_id; y.account = x_player_id;
let mut x_player = Player::new(x_player_id, &"mashy".to_string(), vec![x, y]); let x_player = Player::new(x_player_id, &"mashy".to_string(), vec![x, y]);
game game
.player_add(i_player).unwrap() .player_add(i_player).unwrap()
@ -1027,6 +1036,9 @@ mod tests {
game.add_skill(x_player.id, x_cryp.id, Some(y_cryp.id), Skill::Attack).unwrap(); game.add_skill(x_player.id, x_cryp.id, Some(y_cryp.id), Skill::Attack).unwrap();
game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap(); game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap();
game.player_ready(x_player.id).unwrap();
game.player_ready(y_player.id).unwrap();
assert!(game.skill_phase_finished()); assert!(game.skill_phase_finished());
game = game.resolve_phase_start(); game = game.resolve_phase_start();
@ -1049,6 +1061,9 @@ mod tests {
let _x_stun_id = game.add_skill(x_player.id, x_cryp.id, Some(y_cryp.id), Skill::TestStun).unwrap(); let _x_stun_id = game.add_skill(x_player.id, x_cryp.id, Some(y_cryp.id), Skill::TestStun).unwrap();
game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap(); game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::TestTouch).unwrap();
game.player_ready(x_player.id).unwrap();
game.player_ready(y_player.id).unwrap();
assert!(game.skill_phase_finished()); assert!(game.skill_phase_finished());
game = game.resolve_phase_start(); game = game.resolve_phase_start();
@ -1079,6 +1094,9 @@ mod tests {
let _x_stun_id = game.add_skill(x_player.id, x_cryp.id, Some(y_cryp.id), Skill::TestStun).unwrap(); let _x_stun_id = game.add_skill(x_player.id, x_cryp.id, Some(y_cryp.id), Skill::TestStun).unwrap();
game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap(); game.add_skill(y_player.id, y_cryp.id, Some(x_cryp.id), Skill::Attack).unwrap();
game.player_ready(x_player.id).unwrap();
game.player_ready(y_player.id).unwrap();
assert!(game.skill_phase_finished()); assert!(game.skill_phase_finished());
game = game.resolve_phase_start(); game = game.resolve_phase_start();
@ -1291,8 +1309,9 @@ mod tests {
#[test] #[test]
fn upkeep_test() { fn upkeep_test() {
let mut game = create_2v2_test_game(); let mut game = create_2v2_test_game();
game.phase_start = Utc::now().checked_sub_signed(Duration::seconds(31)).unwrap(); game.players[0].set_ready(true);
game.phase_start = Utc::now().checked_sub_signed(Duration::seconds(61)).unwrap();
println!("{:?}", game.upkeep()); game = game.upkeep();
assert!(game.players[1].warnings == 1);
} }
} }

View File

@ -230,11 +230,16 @@ impl Instance {
.ok_or(err_msg("could not find matchup in current round"))? .ok_or(err_msg("could not find matchup in current round"))?
.finished = true; .finished = true;
let winner = game.winner().ok_or(err_msg("game not finished"))?; // if you don't win, you lose
// ties can happen if both players forfeit
let winner_id = match game.winner() {
Some(w) => w.id,
None => Uuid::nil(),
};
for player in game.players.iter() { for player in game.players.iter() {
let mut player = self.account_player(player.id)?; let mut player = self.account_player(player.id)?;
match player.id == winner.id { match player.id == winner_id {
true => player.add_win(), true => player.add_win(),
false => player.add_loss(), false => player.add_loss(),
}; };
@ -663,7 +668,7 @@ pub fn instance_ready(params: InstanceReadyParams, tx: &mut Transaction, account
} }
pub fn instance_state(params: InstanceStateParams, tx: &mut Transaction, account: &Account) -> Result<RpcResult, Error> { pub fn instance_state(params: InstanceStateParams, tx: &mut Transaction, account: &Account) -> Result<RpcResult, Error> {
let mut instance = instance_get(tx, params.instance_id)?; let instance = instance_get(tx, params.instance_id)?;
if let Some(game_id) = instance.current_game(account.id) { if let Some(game_id) = instance.current_game(account.id) {
let game = game_get(tx, game_id)?; let game = game_get(tx, game_id)?;

View File

@ -32,6 +32,7 @@ pub struct Player {
pub cryps: Vec<Cryp>, pub cryps: Vec<Cryp>,
pub bot: bool, pub bot: bool,
pub ready: bool, pub ready: bool,
pub warnings: u8,
} }
impl Player { impl Player {
@ -44,6 +45,7 @@ impl Player {
cryps, cryps,
bot: false, bot: false,
ready: false, ready: false,
warnings: 0,
} }
} }
@ -57,6 +59,18 @@ impl Player {
self self
} }
pub fn add_warning(&mut self) -> &mut Player {
self.warnings += 1;
self
}
pub fn forfeit(&mut self) -> &mut Player {
for cryp in self.cryps.iter_mut() {
cryp.force_ko();
}
self
}
pub fn add_win(&mut self) -> &mut Player { pub fn add_win(&mut self) -> &mut Player {
self.score.wins += 1; self.score.wins += 1;
self.set_ready(false); self.set_ready(false);