diff --git a/store/src/game_rules_moves.rs b/store/src/game_rules_moves.rs index 7bf0f17..3bf4317 100644 --- a/store/src/game_rules_moves.rs +++ b/store/src/game_rules_moves.rs @@ -364,6 +364,8 @@ impl MoveRules { let mut farthest = 24; let mut next_farthest = 24; let mut has_two_checkers = false; + // Do we need to recalculate farthest after first move ? + let mut first_move_change_farthest = true; if has_filled_quarter { // When a quarter is filled, we can only exit from fields with >2 checkers @@ -377,6 +379,7 @@ impl MoveRules { if available_checkers[0].1 > 3 { next_farthest = available_checkers[0].0; has_two_checkers = true; + first_move_change_farthest = false; } else if available_checkers.len() > 1 { next_farthest = available_checkers[1].0; has_two_checkers = true; @@ -416,14 +419,19 @@ impl MoveRules { if cmp::max(moves.0.get_from(), moves.1.get_from()) > next_farthest { return Err(MoveError::ExitNotFarthest); } + } else if moves.0.get_to() == 0 { + // Seul le premier coup est un coup sortant en excédant, il doit concerner la plus éloignée du bord + if moves.0.get_from() != farthest { + return Err(MoveError::ExitNotFarthest); + } } 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 { + // Seul le second coup est un coup sortant en excédant, + // il doit concerner la plus éloignée du bord APRÈS + // que le premier coup ait été joué + if moves.0.get_from() == farthest && first_move_change_farthest { + farthest = cmp::min(next_farthest, moves.0.get_to()); + } + if moves.1.get_from() != farthest { return Err(MoveError::ExitNotFarthest); } } @@ -569,23 +577,45 @@ impl MoveRules { for second_move in board2.get_possible_moves(*color, dice2, with_excedents, true, forbid_exits) { - if self.check_corner_rules(&(first_move, second_move)).is_ok() + if self + .check_corner_rules(&(first_move, second_move)) + .inspect_err(|e| { + println!( + " 2nd (corner rule): {:?} - {:?}, {:?}", + e, first_move, second_move + ) + }) + .is_ok() && self .check_opponent_can_fill_quarter_rule(&(first_move, second_move)) + .inspect_err(|e| { + println!( + " 2nd (op fill quarter): {:?} - {:?}, {:?}", + e, first_move, second_move + ) + }) .is_ok() && !(self.is_move_by_puissance(&(first_move, second_move)) && self.can_take_corner_by_effect()) && (ignored_rules.contains(&TricTracRule::Exit) - || self.check_exit_rules(&(first_move, second_move)).is_ok()) + || self + .check_exit_rules(&(first_move, second_move)) + .inspect_err(|e| { + println!( + " 2nd (exit rule): {:?} - {:?}, {:?}", + e, first_move, second_move + ) + }) + .is_ok()) && (ignored_rules.contains(&TricTracRule::MustFillQuarter) || self .check_must_fill_quarter_rule(&(first_move, second_move)) - // .inspect_err(|e| { - // println!( - // " 2nd (must fill quar): {:?} - {:?}, {:?}", - // e, first_move, second_move - // ) - // }) + .inspect_err(|e| { + println!( + " 2nd: {:?} - {:?}, {:?} for {:?}", + e, first_move, second_move, self.board + ) + }) .is_ok()) { if second_move.get_to() == 0 @@ -1454,5 +1484,67 @@ mod tests { vec![] ) ); + + state.dice.values = (4, 5); + state.board.set_positions( + &crate::Color::White, + [ + -5, -2, -2, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 2, 3, 2, 3, + ], + ); + let moves = vec![ + ( + CheckerMove::new(19, 23).unwrap(), + CheckerMove::new(22, 0).unwrap(), + ), + ( + CheckerMove::new(19, 24).unwrap(), + CheckerMove::new(22, 0).unwrap(), + ), + ]; + assert_eq!( + moves, + state.get_possible_moves_sequences_by_dices( + state.dice.values.0, + state.dice.values.1, + true, + false, + vec![] + ) + ); + } + + #[test] + fn check_exit_rules() { + let mut state = MoveRules::default(); + state.dice.values = (4, 5); + state.board.set_positions( + &crate::Color::White, + [ + -5, -2, -2, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 2, 3, 2, 3, + ], + ); + let moves = ( + CheckerMove::new(19, 23).unwrap(), + CheckerMove::new(22, 0).unwrap(), + ); + assert!(state.check_exit_rules(&moves).is_ok()); + } + + #[test] + fn check_must_fill_quarter_rule() { + let mut state = MoveRules::default(); + state.dice.values = (4, 5); + state.board.set_positions( + &crate::Color::White, + [ + -5, -2, -2, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 2, 3, 2, 3, + ], + ); + let moves = ( + CheckerMove::new(19, 24).unwrap(), + CheckerMove::new(22, 0).unwrap(), + ); + assert!(state.check_must_fill_quarter_rule(&moves).is_ok()); } }