diff --git a/client_web/Cargo.toml b/client_web/Cargo.toml index 10d91b8..e911eaf 100644 --- a/client_web/Cargo.toml +++ b/client_web/Cargo.toml @@ -34,5 +34,4 @@ web-sys = { version = "0.3", features = [ "OscillatorNode", "OscillatorType", "BaseAudioContext", - "HtmlAudioElement", ] } diff --git a/client_web/assets/diceroll.mp3 b/client_web/assets/diceroll.mp3 deleted file mode 100644 index b16adff..0000000 Binary files a/client_web/assets/diceroll.mp3 and /dev/null differ diff --git a/client_web/assets/style.css b/client_web/assets/style.css index 9b80fbb..3691894 100644 --- a/client_web/assets/style.css +++ b/client_web/assets/style.css @@ -1131,63 +1131,3 @@ body { flex-wrap: wrap; min-height: 2rem; /* reserve height so layout doesn't shift when buttons appear */ } - -/* ── Pre-game ceremony overlay ──────────────────────────────────────────── */ -.ceremony-overlay { - position: fixed; - inset: 0; - background: rgba(0,0,0,0.65); - display: flex; - align-items: center; - justify-content: center; - z-index: 100; -} - -.ceremony-box { - background: var(--ui-parchment); - border-radius: 8px; - padding: 2.5rem 3rem; - text-align: center; - box-shadow: 0 12px 40px rgba(0,0,0,0.5), 0 0 0 2px var(--ui-gold-dark); - display: flex; - flex-direction: column; - align-items: center; - gap: 1.4rem; - min-width: 300px; - animation: game-over-appear 0.4s cubic-bezier(0.22, 0.61, 0.36, 1); -} - -.ceremony-box h2 { - font-family: var(--font-display); - font-size: 1.8rem; - font-weight: 600; - color: var(--ui-ink); - letter-spacing: 0.06em; -} - -.ceremony-dice { - display: flex; - gap: 3rem; - align-items: flex-end; -} - -.ceremony-die-slot { - display: flex; - flex-direction: column; - align-items: center; - gap: 0.5rem; -} - -.ceremony-die-label { - font-family: var(--font-ui); - font-size: 0.85rem; - color: var(--ui-ink); - font-weight: 500; -} - -.ceremony-tie { - font-family: var(--font-display); - font-size: 1rem; - color: var(--ui-red-accent); - font-style: italic; -} diff --git a/client_web/index.html b/client_web/index.html index 7399dbc..b661d76 100644 --- a/client_web/index.html +++ b/client_web/index.html @@ -6,7 +6,6 @@ Trictrac - diff --git a/client_web/locales/en.json b/client_web/locales/en.json index c29121d..f390ce4 100644 --- a/client_web/locales/en.json +++ b/client_web/locales/en.json @@ -42,12 +42,6 @@ "after_opponent_roll": "Opponent rolled", "after_opponent_go": "Opponent chose to continue", "after_opponent_move": "Opponent moved — your turn", - "after_opponent_pre_game_roll": "Opponent rolled — your turn", - "pre_game_roll_title": "Who goes first?", - "pre_game_roll_btn": "Roll", - "pre_game_roll_tie": "Tie! Roll again", - "pre_game_roll_your_die": "Your die", - "pre_game_roll_opp_die": "Opponent's die", "continue_btn": "Continue", "scored_pts": "+{{ n }} pts", "hole_made": "Hole! {{ holes }}/12", diff --git a/client_web/locales/fr.json b/client_web/locales/fr.json index 93f76e5..910d7c0 100644 --- a/client_web/locales/fr.json +++ b/client_web/locales/fr.json @@ -42,12 +42,6 @@ "after_opponent_roll": "L'adversaire a lancé les dés", "after_opponent_go": "L'adversaire s'en va", "after_opponent_move": "L'adversaire a joué — à vous", - "after_opponent_pre_game_roll": "L'adversaire a lancé — à vous", - "pre_game_roll_title": "Qui joue en premier ?", - "pre_game_roll_btn": "Lancer", - "pre_game_roll_tie": "Égalité ! Relancez", - "pre_game_roll_your_die": "Votre dé", - "pre_game_roll_opp_die": "Dé adverse", "continue_btn": "Continuer", "scored_pts": "+{{ n }} pts", "hole_made": "Trou ! {{ holes }}/12", diff --git a/client_web/src/app.rs b/client_web/src/app.rs index cebdb17..aa86ca8 100644 --- a/client_web/src/app.rs +++ b/client_web/src/app.rs @@ -13,7 +13,7 @@ use crate::i18n::I18nContextProvider; use crate::trictrac::backend::TrictracBackend; use crate::trictrac::bot_local::bot_decide; use crate::trictrac::types::{ - GameDelta, JanEntry, PlayerAction, ScoredEvent, SerStage, SerTurnStage, ViewState, + GameDelta, JanEntry, PlayerAction, ScoredEvent, SerTurnStage, ViewState, }; use trictrac_store::CheckerMove; @@ -48,8 +48,6 @@ pub enum PauseReason { AfterOpponentRoll, AfterOpponentGo, AfterOpponentMove, - /// Opponent rolled their die in the pre-game ceremony. - AfterOpponentPreGameRoll, } /// Which screen is currently shown. @@ -384,35 +382,32 @@ async fn run_local_bot_game( } loop { - let pgr = backend.get_view_state().pre_game_roll.clone(); - match bot_decide(backend.get_game(), pgr.as_ref()) { + match bot_decide(backend.get_game()) { None => break, Some(action) => { + let prev_vs = vs.clone(); backend.inform_rpc(1, action); - // Process each delta individually so intermediate ceremony - // states (both dice shown) can trigger a pause via push_or_show. for cmd in backend.drain_commands() { if let BackendCommand::Delta(delta) = cmd { - let delta_prev_vs = vs.clone(); vs.apply_delta(&delta); - push_or_show( - &delta_prev_vs, - GameUiState { - view_state: vs.clone(), - player_id: 0, - room_id: String::new(), - is_bot_game: true, - waiting_for_confirm: false, - pause_reason: None, - my_scored_event: None, - opp_scored_event: None, - last_moves: compute_last_moves(&delta_prev_vs, &vs), - }, - pending, - screen, - ); } } + push_or_show( + &prev_vs, + GameUiState { + view_state: vs.clone(), + player_id: 0, + room_id: String::new(), + is_bot_game: true, + waiting_for_confirm: false, + pause_reason: None, + my_scored_event: None, + opp_scored_event: None, + last_moves: compute_last_moves(&prev_vs, &vs), + }, + pending, + screen, + ); } } } @@ -535,24 +530,6 @@ fn push_or_show( fn infer_pause_reason(prev: &ViewState, next: &ViewState, player_id: u16) -> Option { let opponent_id = 1 - player_id; - // Pre-game ceremony: pause when both dice are revealed simultaneously - // (i.e. the second die was just rolled). Both players see this pause. - if next.stage == SerStage::PreGameRoll { - if let (Some(prev_pgr), Some(next_pgr)) = (&prev.pre_game_roll, &next.pre_game_roll) { - let both_now = next_pgr.host_die.is_some() && next_pgr.guest_die.is_some(); - let both_before = prev_pgr.host_die.is_some() && prev_pgr.guest_die.is_some(); - if both_now && !both_before { - return Some(PauseReason::AfterOpponentPreGameRoll); - } - } - return None; - } - - // Don't fire normal pause rules on the PreGameRoll → InGame transition. - if prev.stage == SerStage::PreGameRoll { - return None; - } - if next.active_mp_player == Some(opponent_id) { // Dice changed → opponent just rolled. if next.dice != prev.dice { @@ -597,7 +574,6 @@ mod tests { dice, dice_jans: Vec::new(), dice_moves: (CheckerMove::default(), CheckerMove::default()), - pre_game_roll: None, } } diff --git a/client_web/src/components/game_screen.rs b/client_web/src/components/game_screen.rs index a94194f..24042be 100644 --- a/client_web/src/components/game_screen.rs +++ b/client_web/src/components/game_screen.rs @@ -7,8 +7,7 @@ use trictrac_store::{Board as StoreBoard, CheckerMove, Color, Dice as StoreDice, use crate::app::{GameUiState, NetCommand, PauseReason}; use crate::i18n::*; -use crate::trictrac::types::{PlayerAction, PreGameRollState, SerStage, SerTurnStage}; -use super::die::Die; +use crate::trictrac::types::{PlayerAction, SerStage, SerTurnStage}; use super::board::Board; use super::score_panel::PlayerScorePanel; @@ -79,11 +78,7 @@ pub fn GameScreen(state: GameUiState) -> impl IntoView { // Guard: suppressed while waiting_for_confirm — the AfterOpponentMove // buffered state shows the human's RollDice turn but the auto-roll must // wait until the buffer is drained and the live screen state is shown. - // Guard: never auto-roll during the pre-game ceremony (the ceremony overlay - // has its own Roll button for PlayerAction::PreGameRoll). - let show_roll = is_my_turn - && vs.turn_stage == SerTurnStage::RollDice - && vs.stage != SerStage::PreGameRoll; + let show_roll = is_my_turn && vs.turn_stage == SerTurnStage::RollDice; if show_roll && !waiting_for_confirm { let cmd_tx_auto = cmd_tx.clone(); Effect::new(move |_| { @@ -137,13 +132,6 @@ pub fn GameScreen(state: GameUiState) -> impl IntoView { let my_score = vs.scores[player_id as usize].clone(); let opp_score = vs.scores[1 - player_id as usize].clone(); - // ── Ceremony state (extracted before vs is moved into Board) ──────────────── - let is_ceremony = vs.stage == SerStage::PreGameRoll; - let pre_game_roll_data: Option = vs.pre_game_roll.clone(); - let my_name_ceremony = my_score.name.clone(); - let opp_name_ceremony = opp_score.name.clone(); - let cmd_tx_ceremony = cmd_tx.clone(); - // ── Scoring notifications ────────────────────────────────────────────────── let my_scored_event = state.my_scored_event.clone(); let opp_scored_event = state.opp_scored_event.clone(); @@ -191,7 +179,7 @@ pub fn GameScreen(state: GameUiState) -> impl IntoView { // ── Sound effects (fire once on mount = once per state snapshot) ────────── // Dice roll: dice just appeared (no preceding moves in this snapshot). if show_dice && last_moves.is_none() { - crate::sound::play_dice_roll(); + crate::sound::play_dice_roll_cinematic(); } // Checker move: moves were committed in the preceding action. if last_moves.is_some() { @@ -258,7 +246,6 @@ pub fn GameScreen(state: GameUiState) -> impl IntoView { PauseReason::AfterOpponentRoll => t_string!(i18n, after_opponent_roll), PauseReason::AfterOpponentGo => t_string!(i18n, after_opponent_go), PauseReason::AfterOpponentMove => t_string!(i18n, after_opponent_move), - PauseReason::AfterOpponentPreGameRoll => t_string!(i18n, after_opponent_pre_game_roll), }); } let n = staged_moves.get().len(); @@ -267,7 +254,7 @@ pub fn GameScreen(state: GameUiState) -> impl IntoView { } else { String::from(match (&stage, is_my_turn, &turn_stage) { (SerStage::Ended, _, _) => t_string!(i18n, game_over), - (SerStage::PreGame, _, _) | (SerStage::PreGameRoll, _, _) => t_string!(i18n, waiting_for_opponent), + (SerStage::PreGame, _, _) => t_string!(i18n, waiting_for_opponent), (SerStage::InGame, true, SerTurnStage::RollDice) => t_string!(i18n, your_turn_roll), (SerStage::InGame, true, SerTurnStage::HoldOrGoChoice) => t_string!(i18n, hold_or_go), (SerStage::InGame, true, _) => t_string!(i18n, your_turn), @@ -365,55 +352,6 @@ pub fn GameScreen(state: GameUiState) -> impl IntoView { // ── Player score (below board) ──────────────────────────────────── - // ── Pre-game ceremony overlay ───────────────────────────────────── - {is_ceremony.then(|| { - let pgr = pre_game_roll_data.unwrap_or(PreGameRollState { - host_die: None, - guest_die: None, - tie_count: 0, - }); - let my_die = if player_id == 0 { pgr.host_die } else { pgr.guest_die }; - let opp_die = if player_id == 0 { pgr.guest_die } else { pgr.host_die }; - let can_roll = is_my_turn && !waiting_for_confirm; - let show_tie = pgr.tie_count > 0; - view! { -
-
-

{t!(i18n, pre_game_roll_title)}

- {show_tie.then(|| view! { -

{t!(i18n, pre_game_roll_tie)}

- })} -
-
- {my_name_ceremony} - -
-
- {opp_name_ceremony} - -
-
- {waiting_for_confirm.then(|| { - let pending_c = pending; - view! { - - } - })} - {can_roll.then(|| { - let cmd_tx_c = cmd_tx_ceremony.clone(); - view! { - - } - })} -
-
- } - })} - // ── Game-over overlay ───────────────────────────────────────────── {stage_is_ended.then(|| { let opp_name_end_clone = opp_name_end.clone(); diff --git a/client_web/src/sound.rs b/client_web/src/sound.rs index 2de584a..4e2c815 100644 --- a/client_web/src/sound.rs +++ b/client_web/src/sound.rs @@ -128,13 +128,6 @@ mod inner { }); } - /// Play the pre-recorded dice-roll MP3 asset. - pub fn play_dice_roll() { - if let Ok(audio) = web_sys::HtmlAudioElement::new_with_src("/diceroll.mp3") { - let _ = audio.play(); - } - } - /// Ascending three-note chime (C5 – E5 – G5). pub fn play_points_scored() { with_ctx(|ctx| { @@ -165,15 +158,12 @@ mod inner { #[cfg(target_arch = "wasm32")] pub use inner::{ - play_checker_move, play_dice_roll, play_dice_roll_cinematic, play_hole_scored, - play_points_scored, + play_checker_move, play_dice_roll_cinematic, play_hole_scored, play_points_scored, }; #[cfg(not(target_arch = "wasm32"))] pub fn play_checker_move() {} #[cfg(not(target_arch = "wasm32"))] -pub fn play_dice_roll() {} -#[cfg(not(target_arch = "wasm32"))] pub fn play_dice_roll_cinematic() {} #[cfg(not(target_arch = "wasm32"))] pub fn play_points_scored() {} diff --git a/client_web/src/trictrac/backend.rs b/client_web/src/trictrac/backend.rs index 288f5e7..486c3b9 100644 --- a/client_web/src/trictrac/backend.rs +++ b/client_web/src/trictrac/backend.rs @@ -1,7 +1,7 @@ use backbone_lib::traits::{BackEndArchitecture, BackendCommand}; use trictrac_store::{DiceRoller, GameEvent, GameState, TurnStage}; -use crate::trictrac::types::{GameDelta, PlayerAction, PreGameRollState, SerStage, ViewState}; +use crate::trictrac::types::{GameDelta, PlayerAction, ViewState}; // Store PlayerId (u64) values used for the two players. const HOST_PLAYER_ID: u64 = 1; @@ -14,32 +14,11 @@ pub struct TrictracBackend { view_state: ViewState, /// Arrival flags: have host (index 0) and guest (index 1) joined? arrived: [bool; 2], - /// Die rolled by each player during the ceremony ([host, guest]). - pre_game_dice: [Option; 2], - /// Number of tied rounds so far. - tie_count: u8, - /// True while the first-player ceremony is running. - ceremony_started: bool, } impl TrictracBackend { fn sync_view_state(&mut self) { - let mut vs = ViewState::from_game_state(&self.game, HOST_PLAYER_ID, GUEST_PLAYER_ID); - if self.ceremony_started { - vs.stage = SerStage::PreGameRoll; - vs.pre_game_roll = Some(PreGameRollState { - host_die: self.pre_game_dice[0], - guest_die: self.pre_game_dice[1], - tie_count: self.tie_count, - }); - // The active mp player is whoever hasn't rolled yet (host rolls first). - vs.active_mp_player = match self.pre_game_dice { - [None, _] => Some(0), - [Some(_), None] => Some(1), - _ => None, - }; - } - self.view_state = vs; + self.view_state = ViewState::from_game_state(&self.game, HOST_PLAYER_ID, GUEST_PLAYER_ID); } fn broadcast_state(&mut self) { @@ -50,42 +29,6 @@ impl TrictracBackend { self.commands.push(BackendCommand::Delta(delta)); } - /// Process one ceremony die-roll for `mp_player` (0 = host, 1 = guest). - fn handle_pre_game_roll(&mut self, mp_player: u16) { - // Enforce turn order: host rolls first, then guest. - let expected: u16 = match self.pre_game_dice { - [None, _] => 0, - [Some(_), None] => 1, - _ => return, // both already rolled (shouldn't happen) - }; - if mp_player != expected { - return; - } - let idx = mp_player as usize; - let single = self.dice_roller.roll().values.0; - self.pre_game_dice[idx] = Some(single); - - if let [Some(h), Some(g)] = self.pre_game_dice { - // Both have rolled — broadcast both dice before resolving. - self.broadcast_state(); - if h == g { - // Tie: reset for another round. - self.tie_count += 1; - self.pre_game_dice = [None; 2]; - self.broadcast_state(); - } else { - // Highest die goes first. - let goes_first = if h > g { HOST_PLAYER_ID } else { GUEST_PLAYER_ID }; - self.ceremony_started = false; - let _ = self.game.consume(&GameEvent::BeginGame { goes_first }); - self.broadcast_state(); - } - } else { - // Only one die rolled so far — broadcast the partial result. - self.broadcast_state(); - } - } - /// Roll dice using the store's DiceRoller and fire Roll + RollResult events. fn do_roll(&mut self) { let dice = self.dice_roller.roll(); @@ -143,9 +86,6 @@ impl BackEndArchitecture for TrictracBackend commands: Vec::new(), view_state, arrived: [false; 2], - pre_game_dice: [None; 2], - tie_count: 0, - ceremony_started: false, } } @@ -170,13 +110,11 @@ impl BackEndArchitecture for TrictracBackend timer_id: mp_player, }); - // Start the ceremony once both players have arrived. - if self.arrived[0] && self.arrived[1] && self.game.stage == trictrac_store::Stage::PreGame - && !self.ceremony_started - { - self.ceremony_started = true; - self.pre_game_dice = [None; 2]; - self.tie_count = 0; + // Start the game once both players have arrived. + if self.arrived[0] && self.arrived[1] && self.game.stage == trictrac_store::Stage::PreGame { + let _ = self.game.consume(&GameEvent::BeginGame { + goes_first: HOST_PLAYER_ID, + }); self.sync_view_state(); self.commands.push(BackendCommand::ResetViewState); } else { @@ -197,14 +135,6 @@ impl BackEndArchitecture for TrictracBackend } fn inform_rpc(&mut self, mp_player: u16, action: PlayerAction) { - // During the first-player ceremony only PreGameRoll actions are accepted. - if self.ceremony_started { - if matches!(action, PlayerAction::PreGameRoll) { - self.handle_pre_game_roll(mp_player); - } - return; - } - if self.game.stage == trictrac_store::Stage::Ended { return; } @@ -237,6 +167,8 @@ impl BackEndArchitecture for TrictracBackend moves: (m1, m2), }; if self.game.validate(&event) { + let message = format!("Event {:?} validated on {:?}", event, self.game); + console_log(message); let _ = self.game.consume(&event); self.drive_automatic_stages(); } @@ -256,7 +188,6 @@ impl BackEndArchitecture for TrictracBackend self.drive_automatic_stages(); } } - PlayerAction::PreGameRoll => {} // ignored outside ceremony } self.broadcast_state(); @@ -285,7 +216,6 @@ impl BackEndArchitecture for TrictracBackend mod tests { use super::*; use backbone_lib::traits::BackEndArchitecture; - use crate::trictrac::types::{SerStage, SerTurnStage}; fn make_backend() -> TrictracBackend { TrictracBackend::new(0) @@ -303,65 +233,26 @@ mod tests { .collect() } - /// Drive the ceremony to completion (both players roll until one wins). - fn complete_ceremony(b: &mut TrictracBackend) { - loop { - if b.get_view_state().stage != SerStage::PreGameRoll { - break; - } - match b.get_view_state().active_mp_player { - Some(0) => b.inform_rpc(0, PlayerAction::PreGameRoll), - Some(1) => b.inform_rpc(1, PlayerAction::PreGameRoll), - _ => break, - } - b.drain_commands(); - } - } - #[test] - fn both_players_arrive_starts_ceremony() { + fn both_players_arrive_starts_game() { let mut b = make_backend(); b.player_arrival(0); // host b.drain_commands(); b.player_arrival(1); // guest let cmds = b.drain_commands(); - // ResetViewState should have been issued to start the ceremony. + // ResetViewState should have been issued after BeginGame. let has_reset = cmds .iter() .any(|c| matches!(c, BackendCommand::ResetViewState)); - assert!(has_reset, "expected ResetViewState after both players arrive"); - - // Stage should now be PreGameRoll, not InGame. - assert_eq!(b.get_view_state().stage, SerStage::PreGameRoll); - } - - #[test] - fn ceremony_resolves_to_in_game() { - let mut b = make_backend(); - b.player_arrival(0); - b.player_arrival(1); - b.drain_commands(); - - complete_ceremony(&mut b); - - assert_eq!(b.get_view_state().stage, SerStage::InGame); - } - - #[test] - fn ceremony_wrong_order_ignored() { - let mut b = make_backend(); - b.player_arrival(0); - b.player_arrival(1); - b.drain_commands(); - - // Guest tries to roll before host (host goes first in ceremony). - b.inform_rpc(1, PlayerAction::PreGameRoll); - let cmds = b.drain_commands(); assert!( - cmds.is_empty(), - "guest PreGameRoll should be ignored when it is host's turn" + has_reset, + "expected ResetViewState after both players arrive" ); + + // Game should now be InGame. + use crate::trictrac::types::SerStage; + assert_eq!(b.get_view_state().stage, SerStage::InGame); } #[test] @@ -381,15 +272,12 @@ mod tests { b.player_arrival(1); b.drain_commands(); - // Complete ceremony before rolling. - complete_ceremony(&mut b); - - // Roll for whoever won the ceremony (either player could go first). - let first_player = b.get_view_state().active_mp_player.expect("someone should be active"); - b.inform_rpc(first_player, PlayerAction::Roll); + // Host rolls (player_id 0, whose store id == HOST_PLAYER_ID == active after BeginGame). + b.inform_rpc(0, PlayerAction::Roll); let states = drain_deltas(&mut b); assert!(!states.is_empty(), "expected a state broadcast after roll"); + use crate::trictrac::types::SerTurnStage; let last = states.last().unwrap(); assert!( matches!( @@ -410,16 +298,13 @@ mod tests { b.player_arrival(0); b.player_arrival(1); b.drain_commands(); - complete_ceremony(&mut b); - // Identify who goes first and have the OTHER player try to roll. - let active = b.get_view_state().active_mp_player; - let wrong_player = if active == Some(0) { 1u16 } else { 0u16 }; - b.inform_rpc(wrong_player, PlayerAction::Roll); + // Guest tries to roll when it's the host's turn. + b.inform_rpc(1, PlayerAction::Roll); let cmds = b.drain_commands(); assert!( cmds.is_empty(), - "wrong player roll should be ignored" + "guest roll should be ignored when it's host's turn" ); } diff --git a/client_web/src/trictrac/bot_local.rs b/client_web/src/trictrac/bot_local.rs index 73658ca..9b379c8 100644 --- a/client_web/src/trictrac/bot_local.rs +++ b/client_web/src/trictrac/bot_local.rs @@ -1,22 +1,12 @@ use rand::prelude::IndexedRandom; use trictrac_store::{CheckerMove, Color, GameState, MoveRules, Stage, TurnStage}; -use crate::trictrac::types::{PlayerAction, PreGameRollState}; +use crate::trictrac::types::PlayerAction; const GUEST_PLAYER_ID: u64 = 2; /// Returns the next action for the bot (mp_player 1 / guest), or None if it is not the bot's turn. -/// `pgr` is the current pre-game ceremony state if the ceremony is in progress. -pub fn bot_decide(game: &GameState, pgr: Option<&PreGameRollState>) -> Option { - // During the ceremony, the bot (guest) rolls when its die is missing. - if game.stage == Stage::PreGame { - if let Some(pgr) = pgr { - if pgr.guest_die.is_none() { - return Some(PlayerAction::PreGameRoll); - } - } - return None; - } +pub fn bot_decide(game: &GameState) -> Option { if game.stage == Stage::Ended { return None; } @@ -25,7 +15,7 @@ pub fn bot_decide(game: &GameState, pgr: Option<&PreGameRollState>) -> Option Some(PlayerAction::Roll), - TurnStage::HoldOrGoChoice => Some(PlayerAction::Go), + TurnStage::HoldOrGoChoice => Some(PlayerAction::Mark), TurnStage::Move => { let rules = MoveRules::new(&Color::Black, &game.board, game.dice); let sequences = rules.get_possible_moves_sequences(true, vec![]); diff --git a/client_web/src/trictrac/types.rs b/client_web/src/trictrac/types.rs index b6f43da..f431482 100644 --- a/client_web/src/trictrac/types.rs +++ b/client_web/src/trictrac/types.rs @@ -14,8 +14,6 @@ pub enum PlayerAction { Go, /// Acknowledge point marking (hold / advance points). Mark, - /// Roll a single die during the pre-game ceremony to decide who goes first. - PreGameRoll, } // ── Incremental state update broadcast to all clients ──────────────────────── @@ -29,18 +27,6 @@ pub struct GameDelta { // ── Full game snapshot ──────────────────────────────────────────────────────── -/// State of the pre-game ceremony where each player rolls one die to decide -/// who goes first. Present only when `stage == SerStage::PreGameRoll`. -#[derive(Clone, PartialEq, Serialize, Deserialize)] -pub struct PreGameRollState { - /// Die value (1–6) rolled by the host; `None` = not yet rolled this round. - pub host_die: Option, - /// Die value (1–6) rolled by the guest; `None` = not yet rolled this round. - pub guest_die: Option, - /// Number of tied rounds so far (0 on the first round). - pub tie_count: u8, -} - #[derive(Clone, PartialEq, Serialize, Deserialize)] pub struct ViewState { /// Board positions: index i = field i+1. Positive = white, negative = black. @@ -57,9 +43,6 @@ pub struct ViewState { pub dice_jans: Vec, /// Last two checker moves played; default when no move has occurred yet. pub dice_moves: (CheckerMove, CheckerMove), - /// Present while the pre-game ceremony is in progress. - #[serde(default)] - pub pre_game_roll: Option, } /// One scoring event from a dice roll. @@ -103,7 +86,6 @@ impl ViewState { dice: (0, 0), dice_jans: Vec::new(), dice_moves: (CheckerMove::default(), CheckerMove::default()), - pre_game_roll: None, } } @@ -202,7 +184,6 @@ impl ViewState { dice: (gs.dice.values.0, gs.dice.values.1), dice_jans, dice_moves: gs.dice_moves, - pre_game_roll: None, } } } @@ -239,8 +220,6 @@ pub struct PlayerScore { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum SerStage { PreGame, - /// Both players have arrived; ceremony in progress to decide who goes first. - PreGameRoll, InGame, Ended, }