From ffa1de686ce4ec6e3548047a2c5a158b99dc8af3 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 29 Oct 2026 17:23:23 +0100 Subject: v2.1.1: color-code roulette numbers red and green --- Cargo.toml | 2 +- docs/GAMES.md | 3 ++ docs/TESTING.md | 4 ++- src/bin/client/repl.rs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9432fcd..08a4a3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zagan-bet" -version = "2.1.0" +version = "2.1.1" edition = "2024" [dependencies] diff --git a/docs/GAMES.md b/docs/GAMES.md index 52ab1bf..12b0e7c 100644 --- a/docs/GAMES.md +++ b/docs/GAMES.md @@ -25,6 +25,9 @@ redesign the loop first. - Bets can be split across all of those; every winning bet is added together. - Straight pays 35:1 (36x returned), outside bets pay 1:1 (2x returned). - 0 loses all outside bets. RTP is 36/37 = 97.30%. +- Numbers are color-coded in the TUI: red numbers are red, 0 is green, and + black numbers stay at the default terminal color. Bet amounts and balances + are not colored. Client controls inside roulette: diff --git a/docs/TESTING.md b/docs/TESTING.md index 2dcb01f..d944b42 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -74,7 +74,9 @@ Use an 80-column terminal because several output lines are width-sensitive. 4. Check a split result: - `17 black odd`: black+odd pay, red+even lose, straight 17 pays 36x. - `0`: all outside bets lose; a straight 0 pays 36x. -5. The result board shows the winning number/color/parity, the payout, and the +5. Numbers are color-coded: red numbers red, 0 green, black default. Check the + bets line, the rolling strip, and the winning number. +6. The result board shows the winning number/color/parity, the payout, and the new balance. The next spin reuses the placed bets. ## Manual server checks diff --git a/src/bin/client/repl.rs b/src/bin/client/repl.rs index e028cc2..f85af47 100644 --- a/src/bin/client/repl.rs +++ b/src/bin/client/repl.rs @@ -20,7 +20,7 @@ use zagan_bet::client::ui::{ visual_line_count, }; use zagan_bet::protocol::io_failure_message; -use zagan_bet::roulette::WHEEL; +use zagan_bet::roulette::{color as roulette_color, WHEEL}; use crate::connection::TlsStream; @@ -247,11 +247,22 @@ impl ClientState { execute!(stdout(), MoveUp(lines_to_move_up(self.game_lines))).unwrap(); } execute!(stdout(), MoveToColumn(0), Clear(ClearType::FromCursorDown)).unwrap(); + let roulette = lines + .first() + .is_some_and(|first| first.contains("ROULETTE")); let rendered: Vec = lines .iter() .map(|line| { if line.starts_with("===") { line.as_str().bold().cyan().to_string() + } else if roulette { + if line.starts_with("Won ") { + line.as_str().bold().green().to_string() + } else if line.starts_with("ERROR:") { + line.as_str().red().to_string() + } else { + style_roulette_numbers(line) + } } else if line.contains('{') { style_winning_cells(line) } else if line.contains("WIN!") || line.starts_with("Won ") { @@ -309,7 +320,13 @@ impl ClientState { let strip = (0..9) .map(|offset| { let index = (center - 4 + offset).rem_euclid(WHEEL.len() as isize) as usize; - format!("[ {:>2} ]", WHEEL[index]) + let number = WHEEL[index]; + let cell = format!("[ {:>2} ]", number); + match roulette_color(number) { + "red" => cell.red().to_string(), + "green" => cell.green().to_string(), + _ => cell, + } }) .collect::>() .join(" "); @@ -498,6 +515,61 @@ impl ClientState { } } +fn style_roulette_number(text: &str, number: u8) -> String { + match roulette_color(number) { + "red" => text.red().to_string(), + "green" => text.green().to_string(), + _ => text.to_string(), + } +} + +fn style_roulette_numbers(line: &str) -> String { + if line.starts_with("Bets:") { + let mut out = String::new(); + let mut rest = line; + while let Some(index) = rest.find('#') { + out.push_str(&rest[..=index]); + let after = &rest[index + 1..]; + let digits: String = after + .chars() + .take_while(|character| character.is_ascii_digit()) + .collect(); + if let Ok(number) = digits.parse::() { + if number <= 36 { + out.push_str(&style_roulette_number(&digits, number)); + } else { + out.push_str(&digits); + } + } + rest = &after[digits.len()..]; + } + out.push_str(rest); + return out; + } + + for label in ["Winning: ", "Number: "] { + if let Some(index) = line.find(label) { + let start = index + label.len(); + let digits: String = line[start..] + .chars() + .take_while(|character| character.is_ascii_digit()) + .collect(); + if let Ok(number) = digits.parse::() { + if number <= 36 { + return format!( + "{}{}{}", + &line[..start], + style_roulette_number(&digits, number), + &line[start + digits.len()..] + ); + } + } + } + } + + line.to_string() +} + fn style_winning_cells(line: &str) -> String { let chars: Vec = line.chars().collect(); let mut out = String::new(); -- cgit v1.2.3