From d9f1fe513e6f7696809d3a9b4d44ca485fe99c97 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 29 Oct 2026 17:18:34 +0100 Subject: v2.1.0: add European roulette with split bets and wheel animation --- src/bin/client/repl.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'src/bin') diff --git a/src/bin/client/repl.rs b/src/bin/client/repl.rs index 1ed3073..e028cc2 100644 --- a/src/bin/client/repl.rs +++ b/src/bin/client/repl.rs @@ -20,6 +20,7 @@ use zagan_bet::client::ui::{ visual_line_count, }; use zagan_bet::protocol::io_failure_message; +use zagan_bet::roulette::WHEEL; use crate::connection::TlsStream; @@ -150,6 +151,16 @@ impl ClientState { } } Effect::ReplaceRegion(lines) => self.draw_region(&lines), + Effect::AnimateRoulette { + winning, + final_lines, + } => { + self.animate_wheel(winning); + self.draw_region(&final_lines); + while crossterm::event::poll(std::time::Duration::ZERO).unwrap_or(false) { + let _ = crossterm::event::read(); + } + } Effect::ClearRegion => self.clear_region(), Effect::SetPrompt { text, cursor_col } => self.draw_prompt(&text, cursor_col), Effect::SendLine(line) => { @@ -276,6 +287,49 @@ impl ClientState { self.game_lines = 0; } + /// CS:GO-style wheel strip: the ball marker is fixed and the numbers move + /// left-to-right under it, ending with the winning number in the center. + fn animate_wheel(&mut self, winning: u8) { + use std::thread; + use std::time::Duration; + + let target = WHEEL + .iter() + .position(|number| *number == winning) + .unwrap_or(0) as f64; + let wheel_len = WHEEL.len() as f64; + let start = target - 4.0 * wheel_len - 7.0; + let frames = 32; + + for frame in 0..frames { + let t = frame as f64 / (frames - 1) as f64; + let ease = 1.0 - (1.0 - t).powi(3); + let center = (start + (target - start) * ease).round() as isize; + + let strip = (0..9) + .map(|offset| { + let index = (center - 4 + offset).rem_euclid(WHEEL.len() as isize) as usize; + format!("[ {:>2} ]", WHEEL[index]) + }) + .collect::>() + .join(" "); + let marker = format!("{}▼", " ".repeat(4 * 7 + 3)); + let lines = vec![ + "=== ROULETTE ===".to_string(), + strip, + marker, + "Spinning...".to_string(), + ]; + + self.draw_region(&lines); + thread::sleep(Duration::from_millis(35)); + } + + // Let the winning number sit under the static ball before the result + // board replaces the wheel. + thread::sleep(Duration::from_millis(450)); + } + fn draw_prompt(&mut self, text: &str, cursor_col: u16) { execute!(stdout(), MoveToColumn(0), Clear(ClearType::CurrentLine)).unwrap(); print!("{}", "> ".cyan()); -- cgit v1.2.3