diff options
| -rw-r--r-- | src/game.rs | 44 | ||||
| -rw-r--r-- | src/player.rs | 39 |
2 files changed, 77 insertions, 6 deletions
diff --git a/src/game.rs b/src/game.rs index 716446d..74b96e5 100644 --- a/src/game.rs +++ b/src/game.rs @@ -212,14 +212,15 @@ impl GameHandler Some(o) => { let block = panel().title_bottom(" Game over "); - let result = match o + // A win in green, a draw in yellow + let (result, colour) = match o { - Outcome::Tiger => format!("{} win!", side_name(Turn::Tiger)), - Outcome::Sheep => format!("{} win!", side_name(Turn::Sheep)), - Outcome::Draw => "Draw by repetition!".to_string(), + Outcome::Tiger => (format!("{} ({}) win!", side_name(Turn::Tiger), players[1].name()), Color::Green), + Outcome::Sheep => (format!("{} ({}) win!", side_name(Turn::Sheep), players[0].name()), Color::Green), + Outcome::Draw => ("Draw by repetition!".to_string(), Color::Yellow), }; let text = vec![ - Line::styled(result, Style::new().add_modifier(Modifier::BOLD)), + Line::styled(result, Style::new().fg(colour).add_modifier(Modifier::BOLD)), Line::from("Click a move to revert to it, or press q to quit."), ]; frame.render_widget(Paragraph::new(text).block(block), current_pane); @@ -498,5 +499,38 @@ mod tests let terminal = draw(&mut game, &[&mut sheep, &mut tiger]); let screen = format!("{:?}", terminal.backend().buffer()); assert!(screen.contains("Draw by repetition!"), "{screen}"); + assert_result_style(&terminal, "Draw by repetition!", Color::Yellow); + } + + #[test] + fn game_over_panel_shows_the_winner_in_green() + { + // Only 15 sheep left, so the tigers have won + let mut game = movement_game(); + game.start.set((0, 1), PieceType::Empty); + assert_eq!(game.outcome(), Some(Outcome::Tiger)); + let mut sheep = LocalPlayer::default(); + let mut tiger = ClaudePlayer::new(std::time::Duration::from_millis(50)); + let terminal = draw(&mut game, &[&mut sheep, &mut tiger]); + assert_result_style(&terminal, "Tigers (Claude) win!", Color::Green); + } + + /// Every cell of `text` on screen is bold and in `colour`. + fn assert_result_style(terminal: &Terminal<TestBackend>, text: &str, colour: Color) + { + let buf = terminal.backend().buffer(); + let area = buf.area; + let found = (0..area.height).find_map(|y| + { + let row: String = (0..area.width).map(|x| buf[(x, y)].symbol()).collect(); + row.find(text).map(|i| (row[..i].chars().count() as u16, y)) + }); + let (x0, y) = found.unwrap_or_else(|| panic!("{text} isn't on screen")); + for x in x0..x0 + text.chars().count() as u16 + { + let cell = &buf[(x, y)]; + assert_eq!(cell.fg, colour, "{text} at column {x}"); + assert!(cell.modifier.contains(Modifier::BOLD), "{text} at column {x}"); + } } } diff --git a/src/player.rs b/src/player.rs index 1766d24..4ac7a10 100644 --- a/src/player.rs +++ b/src/player.rs @@ -581,7 +581,7 @@ impl<P: MinimaxPlayer> Player for P } else { - format!("{:+.1} (+ favours tigers)", r.score) + format!("{} (+ favours tigers)", significant(r.score, 5)) }; Paragraph::new(format!("Played {}\nSearched to depth {}\nScore: {score}", r.mv, r.depth)) .wrap(Wrap { trim: true }).render(area, buf); @@ -589,12 +589,49 @@ impl<P: MinimaxPlayer> Player for P } +/// `x` to `digits` significant figures, with its sign: 1234.5678 to 5 is "+1234.6", 0.012345678 +/// is "+0.012346", and 1234567 is "+1234600". +fn significant(x: f32, digits: usize) -> String +{ + if x == 0.0 + { + return format!("{:.*}", digits.saturating_sub(1), 0.0); + } + // The power of ten of the first significant digit + let magnitude = (x.abs() as f64).log10().floor() as i32; + let decimals = digits as i32 - 1 - magnitude; + if decimals >= 0 + { + // Rounding can carry into a new digit (9.99999 to 10.000), which needs one decimal fewer + let rounded = format!("{:+.*}", decimals as usize, x); + let carried = rounded.trim_start_matches(['+', '-']).trim_start_matches(['0', '.']).chars().filter(char::is_ascii_digit).count() > digits; + if carried && decimals > 0 { format!("{:+.*}", decimals as usize - 1, x) } else { rounded } + } + else + { + let unit = 10f64.powi(-decimals); + format!("{:+.0}", (x as f64 / unit).round() * unit) + } +} + #[cfg(test)] mod tests { use super::*; use crate::board::PieceType; + #[test] + fn significant_keeps_five_figures() + { + assert_eq!(significant(1234.5678, 5), "+1234.6"); + assert_eq!(significant(-212.0, 5), "-212.00"); + assert_eq!(significant(0.012345678, 5), "+0.012346"); + assert_eq!(significant(-0.5, 5), "-0.50000"); + assert_eq!(significant(1234567.0, 5), "+1234600"); + assert_eq!(significant(9.999999, 5), "+10.000"); + assert_eq!(significant(0.0, 5), "0.0000"); + } + /// A minimax player with a cheap evaluation that still varies a lot between positions. struct TestPlayer { |
