diff --git a/clients/web/assets/style.css b/clients/web/assets/style.css index d00a72a..001076e 100644 --- a/clients/web/assets/style.css +++ b/clients/web/assets/style.css @@ -121,15 +121,11 @@ body { .portal-card { background: var(--ui-parchment); - border-radius: 8px; - box-shadow: - 0 20px 60px rgba(0,0,0,0.55), - 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); */ + border: 1px solid rgba(200,164,72,0.3); + border-top: 3px solid var(--ui-gold-dark); + border-radius: 6px; padding: 1.75rem 2rem; + box-shadow: 0 4px 16px rgba(0,0,0,0.18); margin-bottom: 1.5rem; } @@ -408,22 +404,16 @@ a:hover { text-decoration: underline; } /* ── Login card (§11) ───────────────────────────────────────────────── */ .login-card { - background: var(--ui-parchment); - border-radius: 8px; - 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 0 0 1px rgba(200,164,72,0.35), - 0 0 0 5px rgba(42,21,8,0.9), - 0 0 0 6px rgba(200,164,72,0.2); - */ - /* border-top: 3px solid var(--ui-gold-dark); */ width: 340px; margin-top: 5vh; + border-radius: 8px; overflow: hidden; + box-shadow: + 0 20px 60px rgba(0,0,0,0.55), + 0 0 0 1px rgba(200,164,72,0.35), + 0 0 0 5px rgba(42,21,8,0.9), + 0 0 0 6px rgba(200,164,72,0.2); + background: var(--ui-parchment); } /* Decorative header — row of triangular flèches like the actual board */ diff --git a/clients/web/locales/fr.json b/clients/web/locales/fr.json index 7ef3257..b22a69a 100644 --- a/clients/web/locales/fr.json +++ b/clients/web/locales/fr.json @@ -120,7 +120,7 @@ "link_copied": "Copié !", "scan_qr": "ou scannez le QR code", "join_code_label": "Rejoindre par code", - "join_code_placeholder": "Code de la salle", + "join_code_placeholder": "Code de salle", "share_btn": "Partager", "nickname_modal_title": "Choisissez votre pseudo", "nickname_modal_hint": "Vous jouerez sous le nom de :", diff --git a/store/src/game_rules_moves.rs b/store/src/game_rules_moves.rs index 02d3115..e5af72b 100644 --- a/store/src/game_rules_moves.rs +++ b/store/src/game_rules_moves.rs @@ -4,7 +4,6 @@ use crate::dice::Dice; use crate::game::GameState; use crate::player::Color; use log::info; -use rand::seq::IndexedRandom; use std::cmp; use std::collections::HashSet; @@ -328,45 +327,16 @@ impl MoveRules { Ok(()) } - // check if there is still a checker left outside the last quarter after the allowed_move - fn has_checkers_outside_last_quarter(&self, allowed_move: Option) -> 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()); - + fn has_checkers_outside_last_quarter(&self) -> bool { !self .board .get_color_fields(Color::White) .iter() - .filter(|(field, count)| *field < 19 && !(Some(*field) == one_allowed && *count == 1)) + .filter(|(field, _count)| *field < 19) .collect::>() .is_empty() } - fn forbid_exits(&self) -> bool { - let filtered = self - .board - .get_color_fields(Color::White) - .into_iter() - .filter(|(field, _count)| *field < 19) - .collect::>(); - 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( &self, moves: &(CheckerMove, CheckerMove), @@ -375,8 +345,8 @@ impl MoveRules { if !moves.0.is_exit() && !moves.1.is_exit() { return Ok(()); } - // all checkers must be in the return jan - if self.has_checkers_outside_last_quarter(Some(moves.0)) { + // toutes les dames doivent être dans le jan de retour + if self.has_checkers_outside_last_quarter() { return Err(MoveError::ExitNeedsAllCheckersOnLastQuarter); } @@ -614,7 +584,7 @@ impl MoveRules { ) -> Vec<(CheckerMove, CheckerMove)> { let mut moves_seqs = Vec::new(); 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 // the full move generation for every exit-move candidate. // Only needed when Exit is not already ignored and exits are actually reachable. @@ -1717,46 +1687,6 @@ mod tests { CheckerMove::new(23, 0).unwrap(), ); 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]