use actix::Addr; use uuid::Uuid; use crate::data::{BoatsLayout, BotType, Coordinates, CurrentGameStatus, FireResult, GameRules}; use crate::game::{Fire, Game, Player, RespondRequestRematch, SetBoatsLayout}; #[derive(Clone)] pub struct BotPlayer { game: Addr, kind: BotType, uuid: Uuid, } impl BotPlayer { pub fn new(kind: BotType, game: Addr) -> Self { Self { game, kind, uuid: Uuid::new_v4(), } } } impl Player for BotPlayer { fn get_name(&self) -> &str { match self.kind { BotType::Random => "Random bot", BotType::Linear => "Linear bot", BotType::Intermediate => "Intermediate bot", BotType::Smart => "Smart bot", } } fn get_uid(&self) -> Uuid { self.uuid } fn is_bot(&self) -> bool { true } fn set_other_player_name(&self, _name: &str) {} fn query_boats_layout(&self, rules: &GameRules) { match BoatsLayout::gen_random_for_rules(rules) { Ok(layout) => self.game.do_send(SetBoatsLayout(self.uuid, layout)), Err(e) => log::error!( "Failed to use game rules to construct boats layout: {:?}", e ), } } fn rejected_boats_layout(&self, _errors: Vec<&'static str>) { unreachable!() } fn notify_other_player_ready(&self) {} fn notify_game_starting(&self) {} fn request_fire(&self, status: CurrentGameStatus) { self.game.do_send(Fire( self.uuid, status.find_fire_coordinates_for_bot_type(self.kind), )); } fn opponent_must_fire(&self, _status: CurrentGameStatus) {} fn strike_result(&self, _c: Coordinates, _res: FireResult) {} fn other_player_strike_result(&self, _c: Coordinates, _res: FireResult) {} fn lost_game(&self, _status: CurrentGameStatus) {} fn won_game(&self, _status: CurrentGameStatus) {} fn opponent_requested_rematch(&self) { self.game.do_send(RespondRequestRematch(self.uuid, true)); } 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)"); } }