Add game end condition check and simple scoring end screen

This commit is contained in:
2021-01-05 20:40:42 +01:00
parent a67aa2c0d9
commit 7b172b5f03
4 changed files with 186 additions and 11 deletions

View File

@@ -1,4 +1,5 @@
use async_std::{prelude::*, sync::RwLock};
use itertools::Itertools;
use rand::{seq::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, sync::Arc};
@@ -53,6 +54,9 @@ enum ServerMessage {
Notification {
text: String,
},
GameOver {
score: Vec<(usize, usize)>,
},
}
#[derive(Clone, Serialize)]
@@ -130,6 +134,7 @@ impl Player {
enum GameState {
Setup,
InProgress,
Over,
}
impl Default for GameSetup {
@@ -219,10 +224,29 @@ impl Game {
}
}
self.end_game();
self.active_player += 1;
self.active_player %= self.players.len();
}
// Check if the end game condition is reached and finish the game if so,
// sending a message to all clients.
fn end_game(&mut self) {
let provinces = self.supply.iter().any(|(c, n)| *c == "Province" && *n == 0);
let supply = self.supply.iter().filter(|(_, n)| *n == 0).count() > 2;
if supply || provinces {
self.state = GameState::Over;
}
for p in self.players.iter_mut() {
p.draw_pile.append(&mut p.played_cards);
p.draw_pile.append(&mut p.hand);
p.draw_pile.append(&mut p.discard_pile);
}
}
fn is_active_player(&self, player_id: &str) -> bool {
match self.players.get(self.active_player) {
None => false,
@@ -294,6 +318,27 @@ async fn broadcast_state(game: &Game) {
send_msg(&game, &p, &sm).await;
}
if game.state == GameState::Over {
let sm = ServerMessage::GameOver {
score: game
.players
.iter()
.enumerate()
.map(|(i, p)| {
let score = p.draw_pile.iter().fold(0, |acc, card| match card.as_str() {
"Province" => acc + 6,
"Duchery" => acc + 3,
"Estate" => acc + 1,
_ => acc,
});
(i, score)
})
.sorted_by(|a, b| Ord::cmp(&b.1, &a.1))
.collect::<Vec<_>>(),
};
broadcast(&game, &sm).await;
}
}
async fn send_msg(game: &Game, player: &Player, sm: &ServerMessage) {