wip fix moves rules
This commit is contained in:
parent
aff489f134
commit
9b48dea435
|
|
@ -64,6 +64,10 @@ impl CheckerMove {
|
||||||
pub fn get_to(&self) -> Field {
|
pub fn get_to(&self) -> Field {
|
||||||
self.to
|
self.to
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_exit(&self) -> bool {
|
||||||
|
self.to == 0 && self != &EMPTY_MOVE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents the Tric Trac board
|
/// Represents the Tric Trac board
|
||||||
|
|
@ -457,6 +461,9 @@ impl Board {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_checker(&mut self, color: &Color, field: Field) -> Result<(), Error> {
|
pub fn remove_checker(&mut self, color: &Color, field: Field) -> Result<(), Error> {
|
||||||
|
if field == 0 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
let checker_color = self.get_checkers_color(field)?;
|
let checker_color = self.get_checkers_color(field)?;
|
||||||
if Some(color) != checker_color {
|
if Some(color) != checker_color {
|
||||||
return Err(Error::FieldInvalid);
|
return Err(Error::FieldInvalid);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@ pub enum MoveError {
|
||||||
OpponentCanFillQuarter,
|
OpponentCanFillQuarter,
|
||||||
// remplir cadran si possible & conserver cadran rempli si possible ----
|
// remplir cadran si possible & conserver cadran rempli si possible ----
|
||||||
MustFillQuarter,
|
MustFillQuarter,
|
||||||
|
// On n'a pas le droit de jouer d'une manière qui empêche de jouer les deux dés si on a la possibilité de les jouer.
|
||||||
|
MustPlayAllDice,
|
||||||
|
// Si on ne peut jouer qu'un seul dé, on doit jouer le plus fort si possible.
|
||||||
|
MustPlayStrongerDie,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MoveRules {
|
pub trait MoveRules {
|
||||||
|
|
@ -140,8 +144,16 @@ pub trait MoveRules {
|
||||||
return Err(MoveError::CornerByEffectPossible);
|
return Err(MoveError::CornerByEffectPossible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Si possible, les deux dés doivent être joués
|
||||||
|
let possible_moves_sequences = self.get_possible_moves_sequences(color, true);
|
||||||
|
if !possible_moves_sequences.contains(moves) && !possible_moves_sequences.is_empty() {
|
||||||
|
println!(">>{:?}<<", moves);
|
||||||
|
println!("{:?}", possible_moves_sequences);
|
||||||
|
return Err(MoveError::MustPlayAllDice);
|
||||||
|
}
|
||||||
|
|
||||||
// check exit rules
|
// check exit rules
|
||||||
if moves.0.get_to() == 0 || moves.1.get_to() == 0 {
|
if moves.0.is_exit() || moves.1.is_exit() {
|
||||||
// toutes les dames doivent être dans le jan de retour
|
// toutes les dames doivent être dans le jan de retour
|
||||||
let has_outsiders = !self
|
let has_outsiders = !self
|
||||||
.board()
|
.board()
|
||||||
|
|
@ -157,8 +169,8 @@ pub trait MoveRules {
|
||||||
return Err(MoveError::ExitNeedsAllCheckersOnLastQuarter);
|
return Err(MoveError::ExitNeedsAllCheckersOnLastQuarter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// toutes les sorties directes sont autorisées, ainsi que les nombre défaillants
|
// toutes les sorties directes sont autorisées, ainsi que les nombres défaillants
|
||||||
let possible_moves_sequences = self.get_possible_moves_sequences(color);
|
let possible_moves_sequences = self.get_possible_moves_sequences(color, false);
|
||||||
if !possible_moves_sequences.contains(moves) {
|
if !possible_moves_sequences.contains(moves) {
|
||||||
// À 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 étaient possibles, on
|
// - si d'autres séquences de mouvements sans nombre en excédant étaient possibles, on
|
||||||
|
|
@ -245,10 +257,16 @@ pub trait MoveRules {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_possible_moves_sequences(&self, color: &Color) -> Vec<(CheckerMove, CheckerMove)> {
|
fn get_possible_moves_sequences(
|
||||||
|
&self,
|
||||||
|
color: &Color,
|
||||||
|
with_excedents: bool,
|
||||||
|
) -> Vec<(CheckerMove, CheckerMove)> {
|
||||||
let (dice1, dice2) = self.dice().values;
|
let (dice1, dice2) = self.dice().values;
|
||||||
let mut moves_seqs = self.get_possible_moves_sequences_by_dices(color, dice1, dice2);
|
let mut moves_seqs =
|
||||||
let mut moves_seqs_order2 = self.get_possible_moves_sequences_by_dices(color, dice1, dice2);
|
self.get_possible_moves_sequences_by_dices(color, dice1, dice2, with_excedents);
|
||||||
|
let mut moves_seqs_order2 =
|
||||||
|
self.get_possible_moves_sequences_by_dices(color, dice2, dice1, with_excedents);
|
||||||
moves_seqs.append(&mut moves_seqs_order2);
|
moves_seqs.append(&mut moves_seqs_order2);
|
||||||
moves_seqs
|
moves_seqs
|
||||||
}
|
}
|
||||||
|
|
@ -258,7 +276,7 @@ pub trait MoveRules {
|
||||||
color: &Color,
|
color: &Color,
|
||||||
) -> Vec<(CheckerMove, CheckerMove)> {
|
) -> Vec<(CheckerMove, CheckerMove)> {
|
||||||
let mut moves_seqs = Vec::new();
|
let mut moves_seqs = Vec::new();
|
||||||
for moves in self.get_possible_moves_sequences(color) {
|
for moves in self.get_possible_moves_sequences(color, true) {
|
||||||
let mut board = self.board().clone();
|
let mut board = self.board().clone();
|
||||||
board.move_checker(color, moves.0).unwrap();
|
board.move_checker(color, moves.0).unwrap();
|
||||||
board.move_checker(color, moves.1).unwrap();
|
board.move_checker(color, moves.1).unwrap();
|
||||||
|
|
@ -274,9 +292,13 @@ pub trait MoveRules {
|
||||||
color: &Color,
|
color: &Color,
|
||||||
dice1: u8,
|
dice1: u8,
|
||||||
dice2: u8,
|
dice2: u8,
|
||||||
|
with_excedents: bool,
|
||||||
) -> Vec<(CheckerMove, CheckerMove)> {
|
) -> Vec<(CheckerMove, CheckerMove)> {
|
||||||
let mut moves_seqs = Vec::new();
|
let mut moves_seqs = Vec::new();
|
||||||
for first_move in self.board().get_possible_moves(*color, dice1, false) {
|
for first_move in self
|
||||||
|
.board()
|
||||||
|
.get_possible_moves(*color, dice1, with_excedents)
|
||||||
|
{
|
||||||
let mut board2 = self.board().clone();
|
let mut board2 = self.board().clone();
|
||||||
if board2.move_checker(color, first_move).is_err() {
|
if board2.move_checker(color, first_move).is_err() {
|
||||||
println!("err move");
|
println!("err move");
|
||||||
|
|
@ -284,14 +306,14 @@ pub trait MoveRules {
|
||||||
}
|
}
|
||||||
if board2.get_color_fields(*color).is_empty() {
|
if board2.get_color_fields(*color).is_empty() {
|
||||||
// no checkers left : empty move
|
// no checkers left : empty move
|
||||||
println!("empty move");
|
|
||||||
moves_seqs.push((first_move, EMPTY_MOVE));
|
moves_seqs.push((first_move, EMPTY_MOVE));
|
||||||
} else {
|
} else {
|
||||||
for second_move in board2.get_possible_moves(*color, dice2, false) {
|
for second_move in board2.get_possible_moves(*color, dice2, with_excedents) {
|
||||||
moves_seqs.push((first_move, second_move));
|
moves_seqs.push((first_move, second_move));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO : ajouter la prise de son coin de repos (directement et par puissance)
|
||||||
moves_seqs
|
moves_seqs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,7 +535,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
let moves = (
|
let moves = (
|
||||||
CheckerMove::new(20, 0).unwrap(),
|
CheckerMove::new(20, 0).unwrap(),
|
||||||
CheckerMove::new(20, 0).unwrap(),
|
CheckerMove::new(21, 0).unwrap(),
|
||||||
);
|
);
|
||||||
assert!(state.moves_allowed(&Color::White, &moves).is_ok());
|
assert!(state.moves_allowed(&Color::White, &moves).is_ok());
|
||||||
|
|
||||||
|
|
@ -597,6 +619,54 @@ mod tests {
|
||||||
assert!(state.moves_allowed(&Color::White, &moves).is_ok());
|
assert!(state.moves_allowed(&Color::White, &moves).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn move_play_all_dice() {
|
||||||
|
let mut state = GameState::default();
|
||||||
|
state.board.set_positions([
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
]);
|
||||||
|
state.dice.values = (1, 3);
|
||||||
|
let moves = (
|
||||||
|
CheckerMove::new(22, 0).unwrap(),
|
||||||
|
CheckerMove::new(0, 0).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let poss = state.get_possible_moves_sequences(&Color::White, true);
|
||||||
|
println!("{:?}", poss);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Err(MoveError::MustPlayAllDice),
|
||||||
|
state.moves_allowed(&Color::White, &moves)
|
||||||
|
);
|
||||||
|
let moves = (
|
||||||
|
CheckerMove::new(22, 23).unwrap(),
|
||||||
|
CheckerMove::new(23, 0).unwrap(),
|
||||||
|
);
|
||||||
|
assert!(state.moves_allowed(&Color::White, &moves).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn move_play_stronger_dice() {
|
||||||
|
let mut state = GameState::default();
|
||||||
|
state.board.set_positions([
|
||||||
|
0, 0, 0, 0, 0, 3, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
]);
|
||||||
|
state.dice.values = (2, 3);
|
||||||
|
let moves = (
|
||||||
|
CheckerMove::new(6, 8).unwrap(),
|
||||||
|
CheckerMove::new(0, 0).unwrap(),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Err(MoveError::MustPlayStrongerDie),
|
||||||
|
state.moves_allowed(&Color::White, &moves)
|
||||||
|
);
|
||||||
|
let moves = (
|
||||||
|
CheckerMove::new(6, 9).unwrap(),
|
||||||
|
CheckerMove::new(0, 0).unwrap(),
|
||||||
|
);
|
||||||
|
assert!(state.moves_allowed(&Color::White, &moves).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn moves_possible() {
|
fn moves_possible() {
|
||||||
let state = GameState::default();
|
let state = GameState::default();
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,15 @@ use crate::dice::Dice;
|
||||||
#[derive(std::cmp::PartialEq, Debug)]
|
#[derive(std::cmp::PartialEq, Debug)]
|
||||||
pub enum PointsRule {
|
pub enum PointsRule {
|
||||||
FilledQuarter,
|
FilledQuarter,
|
||||||
|
// jans de récompense :
|
||||||
|
// - battre une dame seule (par autant de façons de le faire, y compris
|
||||||
|
// utilisant une dame du coin de repos)
|
||||||
|
// - battre le coin adverse : si deux dames (hormis les deux dernière de son propre coin de
|
||||||
|
// repos) peuvent battre le coin vide adverse
|
||||||
|
// jans qui ne peut (pts pour l'adversaire) :
|
||||||
|
// - battre à faux : si on passe par une case pleine pour atteindre la
|
||||||
|
// case que l'on peut battre
|
||||||
|
// - si on ne peut pas jouer ses deux dés
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PointsRules {
|
pub trait PointsRules {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue