pub mod game_settings;
pub mod ui_settings;
use std::{str::FromStr, io::stdin, thread::sleep, time::Duration, process::Command};
use chess::{Board, BoardStatus, Color};
use game_settings::*;
use method_shorthands::methods::*;
use ui_settings::*;
use crate::{turn::handle_turn, gui::display_board, player::Player, color::Opposite};
#[derive(Debug, Copy, Clone, PartialEq, Default)]
pub struct Game<'a, W, B> {
pub board: Board,
pub game_settings: GameSettings<'a, W, B>,
pub ui_settings: UISettings,
pub num_moves: usize
}
impl<W: Player, B: Player> Game<'_, W, B> {
pub fn new(game_settings: GameSettings<W, B>, ui_settings: UISettings) -> Game<W, B> {
let mut game = Game {
board: Board::from_str("k1K5/8/8/8/8/8/8/8 w - 0 1").uw(),
game_settings: game_settings,
ui_settings: ui_settings,
num_moves: 0
};
game.set_board_state();
game
}
fn set_board_state(&mut self) {
self.board = Board::from_str(self.game_settings.initial_state).uw();
}
pub fn start(&mut self) {
loop {
self.set_board_state();
self.num_moves = 0;
if self.ui_settings.cls { Command::new("clear").spawn().uw(); sleep(Duration::from_millis(10)); }
if self.ui_settings.view_board_display { display_board(self.board, self.ui_settings); }
self.game_loop();
}
}
fn game_loop(&mut self) {
loop {
let m = match self.board.side_to_move() {
Color::White => W::get_move(self.board, self.num_moves, self.ui_settings.bot_wait_ms),
Color::Black => B::get_move(self.board, self.num_moves, self.ui_settings.bot_wait_ms),
};
if m.is_err() {
println!("Invalid input.");
continue;
}
let m = m.uw();
let res = handle_turn(self.board, m, self.ui_settings);
if res.is_err() {
if res.unwrap_err() == "insuff mat" {
println!("Insufficient material.");
Game::<W, B>::stalemate();
break;
}
else if res.unwrap_err() == "Illegal move." && self.game_settings.disqualification {
println!("Illegal move.");
Game::<W, B>::checkmate(self.board.side_to_move());
break;
}
println!("{:?}", res.unwrap_err().ts());
continue;
}
else { self.board = res.uw(); }
if self.board.status() == BoardStatus::Checkmate {
Game::<W, B>::checkmate(self.board.side_to_move());
break;
}
else if self.board.status() == BoardStatus::Stalemate {
Game::<W, B>::stalemate();
break;
}
self.num_moves += 1;
if self.num_moves == self.game_settings.move_limit {
println!("{} move limit has been reached.", self.game_settings.move_limit);
Game::<W, B>::stalemate();
break;
}
}
}
fn checkmate(side_to_move: Color) {
let color = side_to_move.opposite();
println!("Game over: {:?} won!", color);
stdin().read_line(&mut String::new()).uw();
}
fn stalemate() {
println!("Game over: Stalemate.");
stdin().read_line(&mut String::new()).uw();
}
}