From 2a67996453eaf1a64ceac69dce2d2ab62f688844 Mon Sep 17 00:00:00 2001 From: Henri Bourcereau Date: Sun, 26 Jan 2025 17:52:57 +0100 Subject: [PATCH] wip fix allowed moves infinite loop --- store/src/game_rules_moves.rs | 106 ++++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 44 deletions(-) diff --git a/store/src/game_rules_moves.rs b/store/src/game_rules_moves.rs index bd6c0f7..a68d8a0 100644 --- a/store/src/game_rules_moves.rs +++ b/store/src/game_rules_moves.rs @@ -33,6 +33,13 @@ pub enum MoveError { MustPlayStrongerDie, } +#[derive(std::cmp::PartialEq, Debug)] +pub enum TricTracRule { + ExitRule, + MustFillQuarterRule, + CornerRule, +} + /// MoveRules always consider that the current player is White /// You must use 'mirror' functions on board & CheckerMoves if player is Black #[derive(Default)] @@ -62,12 +69,16 @@ impl MoveRules { } } - pub fn moves_follow_rules(&self, moves: &(CheckerMove, CheckerMove)) -> bool { + pub fn moves_follow_rules( + &self, + moves: &(CheckerMove, CheckerMove), + ignored_rules: Vec, + ) -> bool { // Check moves possibles on the board // Check moves conforms to the dice // Check move is allowed by the rules (to desactivate when playing with schools) self.moves_possible(moves) && self.moves_follows_dices(moves) && { - let is_allowed = self.moves_allowed(moves); + let is_allowed = self.moves_allowed(moves, ignored_rules); if is_allowed.is_err() { info!("Move not allowed : {:?}", is_allowed.unwrap_err()); false @@ -165,7 +176,11 @@ impl MoveRules { } /// ---- moves_allowed : Third of three checks for moves - pub fn moves_allowed(&self, moves: &(CheckerMove, CheckerMove)) -> Result<(), MoveError> { + pub fn moves_allowed( + &self, + moves: &(CheckerMove, CheckerMove), + ignored_rules: Vec, + ) -> Result<(), MoveError> { self.check_corner_rules(moves)?; if self.is_move_by_puissance(moves) { @@ -197,7 +212,9 @@ impl MoveRules { } // check exit rules - self.check_exit_rules(moves)?; + if !ignored_rules.contains(&TricTracRule::ExitRule) { + self.check_exit_rules(moves)?; + } // --- interdit de jouer dans un cadran que l'adversaire peut encore remplir ---- let farthest = cmp::max(moves.0.get_to(), moves.1.get_to()); @@ -267,49 +284,50 @@ impl MoveRules { } // toutes les sorties directes sont autorisées, ainsi que les nombres défaillants - let possible_moves_sequences = self.get_possible_moves_sequences(false); - if !possible_moves_sequences.contains(moves) { - // À ce stade au moins un des déplacements concerne un nombre en excédant - // - si d'autres séquences de mouvements sans nombre en excédant étaient possibles, on - // refuse cette séquence - if !possible_moves_sequences.is_empty() { - return Err(MoveError::ExitByEffectPossible); - } + let possible_moves_sequences_without_excedent = self.get_possible_moves_sequences(false); + if possible_moves_sequences_without_excedent.contains(moves) { + return Ok(()); + } + // À ce stade au moins un des déplacements concerne un nombre en excédant + // - si d'autres séquences de mouvements sans nombre en excédant sont possibles, on + // refuse cette séquence + if !possible_moves_sequences_without_excedent.is_empty() { + return Err(MoveError::ExitByEffectPossible); + } - // - la dame choisie doit être la plus éloignée de la sortie - let mut checkers = self.board.get_color_fields(Color::White); - checkers.sort_by(|a, b| b.0.cmp(&a.0)); - let mut farthest = 24; - let mut next_farthest = 24; - let mut has_two_checkers = false; - if let Some((field, count)) = checkers.first() { - farthest = *field; - if *count > 1 { - next_farthest = *field; - has_two_checkers = true; - } else if let Some((field, _count)) = checkers.get(1) { - next_farthest = *field; - has_two_checkers = true; + // - la dame choisie doit être la plus éloignée de la sortie + let mut checkers = self.board.get_color_fields(Color::White); + checkers.sort_by(|a, b| b.0.cmp(&a.0)); + let mut farthest = 24; + let mut next_farthest = 24; + let mut has_two_checkers = false; + if let Some((field, count)) = checkers.first() { + farthest = *field; + if *count > 1 { + next_farthest = *field; + has_two_checkers = true; + } else if let Some((field, _count)) = checkers.get(1) { + next_farthest = *field; + has_two_checkers = true; + } + } + + // s'il reste au moins deux dames, on vérifie que les plus éloignées soint choisies + if has_two_checkers { + if moves.0.get_to() == 0 && moves.1.get_to() == 0 { + // Deux coups sortants en excédant + if cmp::max(moves.0.get_from(), moves.1.get_from()) > next_farthest { + return Err(MoveError::ExitNotFasthest); } - } - - // s'il reste au moins deux dames, on vérifie que les plus éloignées soint choisies - if has_two_checkers { - if moves.0.get_to() == 0 && moves.1.get_to() == 0 { - // Deux coups sortants en excédant - if cmp::max(moves.0.get_from(), moves.1.get_from()) > next_farthest { - return Err(MoveError::ExitNotFasthest); - } + } else { + // Un seul coup sortant en excédant le coup sortant doit concerner la plus éloignée du bord + let exit_move_field = if moves.0.get_to() == 0 { + moves.0.get_from() } else { - // Un seul coup sortant en excédant le coup sortant doit concerner la plus éloignée du bord - let exit_move_field = if moves.0.get_to() == 0 { - moves.0.get_from() - } else { - moves.1.get_from() - }; - if exit_move_field != farthest { - return Err(MoveError::ExitNotFasthest); - } + moves.1.get_from() + }; + if exit_move_field != farthest { + return Err(MoveError::ExitNotFasthest); } } }