summaryrefslogtreecommitdiffstats
path: root/src/client/games/slots.rs
blob: 5eed34dc3c826689e26ca2a97a2d69aaa0f71418 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use super::traits::{Game, GamePhase, GameState};

/// Height of the game board. It must never depend on the spin result, or an
/// in-place redraw would move to the wrong line.
pub const SLOT_BOARD_LINES: usize = 7;

pub struct SlotsGame;

impl SlotsGame {
    pub fn new() -> Self {
        Self
    }

    fn render_reels(&self, reels: &str) -> String {
        let mut chars = reels.chars();
        format!(
            "[ {} ] [ {} ] [ {} ]",
            chars.next().unwrap_or('?'),
            chars.next().unwrap_or('?'),
            chars.next().unwrap_or('?')
        )
    }

    /// The fifth board line: current status, result, or error.
    fn render_status(&self, state: &GameState) -> String {
        if let Some(error) = state.data.get("error") {
            return format!("ERROR: {error}");
        }
        if state.phase == GamePhase::Playing {
            return "Spinning...".to_string();
        }
        if state.phase == GamePhase::Finished {
            let winnings = state
                .data
                .get("winnings")
                .map(String::as_str)
                .unwrap_or("0");
            return match state.data.get("win_type").map(String::as_str) {
                Some("jackpot") => format!("JACKPOT! Winnings: {winnings} PLN"),
                Some("two") => format!("Two of a kind! Winnings: {winnings} PLN"),
                _ => "No win.".to_string(),
            };
        }
        "Press [SPACE] to spin!".to_string()
    }
}

impl Game for SlotsGame {
    fn get_name(&self) -> &'static str {
        "Slots"
    }

    fn render(&self, state: &GameState) -> String {
        let reels = state.data.get("reels").cloned().unwrap_or_default();
        let balance = state
            .data
            .get("balance")
            .map(String::as_str)
            .unwrap_or("?");

        format!(
            "=== SLOTS ===\r\nBet: {} PLN   Balance: {} PLN\r\n{}\r\n\r\n{}\r\n\r\n[+/-] Adjust Bet   [Q] Quit",
            state.bet_amount,
            balance,
            self.render_reels(&reels),
            self.render_status(state)
        )
    }

    fn render_lines(&self, _state: &GameState) -> usize {
        SLOT_BOARD_LINES
    }

    fn get_help(&self) -> String {
        "SLOTS GAME\n\
        =========\n\
        Match symbols to win!\n\
        \n\
        Payouts:\n\
        Three of a kind: 2x-28x bet\n\
        Two of a kind: 1x-3x bet\n\
        \n\
        Symbols: C=Cherry, L=Lemon, O=Orange, G=Grapes, D=Diamond, S=Seven\n\
        \n\
        Controls:\n\
        SPACE - Spin the reels\n\
        +/- - Adjust bet amount\n\
        Q - Exit the game"
            .to_string()
    }
}