feat: Battage du coin adverse

This commit is contained in:
Henri Bourcereau 2024-09-13 18:07:57 +02:00
parent 90c3db3ba7
commit 5fd11f7ef2

View file

@ -12,6 +12,7 @@ enum Jan {
FilledQuarter, FilledQuarter,
TrueHitSmallJan, TrueHitSmallJan,
TrueHitBigJan, TrueHitBigJan,
TrueHitOpponentCorner,
// jans de récompense : // jans de récompense :
// - battre une dame seule (par autant de façons de le faire, y compris // - battre une dame seule (par autant de façons de le faire, y compris
// utilisant une dame du coin de repos) // utilisant une dame du coin de repos)
@ -44,9 +45,13 @@ impl Jan {
} }
// « JAN DE RÉCOMPENSE » // « JAN DE RÉCOMPENSE »
// Battre à vrai une dame située dans la table des grands jans 2 | 4 1, 2 ou 3 (sauf doublet) Joueur // Battre à vrai une dame située dans la table des grands jans (2 par simple, 4 par double)
// Battre à vrai une dame située dans la table des petits jans 4 | 6 1, 2 ou 3 Joueur // Battre à vrai une dame située dans la table des petits jans (4 par simple, 6 par double)
// Battre le coin adverse 4 6 1 Joueur // Battre le coin adverse (4 par simple, 6 par double)
// « JAN DE REMPLISSAGE »
// Faire un petit jan, un grand jan ou un jan de retour (4 par simple, 6 par double)
// Conserver un petit jan, un grand jan ou un jan de retour (4 par simple, 6 par double)
} }
type PossibleJans = HashMap<Jan, Vec<(CheckerMove, CheckerMove)>>; type PossibleJans = HashMap<Jan, Vec<(CheckerMove, CheckerMove)>>;
@ -121,10 +126,40 @@ impl PointsRules {
// « JAN DE RÉCOMPENSE » // « JAN DE RÉCOMPENSE »
// Battre à vrai une dame située dans la table des grands jans // Battre à vrai une dame située dans la table des grands jans
// Battre à vrai une dame située dans la table des petits jans // Battre à vrai une dame située dans la table des petits jans
let mut jans = self.get_jans_by_dice_order(board_ini, dices); let mut jans = self.get_jans_by_ordered_dice(board_ini, dices);
let jans_revert_dices = self.get_jans_by_dice_order(board_ini, dices_reversed); let jans_revert_dices = self.get_jans_by_ordered_dice(board_ini, dices_reversed);
jans.merge(jans_revert_dices); jans.merge(jans_revert_dices);
// Battre à vrai le coin de repos de l'adversaire
let corner_field = board_ini.get_color_corner(&Color::White);
let adv_corner_field = board_ini.get_color_corner(&Color::Black);
let (adv_corner_count, _color) = board_ini.get_field_checkers(adv_corner_field).unwrap();
if adv_corner_count == 0 {
let from0 = adv_corner_field - self.dice.values.0 as usize;
let from1 = adv_corner_field - self.dice.values.1 as usize;
let (from0_count, from0_color) = board_ini.get_field_checkers(from0).unwrap();
let (from1_count, from1_color) = board_ini.get_field_checkers(from1).unwrap();
let hit_moves = vec![(
CheckerMove::new(from0, adv_corner_field).unwrap(),
CheckerMove::new(from1, adv_corner_field).unwrap(),
)];
if from0 == from1 {
// doublet
if from0_count > if from0 == corner_field { 3 } else { 0 } {
jans.insert(Jan::TrueHitOpponentCorner, hit_moves);
}
} else {
// simple
if from0_count > if from0 == corner_field { 2 } else { 0 }
&& from1_count > if from1 == corner_field { 2 } else { 0 }
{
jans.insert(Jan::TrueHitOpponentCorner, hit_moves);
}
}
}
// « JAN DE REMPLISSAGE » // « JAN DE REMPLISSAGE »
// Faire un petit jan, un grand jan ou un jan de retour // Faire un petit jan, un grand jan ou un jan de retour
let filling_moves_sequences = self let filling_moves_sequences = self
@ -137,7 +172,7 @@ impl PointsRules {
jans jans
} }
fn get_jans_by_dice_order(&self, board_ini: &Board, dices: &Vec<u8>) -> PossibleJans { fn get_jans_by_ordered_dice(&self, board_ini: &Board, dices: &Vec<u8>) -> PossibleJans {
let mut jans = PossibleJans::default(); let mut jans = PossibleJans::default();
let mut dices = dices.clone(); let mut dices = dices.clone();
if let Some(dice) = dices.pop() { if let Some(dice) = dices.pop() {
@ -159,7 +194,7 @@ impl PointsRules {
// repos : // repos :
// - on ne va pas sur le coin de l'adversaire // - on ne va pas sur le coin de l'adversaire
// - ni sur son propre coin de repos avec une seule dame // - ni sur son propre coin de repos avec une seule dame
// - règle non prise en compte pour le battage des dames : on ne sort pas de son coin de repos s'il ni reste que deux dames // - 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
let (corner_count, _color) = board.get_field_checkers(corner_field).unwrap(); let (corner_count, _color) = board.get_field_checkers(corner_field).unwrap();
if to != adv_corner_field && (to != corner_field || corner_count > 1) if to != adv_corner_field && (to != corner_field || corner_count > 1)
// && (from != corner_field || corner_count > 2) // && (from != corner_field || corner_count > 2)
@ -190,7 +225,7 @@ impl PointsRules {
// Try tout d'une : // Try tout d'une :
// - use original board before first die move // - use original board before first die move
// - use a virtual dice by adding current dice to remaining dice // - use a virtual dice by adding current dice to remaining dice
let next_dice_jan = self.get_jans_by_dice_order( let next_dice_jan = self.get_jans_by_ordered_dice(
&board_ini, &board_ini,
&dices.iter().map(|d| d + dice).collect(), &dices.iter().map(|d| d + dice).collect(),
); );
@ -198,17 +233,12 @@ impl PointsRules {
} }
} }
// Second die // Second die
let next_dice_jan = self.get_jans_by_dice_order(&board_ini, &dices); let next_dice_jan = self.get_jans_by_ordered_dice(&board_ini, &dices);
jans.merge(next_dice_jan); jans.merge(next_dice_jan);
} }
} }
} }
// TODO : mouvements en tout d'une asdf
// - faire un dé d1+d2 et regarder si hit
// - si hit : regarder s'il existe le truehit intermédiaire
// - regarder les TrueHit qui nécessitent deux mouvemments non nuls
// TODO : tout d'une (sans doublons avec 1 + 1) ?
jans jans
} }
@ -218,9 +248,10 @@ impl PointsRules {
// « JAN DE RÉCOMPENSE » // « JAN DE RÉCOMPENSE »
// Battre à vrai une dame située dans la table des grands jans // Battre à vrai une dame située dans la table des grands jans
// Battre à vrai une dame située dans la table des petits jans // Battre à vrai une dame située dans la table des petits jans
// TODO : Battre le coin adverse // Battre le coin adverse
let jans = self.get_jans(&self.board); let jans = self.get_jans(&self.board);
points += jans.into_iter().fold(0, |acc: i8, (jan, moves)| { points += jans.into_iter().fold(0, |acc: i8, (jan, moves)| {
println!("get_points : {:?}", jan);
acc + jan.get_points(self.dice.is_double()) * (moves.len() as i8) acc + jan.get_points(self.dice.is_double()) * (moves.len() as i8)
}); });
@ -261,11 +292,11 @@ mod tests {
2, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
let jans = rules.get_jans_by_dice_order(&rules.board, &vec![2, 3]); let jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![2, 3]);
assert_eq!(1, jans.len()); assert_eq!(1, jans.len());
assert_eq!(3, jans.get(&Jan::TrueHitSmallJan).unwrap().len()); assert_eq!(3, jans.get(&Jan::TrueHitSmallJan).unwrap().len());
let jans = rules.get_jans_by_dice_order(&rules.board, &vec![2, 2]); let jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![2, 2]);
assert_eq!(1, jans.len()); assert_eq!(1, jans.len());
assert_eq!(1, jans.get(&Jan::TrueHitSmallJan).unwrap().len()); assert_eq!(1, jans.get(&Jan::TrueHitSmallJan).unwrap().len());
@ -275,8 +306,8 @@ mod tests {
2, 0, -1, -2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -1, -2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
let mut jans = rules.get_jans_by_dice_order(&rules.board, &vec![2, 3]); let mut jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![2, 3]);
let jans_revert_dices = rules.get_jans_by_dice_order(&rules.board, &vec![3, 2]); let jans_revert_dices = rules.get_jans_by_ordered_dice(&rules.board, &vec![3, 2]);
assert_eq!(1, jans.len()); assert_eq!(1, jans.len());
assert_eq!(1, jans_revert_dices.len()); assert_eq!(1, jans_revert_dices.len());
jans.merge(jans_revert_dices); jans.merge(jans_revert_dices);
@ -286,7 +317,7 @@ mod tests {
2, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
let jans = rules.get_jans_by_dice_order(&rules.board, &vec![2, 3]); let jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![2, 3]);
assert_eq!(1, jans.len()); assert_eq!(1, jans.len());
assert_eq!(2, jans.get(&Jan::TrueHitSmallJan).unwrap().len()); assert_eq!(2, jans.get(&Jan::TrueHitSmallJan).unwrap().len());
@ -294,7 +325,7 @@ mod tests {
2, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
let jans = rules.get_jans_by_dice_order(&rules.board, &vec![2, 3]); let jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![2, 3]);
assert_eq!(1, jans.len()); assert_eq!(1, jans.len());
assert_eq!(1, jans.get(&Jan::TrueHitSmallJan).unwrap().len()); assert_eq!(1, jans.get(&Jan::TrueHitSmallJan).unwrap().len());
@ -302,7 +333,7 @@ mod tests {
2, 0, 1, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
let jans = rules.get_jans_by_dice_order(&rules.board, &vec![2, 3]); let jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![2, 3]);
assert_eq!(1, jans.len()); assert_eq!(1, jans.len());
assert_eq!(3, jans.get(&Jan::TrueHitSmallJan).unwrap().len()); assert_eq!(3, jans.get(&Jan::TrueHitSmallJan).unwrap().len());
@ -313,7 +344,7 @@ mod tests {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 // le premier dé traité est le dernier du vecteur : 1
let jans = rules.get_jans_by_dice_order(&rules.board, &vec![2, 1]); let jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![2, 1]);
// println!("jans (dés bloqués) : {:?}", jans.get(&Jan::TrueHit)); // println!("jans (dés bloqués) : {:?}", jans.get(&Jan::TrueHit));
assert_eq!(0, jans.len()); assert_eq!(0, jans.len());
@ -321,15 +352,15 @@ mod tests {
rules.board.set_positions([ rules.board.set_positions([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
let mut jans = rules.get_jans_by_dice_order(&rules.board, &vec![3, 3]); let mut jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![3, 3]);
assert_eq!(1, jans.len()); assert_eq!(1, jans.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([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
let mut jans = rules.get_jans_by_dice_order(&rules.board, &vec![3, 1]); let mut jans = rules.get_jans_by_ordered_dice(&rules.board, &vec![3, 1]);
let jans_revert_dices = rules.get_jans_by_dice_order(&rules.board, &vec![1, 3]); let jans_revert_dices = rules.get_jans_by_ordered_dice(&rules.board, &vec![1, 3]);
assert_eq!(1, jans_revert_dices.len()); assert_eq!(1, jans_revert_dices.len());
jans.merge(jans_revert_dices); jans.merge(jans_revert_dices);
@ -343,6 +374,7 @@ mod tests {
#[test] #[test]
fn get_points() { fn get_points() {
// ----- Jan de récompense // ----- Jan de récompense
// Battre à vrai une dame située dans la table des petits jans : 4 + 4 + 4 = 12
let mut rules = PointsRules::default(); let mut rules = PointsRules::default();
rules.update_positions([ rules.update_positions([
2, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -350,7 +382,30 @@ mod tests {
rules.set_dice(Dice { values: (2, 3) }); rules.set_dice(Dice { values: (2, 3) });
assert_eq!(12, rules.get_points()); assert_eq!(12, rules.get_points());
// Battre à vrai une dame située dans la table des grands jans : 2 + 2 = 4
let mut rules = PointsRules::default();
rules.update_positions([
2, 0, 0, -1, 2, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
rules.set_dice(Dice { values: (2, 4) });
assert_eq!(4, rules.get_points());
// Battre à vrai le coin adverse par doublet : 6
rules.update_positions([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
rules.set_dice(Dice { values: (2, 2) });
assert_eq!(6, rules.get_points());
// Cas de battage du coin de repos adverse impossible
rules.update_positions([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
rules.set_dice(Dice { values: (1, 1) });
assert_eq!(0, rules.get_points());
// ---- Jan de remplissage // ---- Jan de remplissage
// Faire un petit jan : 4
rules.update_positions([ rules.update_positions([
3, 1, 2, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
@ -358,19 +413,21 @@ mod tests {
assert_eq!(1, rules.get_jans(&rules.board).len()); assert_eq!(1, rules.get_jans(&rules.board).len());
assert_eq!(4, rules.get_points()); assert_eq!(4, rules.get_points());
// Faire un petit jan avec un doublet : 6
rules.update_positions([ rules.update_positions([
2, 3, 1, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 1, 2, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
rules.set_dice(Dice { values: (1, 1) }); rules.set_dice(Dice { values: (1, 1) });
assert_eq!(6, rules.get_points()); assert_eq!(6, rules.get_points());
// Faire un petit jan avec 2 moyens : 6 + 6 = 12
rules.update_positions([ rules.update_positions([
3, 3, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);
rules.set_dice(Dice { values: (1, 1) }); rules.set_dice(Dice { values: (1, 1) });
assert_eq!(12, rules.get_points()); assert_eq!(12, rules.get_points());
// conservation jan rempli // Conserver un jan avec un doublet : 6
rules.update_positions([ rules.update_positions([
3, 3, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]); ]);