From 7b172b5f036e87216fc86cf31cc6714ed544c1cd Mon Sep 17 00:00:00 2001 From: Markus Wagner Date: Tue, 5 Jan 2021 20:40:42 +0100 Subject: [PATCH] Add game end condition check and simple scoring end screen --- Cargo.lock | 16 ++++++ Cargo.toml | 1 + src/main.rs | 45 ++++++++++++++++ static/game.html | 135 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 186 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ebfd9b..16f2226 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -580,6 +580,7 @@ version = "0.1.0" dependencies = [ "async-std", "html-escape", + "itertools", "rand 0.8.0", "serde", "serde_json", @@ -588,6 +589,12 @@ dependencies = [ "uuid", ] +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "event-listener" version = "2.5.1" @@ -902,6 +909,15 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "itertools" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.6" diff --git a/Cargo.toml b/Cargo.toml index 6c0f5e8..e68136f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" [dependencies] async-std = { version = "1.8.0", features = ["attributes"] } html-escape = "0.2.6" +itertools = "0.10.0" rand = "0.8.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.60" diff --git a/src/main.rs b/src/main.rs index 98681d8..8b1426d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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::>(), + }; + broadcast(&game, &sm).await; + } } async fn send_msg(game: &Game, player: &Player, sm: &ServerMessage) { diff --git a/static/game.html b/static/game.html index ce88a2d..a3d3584 100644 --- a/static/game.html +++ b/static/game.html @@ -8,8 +8,9 @@ @@ -316,7 +374,17 @@