use std::io::{self, Stdin};
use pachislo::{
CONFIG_EXAMPLE as CONFIG, Game, START_HOLE_PROBABILITY_EXAMPLE,
command::{Command, FinishGame, LaunchBallFlowProducer, StartGame},
game::{GameState, Transition},
interface::{UserInput, UserOutput},
lottery::LotteryResult,
slot::SlotProducer,
};
fn main() {
let input = CuiInput::new(START_HOLE_PROBABILITY_EXAMPLE);
let output = CuiOutput::new();
let mut game = Game::new(CONFIG, input, output).unwrap();
game.run();
}
pub struct CuiInput {
launch_ball_flow_producer: LaunchBallFlowProducer,
stdin: Stdin,
}
impl<O: UserOutput> UserInput<O> for CuiInput {
fn wait_for_input(&mut self) -> Command<Self, O> {
loop {
let mut s = String::new();
self.stdin.read_line(&mut s).ok();
match s.trim() {
"s" => return Command::Control(Box::new(StartGame)),
"l" | "" => {
return Command::Control(Box::new(self.launch_ball_flow_producer.produce()));
}
"q" => return Command::Control(Box::new(FinishGame)),
"q!" => return Command::FinishGame,
_ => (),
}
}
}
}
impl CuiInput {
pub fn new(start_hole_probability: f64) -> Self {
assert!((0.0..=1.0).contains(&start_hole_probability));
Self {
launch_ball_flow_producer: LaunchBallFlowProducer::new(start_hole_probability),
stdin: io::stdin(),
}
}
}
pub struct CuiOutput {
slot_producer: SlotProducer<u8>,
}
impl UserOutput for CuiOutput {
fn default(&mut self, state: Transition) {
let Transition {
before,
after: state,
} = state;
match (state, before) {
(GameState::Uninitialized, _) => {
println!("Welcome to Pachislo!");
println!();
return;
}
(GameState::Normal { .. }, Some(GameState::Rush { n, .. })) => {
println!("RUSH finished!, Number of RUSH times: {n}")
}
_ => {}
}
println!("Current state: {state:?}");
println!();
}
fn finish_game(&mut self, state: &GameState) {
println!("Game finished!");
println!("Final state: {state:?}");
}
fn lottery_normal(&mut self, result: LotteryResult) {
let slot = self.slot_producer.produce(&result);
Self::print_slot(slot);
println!("Lottery result: {result:?}");
}
fn lottery_rush(&mut self, result: LotteryResult) {
let slot = self.slot_producer.produce(&result);
Self::print_slot(slot);
println!("Lottery result in rush mode: {result:?}");
}
fn lottery_rush_continue(&mut self, result: LotteryResult) {
let slot = self.slot_producer.produce(&result);
Self::print_slot(slot);
println!("Lottery result in rush continue: {result:?}");
}
}
impl CuiOutput {
pub fn new() -> Self {
Self {
slot_producer: SlotProducer::new(3, (1..=9).collect()),
}
}
pub fn print_slot(slot: (Vec<u8>, Option<Vec<u8>>)) {
println!("Slot: {:?}", slot.0);
if let Some(but) = slot.1 {
println!("But: {but:?}");
}
}
}
impl Default for CuiOutput {
fn default() -> Self {
Self::new()
}
}