refact(perf): precompute non excedant get_possible_moves_sequences
This commit is contained in:
parent
a239c02937
commit
dfc485a47a
1 changed files with 31 additions and 19 deletions
|
|
@ -220,7 +220,7 @@ impl MoveRules {
|
||||||
// Si possible, les deux dés doivent être joués
|
// Si possible, les deux dés doivent être joués
|
||||||
if moves.0.get_from() == 0 || moves.1.get_from() == 0 {
|
if moves.0.get_from() == 0 || moves.1.get_from() == 0 {
|
||||||
let mut possible_moves_sequences = self.get_possible_moves_sequences(true, vec![]);
|
let mut possible_moves_sequences = self.get_possible_moves_sequences(true, vec![]);
|
||||||
possible_moves_sequences.retain(|moves| self.check_exit_rules(moves).is_ok());
|
possible_moves_sequences.retain(|moves| self.check_exit_rules(moves, None).is_ok());
|
||||||
// possible_moves_sequences.retain(|moves| self.check_corner_rules(moves).is_ok());
|
// possible_moves_sequences.retain(|moves| self.check_corner_rules(moves).is_ok());
|
||||||
if !possible_moves_sequences.contains(moves) && !possible_moves_sequences.is_empty() {
|
if !possible_moves_sequences.contains(moves) && !possible_moves_sequences.is_empty() {
|
||||||
if *moves == (EMPTY_MOVE, EMPTY_MOVE) {
|
if *moves == (EMPTY_MOVE, EMPTY_MOVE) {
|
||||||
|
|
@ -238,7 +238,7 @@ impl MoveRules {
|
||||||
|
|
||||||
// check exit rules
|
// check exit rules
|
||||||
// if !ignored_rules.contains(&TricTracRule::Exit) {
|
// if !ignored_rules.contains(&TricTracRule::Exit) {
|
||||||
self.check_exit_rules(moves)?;
|
self.check_exit_rules(moves, None)?;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// --- interdit de jouer dans un cadran que l'adversaire peut encore remplir ----
|
// --- interdit de jouer dans un cadran que l'adversaire peut encore remplir ----
|
||||||
|
|
@ -321,7 +321,11 @@ impl MoveRules {
|
||||||
.is_empty()
|
.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_exit_rules(&self, moves: &(CheckerMove, CheckerMove)) -> Result<(), MoveError> {
|
fn check_exit_rules(
|
||||||
|
&self,
|
||||||
|
moves: &(CheckerMove, CheckerMove),
|
||||||
|
exit_seqs: Option<&[(CheckerMove, CheckerMove)]>,
|
||||||
|
) -> Result<(), MoveError> {
|
||||||
if !moves.0.is_exit() && !moves.1.is_exit() {
|
if !moves.0.is_exit() && !moves.1.is_exit() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
@ -331,16 +335,22 @@ 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 ignored_rules = vec![TricTracRule::Exit];
|
let owned;
|
||||||
let possible_moves_sequences_without_excedent =
|
let seqs = match exit_seqs {
|
||||||
self.get_possible_moves_sequences(false, ignored_rules);
|
Some(s) => s,
|
||||||
if possible_moves_sequences_without_excedent.contains(moves) {
|
None => {
|
||||||
|
owned = self
|
||||||
|
.get_possible_moves_sequences(false, vec![TricTracRule::Exit]);
|
||||||
|
&owned
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if seqs.contains(moves) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// À ce stade au moins un des déplacements concerne un nombre en excédant
|
// À 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
|
// - si d'autres séquences de mouvements sans nombre en excédant sont possibles, on
|
||||||
// refuse cette séquence
|
// refuse cette séquence
|
||||||
if !possible_moves_sequences_without_excedent.is_empty() {
|
if !seqs.is_empty() {
|
||||||
return Err(MoveError::ExitByEffectPossible);
|
return Err(MoveError::ExitByEffectPossible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,6 +570,14 @@ impl MoveRules {
|
||||||
let mut moves_seqs = Vec::new();
|
let mut moves_seqs = Vec::new();
|
||||||
let color = &Color::White;
|
let color = &Color::White;
|
||||||
let forbid_exits = self.has_checkers_outside_last_quarter();
|
let forbid_exits = self.has_checkers_outside_last_quarter();
|
||||||
|
// Precompute non-excedant sequences once so check_exit_rules need not repeat
|
||||||
|
// the full move generation for every exit-move candidate.
|
||||||
|
// Only needed when Exit is not already ignored and exits are actually reachable.
|
||||||
|
let exit_seqs = if !ignored_rules.contains(&TricTracRule::Exit) && !forbid_exits {
|
||||||
|
Some(self.get_possible_moves_sequences(false, vec![TricTracRule::Exit]))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let mut board = self.board.clone();
|
let mut board = self.board.clone();
|
||||||
// println!("==== First");
|
// println!("==== First");
|
||||||
for first_move in
|
for first_move in
|
||||||
|
|
@ -600,13 +618,7 @@ impl MoveRules {
|
||||||
&& self.can_take_corner_by_effect())
|
&& self.can_take_corner_by_effect())
|
||||||
&& (ignored_rules.contains(&TricTracRule::Exit)
|
&& (ignored_rules.contains(&TricTracRule::Exit)
|
||||||
|| self
|
|| self
|
||||||
.check_exit_rules(&(first_move, second_move))
|
.check_exit_rules(&(first_move, second_move), exit_seqs.as_deref())
|
||||||
// .inspect_err(|e| {
|
|
||||||
// println!(
|
|
||||||
// " 2nd (exit rule): {:?} - {:?}, {:?}",
|
|
||||||
// e, first_move, second_move
|
|
||||||
// )
|
|
||||||
// })
|
|
||||||
.is_ok())
|
.is_ok())
|
||||||
&& filling_seqs
|
&& filling_seqs
|
||||||
.map_or(true, |seqs| seqs.is_empty() || seqs.contains(&(first_move, second_move)))
|
.map_or(true, |seqs| seqs.is_empty() || seqs.contains(&(first_move, second_move)))
|
||||||
|
|
@ -632,7 +644,7 @@ impl MoveRules {
|
||||||
&& !(self.is_move_by_puissance(&(first_move, EMPTY_MOVE))
|
&& !(self.is_move_by_puissance(&(first_move, EMPTY_MOVE))
|
||||||
&& self.can_take_corner_by_effect())
|
&& self.can_take_corner_by_effect())
|
||||||
&& (ignored_rules.contains(&TricTracRule::Exit)
|
&& (ignored_rules.contains(&TricTracRule::Exit)
|
||||||
|| self.check_exit_rules(&(first_move, EMPTY_MOVE)).is_ok())
|
|| self.check_exit_rules(&(first_move, EMPTY_MOVE), exit_seqs.as_deref()).is_ok())
|
||||||
&& filling_seqs
|
&& filling_seqs
|
||||||
.map_or(true, |seqs| seqs.is_empty() || seqs.contains(&(first_move, EMPTY_MOVE)))
|
.map_or(true, |seqs| seqs.is_empty() || seqs.contains(&(first_move, EMPTY_MOVE)))
|
||||||
{
|
{
|
||||||
|
|
@ -1590,13 +1602,13 @@ mod tests {
|
||||||
CheckerMove::new(19, 23).unwrap(),
|
CheckerMove::new(19, 23).unwrap(),
|
||||||
CheckerMove::new(22, 0).unwrap(),
|
CheckerMove::new(22, 0).unwrap(),
|
||||||
);
|
);
|
||||||
assert!(state.check_exit_rules(&moves).is_ok());
|
assert!(state.check_exit_rules(&moves, None).is_ok());
|
||||||
|
|
||||||
let moves = (
|
let moves = (
|
||||||
CheckerMove::new(19, 24).unwrap(),
|
CheckerMove::new(19, 24).unwrap(),
|
||||||
CheckerMove::new(22, 0).unwrap(),
|
CheckerMove::new(22, 0).unwrap(),
|
||||||
);
|
);
|
||||||
assert!(state.check_exit_rules(&moves).is_ok());
|
assert!(state.check_exit_rules(&moves, None).is_ok());
|
||||||
|
|
||||||
state.dice.values = (6, 4);
|
state.dice.values = (6, 4);
|
||||||
state.board.set_positions(
|
state.board.set_positions(
|
||||||
|
|
@ -1609,7 +1621,7 @@ mod tests {
|
||||||
CheckerMove::new(20, 24).unwrap(),
|
CheckerMove::new(20, 24).unwrap(),
|
||||||
CheckerMove::new(23, 0).unwrap(),
|
CheckerMove::new(23, 0).unwrap(),
|
||||||
);
|
);
|
||||||
assert!(state.check_exit_rules(&moves).is_ok());
|
assert!(state.check_exit_rules(&moves, None).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue