Implement strike timeout on server side

This commit is contained in:
2022-10-17 07:59:42 +02:00
parent ba1ed84b33
commit 42b0d84f9d
7 changed files with 77 additions and 25 deletions

View File

@@ -1,4 +1,5 @@
use std::sync::Arc;
use std::time::Duration;
use actix::prelude::*;
use actix::{Actor, Context, Handler};
@@ -6,6 +7,7 @@ use uuid::Uuid;
use crate::bot_player::BotPlayer;
use crate::data::*;
use crate::utils::time_utils::time;
pub trait Player {
fn get_name(&self) -> &str;
@@ -51,6 +53,9 @@ pub trait Player {
fn opponent_replaced_by_bot(&self);
}
/// How often strike timeout controller is run
const STRIKE_TIMEOUT_CONTROL: Duration = Duration::from_secs(1);
fn opponent(index: usize) -> usize {
match index {
0 => 1,
@@ -85,6 +90,7 @@ pub struct Game {
map_0: Option<GameMap>,
map_1: Option<GameMap>,
turn: usize,
curr_strike_request_started: u64,
}
impl Game {
@@ -96,6 +102,7 @@ impl Game {
map_0: None,
map_1: None,
turn: 0,
curr_strike_request_started: 0,
}
}
@@ -130,10 +137,14 @@ impl Game {
self.turn
);
self.request_fire();
self.request_fire(true);
}
fn request_fire(&self) {
fn request_fire(&mut self, reset_counter: bool) {
if reset_counter {
self.curr_strike_request_started = time();
}
self.players[self.turn].request_fire(self.get_game_status_for_player(self.turn));
self.players[opponent(self.turn)]
.opponent_must_fire(self.get_game_status_for_player(opponent(self.turn)));
@@ -148,6 +159,27 @@ impl Game {
.unwrap()
}
/// Replace user for a fire in case of timeout
fn force_fire_in_case_of_timeout(&mut self) {
if self.status != GameStatus::Started || self.rules.strike_timeout.is_none() {
return;
}
let timeout = self.rules.strike_timeout.unwrap_or_default();
if time() <= self.curr_strike_request_started + timeout {
return;
}
// Determine target of fire
let target = self
.get_game_status_for_player(opponent(self.turn))
.find_fire_coordinates_for_bot_type(self.rules.bot_type);
// Fire as player
self.handle_fire(target);
}
fn player_map_mut(&mut self, id: usize) -> &mut GameMap {
match id {
0 => self.map_0.as_mut(),
@@ -166,7 +198,7 @@ impl Game {
// Easiest case : player missed his fire
if result == FireResult::Missed {
self.turn = opponent(self.turn);
self.request_fire();
self.request_fire(true);
return;
}
@@ -188,7 +220,9 @@ impl Game {
self.turn = opponent(self.turn);
}
self.request_fire();
self.request_fire(
result != FireResult::AlreadyTargetedPosition && result != FireResult::Rejected,
);
}
fn handle_request_rematch(&mut self, player_id: Uuid) {
@@ -234,6 +268,14 @@ impl Game {
impl Actor for Game {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
if self.rules.strike_timeout.is_some() {
ctx.run_interval(STRIKE_TIMEOUT_CONTROL, |act, _ctx| {
act.force_fire_in_case_of_timeout();
});
}
}
}
#[derive(Message)]
@@ -387,7 +429,7 @@ impl Handler<PlayerLeftGame> for Game {
// Re-do current action
if self.status == GameStatus::Started {
self.request_fire();
self.request_fire(true);
} else if self.status == GameStatus::WaitingForBoatsDisposition {
self.players[offline_player].query_boats_layout(&self.rules);
}