Players get live game status updates
This commit is contained in:
parent
8fac31e97b
commit
a6040fe89c
@ -34,7 +34,7 @@ pub async fn run_client(
|
|||||||
while let Some(chunk) = socket.next().await {
|
while let Some(chunk) = socket.next().await {
|
||||||
let message = match chunk? {
|
let message = match chunk? {
|
||||||
Message::Text(message) => {
|
Message::Text(message) => {
|
||||||
log::debug!("TEXT message from server: {}", message);
|
log::trace!("TEXT message from server: {}", message);
|
||||||
|
|
||||||
let msg: ServerMessage = serde_json::from_str(&message)?;
|
let msg: ServerMessage = serde_json::from_str(&message)?;
|
||||||
msg
|
msg
|
||||||
@ -79,8 +79,13 @@ pub async fn run_client(
|
|||||||
}
|
}
|
||||||
ServerMessage::OtherPlayerReady => log::debug!("Other player is ready!"),
|
ServerMessage::OtherPlayerReady => log::debug!("Other player is ready!"),
|
||||||
ServerMessage::GameStarting => log::debug!("The game is starting..."),
|
ServerMessage::GameStarting => log::debug!("The game is starting..."),
|
||||||
ServerMessage::OtherPlayerMustFire { .. } => log::debug!("Other player must fire!"),
|
ServerMessage::OtherPlayerMustFire { status } => {
|
||||||
|
assert_eq!(status.opponent_map.boats.number_of_boats(), 0);
|
||||||
|
log::debug!("Other player must fire!")
|
||||||
|
}
|
||||||
ServerMessage::RequestFire { status } => {
|
ServerMessage::RequestFire { status } => {
|
||||||
|
assert_eq!(status.opponent_map.boats.number_of_boats(), 0);
|
||||||
|
|
||||||
let location = status.find_valid_random_fire_location();
|
let location = status.find_valid_random_fire_location();
|
||||||
log::debug!("Will fire at {:?}", location);
|
log::debug!("Will fire at {:?}", location);
|
||||||
socket
|
socket
|
||||||
@ -119,6 +124,7 @@ pub async fn run_client(
|
|||||||
log::warn!("Rejected boat layout: {:?}", errors);
|
log::warn!("Rejected boat layout: {:?}", errors);
|
||||||
return Ok(ClientEndResult::InvalidBoatsLayout);
|
return Ok(ClientEndResult::InvalidBoatsLayout);
|
||||||
}
|
}
|
||||||
|
ServerMessage::SetOpponentName { name } => log::debug!("Opponent name: {}", name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +151,11 @@ impl BoatPosition {
|
|||||||
pub struct BoatsLayout(Vec<BoatPosition>);
|
pub struct BoatsLayout(Vec<BoatPosition>);
|
||||||
|
|
||||||
impl BoatsLayout {
|
impl BoatsLayout {
|
||||||
|
/// Generate a new invalid (empty) boats layout
|
||||||
|
pub fn new_invalid() -> Self {
|
||||||
|
Self(vec![])
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate random boats layout for given game rules
|
/// Generate random boats layout for given game rules
|
||||||
pub fn gen_random_for_rules(rules: &GameRules) -> std::io::Result<Self> {
|
pub fn gen_random_for_rules(rules: &GameRules) -> std::io::Result<Self> {
|
||||||
let mut boats = Self(Vec::with_capacity(rules.boats_list().len()));
|
let mut boats = Self(Vec::with_capacity(rules.boats_list().len()));
|
||||||
|
@ -1,17 +1,27 @@
|
|||||||
use crate::data::{Coordinates, GameRules};
|
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
|
use crate::data::{BoatPosition, BoatsLayout, Coordinates, GameRules};
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct CurrentGameMapStatus {
|
||||||
|
pub boats: BoatsLayout,
|
||||||
|
pub successful_strikes: Vec<Coordinates>,
|
||||||
|
pub failed_strikes: Vec<Coordinates>,
|
||||||
|
pub sunk_boats: Vec<BoatPosition>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct CurrentGameStatus {
|
pub struct CurrentGameStatus {
|
||||||
pub rules: GameRules,
|
pub rules: GameRules,
|
||||||
//TODO
|
pub your_map: CurrentGameMapStatus,
|
||||||
|
pub opponent_map: CurrentGameMapStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CurrentGameStatus {
|
impl CurrentGameStatus {
|
||||||
/// Check if user can fire at a given location
|
/// Check if opponent can fire at a given location
|
||||||
pub fn can_fire_at_location(&self, _location: Coordinates) -> bool {
|
pub fn can_fire_at_location(&self, location: Coordinates) -> bool {
|
||||||
//TODO
|
!self.opponent_map.successful_strikes.contains(&location)
|
||||||
true
|
&& !self.opponent_map.failed_strikes.contains(&location)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find valid random fire location. Loop until one is found
|
/// Find valid random fire location. Loop until one is found
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::data::boats_layout::{BoatsLayout, Coordinates};
|
use crate::data::boats_layout::{BoatsLayout, Coordinates};
|
||||||
use crate::data::{BoatPosition, EndGameMap, GameRules};
|
use crate::data::{BoatPosition, CurrentGameMapStatus, EndGameMap, GameRules};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum FireResult {
|
pub enum FireResult {
|
||||||
@ -133,6 +133,18 @@ impl GameMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn current_map_status(&self, for_opponent: bool) -> CurrentGameMapStatus {
|
||||||
|
CurrentGameMapStatus {
|
||||||
|
boats: match for_opponent {
|
||||||
|
true => BoatsLayout::new_invalid(),
|
||||||
|
false => self.boats_config.clone(),
|
||||||
|
},
|
||||||
|
successful_strikes: self.successful_strikes.clone(),
|
||||||
|
failed_strikes: self.failed_strikes.clone(),
|
||||||
|
sunk_boats: self.sunk_boats.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn final_map(&self) -> EndGameMap {
|
pub fn final_map(&self) -> EndGameMap {
|
||||||
EndGameMap {
|
EndGameMap {
|
||||||
boats: self.boats_config.clone(),
|
boats: self.boats_config.clone(),
|
||||||
|
@ -11,6 +11,8 @@ pub trait Player {
|
|||||||
|
|
||||||
fn get_uid(&self) -> Uuid;
|
fn get_uid(&self) -> Uuid;
|
||||||
|
|
||||||
|
fn set_other_player_name(&self, name: &str);
|
||||||
|
|
||||||
fn query_boats_layout(&self, rules: &GameRules);
|
fn query_boats_layout(&self, rules: &GameRules);
|
||||||
|
|
||||||
fn rejected_boats_layout(&self, errors: Vec<&'static str>);
|
fn rejected_boats_layout(&self, errors: Vec<&'static str>);
|
||||||
@ -82,6 +84,9 @@ impl Game {
|
|||||||
|
|
||||||
/// Once the two player has been registered, the game may start
|
/// Once the two player has been registered, the game may start
|
||||||
fn query_boats_disposition(&mut self) {
|
fn query_boats_disposition(&mut self) {
|
||||||
|
self.players[0].set_other_player_name(self.players[1].get_name());
|
||||||
|
self.players[1].set_other_player_name(self.players[0].get_name());
|
||||||
|
|
||||||
log::debug!("Query boats disposition");
|
log::debug!("Query boats disposition");
|
||||||
assert_eq!(self.status, GameStatus::Created);
|
assert_eq!(self.status, GameStatus::Created);
|
||||||
self.status = GameStatus::WaitingForBoatsDisposition;
|
self.status = GameStatus::WaitingForBoatsDisposition;
|
||||||
@ -160,9 +165,11 @@ impl Game {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get current game status for a specific player
|
/// Get current game status for a specific player
|
||||||
fn get_game_status_for_player(&self, _id: usize) -> CurrentGameStatus {
|
fn get_game_status_for_player(&self, id: usize) -> CurrentGameStatus {
|
||||||
CurrentGameStatus {
|
CurrentGameStatus {
|
||||||
rules: self.rules.clone(),
|
rules: self.rules.clone(),
|
||||||
|
your_map: self.player_map(id).current_map_status(false),
|
||||||
|
opponent_map: self.player_map(opponent(id)).current_map_status(true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,12 @@ impl Player for HumanPlayer {
|
|||||||
self.uuid
|
self.uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_other_player_name(&self, name: &str) {
|
||||||
|
self.player.do_send(ServerMessage::SetOpponentName {
|
||||||
|
name: name.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
fn query_boats_layout(&self, rules: &GameRules) {
|
fn query_boats_layout(&self, rules: &GameRules) {
|
||||||
self.player.do_send(ServerMessage::QueryBoatsLayout {
|
self.player.do_send(ServerMessage::QueryBoatsLayout {
|
||||||
rules: rules.clone(),
|
rules: rules.clone(),
|
||||||
|
@ -41,6 +41,9 @@ pub enum ClientMessage {
|
|||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum ServerMessage {
|
pub enum ServerMessage {
|
||||||
WaitingForAnotherPlayer,
|
WaitingForAnotherPlayer,
|
||||||
|
SetOpponentName {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
QueryBoatsLayout {
|
QueryBoatsLayout {
|
||||||
rules: GameRules,
|
rules: GameRules,
|
||||||
},
|
},
|
||||||
|
@ -28,6 +28,8 @@ impl Player for RandomBot {
|
|||||||
self.uuid
|
self.uuid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_other_player_name(&self, _name: &str) {}
|
||||||
|
|
||||||
fn query_boats_layout(&self, rules: &GameRules) {
|
fn query_boats_layout(&self, rules: &GameRules) {
|
||||||
match BoatsLayout::gen_random_for_rules(rules) {
|
match BoatsLayout::gen_random_for_rules(rules) {
|
||||||
Ok(layout) => self.game.do_send(SetBoatsLayout(self.uuid, layout)),
|
Ok(layout) => self.game.do_send(SetBoatsLayout(self.uuid, layout)),
|
||||||
|
Loading…
Reference in New Issue
Block a user