feat: jan de 6 tables : check dice roll count

This commit is contained in:
Henri Bourcereau 2024-09-23 17:53:21 +02:00
parent 17605efe76
commit 3d41517909
5 changed files with 102 additions and 68 deletions

View file

@ -77,13 +77,25 @@ impl Bot {
}
fn calculate_points(&self) -> u8 {
let dice_roll_count = self
.game
.players
.get(&self.player_id)
.unwrap()
.dice_roll_count;
let points_rules = PointsRules::new(&Color::White, &self.game.board, self.game.dice);
points_rules.get_points().0
points_rules.get_points(dice_roll_count).0
}
fn calculate_adv_points(&self) -> u8 {
let dice_roll_count = self
.game
.players
.get(&self.player_id)
.unwrap()
.dice_roll_count;
let points_rules = PointsRules::new(&Color::White, &self.game.board, self.game.dice);
points_rules.get_points().1
points_rules.get_points(dice_roll_count).0
}
fn choose_move(&self) -> (CheckerMove, CheckerMove) {

View file

@ -209,7 +209,7 @@ impl App {
let player = &self.game.state.players[player_id];
output += format!(
"\n{}. {:<8} :: {:<5} :: {}",
&player_id, &player.name, &player.holes, &player.points
&player_id, &player.name, &player.holes, &player.points,
)
.as_str();
}
@ -263,7 +263,7 @@ Rolled dice : 0 & 0
#[test]
fn test_move() {
let expected = "-------------------------------
InGame > myself > MarkAdvPoints
InGame > myself > RollDice
Rolled dice : 4 & 6
Player :: holes :: points

View file

@ -373,6 +373,7 @@ impl GameState {
points: 0,
can_bredouille: true,
can_big_bredouille: true,
dice_roll_count: 0,
},
);
}
@ -388,14 +389,9 @@ impl GameState {
}
RollResult { player_id, dice } => {
self.dice = *dice;
self.inc_roll_count(self.active_player_id);
self.turn_stage = TurnStage::MarkPoints;
// We compute points for the move
let points_rules = PointsRules::new(
&self.player_color_by_id(&self.active_player_id).unwrap(),
&self.board,
*dice,
);
self.dice_points = points_rules.get_points();
self.dice_points = self.get_rollresult_points(dice);
if !self.schools_enabled {
// Schools are not enabled. We mark points automatically
// the points earned by the opponent will be marked on its turn
@ -431,11 +427,24 @@ impl GameState {
self.history.push(valid_event.clone());
}
fn get_rollresult_points(&self, dice: &Dice) -> (u8, u8) {
let player = &self.players.get(&self.active_player_id).unwrap();
let points_rules = PointsRules::new(&player.color, &self.board, *dice);
points_rules.get_points(player.dice_roll_count)
}
/// Determines if someone has won the game
pub fn determine_winner(&self) -> Option<PlayerId> {
None
}
fn inc_roll_count(&mut self, player_id: PlayerId) {
self.players.get_mut(&player_id).map(|p| {
p.dice_roll_count += 1;
p
});
}
fn mark_points(&mut self, player_id: PlayerId, points: u8) {
self.players.get_mut(&player_id).map(|p| {
let sum_points = p.points + points;

View file

@ -2,14 +2,14 @@ use std::cmp;
use std::collections::HashMap;
use crate::board::{Board, Field, EMPTY_MOVE};
use crate::dice::Dice;
use crate::dice::{self, Dice};
use crate::game_rules_moves::MoveRules;
use crate::player::Color;
use crate::CheckerMove;
use crate::Error;
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
enum Jan {
pub enum Jan {
FilledQuarter,
TrueHitSmallJan,
TrueHitBigJan,
@ -161,7 +161,7 @@ impl PointsRules {
self.move_rules.board.set_positions(positions);
}
fn get_jans(&self, board_ini: &Board) -> PossibleJans {
fn get_jans(&self, board_ini: &Board, dice_rolls_count: u8) -> PossibleJans {
let dices = &vec![self.dice.values.0, self.dice.values.1];
let dices_reversed = &vec![self.dice.values.1, self.dice.values.0];
let dice1 = self.dice.values.0 as usize;
@ -248,7 +248,8 @@ impl PointsRules {
}
// « JANS RARES »
// Jan de 6 tables
// Jan de 3 coups ou de 6 tables
if dice_rolls_count == 3 {
// on devrait avoir 4 cases occupées par une dame chacune
let fields_with_single: Vec<&(usize, i8)> =
checkers.iter().filter(|(f, c)| c == &1).collect();
@ -276,6 +277,7 @@ impl PointsRules {
}
}
}
}
// Jans nécessitant que deux dames uniquement soient sorties du talon
let (talon, candidates): (Vec<(usize, i8)>, Vec<(usize, i8)>) =
@ -441,11 +443,7 @@ impl PointsRules {
jans
}
pub fn get_points(&self) -> (u8, u8) {
let jans = self.get_jans(&self.board);
// if !jans.is_empty() {
// println!("get points : {:?}", jans);
// }
pub fn get_jans_points(&self, jans: HashMap<Jan, Vec<(CheckerMove, CheckerMove)>>) -> (u8, u8) {
let (points, adv_points) = jans
.into_iter()
.fold((0, 0), |acc: (i8, i8), (jan, moves)| {
@ -465,6 +463,11 @@ impl PointsRules {
(points as u8, adv_points as u8)
}
pub fn get_points(&self, dice_rolls_count: u8) -> (u8, u8) {
let jans = self.get_jans(&self.board, dice_rolls_count);
self.get_jans_points(jans)
}
}
#[cfg(test)]
@ -567,7 +570,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,
]);
rules.set_dice(Dice { values: (2, 3) });
assert_eq!(12, rules.get_points().0);
assert_eq!(12, rules.get_points(5).0);
// Battre à vrai une dame située dans la table des grands jans : 2 + 2 = 4
let mut rules = PointsRules::default();
@ -575,28 +578,28 @@ mod tests {
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().0);
assert_eq!(4, rules.get_points(5).0);
// Battre à vrai une dame située dans la table des grands jans : 2
let mut rules = PointsRules::default();
rules.update_positions([
2, 0, -2, -1, 0, 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!((2, 2), rules.get_points());
assert_eq!((2, 2), rules.get_points(5));
// 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().0);
assert_eq!(6, rules.get_points(5).0);
// 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().0);
assert_eq!(0, rules.get_points(5).0);
// ---- Jan de remplissage
// Faire un petit jan : 4
@ -604,29 +607,29 @@ mod tests {
3, 1, 2, 2, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
rules.set_dice(Dice { values: (2, 1) });
assert_eq!(1, rules.get_jans(&rules.board).len());
assert_eq!(4, rules.get_points().0);
assert_eq!(1, rules.get_jans(&rules.board, 5).len());
assert_eq!(4, rules.get_points(5).0);
// Faire un petit jan avec un doublet : 6
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,
]);
rules.set_dice(Dice { values: (1, 1) });
assert_eq!(6, rules.get_points().0);
assert_eq!(6, rules.get_points(5).0);
// Faire un petit jan avec 2 moyens : 6 + 6 = 12
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,
]);
rules.set_dice(Dice { values: (1, 1) });
assert_eq!(12, rules.get_points().0);
assert_eq!(12, rules.get_points(5).0);
// Conserver un jan avec un doublet : 6
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,
]);
rules.set_dice(Dice { values: (1, 1) });
assert_eq!(6, rules.get_points().0);
assert_eq!(6, rules.get_points(5).0);
// ---- Sorties
// Sortir toutes ses dames avant l'adversaire (simple)
@ -634,14 +637,14 @@ mod tests {
0, 0, -2, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
]);
rules.set_dice(Dice { values: (3, 1) });
assert_eq!(4, rules.get_points().0);
assert_eq!(4, rules.get_points(5).0);
// Sortir toutes ses dames avant l'adversaire (doublet)
rules.update_positions([
0, 0, -2, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
]);
rules.set_dice(Dice { values: (2, 2) });
assert_eq!(6, rules.get_points().0);
assert_eq!(6, rules.get_points(5).0);
// ---- JANS RARES
// Jan de six tables
@ -649,55 +652,60 @@ mod tests {
10, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (2, 3) });
assert_eq!(4, rules.get_points().0);
assert_eq!(0, rules.get_points(5).0);
rules.update_positions([
10, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (2, 3) });
assert_eq!(4, rules.get_points(3).0);
rules.update_positions([
10, 1, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (2, 3) });
assert_eq!(0, rules.get_points().0);
assert_eq!(0, rules.get_points(3).0);
rules.update_positions([
10, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (2, 3) });
assert_eq!(0, rules.get_points().0);
assert_eq!(0, rules.get_points(3).0);
// Jan de deux tables
rules.update_positions([
13, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (2, 2) });
assert_eq!(6, rules.get_points().0);
assert_eq!(6, rules.get_points(5).0);
rules.update_positions([
12, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (2, 2) });
assert_eq!(0, rules.get_points().0);
assert_eq!(0, rules.get_points(5).0);
// Contre jan de deux tables
rules.update_positions([
13, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (2, 2) });
assert_eq!((0, 6), rules.get_points());
assert_eq!((0, 6), rules.get_points(5));
// Jan de mézéas
rules.update_positions([
13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (1, 1) });
assert_eq!(6, rules.get_points().0);
assert_eq!(6, rules.get_points(5).0);
rules.update_positions([
13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (1, 2) });
assert_eq!(4, rules.get_points().0);
assert_eq!(4, rules.get_points(5).0);
// Contre jan de mézéas
rules.update_positions([
13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0,
]);
rules.set_dice(Dice { values: (1, 1) });
assert_eq!((0, 6), rules.get_points());
assert_eq!((0, 6), rules.get_points(5));
// ---- JANS QUI NE PEUT
// Battre à faux une dame située dans la table des petits jans
@ -706,7 +714,7 @@ mod tests {
2, 0, -2, -2, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
rules.set_dice(Dice { values: (2, 3) });
assert_eq!((0, 4), rules.get_points());
assert_eq!((0, 4), rules.get_points(5));
// Battre à faux une dame située dans la table des grands jans
let mut rules = PointsRules::default();
@ -714,7 +722,7 @@ mod tests {
2, 0, -2, -1, -2, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
rules.set_dice(Dice { values: (2, 4) });
assert_eq!((0, 2), rules.get_points());
assert_eq!((0, 2), rules.get_points(5));
// Pour chaque dé non jouable (dame impuissante)
let mut rules = PointsRules::default();
@ -722,6 +730,6 @@ mod tests {
2, 0, -2, -2, -2, 0, -2, 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!((0, 4), rules.get_points());
assert_eq!((0, 4), rules.get_points(5));
}
}

View file

@ -28,6 +28,9 @@ pub struct Player {
pub holes: u8,
pub can_bredouille: bool,
pub can_big_bredouille: bool,
/// Number of dice rolls since beginning of the current setting (all 15 dames in the talon )
/// (used to check jan de 3 coups)
pub dice_roll_count: u8,
}
impl Player {
@ -39,6 +42,7 @@ impl Player {
holes: 0,
can_bredouille: true,
can_big_bredouille: true,
dice_roll_count: 0,
}
}
@ -113,6 +117,7 @@ mod tests {
holes: 3,
can_bredouille: true,
can_big_bredouille: false,
dice_roll_count: 0,
};
println!("{}", player.to_bits_string());
assert!(player.to_bits_string() == "1011001110");