use chess::{Board, ChessMove, Color, Game, MoveGen, Square, BoardStatus};
use std::str::FromStr;
#[derive(Clone)]
pub struct AppState {
pub game: Game,
pub board: Board,
pub selected_square: Option<Square>,
pub valid_moves: Vec<Square>,
pub debug_msg: String,
pub game_over: bool,
pub my_color: Option<Color>,
}
impl AppState {
pub fn new() -> Self {
Self {
game: Game::new(),
board: Board::default(),
selected_square: None,
valid_moves: Vec::new(),
debug_msg: String::from("Welcome! Local Hotseat Mode."),
game_over: false,
my_color: None, }
}
pub fn set_player_color(&mut self, color: Color) {
self.my_color = Some(color);
self.debug_msg = format!("Multiplayer: You are {:?}.", color);
}
pub fn handle_click(&mut self, square: Square) -> Option<(String, String)> {
if self.game_over { return None; }
let current_turn = self.board.side_to_move();
if let Some(my_c) = self.my_color {
if my_c != current_turn {
self.debug_msg = String::from("Wait for opponent...");
return None;
}
if self.selected_square.is_none() {
if let Some(p_color) = self.board.color_on(square) {
if p_color != my_c {
return None;
}
}
}
}
match self.selected_square {
Some(selected) => {
if selected == square {
self.selected_square = None;
self.valid_moves.clear();
self.debug_msg = String::from("Deselected.");
} else {
let move_result = self.make_move(selected, square);
if move_result {
self.selected_square = None;
self.valid_moves.clear();
return Some((format!("{}", selected), format!("{}", square)));
} else {
if let Some(color) = self.board.color_on(square) {
if color == current_turn {
self.selected_square = Some(square);
self.calculate_valid_moves(square);
return None;
}
}
self.selected_square = None;
self.valid_moves.clear();
}
}
}
None => {
if let Some(color) = self.board.color_on(square) {
if color == current_turn {
self.selected_square = Some(square);
self.calculate_valid_moves(square);
self.debug_msg = format!("Selected: {}", square);
}
}
}
}
None
}
pub fn network_apply_move(&mut self, from: String, to: String) {
if let (Ok(src), Ok(dst)) = (Square::from_str(&from), Square::from_str(&to)) {
self.make_move(src, dst);
self.debug_msg = format!("Opponent moved {} -> {}", from, to);
}
}
fn calculate_valid_moves(&mut self, source: Square) {
self.valid_moves.clear();
let legal_moves = MoveGen::new_legal(&self.board);
for m in legal_moves {
if m.get_source() == source {
self.valid_moves.push(m.get_dest());
}
}
}
pub fn make_move(&mut self, source: Square, dest: Square) -> bool {
let m = ChessMove::new(source, dest, None);
let legal_moves = MoveGen::new_legal(&self.board);
if legal_moves.into_iter().any(|lm| lm == m) {
self.game.make_move(m);
self.board = self.game.current_position();
self.update_status();
return true;
}
false
}
fn update_status(&mut self) {
match self.board.status() {
BoardStatus::Checkmate => {
self.debug_msg = format!("CHECKMATE! {:?} WINS!", !self.board.side_to_move());
self.game_over = true;
}
BoardStatus::Stalemate => {
self.debug_msg = String::from("Stalemate!");
self.game_over = true;
}
BoardStatus::Ongoing => {
if self.board.checkers().popcnt() > 0 {
self.debug_msg = format!("CHECK! {:?} to move", self.board.side_to_move());
} else {
self.debug_msg = format!("{:?}'s turn.", self.board.side_to_move());
}
}
}
}
}