fix(store): battage en passant par coin de repos vide
This commit is contained in:
parent
7383b7d5e8
commit
c6031b0ace
1 changed files with 91 additions and 82 deletions
|
|
@ -417,86 +417,96 @@ fn get_jans_by_ordered_dice(
|
||||||
) -> PossibleJans {
|
) -> PossibleJans {
|
||||||
let mut jans = PossibleJans::default();
|
let mut jans = PossibleJans::default();
|
||||||
let mut dices: Vec<u8> = dices.to_vec();
|
let mut dices: Vec<u8> = dices.to_vec();
|
||||||
if let Some(dice) = dices.pop() {
|
let dice = match dices.pop() {
|
||||||
let color = Color::White;
|
Some(dice) => dice,
|
||||||
let mut board = board_ini.clone();
|
None => return jans,
|
||||||
let corner_field = board.get_color_corner(&color);
|
};
|
||||||
let adv_corner_field = board.get_color_corner(&Color::Black);
|
let color = Color::White;
|
||||||
let froms = if let Some(from) = only_from {
|
let mut board = board_ini.clone();
|
||||||
vec![from]
|
let corner_field = board.get_color_corner(&color);
|
||||||
|
let adv_corner_field = board.get_color_corner(&Color::Black);
|
||||||
|
let froms = if let Some(from) = only_from {
|
||||||
|
vec![from]
|
||||||
|
} else {
|
||||||
|
board
|
||||||
|
.get_color_fields(color)
|
||||||
|
.iter()
|
||||||
|
.map(|cf| cf.0)
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
for from in froms {
|
||||||
|
// for (from, _) in board.get_color_fields(color) {
|
||||||
|
let to = if from + dice as usize > 24 {
|
||||||
|
0
|
||||||
} else {
|
} else {
|
||||||
board
|
from + dice as usize
|
||||||
.get_color_fields(color)
|
|
||||||
.iter()
|
|
||||||
.map(|cf| cf.0)
|
|
||||||
.collect()
|
|
||||||
};
|
};
|
||||||
for from in froms {
|
if let Ok(cmove) = CheckerMove::new(from, to) {
|
||||||
// for (from, _) in board.get_color_fields(color) {
|
// On vérifie que le mouvement n'est pas interdit par les règles des coins de
|
||||||
let to = if from + dice as usize > 24 {
|
// repos :
|
||||||
0
|
// - on ne va pas sur le coin de l'adversaire (sauf pour repos d'un tout d'une si vide)
|
||||||
} else {
|
// - ni sur son propre coin de repos avec une seule dame (sauf pour repos d'un tout
|
||||||
from + dice as usize
|
// d'une)
|
||||||
};
|
// - règle non prise en compte pour le battage des dames : on ne sort pas de son coin de repos s'il n'y reste que deux dames
|
||||||
if let Ok(cmove) = CheckerMove::new(from, to) {
|
let (corner_count, _color) = board.get_field_checkers(corner_field).unwrap();
|
||||||
// print!(
|
let (adv_corner_count, _color) = board.get_field_checkers(adv_corner_field).unwrap();
|
||||||
// " <dice_move dice='{:?}' moves='{:?} -> {:?}'> ",
|
// si only_false_hit est vrai, on est déja dans une tentative tout d'une
|
||||||
// dice, from, to
|
let mut can_try_toutdune = !only_false_hit;
|
||||||
// );
|
if (to == adv_corner_field && adv_corner_count < 2)
|
||||||
// On vérifie que le mouvement n'est pas interdit par les règles des coins de
|
|| to == corner_field && corner_count < 2
|
||||||
// repos :
|
{
|
||||||
// - on ne va pas sur le coin de l'adversaire
|
// Cas d'un tout d'une en passant par un coin de repos non rempli
|
||||||
// - ni sur son propre coin de repos avec une seule dame
|
// on s'assure qu'on est sur le premier dé
|
||||||
// - règle non prise en compte pour le battage des dames : on ne sort pas de son coin de repos s'il n'y reste que deux dames
|
if 0 < dices.len() {
|
||||||
let (corner_count, _color) = board.get_field_checkers(corner_field).unwrap();
|
can_try_toutdune = true;
|
||||||
if to != adv_corner_field && (to != corner_field || corner_count > 1) {
|
} else {
|
||||||
// si only_false_hit est vrai, on est déja dans une tentative tout d'une
|
continue;
|
||||||
let mut can_try_toutdune = !only_false_hit;
|
|
||||||
let mut only_falsehit = false;
|
|
||||||
match board.move_checker(&color, cmove) {
|
|
||||||
Err(Error::FieldBlockedByOne) => {
|
|
||||||
let jan = match (Board::is_field_in_small_jan(to), only_false_hit) {
|
|
||||||
(true, false) => Jan::TrueHitSmallJan,
|
|
||||||
(true, true) => Jan::FalseHitSmallJan,
|
|
||||||
(false, false) => Jan::TrueHitBigJan,
|
|
||||||
(false, true) => Jan::FalseHitBigJan,
|
|
||||||
};
|
|
||||||
jans.push(jan, (cmove, EMPTY_MOVE));
|
|
||||||
}
|
|
||||||
Err(Error::FieldBlocked) => {
|
|
||||||
only_falsehit = true;
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
can_try_toutdune = false;
|
|
||||||
// let next_dice_jan = self.get_jans(&board, &dices);
|
|
||||||
// jans possibles en tout d'une après un battage à vrai :
|
|
||||||
// truehit
|
|
||||||
}
|
|
||||||
Ok(()) => {}
|
|
||||||
}
|
|
||||||
if can_try_toutdune {
|
|
||||||
// Try tout d'une :
|
|
||||||
// - use original board before first die move
|
|
||||||
// - use a virtual dice by adding current dice to remaining dice
|
|
||||||
// - limit the checker to the current one
|
|
||||||
let next_dice_jan = get_jans_by_ordered_dice(
|
|
||||||
board_ini,
|
|
||||||
&dices.iter().map(|d| d + dice).collect::<Vec<u8>>(),
|
|
||||||
Some(from),
|
|
||||||
only_falsehit,
|
|
||||||
);
|
|
||||||
jans.merge(next_dice_jan);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Second die
|
}
|
||||||
let next_dice_jan = get_jans_by_ordered_dice(board_ini, &dices, None, false);
|
let mut only_falsehit = false;
|
||||||
|
match board.move_checker(&color, cmove) {
|
||||||
|
Err(Error::FieldBlockedByOne) => {
|
||||||
|
let jan = match (Board::is_field_in_small_jan(to), only_false_hit) {
|
||||||
|
(true, false) => Jan::TrueHitSmallJan,
|
||||||
|
(true, true) => Jan::FalseHitSmallJan,
|
||||||
|
(false, false) => Jan::TrueHitBigJan,
|
||||||
|
(false, true) => Jan::FalseHitBigJan,
|
||||||
|
};
|
||||||
|
jans.push(jan, (cmove, EMPTY_MOVE));
|
||||||
|
}
|
||||||
|
Err(Error::FieldBlocked) => {
|
||||||
|
only_falsehit = true;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
can_try_toutdune = false;
|
||||||
|
// let next_dice_jan = self.get_jans(&board, &dices);
|
||||||
|
// jans possibles en tout d'une après un battage à vrai :
|
||||||
|
// truehit
|
||||||
|
}
|
||||||
|
Ok(()) => {}
|
||||||
|
}
|
||||||
|
if can_try_toutdune {
|
||||||
|
// Try tout d'une :
|
||||||
|
// - use original board before first die move
|
||||||
|
// - use a virtual dice by adding current dice to remaining dice
|
||||||
|
// - limit the checker to the current one
|
||||||
|
let next_dice_jan = get_jans_by_ordered_dice(
|
||||||
|
board_ini,
|
||||||
|
&dices.iter().map(|d| d + dice).collect::<Vec<u8>>(),
|
||||||
|
Some(from),
|
||||||
|
only_falsehit,
|
||||||
|
);
|
||||||
jans.merge(next_dice_jan);
|
jans.merge(next_dice_jan);
|
||||||
}
|
}
|
||||||
|
// Second die
|
||||||
|
let next_dice_jan = get_jans_by_ordered_dice(board_ini, &dices, None, false);
|
||||||
|
jans.merge(next_dice_jan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jans
|
jans
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -569,18 +579,6 @@ mod tests {
|
||||||
|
|
||||||
// corners handling
|
// corners handling
|
||||||
|
|
||||||
// deux dés bloqués (coin de repos et coin de l'adversaire)
|
|
||||||
rules.board.set_positions(
|
|
||||||
&Color::White,
|
|
||||||
[
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
// le premier dé traité est le dernier du vecteur : 1
|
|
||||||
let jans = get_jans_by_ordered_dice(&rules.board, &[2, 1], None, false);
|
|
||||||
// println!("jans (dés bloqués) : {:?}", jans.get(&Jan::TrueHit));
|
|
||||||
assert_eq!(0, jans.len());
|
|
||||||
|
|
||||||
// dé dans son coin de repos : peut tout de même battre à vrai
|
// dé dans son coin de repos : peut tout de même battre à vrai
|
||||||
rules.board.set_positions(
|
rules.board.set_positions(
|
||||||
&Color::White,
|
&Color::White,
|
||||||
|
|
@ -591,6 +589,17 @@ mod tests {
|
||||||
let jans = get_jans_by_ordered_dice(&rules.board, &[3, 3], None, false);
|
let jans = get_jans_by_ordered_dice(&rules.board, &[3, 3], None, false);
|
||||||
assert_eq!(1, jans.len());
|
assert_eq!(1, jans.len());
|
||||||
|
|
||||||
|
// case intermédiaire dans coin de repos vide : peut tout de même battre à vrai
|
||||||
|
rules.board.set_positions(
|
||||||
|
&Color::White,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
let jans = get_jans_by_ordered_dice(&rules.board, &[4, 1], None, false);
|
||||||
|
assert_eq!(1, jans.len());
|
||||||
|
assert_eq!(1, jans.get(&Jan::TrueHitBigJan).unwrap().len());
|
||||||
|
|
||||||
// premier dé bloqué, mais tout d'une possible en commençant par le second
|
// premier dé bloqué, mais tout d'une possible en commençant par le second
|
||||||
rules.board.set_positions(
|
rules.board.set_positions(
|
||||||
&Color::White,
|
&Color::White,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue