use std::sync::Arc; use crate::data::GameRules; use crate::human_player::HumanPlayer; use crate::random_bot::RandomBot; use actix::prelude::*; use actix::{Actor, Context, Handler}; use uuid::Uuid; pub trait Player { fn get_name(&self) -> &str; fn get_uid(&self) -> Uuid; fn query_boats_layout(&self, rules: &GameRules); } pub enum PlayerWrapper { Human(Arc), RandomBot(RandomBot), } impl PlayerWrapper { fn extract(self) -> Arc { match self { PlayerWrapper::Human(h) => h, PlayerWrapper::RandomBot(r) => Arc::new(r), } } } #[derive(Default, Eq, PartialEq, Debug, Copy, Clone)] enum GameStatus { #[default] Created, WaitingForBoatsDisposition, } pub struct Game { rules: GameRules, players: Vec>, status: GameStatus, } impl Game { pub fn new(rules: GameRules) -> Self { Self { rules, players: vec![], status: GameStatus::Created, } } /// Once the two player has been registered, the game may start fn query_boats_disposition(&mut self) { assert_eq!(self.status, GameStatus::Created); self.status = GameStatus::WaitingForBoatsDisposition; self.players[0].query_boats_layout(&self.rules); self.players[1].query_boats_layout(&self.rules); } } impl Actor for Game { type Context = Context; } #[derive(Message)] #[rtype(result = "()")] pub struct AddPlayer(pub PlayerWrapper); impl Handler for Game { type Result = (); /// Add a new player to the game fn handle(&mut self, msg: AddPlayer, _ctx: &mut Self::Context) -> Self::Result { assert!(self.players.len() < 2); self.players.push(msg.0.extract()); if self.players.len() == 2 { self.query_boats_disposition(); } } }