wip fix allowed moves infinite loop

This commit is contained in:
Henri Bourcereau 2025-01-26 17:52:57 +01:00
parent 38100a61b2
commit 2a67996453

View file

@ -33,6 +33,13 @@ pub enum MoveError {
MustPlayStrongerDie, MustPlayStrongerDie,
} }
#[derive(std::cmp::PartialEq, Debug)]
pub enum TricTracRule {
ExitRule,
MustFillQuarterRule,
CornerRule,
}
/// MoveRules always consider that the current player is White /// MoveRules always consider that the current player is White
/// You must use 'mirror' functions on board & CheckerMoves if player is Black /// You must use 'mirror' functions on board & CheckerMoves if player is Black
#[derive(Default)] #[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<TricTracRule>,
) -> bool {
// Check moves possibles on the board // Check moves possibles on the board
// Check moves conforms to the dice // Check moves conforms to the dice
// Check move is allowed by the rules (to desactivate when playing with schools) // Check move is allowed by the rules (to desactivate when playing with schools)
self.moves_possible(moves) && self.moves_follows_dices(moves) && { 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() { if is_allowed.is_err() {
info!("Move not allowed : {:?}", is_allowed.unwrap_err()); info!("Move not allowed : {:?}", is_allowed.unwrap_err());
false false
@ -165,7 +176,11 @@ impl MoveRules {
} }
/// ---- moves_allowed : Third of three checks for moves /// ---- 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<TricTracRule>,
) -> Result<(), MoveError> {
self.check_corner_rules(moves)?; self.check_corner_rules(moves)?;
if self.is_move_by_puissance(moves) { if self.is_move_by_puissance(moves) {
@ -197,7 +212,9 @@ impl MoveRules {
} }
// check exit rules // 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 ---- // --- interdit de jouer dans un cadran que l'adversaire peut encore remplir ----
let farthest = cmp::max(moves.0.get_to(), moves.1.get_to()); 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 // toutes les sorties directes sont autorisées, ainsi que les nombres défaillants
let possible_moves_sequences = self.get_possible_moves_sequences(false); let possible_moves_sequences_without_excedent = self.get_possible_moves_sequences(false);
if !possible_moves_sequences.contains(moves) { if possible_moves_sequences_without_excedent.contains(moves) {
// À ce stade au moins un des déplacements concerne un nombre en excédant return Ok(());
// - si d'autres séquences de mouvements sans nombre en excédant étaient possibles, on }
// refuse cette séquence // À ce stade au moins un des déplacements concerne un nombre en excédant
if !possible_moves_sequences.is_empty() { // - si d'autres séquences de mouvements sans nombre en excédant sont possibles, on
return Err(MoveError::ExitByEffectPossible); // 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 // - la dame choisie doit être la plus éloignée de la sortie
let mut checkers = self.board.get_color_fields(Color::White); let mut checkers = self.board.get_color_fields(Color::White);
checkers.sort_by(|a, b| b.0.cmp(&a.0)); checkers.sort_by(|a, b| b.0.cmp(&a.0));
let mut farthest = 24; let mut farthest = 24;
let mut next_farthest = 24; let mut next_farthest = 24;
let mut has_two_checkers = false; let mut has_two_checkers = false;
if let Some((field, count)) = checkers.first() { if let Some((field, count)) = checkers.first() {
farthest = *field; farthest = *field;
if *count > 1 { if *count > 1 {
next_farthest = *field; next_farthest = *field;
has_two_checkers = true; has_two_checkers = true;
} else if let Some((field, _count)) = checkers.get(1) { } else if let Some((field, _count)) = checkers.get(1) {
next_farthest = *field; next_farthest = *field;
has_two_checkers = true; 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);
} }
} } else {
// Un seul coup sortant en excédant le coup sortant doit concerner la plus éloignée du bord
// s'il reste au moins deux dames, on vérifie que les plus éloignées soint choisies let exit_move_field = if moves.0.get_to() == 0 {
if has_two_checkers { moves.0.get_from()
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 { } else {
// Un seul coup sortant en excédant le coup sortant doit concerner la plus éloignée du bord moves.1.get_from()
let exit_move_field = if moves.0.get_to() == 0 { };
moves.0.get_from() if exit_move_field != farthest {
} else { return Err(MoveError::ExitNotFasthest);
moves.1.get_from()
};
if exit_move_field != farthest {
return Err(MoveError::ExitNotFasthest);
}
} }
} }
} }