Skip to main content

cli/
cli.rs

1use std::io::{self, Stdin};
2
3use pachislo::{
4    CONFIG_EXAMPLE as CONFIG, Game, START_HOLE_PROBABILITY_EXAMPLE,
5    command::{Command, FinishGame, LaunchBallFlowProducer, StartGame},
6    game::{GameState, Transition},
7    interface::{UserInput, UserOutput},
8    lottery::LotteryResult,
9    slot::SlotProducer,
10};
11
12fn main() {
13    let input = CuiInput::new(START_HOLE_PROBABILITY_EXAMPLE);
14
15    let output = CuiOutput::new();
16
17    let mut game = Game::new(CONFIG, input, output).unwrap();
18
19    game.run();
20}
21
22pub struct CuiInput {
23    launch_ball_flow_producer: LaunchBallFlowProducer,
24    stdin: Stdin,
25}
26
27impl<O: UserOutput> UserInput<O> for CuiInput {
28    fn wait_for_input(&mut self) -> Command<Self, O> {
29        loop {
30            let mut s = String::new();
31            self.stdin.read_line(&mut s).ok();
32            match s.trim() {
33                "s" => return Command::Control(Box::new(StartGame)),
34                "l" | "" => {
35                    return Command::Control(Box::new(self.launch_ball_flow_producer.produce()));
36                }
37                "q" => return Command::Control(Box::new(FinishGame)),
38                "q!" => return Command::FinishGame,
39                _ => (),
40            }
41        }
42    }
43}
44
45impl CuiInput {
46    pub fn new(start_hole_probability: f64) -> Self {
47        assert!((0.0..=1.0).contains(&start_hole_probability));
48        Self {
49            launch_ball_flow_producer: LaunchBallFlowProducer::new(start_hole_probability),
50            stdin: io::stdin(),
51        }
52    }
53}
54
55pub struct CuiOutput {
56    slot_producer: SlotProducer<u8>,
57}
58
59impl UserOutput for CuiOutput {
60    fn default(&mut self, state: Transition) {
61        let Transition {
62            before,
63            after: state,
64        } = state;
65
66        match (state, before) {
67            (GameState::Uninitialized, _) => {
68                println!("Welcome to Pachislo!");
69                println!();
70                return;
71            }
72            (GameState::Normal { .. }, Some(GameState::Rush { n, .. })) => {
73                println!("RUSH finished!, Number of RUSH times: {n}")
74            }
75            _ => {}
76        }
77
78        println!("Current state: {state:?}");
79        println!();
80    }
81
82    fn finish_game(&mut self, state: &GameState) {
83        println!("Game finished!");
84        println!("Final state: {state:?}");
85    }
86
87    fn lottery_normal(&mut self, result: LotteryResult) {
88        let slot = self.slot_producer.produce(&result);
89        Self::print_slot(slot);
90        println!("Lottery result: {result:?}");
91    }
92
93    fn lottery_rush(&mut self, result: LotteryResult) {
94        let slot = self.slot_producer.produce(&result);
95        Self::print_slot(slot);
96        println!("Lottery result in rush mode: {result:?}");
97    }
98
99    fn lottery_rush_continue(&mut self, result: LotteryResult) {
100        let slot = self.slot_producer.produce(&result);
101        Self::print_slot(slot);
102        println!("Lottery result in rush continue: {result:?}");
103    }
104}
105
106impl CuiOutput {
107    pub fn new() -> Self {
108        Self {
109            slot_producer: SlotProducer::new(3, (1..=9).collect()),
110        }
111    }
112
113    pub fn print_slot(slot: (Vec<u8>, Option<Vec<u8>>)) {
114        println!("Slot: {:?}", slot.0);
115
116        if let Some(but) = slot.1 {
117            println!("But: {but:?}");
118        }
119    }
120}
121
122impl Default for CuiOutput {
123    fn default() -> Self {
124        Self::new()
125    }
126}