Automatically replace player by boat if he leaves game

This commit is contained in:
Pierre HUBERT 2022-09-16 17:59:07 +02:00
parent 45060ae14b
commit 6efaa81ecb
5 changed files with 69 additions and 3 deletions

View File

@ -5,12 +5,15 @@ use actix::{Actor, Context, Handler};
use uuid::Uuid; use uuid::Uuid;
use crate::data::*; use crate::data::*;
use crate::random_bot::RandomBot;
pub trait Player { pub trait Player {
fn get_name(&self) -> &str; fn get_name(&self) -> &str;
fn get_uid(&self) -> Uuid; fn get_uid(&self) -> Uuid;
fn is_bot(&self) -> bool;
fn set_other_player_name(&self, name: &str); fn set_other_player_name(&self, name: &str);
fn query_boats_layout(&self, rules: &GameRules); fn query_boats_layout(&self, rules: &GameRules);
@ -38,6 +41,10 @@ pub trait Player {
fn opponent_rejected_rematch(&self); fn opponent_rejected_rematch(&self);
fn opponent_accepted_rematch(&self); fn opponent_accepted_rematch(&self);
fn opponent_left_game(&self);
fn opponent_replaced_by_bot(&self);
} }
fn opponent(index: usize) -> usize { fn opponent(index: usize) -> usize {
@ -338,3 +345,29 @@ impl Handler<RespondRequestRematch> for Game {
self.handle_request_rematch_response(msg.1); self.handle_request_rematch_response(msg.1);
} }
} }
#[derive(Message, Debug)]
#[rtype(result = "()")]
pub struct PlayerLeftGame(pub Uuid);
impl Handler<PlayerLeftGame> for Game {
type Result = ();
fn handle(&mut self, msg: PlayerLeftGame, ctx: &mut Self::Context) -> Self::Result {
let offline_player = self.player_id_by_uuid(msg.0);
self.players[opponent(offline_player)].opponent_left_game();
// If the other player is a bot or if the game is not running, stop the game
if self.status != GameStatus::Started || self.players[opponent(offline_player)].is_bot() {
ctx.stop();
} else {
// Replace the player with a bot
self.players[offline_player] = Arc::new(RandomBot::new(ctx.address()));
self.players[opponent(offline_player)].opponent_replaced_by_bot();
if self.turn == offline_player {
self.request_fire();
}
}
}
}

View File

@ -21,6 +21,10 @@ impl Player for HumanPlayer {
self.uuid self.uuid
} }
fn is_bot(&self) -> bool {
false
}
fn set_other_player_name(&self, name: &str) { fn set_other_player_name(&self, name: &str) {
self.player.do_send(ServerMessage::SetOpponentName { self.player.do_send(ServerMessage::SetOpponentName {
name: name.to_string(), name: name.to_string(),
@ -95,14 +99,20 @@ impl Player for HumanPlayer {
fn opponent_accepted_rematch(&self) { fn opponent_accepted_rematch(&self) {
self.player.do_send(ServerMessage::OpponentAcceptedRematch); self.player.do_send(ServerMessage::OpponentAcceptedRematch);
} }
fn opponent_left_game(&self) {
self.player.do_send(ServerMessage::OpponentLeftGame);
}
fn opponent_replaced_by_bot(&self) {
self.player.do_send(ServerMessage::OpponentReplacedByBot);
}
} }
impl HumanPlayer { impl HumanPlayer {
pub fn handle_client_message(&self, msg: ClientMessage) { pub fn handle_client_message(&self, msg: ClientMessage) {
match msg { match msg {
ClientMessage::StopGame => { ClientMessage::StopGame => self.game.do_send(PlayerLeftGame(self.uuid)),
// TODO : do something
}
ClientMessage::BoatsLayout { layout } => { ClientMessage::BoatsLayout { layout } => {
self.game.do_send(SetBoatsLayout(self.uuid, layout)) self.game.do_send(SetBoatsLayout(self.uuid, layout))
} }

View File

@ -82,6 +82,8 @@ pub enum ServerMessage {
OpponentRequestedRematch, OpponentRequestedRematch,
OpponentAcceptedRematch, OpponentAcceptedRematch,
OpponentRejectedRematch, OpponentRejectedRematch,
OpponentLeftGame,
OpponentReplacedByBot,
} }
pub struct HumanPlayerWS { pub struct HumanPlayerWS {

View File

@ -28,6 +28,10 @@ impl Player for RandomBot {
self.uuid self.uuid
} }
fn is_bot(&self) -> bool {
true
}
fn set_other_player_name(&self, _name: &str) {} fn set_other_player_name(&self, _name: &str) {}
fn query_boats_layout(&self, rules: &GameRules) { fn query_boats_layout(&self, rules: &GameRules) {
@ -71,4 +75,13 @@ impl Player for RandomBot {
fn opponent_rejected_rematch(&self) {} fn opponent_rejected_rematch(&self) {}
fn opponent_accepted_rematch(&self) {} fn opponent_accepted_rematch(&self) {}
fn opponent_left_game(&self) {
// Human are not reliable lol
}
fn opponent_replaced_by_bot(&self) {
// Not such a good idea. will panic, just in case
panic!("Bot shall not play against each other (it is completely useless)");
}
} }

View File

@ -12,6 +12,7 @@ pub enum ClientEndResult {
Finished, Finished,
InvalidBoatsLayout, InvalidBoatsLayout,
OpponentRejectedRematch, OpponentRejectedRematch,
OpponentLeftGame,
} }
pub struct BotClient { pub struct BotClient {
@ -197,6 +198,13 @@ impl BotClient {
log::debug!("Opponent rejected rematch"); log::debug!("Opponent rejected rematch");
return Ok(ClientEndResult::OpponentRejectedRematch); return Ok(ClientEndResult::OpponentRejectedRematch);
} }
ServerMessage::OpponentLeftGame => {
log::debug!("Opponent left game");
return Ok(ClientEndResult::OpponentLeftGame);
}
ServerMessage::OpponentReplacedByBot => {
log::debug!("Opponent replaced by bot");
}
} }
} }