store : validation : check dices

This commit is contained in:
Henri Bourcereau 2024-02-03 22:16:14 +01:00
parent 41647ebd1b
commit 8c99b228d3
2 changed files with 90 additions and 24 deletions

View file

@ -19,9 +19,7 @@ impl Dices {
let v = (between.sample(&mut rng), between.sample(&mut rng));
Dices {
values: (v.0, v.1),
}
Dices { values: (v.0, v.1) }
}
/// Heads or tails
@ -31,7 +29,6 @@ impl Dices {
between.sample(&mut rng) == 1
}
pub fn to_bits_string(self) -> String {
format!("{:0>3b}{:0>3b}", self.values.0, self.values.1)
}
@ -51,7 +48,7 @@ impl Dices {
/// Trait to roll the dices
pub trait Roll {
/// Roll the dices
fn roll(&mut self) -> Result<&mut Self, Error>;
fn roll(&mut self) -> &mut Self;
}
#[cfg(test)]
@ -70,5 +67,4 @@ mod tests {
let dices = Dices { values: (4, 2) };
assert!(dices.to_bits_string() == "100010");
}
}

View file

@ -75,9 +75,9 @@ impl GameState {
GameState::default()
}
fn add_player(&mut self, player_id: PlayerId, player: Player) {
self.players.insert(player_id, player);
}
// -------------------------------------------------------------------------
// accessors
// -------------------------------------------------------------------------
/// Calculate game state id :
pub fn to_string_id(&self) -> String {
@ -148,16 +148,6 @@ impl GameState {
.next()
}
pub fn switch_active_player(&mut self) {
let other_player_id = self
.players
.iter()
.filter(|(id, _player)| **id != self.active_player_id)
.map(|(id, _player)| *id)
.next();
self.active_player_id = other_player_id.unwrap_or(0);
}
pub fn player_id_by_color(&self, color: Color) -> Option<&PlayerId> {
self.players
.iter()
@ -174,6 +164,10 @@ impl GameState {
.next()
}
// ----------------------------------------------------------------------------------
// Rules checks
// ----------------------------------------------------------------------------------
/// Determines whether an event is valid considering the current GameState
pub fn validate(&self, event: &GameEvent) -> bool {
use GameEvent::*;
@ -220,6 +214,16 @@ impl GameState {
return false;
}
}
Mark { player_id, points } => {
// Check player exists
if !self.players.contains_key(player_id) {
return false;
}
// Check player is currently the one making their move
if self.active_player_id != *player_id {
return false;
}
}
Move { player_id, moves } => {
// Check player exists
if !self.players.contains_key(player_id) {
@ -231,9 +235,14 @@ impl GameState {
error!("Player not active : {}", self.active_player_id);
return false;
}
let color = &self.players[player_id].color;
// Check moves conforms to the dices
if !self.moves_follows_dices(color, moves) {
return false;
}
// Check move is physically possible
let color = &self.players[player_id].color;
if !self.board.move_possible(color, &moves.0) {
return false;
}
@ -259,6 +268,14 @@ impl GameState {
true
}
fn moves_follows_dices(&self, color: &Color, moves: &(CheckerMove, CheckerMove)) -> bool {
// basic : same number
// prise de coin par puissance
// sorties
// no rule was broken
false
}
fn moves_allowed(&self, color: &Color, moves: &(CheckerMove, CheckerMove)) -> bool {
// ------- corner rules ----------
let corner_field: Field = self.board.get_color_corner(color);
@ -294,6 +311,23 @@ impl GameState {
true
}
// ----------------------------------------------------------------------------------
// State updates
// ----------------------------------------------------------------------------------
fn add_player(&mut self, player_id: PlayerId, player: Player) {
self.players.insert(player_id, player);
}
pub fn switch_active_player(&mut self) {
let other_player_id = self
.players
.iter()
.filter(|(id, _player)| **id != self.active_player_id)
.map(|(id, _player)| *id)
.next();
self.active_player_id = other_player_id.unwrap_or(0);
}
/// Consumes an event, modifying the GameState and adding the event to its history
/// NOTE: consume assumes the event to have already been validated and will accept *any* event passed to it
pub fn consume(&mut self, valid_event: &GameEvent) {
@ -302,6 +336,7 @@ impl GameState {
BeginGame { goes_first } => {
self.active_player_id = *goes_first;
self.stage = Stage::InGame;
self.turn_stage = TurnStage::RollDice;
}
EndGame { reason: _ } => self.stage = Stage::Ended,
PlayerJoined { player_id, name } => {
@ -325,7 +360,16 @@ impl GameState {
PlayerDisconnected { player_id } => {
self.players.remove(player_id);
}
Roll { player_id: _ } => {}
Roll { player_id: _ } => {
self.roll();
self.turn_stage = TurnStage::MarkPoints;
}
Mark { player_id, points } => {
self.mark_points(*player_id, *points);
if self.stage != Stage::Ended {
self.turn_stage = TurnStage::Move;
}
}
Move { player_id, moves } => {
let player = self.players.get(player_id).unwrap();
self.board.move_checker(&player.color, moves.0).unwrap();
@ -346,6 +390,10 @@ impl GameState {
pub fn determine_winner(&self) -> Option<PlayerId> {
None
}
fn mark_points(&mut self, player_id: PlayerId, points: u8) {
todo!()
}
}
/// The reasons why a game could end
@ -376,6 +424,10 @@ pub enum GameEvent {
Roll {
player_id: PlayerId,
},
Mark {
player_id: PlayerId,
points: u8,
},
Move {
player_id: PlayerId,
moves: (CheckerMove, CheckerMove),
@ -383,7 +435,7 @@ pub enum GameEvent {
}
impl Roll for GameState {
fn roll(&mut self) -> Result<&mut Self, Error> {
fn roll(&mut self) -> &mut Self {
self.dices = self.dices.roll();
if self.who_plays().is_none() {
let active_color = match self.dices.coin() {
@ -395,7 +447,7 @@ impl Roll for GameState {
self.active_player_id = *color_player_id.unwrap();
}
}
Ok(self)
self
}
}
@ -490,4 +542,22 @@ mod tests {
let event: GameEvent = GameEvent::Move { player_id, moves };
assert!(!state.validate(&event));
}
#[test]
fn test_moves_follow_dices() {
let mut state = GameState::default();
let player1 = Player::new("player1".into(), Color::White);
let player_id = 1;
state.add_player(player_id, player1);
state.add_player(2, Player::new("player2".into(), Color::Black));
state.consume(&GameEvent::BeginGame {
goes_first: player_id,
});
state.consume(&GameEvent::Roll { player_id });
let moves = (
CheckerMove::new(1, 5).unwrap(),
CheckerMove::new(6, 9).unwrap(),
);
assert!(state.moves_follows_dices(&Color::White, &moves));
}
}