Compare commits
No commits in common. "f893ecaf9ff4cea0212d919ab21bc4acc996357c" and "0eb52661e1921c72589ad95ed289eba3aec90df9" have entirely different histories.
f893ecaf9f
...
0eb52661e1
3 changed files with 17 additions and 97 deletions
|
|
@ -121,15 +121,11 @@ body {
|
||||||
|
|
||||||
.portal-card {
|
.portal-card {
|
||||||
background: var(--ui-parchment);
|
background: var(--ui-parchment);
|
||||||
border-radius: 8px;
|
border: 1px solid rgba(200,164,72,0.3);
|
||||||
box-shadow:
|
border-top: 3px solid var(--ui-gold-dark);
|
||||||
0 20px 60px rgba(0,0,0,0.55),
|
border-radius: 6px;
|
||||||
0 0 3px 3px rgba(42,21,8,0.9)
|
|
||||||
;
|
|
||||||
/* box-shadow: 0 4px 16px rgba(0,0,0,0.18); */
|
|
||||||
/* border: 1px solid rgba(200,164,72,0.3); */
|
|
||||||
/* border-top: 3px solid var(--ui-gold-dark); */
|
|
||||||
padding: 1.75rem 2rem;
|
padding: 1.75rem 2rem;
|
||||||
|
box-shadow: 0 4px 16px rgba(0,0,0,0.18);
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -408,22 +404,16 @@ a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
/* ── Login card (§11) ───────────────────────────────────────────────── */
|
/* ── Login card (§11) ───────────────────────────────────────────────── */
|
||||||
.login-card {
|
.login-card {
|
||||||
background: var(--ui-parchment);
|
width: 340px;
|
||||||
|
margin-top: 5vh;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 20px 60px rgba(0,0,0,0.55),
|
|
||||||
0 0 3px 3px rgba(42,21,8,0.9)
|
|
||||||
;
|
|
||||||
/* box-shadow:
|
|
||||||
0 20px 60px rgba(0,0,0,0.55),
|
0 20px 60px rgba(0,0,0,0.55),
|
||||||
0 0 0 1px rgba(200,164,72,0.35),
|
0 0 0 1px rgba(200,164,72,0.35),
|
||||||
0 0 0 5px rgba(42,21,8,0.9),
|
0 0 0 5px rgba(42,21,8,0.9),
|
||||||
0 0 0 6px rgba(200,164,72,0.2);
|
0 0 0 6px rgba(200,164,72,0.2);
|
||||||
*/
|
background: var(--ui-parchment);
|
||||||
/* border-top: 3px solid var(--ui-gold-dark); */
|
|
||||||
width: 340px;
|
|
||||||
margin-top: 5vh;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Decorative header — row of triangular flèches like the actual board */
|
/* Decorative header — row of triangular flèches like the actual board */
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@
|
||||||
"link_copied": "Copié !",
|
"link_copied": "Copié !",
|
||||||
"scan_qr": "ou scannez le QR code",
|
"scan_qr": "ou scannez le QR code",
|
||||||
"join_code_label": "Rejoindre par code",
|
"join_code_label": "Rejoindre par code",
|
||||||
"join_code_placeholder": "Code de la salle",
|
"join_code_placeholder": "Code de salle",
|
||||||
"share_btn": "Partager",
|
"share_btn": "Partager",
|
||||||
"nickname_modal_title": "Choisissez votre pseudo",
|
"nickname_modal_title": "Choisissez votre pseudo",
|
||||||
"nickname_modal_hint": "Vous jouerez sous le nom de :",
|
"nickname_modal_hint": "Vous jouerez sous le nom de :",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ use crate::dice::Dice;
|
||||||
use crate::game::GameState;
|
use crate::game::GameState;
|
||||||
use crate::player::Color;
|
use crate::player::Color;
|
||||||
use log::info;
|
use log::info;
|
||||||
use rand::seq::IndexedRandom;
|
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
|
@ -328,45 +327,16 @@ impl MoveRules {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if there is still a checker left outside the last quarter after the allowed_move
|
fn has_checkers_outside_last_quarter(&self) -> bool {
|
||||||
fn has_checkers_outside_last_quarter(&self, allowed_move: Option<CheckerMove>) -> bool {
|
|
||||||
// Get the unique field allowed outside the last quarter, when the firt move origin is
|
|
||||||
// outside and the destination is inside the last quarter
|
|
||||||
let one_allowed = allowed_move
|
|
||||||
.filter(|m| m.get_to() > 18)
|
|
||||||
.map(|m| m.get_from());
|
|
||||||
|
|
||||||
!self
|
!self
|
||||||
.board
|
.board
|
||||||
.get_color_fields(Color::White)
|
.get_color_fields(Color::White)
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(field, count)| *field < 19 && !(Some(*field) == one_allowed && *count == 1))
|
.filter(|(field, _count)| *field < 19)
|
||||||
.collect::<Vec<&(usize, i8)>>()
|
.collect::<Vec<&(usize, i8)>>()
|
||||||
.is_empty()
|
.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn forbid_exits(&self) -> bool {
|
|
||||||
let filtered = self
|
|
||||||
.board
|
|
||||||
.get_color_fields(Color::White)
|
|
||||||
.into_iter()
|
|
||||||
.filter(|(field, _count)| *field < 19)
|
|
||||||
.collect::<Vec<(usize, i8)>>();
|
|
||||||
let max_dice = if self.dice.values.0 > self.dice.values.1 {
|
|
||||||
self.dice.values.0
|
|
||||||
} else {
|
|
||||||
self.dice.values.1
|
|
||||||
};
|
|
||||||
match filtered[..] {
|
|
||||||
// all checkers in the last jan, exits are possible
|
|
||||||
[] => false,
|
|
||||||
// if there is only one checker outside the last jan, and it can go to the last jan with
|
|
||||||
// one of the dice, an exit is possible with the other dice.
|
|
||||||
[(field, 1)] if field + (max_dice as usize) > 18 => false,
|
|
||||||
_ => true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_exit_rules(
|
fn check_exit_rules(
|
||||||
&self,
|
&self,
|
||||||
moves: &(CheckerMove, CheckerMove),
|
moves: &(CheckerMove, CheckerMove),
|
||||||
|
|
@ -375,8 +345,8 @@ impl MoveRules {
|
||||||
if !moves.0.is_exit() && !moves.1.is_exit() {
|
if !moves.0.is_exit() && !moves.1.is_exit() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// all checkers must be in the return jan
|
// toutes les dames doivent être dans le jan de retour
|
||||||
if self.has_checkers_outside_last_quarter(Some(moves.0)) {
|
if self.has_checkers_outside_last_quarter() {
|
||||||
return Err(MoveError::ExitNeedsAllCheckersOnLastQuarter);
|
return Err(MoveError::ExitNeedsAllCheckersOnLastQuarter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,7 +584,7 @@ impl MoveRules {
|
||||||
) -> Vec<(CheckerMove, CheckerMove)> {
|
) -> Vec<(CheckerMove, CheckerMove)> {
|
||||||
let mut moves_seqs = Vec::new();
|
let mut moves_seqs = Vec::new();
|
||||||
let color = &Color::White;
|
let color = &Color::White;
|
||||||
let forbid_exits = self.forbid_exits();
|
let forbid_exits = self.has_checkers_outside_last_quarter();
|
||||||
// Precompute non-excedant sequences once so check_exit_rules need not repeat
|
// Precompute non-excedant sequences once so check_exit_rules need not repeat
|
||||||
// the full move generation for every exit-move candidate.
|
// the full move generation for every exit-move candidate.
|
||||||
// Only needed when Exit is not already ignored and exits are actually reachable.
|
// Only needed when Exit is not already ignored and exits are actually reachable.
|
||||||
|
|
@ -1717,46 +1687,6 @@ mod tests {
|
||||||
CheckerMove::new(23, 0).unwrap(),
|
CheckerMove::new(23, 0).unwrap(),
|
||||||
);
|
);
|
||||||
assert!(state.check_exit_rules(&moves, None).is_ok());
|
assert!(state.check_exit_rules(&moves, None).is_ok());
|
||||||
|
|
||||||
state.dice.values = (2, 6);
|
|
||||||
state.board.set_positions(
|
|
||||||
&crate::Color::White,
|
|
||||||
[
|
|
||||||
-9, -1, 0, 0, -2, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -2, 1, 0, 0, 1, 0, 1, 10, 2,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
let moves = (
|
|
||||||
CheckerMove::new(17, 23).unwrap(),
|
|
||||||
CheckerMove::new(23, 0).unwrap(),
|
|
||||||
);
|
|
||||||
assert!(state.check_exit_rules(&moves, None).is_ok());
|
|
||||||
|
|
||||||
state.dice.values = (3, 1);
|
|
||||||
state.board.set_positions(
|
|
||||||
&crate::Color::White,
|
|
||||||
[
|
|
||||||
-10, -2, 0, 0, 0, 0, -1, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 2, 1,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
let moves = (
|
|
||||||
CheckerMove::new(22, 0).unwrap(),
|
|
||||||
CheckerMove::new(24, 0).unwrap(),
|
|
||||||
);
|
|
||||||
assert!(state.check_exit_rules(&moves, None).is_ok());
|
|
||||||
|
|
||||||
// Bad exit order: the first move must be with the checker furthest from the exit
|
|
||||||
state.dice.values = (3, 1);
|
|
||||||
state.board.set_positions(
|
|
||||||
&crate::Color::White,
|
|
||||||
[
|
|
||||||
-10, -2, 0, 0, 0, 0, -1, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 3, 2, 1,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
let moves = (
|
|
||||||
CheckerMove::new(24, 0).unwrap(),
|
|
||||||
CheckerMove::new(22, 0).unwrap(),
|
|
||||||
);
|
|
||||||
assert!(state.check_exit_rules(&moves, None).is_err());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue