Sync scores between players
This commit is contained in:
@@ -51,6 +51,8 @@ pub enum ServerMessage {
|
||||
PlayerTurn(usize),
|
||||
/// Update the current hand of the player
|
||||
SyncHand(Vec<TileRef>),
|
||||
/// Update the score of the n-th player.
|
||||
SyncScore(usize, u32),
|
||||
/// Informs that a tile has been placed
|
||||
TilePlaced(Position2dRef, TileRef),
|
||||
/// Informs that a tile has been removed
|
||||
|
@@ -6,6 +6,7 @@ use board_shared::deck::RngDeck;
|
||||
use board_shared::expr::is_valid_guess;
|
||||
use board_shared::game::Hand;
|
||||
use board_shared::position::Position2d;
|
||||
use board_shared::score::calc_score;
|
||||
use board_shared::tile::Tile;
|
||||
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||
use futures::StreamExt;
|
||||
@@ -189,6 +190,7 @@ impl Room {
|
||||
.hand
|
||||
.complete(&mut self.deck)
|
||||
.ok();
|
||||
self.on_validated_move(self.active_player, &diff);
|
||||
self.next_player();
|
||||
} else {
|
||||
self.send(
|
||||
@@ -198,6 +200,23 @@ impl Room {
|
||||
}
|
||||
}
|
||||
|
||||
fn on_validated_move(&mut self, player_id: usize, diff: &[Position2d]) {
|
||||
let tiles_placed = diff
|
||||
.iter()
|
||||
.map(|&pos| {
|
||||
self.board
|
||||
.get(pos.x, pos.y)
|
||||
.expect("A placed tile should not be empty.")
|
||||
})
|
||||
.collect::<Vec<Tile>>();
|
||||
self.players[player_id].score += calc_score(&tiles_placed);
|
||||
self.broadcast(ServerMessage::SyncScore(
|
||||
player_id,
|
||||
self.players[player_id].score,
|
||||
));
|
||||
self.validated_board = self.board.clone();
|
||||
}
|
||||
|
||||
fn reset_player_moves(&mut self) {
|
||||
let diff = self.board.difference(&self.validated_board);
|
||||
for pos in diff {
|
||||
|
@@ -7,4 +7,5 @@ pub mod game;
|
||||
mod lexer;
|
||||
mod parser;
|
||||
pub mod position;
|
||||
pub mod score;
|
||||
pub mod tile;
|
||||
|
79
board-shared/src/score.rs
Normal file
79
board-shared/src/score.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use crate::tile::{Operator, Tile};
|
||||
|
||||
/// Calculate the score for a given list of tiles.
|
||||
pub fn calc_score(tiles: &[Tile]) -> u32 {
|
||||
tiles
|
||||
.split(|tile| matches!(tile, Tile::Equals))
|
||||
.map(calc_expression_score)
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn calc_expression_score(tiles: &[Tile]) -> u32 {
|
||||
let mut digit_score = 0u32;
|
||||
let mut multiplier = 1u32;
|
||||
for token in tiles {
|
||||
match token {
|
||||
Tile::Digit(_) => digit_score += 1,
|
||||
Tile::Operator(op) => {
|
||||
match op {
|
||||
Operator::Add | Operator::Subtract => multiplier = 2,
|
||||
Operator::Multiply => multiplier = 3,
|
||||
Operator::Divide => digit_score += 10,
|
||||
};
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
digit_score * multiplier
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tile::Digit;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn only_digits() {
|
||||
assert_eq!(
|
||||
calc_score(&[
|
||||
Tile::Digit(Digit::new(7)),
|
||||
Tile::Digit(Digit::new(8)),
|
||||
Tile::Equals,
|
||||
Tile::Digit(Digit::new(9)),
|
||||
Tile::Digit(Digit::new(4)),
|
||||
]),
|
||||
4
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn calc_individually() {
|
||||
assert_eq!(
|
||||
calc_score(&[
|
||||
Tile::Digit(Digit::new(4)),
|
||||
Tile::Operator(Operator::Add),
|
||||
Tile::Digit(Digit::new(5)),
|
||||
Tile::Equals,
|
||||
Tile::Digit(Digit::new(3)),
|
||||
Tile::Operator(Operator::Multiply),
|
||||
Tile::Digit(Digit::new(3)),
|
||||
]),
|
||||
10
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diviser_add_to_original_sum() {
|
||||
assert_eq!(
|
||||
calc_score(&[
|
||||
Tile::Digit(Digit::new(8)),
|
||||
Tile::Operator(Operator::Divide),
|
||||
Tile::Digit(Digit::new(4)),
|
||||
Tile::Equals,
|
||||
Tile::Digit(Digit::new(2)),
|
||||
]),
|
||||
13
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user