From 6efaa81ecb362f8eef4bd0dc53544a38cfce606a Mon Sep 17 00:00:00 2001 From: Pierre Hubert Date: Fri, 16 Sep 2022 17:59:07 +0200 Subject: [PATCH] Automatically replace player by boat if he leaves game --- sea_battle_backend/src/game.rs | 33 +++++++++++++++++++++++ sea_battle_backend/src/human_player.rs | 16 ++++++++--- sea_battle_backend/src/human_player_ws.rs | 2 ++ sea_battle_backend/src/random_bot.rs | 13 +++++++++ sea_battle_backend/src/test/bot_client.rs | 8 ++++++ 5 files changed, 69 insertions(+), 3 deletions(-) diff --git a/sea_battle_backend/src/game.rs b/sea_battle_backend/src/game.rs index 1fe3f39..82ef526 100644 --- a/sea_battle_backend/src/game.rs +++ b/sea_battle_backend/src/game.rs @@ -5,12 +5,15 @@ use actix::{Actor, Context, Handler}; use uuid::Uuid; use crate::data::*; +use crate::random_bot::RandomBot; pub trait Player { fn get_name(&self) -> &str; fn get_uid(&self) -> Uuid; + fn is_bot(&self) -> bool; + fn set_other_player_name(&self, name: &str); fn query_boats_layout(&self, rules: &GameRules); @@ -38,6 +41,10 @@ pub trait Player { fn opponent_rejected_rematch(&self); fn opponent_accepted_rematch(&self); + + fn opponent_left_game(&self); + + fn opponent_replaced_by_bot(&self); } fn opponent(index: usize) -> usize { @@ -338,3 +345,29 @@ impl Handler for Game { self.handle_request_rematch_response(msg.1); } } + +#[derive(Message, Debug)] +#[rtype(result = "()")] +pub struct PlayerLeftGame(pub Uuid); + +impl Handler 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(); + } + } + } +} diff --git a/sea_battle_backend/src/human_player.rs b/sea_battle_backend/src/human_player.rs index 7c73751..37cc414 100644 --- a/sea_battle_backend/src/human_player.rs +++ b/sea_battle_backend/src/human_player.rs @@ -21,6 +21,10 @@ impl Player for HumanPlayer { self.uuid } + fn is_bot(&self) -> bool { + false + } + fn set_other_player_name(&self, name: &str) { self.player.do_send(ServerMessage::SetOpponentName { name: name.to_string(), @@ -95,14 +99,20 @@ impl Player for HumanPlayer { fn opponent_accepted_rematch(&self) { 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 { pub fn handle_client_message(&self, msg: ClientMessage) { match msg { - ClientMessage::StopGame => { - // TODO : do something - } + ClientMessage::StopGame => self.game.do_send(PlayerLeftGame(self.uuid)), ClientMessage::BoatsLayout { layout } => { self.game.do_send(SetBoatsLayout(self.uuid, layout)) } diff --git a/sea_battle_backend/src/human_player_ws.rs b/sea_battle_backend/src/human_player_ws.rs index f43898f..9181270 100644 --- a/sea_battle_backend/src/human_player_ws.rs +++ b/sea_battle_backend/src/human_player_ws.rs @@ -82,6 +82,8 @@ pub enum ServerMessage { OpponentRequestedRematch, OpponentAcceptedRematch, OpponentRejectedRematch, + OpponentLeftGame, + OpponentReplacedByBot, } pub struct HumanPlayerWS { diff --git a/sea_battle_backend/src/random_bot.rs b/sea_battle_backend/src/random_bot.rs index 948eab9..609c9ee 100644 --- a/sea_battle_backend/src/random_bot.rs +++ b/sea_battle_backend/src/random_bot.rs @@ -28,6 +28,10 @@ impl Player for RandomBot { self.uuid } + fn is_bot(&self) -> bool { + true + } + fn set_other_player_name(&self, _name: &str) {} fn query_boats_layout(&self, rules: &GameRules) { @@ -71,4 +75,13 @@ impl Player for RandomBot { fn opponent_rejected_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)"); + } } diff --git a/sea_battle_backend/src/test/bot_client.rs b/sea_battle_backend/src/test/bot_client.rs index d6c6b45..78ae655 100644 --- a/sea_battle_backend/src/test/bot_client.rs +++ b/sea_battle_backend/src/test/bot_client.rs @@ -12,6 +12,7 @@ pub enum ClientEndResult { Finished, InvalidBoatsLayout, OpponentRejectedRematch, + OpponentLeftGame, } pub struct BotClient { @@ -197,6 +198,13 @@ impl BotClient { log::debug!("Opponent rejected rematch"); return Ok(ClientEndResult::OpponentRejectedRematch); } + ServerMessage::OpponentLeftGame => { + log::debug!("Opponent left game"); + return Ok(ClientEndResult::OpponentLeftGame); + } + ServerMessage::OpponentReplacedByBot => { + log::debug!("Opponent replaced by bot"); + } } }