diff --git a/src/board.rs b/src/board.rs index 9a68abb..d292bfa 100644 --- a/src/board.rs +++ b/src/board.rs @@ -1,6 +1,6 @@ use crate::{ constants::{BLACK, UNDEFINED_POSITION, WHITE}, - pieces::{PieceColor, PieceType}, + pieces::{PieceColor, PieceMove, PieceType}, utils::{ col_to_letter, convert_notation_into_position, convert_position_into_notation, did_piece_already_move, get_cell_paragraph, get_int_from_char, get_king_coordinates, @@ -28,7 +28,7 @@ pub struct Board { pub selected_piece_cursor: i8, pub old_cursor_position: [i8; 2], pub player_turn: PieceColor, - pub move_history: Vec<(Option, String)>, + pub move_history: Vec, pub is_draw: bool, pub is_checkmate: bool, pub is_promotion: bool, @@ -110,7 +110,7 @@ impl Board { pub fn new( board: [[Option<(PieceType, PieceColor)>; 8]; 8], player_turn: PieceColor, - move_history: Vec<(Option, String)>, + move_history: Vec, ) -> Self { Self { board, @@ -229,15 +229,10 @@ impl Board { pub fn did_king_already_move(&self) -> bool { for i in 0..self.move_history.len() { - match self.move_history[i] { - (Some(piece_type), _) => { - if piece_type == PieceType::King - && get_player_turn_in_modulo(self.player_turn) == i % 2 - { - return true; - } - } - _ => unreachable!("Invalid move in history"), + if self.move_history[i].piece_type == PieceType::King + && get_player_turn_in_modulo(self.player_turn) == i % 2 + { + return true; } } false @@ -424,22 +419,15 @@ impl Board { // We check if the latest move is a pawn moving 2 cells, meaning the next move can be en passant if self.did_pawn_move_two_cells() { // Use an if-let pattern for better readability - if let Some((_, latest_move_string)) = self.move_history.last() { - let mut converted_move: String = String::new(); + if let Some(last_move) = self.move_history.last() { + let mut converted_move = String::new(); - if let (Some(from_y_char), Some(from_x_char)) = ( - latest_move_string.chars().nth(0), - latest_move_string.chars().nth(1), - ) { - let from_y = get_int_from_char(Some(from_y_char)) - 1; - let from_x = get_int_from_char(Some(from_x_char)); - - converted_move += &col_to_letter(from_x); - converted_move += &format!("{}", 8 - from_y).to_string(); + converted_move += &col_to_letter(last_move.from_x); + // FEN starts counting from 1 not 0 + converted_move += &format!("{}", 8 - last_move.from_y + 1).to_string(); - result.push_str(" "); - result.push_str(&converted_move); - } + result.push_str(" "); + result.push_str(&converted_move); } } else { result.push_str(" -"); @@ -457,13 +445,10 @@ impl Board { pub fn did_pawn_move_two_cells(&self) -> bool { match self.move_history.last() { - Some((Some(piece_type), move_string)) => { - let from_y = get_int_from_char(move_string.chars().next()); - let to_y = get_int_from_char(move_string.chars().nth(2)); + Some(last_move) => { + let distance = (last_move.to_y - last_move.from_y).abs(); - let distance = (to_y - from_y).abs(); - - if piece_type == &PieceType::Pawn && distance == 2 { + if last_move.piece_type == PieceType::Pawn && distance == 2 { return true; } return false; @@ -472,10 +457,7 @@ impl Board { } } pub fn promote_piece(&mut self) { - if let Some(position) = self.move_history.last() { - let to_y = get_int_from_char(position.1.chars().nth(2)); - let to_x = get_int_from_char(position.1.chars().nth(3)); - + if let Some(last_move) = self.move_history.last() { let new_piece = match self.promotion_cursor { 0 => PieceType::Queen, 1 => PieceType::Rook, @@ -484,10 +466,11 @@ impl Board { _ => unreachable!("Promotion cursor out of boundaries"), }; - let current_piece_color = get_piece_color(self.board, [to_y, to_x]); + let current_piece_color = get_piece_color(self.board, [last_move.to_y, last_move.to_x]); if let Some(piece_color) = current_piece_color { // we replace the piece by the new piece type - self.board[to_y as usize][to_x as usize] = Some((new_piece, piece_color)); + self.board[last_move.to_y as usize][last_move.to_x as usize] = + Some((new_piece, piece_color)); } } self.is_promotion = false; @@ -506,11 +489,16 @@ impl Board { let piece_type_from = get_piece_type(self.board, [from[0] as i8, from[1] as i8]); let piece_type_to = get_piece_type(self.board, [to[0] as i8, to[1] as i8]); - let position_number: String = format!("{}{}{}{}", from[0], from[1], to[0], to[1]); + + // Check if moving a piece + let piece_type_from = match piece_type_from { + Some(piece) => piece, + None => return, + }; // We increment the consecutive_non_pawn_or_capture if the piece type is a pawn or if there is no capture match (piece_type_from, piece_type_to) { - (Some(PieceType::Pawn), _) | (Some(_), Some(_)) => { + (PieceType::Pawn, _) | (_, Some(_)) => { self.consecutive_non_pawn_or_capture = 0; } _ => { @@ -518,8 +506,6 @@ impl Board { } } - let tuple = (piece_type_from, position_number); - // We check for en passant as the latest move if self.is_latest_move_en_passant(from, to) { // we kill the pawn @@ -571,7 +557,14 @@ impl Board { self.board[from[0]][from[1]] = None; // We store it in the history - self.move_history.push(tuple.clone()); + + self.move_history.push(PieceMove { + piece_type: piece_type_from, + from_y: from[0] as i8, + from_x: from[1] as i8, + to_y: to[0] as i8, + to_x: to[1] as i8, + }); } pub fn unselect_cell(&mut self) { @@ -634,21 +627,17 @@ impl Board { } fn is_latest_move_promotion(&self) -> bool { - if let Some(position) = self.move_history.last() { - let to_y = get_int_from_char(position.1.chars().nth(2)); - let to_x = get_int_from_char(position.1.chars().nth(3)); - - if let Some(piece_type_from) = get_piece_type(self.board, [to_y, to_x]) { - if let Some(piece_color) = get_piece_color(self.board, [to_y, to_x]) { - let last_row = if piece_color == PieceColor::White { - 0 - } else { - 7 - }; + if let Some(last_move) = self.move_history.last() { + if let Some(piece_color) = get_piece_color(self.board, [last_move.to_y, last_move.to_x]) + { + let last_row = if piece_color == PieceColor::White { + 0 + } else { + 7 + }; - if to_y == last_row && piece_type_from == PieceType::Pawn { - return true; - } + if last_move.to_y == last_row && last_move.piece_type == PieceType::Pawn { + return true; } } } @@ -665,7 +654,7 @@ impl Board { pub fn draw_by_repetition(&self) -> bool { if self.move_history.len() >= 9 { - let last_ten: Vec<(Option, String)> = + let last_ten: Vec = self.move_history.iter().rev().take(9).cloned().collect(); if (last_ten[0].clone(), last_ten[1].clone()) @@ -807,22 +796,32 @@ impl Board { let mut lines: Vec = vec![]; for i in (0..self.move_history.len()).step_by(2) { - let piece_type_from = self.move_history[i].0; - let number_move = &self.move_history[i].1; + let piece_type_from = self.move_history[i].piece_type; let utf_icon_white = PieceType::piece_to_utf_enum(piece_type_from, Some(PieceColor::White)); - let move_white = convert_position_into_notation(number_move.to_string()); + let move_white = convert_position_into_notation(format!( + "{}{}{}{}", + self.move_history[i].from_y, + self.move_history[i].from_x, + self.move_history[i].to_y, + self.move_history[i].to_x + )); let mut utf_icon_black = " "; let mut move_black: String = " ".to_string(); // If there is something for black if i + 1 < self.move_history.len() { - let piece_type_to = self.move_history[i + 1].0; - let number = &self.move_history[i + 1].1; - - move_black = convert_position_into_notation(number.to_string()); + let piece_type_to = self.move_history[i + 1].piece_type; + + move_black = convert_position_into_notation(format!( + "{}{}{}{}", + self.move_history[i + 1].from_y, + self.move_history[i + 1].from_x, + self.move_history[i + 1].to_y, + self.move_history[i + 1].to_x + )); utf_icon_black = PieceType::piece_to_utf_enum(piece_type_to, Some(PieceColor::Black)) } @@ -866,7 +865,7 @@ impl Board { mod tests { use crate::{ board::Board, - pieces::{PieceColor, PieceType}, + pieces::{PieceColor, PieceMove, PieceType}, utils::is_getting_checked, }; @@ -1348,7 +1347,15 @@ mod tests { let board = Board::new( custom_board, PieceColor::Black, - vec![(Some(PieceType::Pawn), "7363".to_string())], + vec![ + (PieceMove { + piece_type: PieceType::Pawn, + from_y: 7, + from_x: 3, + to_y: 6, + to_x: 3, + }), + ], ); assert!(!board.is_latest_move_promotion()); @@ -1395,7 +1402,15 @@ mod tests { let board = Board::new( custom_board, PieceColor::Black, - vec![(Some(PieceType::Pawn), "1404".to_string())], + vec![ + (PieceMove { + piece_type: PieceType::Pawn, + from_y: 1, + from_x: 4, + to_y: 0, + to_x: 4, + }), + ], ); assert!(board.is_latest_move_promotion()); @@ -1498,7 +1513,15 @@ mod tests { let board = Board::new( custom_board, PieceColor::White, - vec![(Some(PieceType::Pawn), "6474".to_string())], + vec![ + (PieceMove { + piece_type: PieceType::Pawn, + from_y: 6, + from_x: 4, + to_y: 7, + to_x: 4, + }), + ], ); assert!(board.is_latest_move_promotion()); @@ -1592,7 +1615,7 @@ mod tests { assert!(!board.is_draw()); // Move the pawn to a make the 50th move - board.move_piece_on_the_board([0, 6], [0, 5]); + board.move_piece_on_the_board([1, 6], [1, 5]); assert!(board.is_draw()); } @@ -1622,14 +1645,62 @@ mod tests { custom_board, PieceColor::White, vec![ - (Some(PieceType::King), "0201".to_string()), - (Some(PieceType::King), "0605".to_string()), - (Some(PieceType::King), "0102".to_string()), - (Some(PieceType::King), "0506".to_string()), - (Some(PieceType::King), "0201".to_string()), - (Some(PieceType::King), "0605".to_string()), - (Some(PieceType::King), "0102".to_string()), - (Some(PieceType::King), "0506".to_string()), + (PieceMove { + piece_type: PieceType::King, + from_y: 0, + from_x: 2, + to_y: 0, + to_x: 1, + }), + (PieceMove { + piece_type: PieceType::King, + from_y: 0, + from_x: 6, + to_y: 0, + to_x: 5, + }), + (PieceMove { + piece_type: PieceType::King, + from_y: 0, + from_x: 1, + to_y: 0, + to_x: 2, + }), + (PieceMove { + piece_type: PieceType::King, + from_y: 0, + from_x: 5, + to_y: 0, + to_x: 6, + }), + (PieceMove { + piece_type: PieceType::King, + from_y: 0, + from_x: 2, + to_y: 0, + to_x: 1, + }), + (PieceMove { + piece_type: PieceType::King, + from_y: 0, + from_x: 6, + to_y: 0, + to_x: 5, + }), + (PieceMove { + piece_type: PieceType::King, + from_y: 0, + from_x: 1, + to_y: 0, + to_x: 2, + }), + (PieceMove { + piece_type: PieceType::King, + from_y: 0, + from_x: 5, + to_y: 0, + to_x: 6, + }), ], ); @@ -1720,7 +1791,15 @@ mod tests { let board = Board::new( custom_board, PieceColor::White, - vec![(Some(PieceType::Pawn), "6242".to_string())], + vec![ + (PieceMove { + piece_type: PieceType::Pawn, + from_y: 6, + from_x: 2, + to_y: 4, + to_x: 2, + }), + ], ); // Move the king to replicate a third time the same position diff --git a/src/pieces/bishop.rs b/src/pieces/bishop.rs index f1a01ae..9c7f1a1 100644 --- a/src/pieces/bishop.rs +++ b/src/pieces/bishop.rs @@ -1,4 +1,4 @@ -use super::{Movable, PieceColor, PieceType, Position}; +use super::{Movable, PieceColor, PieceMove, PieceType, Position}; use crate::board::DisplayMode; use crate::utils::{ cleaned_positions, get_piece_color, impossible_positions_king_checked, is_cell_color_ally, @@ -12,7 +12,7 @@ impl Movable for Bishop { color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], allow_move_on_ally_positions: bool, - _move_history: &[(Option, String)], + _move_history: &[PieceMove], ) -> Vec> { let mut positions: Vec> = vec![]; @@ -168,7 +168,7 @@ impl Position for Bishop { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], _is_king_checked: bool, ) -> Vec> { // if the king is checked we clean all the position not resolving the check @@ -184,7 +184,7 @@ impl Position for Bishop { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { Self::piece_move(coordinates, color, board, true, move_history) } diff --git a/src/pieces/king.rs b/src/pieces/king.rs index 34d4d70..22835f6 100644 --- a/src/pieces/king.rs +++ b/src/pieces/king.rs @@ -1,4 +1,4 @@ -use super::{Movable, PieceColor, PieceType, Position}; +use super::{Movable, PieceColor, PieceMove, PieceType, Position}; use crate::board::DisplayMode; use crate::utils::{ cleaned_positions, did_piece_already_move, get_all_protected_cells, get_piece_type, @@ -12,7 +12,7 @@ impl Movable for King { color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], allow_move_on_ally_positions: bool, - _move_history: &[(Option, String)], + _move_history: &[PieceMove], ) -> Vec> { let mut positions: Vec> = vec![]; let y = coordinates[0]; @@ -45,7 +45,7 @@ impl Position for King { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], is_king_checked: bool, ) -> Vec> { let mut positions: Vec> = vec![]; @@ -97,7 +97,7 @@ impl Position for King { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { Self::piece_move(coordinates, color, board, true, move_history) } @@ -154,7 +154,7 @@ impl King { mod tests { use crate::{ board::Board, - pieces::{king::King, PieceColor, PieceType, Position}, + pieces::{king::King, PieceColor, PieceMove, PieceType, Position}, utils::is_getting_checked, }; @@ -652,9 +652,27 @@ mod tests { PieceColor::Black, board.board, &[ - (Some(PieceType::Rook), "0747".to_string()), - (Some(PieceType::Pawn), "6252".to_string()), - (Some(PieceType::Rook), "4707".to_string()), + (PieceMove { + piece_type: PieceType::Rook, + from_y: 0, + from_x: 7, + to_y: 4, + to_x: 7, + }), + (PieceMove { + piece_type: PieceType::Pawn, + from_y: 6, + from_x: 2, + to_y: 5, + to_x: 2, + }), + (PieceMove { + piece_type: PieceType::Rook, + from_y: 4, + from_x: 7, + to_y: 0, + to_x: 7, + }), ], false, ); diff --git a/src/pieces/knight.rs b/src/pieces/knight.rs index 7f0c433..fccd14d 100644 --- a/src/pieces/knight.rs +++ b/src/pieces/knight.rs @@ -1,4 +1,4 @@ -use super::{Movable, PieceColor, PieceType, Position}; +use super::{Movable, PieceColor, PieceMove, PieceType, Position}; use crate::board::DisplayMode; use crate::utils::{ cleaned_positions, impossible_positions_king_checked, is_cell_color_ally, is_valid, @@ -11,7 +11,7 @@ impl Movable for Knight { color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], allow_move_on_ally_positions: bool, - _move_history: &[(Option, String)], + _move_history: &[PieceMove], ) -> Vec> { let mut positions: Vec> = Vec::new(); @@ -52,7 +52,7 @@ impl Position for Knight { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], _is_king_checked: bool, ) -> Vec> { impossible_positions_king_checked( @@ -68,7 +68,7 @@ impl Position for Knight { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - _move_history: &[(Option, String)], + _move_history: &[PieceMove], ) -> Vec> { Self::piece_move(coordinates, color, board, true, _move_history) } diff --git a/src/pieces/mod.rs b/src/pieces/mod.rs index 961f236..10ff849 100644 --- a/src/pieces/mod.rs +++ b/src/pieces/mod.rs @@ -23,7 +23,7 @@ impl PieceType { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], is_king_checked: bool, ) -> Vec> { match self { @@ -65,7 +65,7 @@ impl PieceType { piece_type: PieceType, color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { match piece_type { PieceType::Pawn => { @@ -90,22 +90,22 @@ impl PieceType { } pub fn piece_to_utf_enum( - piece_type: Option, + piece_type: PieceType, piece_color: Option, ) -> &'static str { match (piece_type, piece_color) { - (Some(PieceType::Queen), Some(PieceColor::Black)) => "♕", - (Some(PieceType::Queen), Some(PieceColor::White)) => "♛", - (Some(PieceType::King), Some(PieceColor::Black)) => "♔", - (Some(PieceType::King), Some(PieceColor::White)) => "♚", - (Some(PieceType::Rook), Some(PieceColor::Black)) => "♖", - (Some(PieceType::Rook), Some(PieceColor::White)) => "♜", - (Some(PieceType::Bishop), Some(PieceColor::Black)) => "♗", - (Some(PieceType::Bishop), Some(PieceColor::White)) => "♝", - (Some(PieceType::Knight), Some(PieceColor::Black)) => "♘", - (Some(PieceType::Knight), Some(PieceColor::White)) => "♞", - (Some(PieceType::Pawn), Some(PieceColor::Black)) => "♙", - (Some(PieceType::Pawn), Some(PieceColor::White)) => "♟", + (PieceType::Queen, Some(PieceColor::Black)) => "♕", + (PieceType::Queen, Some(PieceColor::White)) => "♛", + (PieceType::King, Some(PieceColor::Black)) => "♔", + (PieceType::King, Some(PieceColor::White)) => "♚", + (PieceType::Rook, Some(PieceColor::Black)) => "♖", + (PieceType::Rook, Some(PieceColor::White)) => "♜", + (PieceType::Bishop, Some(PieceColor::Black)) => "♗", + (PieceType::Bishop, Some(PieceColor::White)) => "♝", + (PieceType::Knight, Some(PieceColor::Black)) => "♘", + (PieceType::Knight, Some(PieceColor::White)) => "♞", + (PieceType::Pawn, Some(PieceColor::Black)) => "♙", + (PieceType::Pawn, Some(PieceColor::White)) => "♟", _ => "NONE", } } @@ -148,6 +148,15 @@ impl PieceType { } } +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct PieceMove { + pub piece_type: PieceType, + pub from_x: i8, + pub from_y: i8, + pub to_x: i8, + pub to_y: i8, +} + #[derive(Debug, Copy, Clone, PartialEq)] pub enum PieceColor { Black, @@ -160,7 +169,7 @@ pub trait Movable { color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], allow_move_on_ally_positions: bool, - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec>; } @@ -169,7 +178,7 @@ pub trait Position { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], is_king_checked: bool, ) -> Vec>; @@ -177,6 +186,6 @@ pub trait Position { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec>; } diff --git a/src/pieces/pawn.rs b/src/pieces/pawn.rs index 4641c76..37b0031 100644 --- a/src/pieces/pawn.rs +++ b/src/pieces/pawn.rs @@ -1,8 +1,8 @@ -use super::{Movable, PieceColor, PieceType, Position}; +use super::{Movable, PieceColor, PieceMove, PieceType, Position}; use crate::board::DisplayMode; use crate::utils::{ - cleaned_positions, get_int_from_char, get_latest_move, get_piece_color, - impossible_positions_king_checked, is_cell_color_ally, is_valid, + cleaned_positions, get_latest_move, get_piece_color, impossible_positions_king_checked, + is_cell_color_ally, is_valid, }; pub struct Pawn; @@ -13,7 +13,7 @@ impl Movable for Pawn { color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], allow_move_on_ally_positions: bool, - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { // Pawns can only move in one direction depending of their color // -1 if they are white (go up) +1 if they are black (go down) @@ -85,35 +85,28 @@ impl Movable for Pawn { } // We check for en passant - let latest_move = get_latest_move(move_history); - - if let (Some(PieceType::Pawn), piece_move) = latest_move { - let from_y = get_int_from_char(piece_move.chars().nth(0)); - let from_x = get_int_from_char(piece_move.chars().nth(1)); - let to_y = get_int_from_char(piece_move.chars().nth(2)); - let to_x = get_int_from_char(piece_move.chars().nth(3)); - + if let Some(latest_move) = get_latest_move(move_history) { let valid_y_start: i8; let number_of_cells_move: i8; if color == PieceColor::White { valid_y_start = 1; - number_of_cells_move = to_y - from_y; + number_of_cells_move = latest_move.to_y - latest_move.from_y; } else { valid_y_start = 6; - number_of_cells_move = from_y - to_y; + number_of_cells_move = latest_move.from_y - latest_move.to_y; }; // We check if the latest move was on the right start cell // if it moved 2 cells // and if the current pawn is next to this pawn latest position - if from_y == valid_y_start + if latest_move.from_y == valid_y_start && number_of_cells_move == 2 - && y == to_y - && (x == to_x - 1 || x == to_x + 1) + && y == latest_move.to_y + && (x == latest_move.to_x - 1 || x == latest_move.to_x + 1) { - let new_y = from_y + -direction; - let new_x = from_x; + let new_y = latest_move.from_y + -direction; + let new_x = latest_move.from_x; positions.push([new_y, new_x].to_vec()); } } @@ -127,7 +120,7 @@ impl Position for Pawn { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], _is_king_checked: bool, ) -> Vec> { // If the king is not checked we get then normal moves @@ -145,7 +138,7 @@ impl Position for Pawn { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { Self::piece_move(coordinates, color, board, true, move_history) } @@ -172,7 +165,7 @@ impl Pawn { mod tests { use crate::{ board::Board, - pieces::{pawn::Pawn, PieceColor, PieceType, Position}, + pieces::{pawn::Pawn, PieceColor, PieceMove, PieceType, Position}, utils::is_getting_checked, }; @@ -203,13 +196,8 @@ mod tests { let mut right_positions = vec![vec![3, 4]]; right_positions.sort(); - let mut positions = Pawn::authorized_positions( - [4, 4], - PieceColor::White, - board.board, - &[(None, "0000".to_string())], - false, - ); + let mut positions = + Pawn::authorized_positions([4, 4], PieceColor::White, board.board, &[], false); positions.sort(); assert_eq!(right_positions, positions); } @@ -241,13 +229,8 @@ mod tests { let mut right_positions = vec![vec![5, 4], vec![4, 4]]; right_positions.sort(); - let mut positions = Pawn::authorized_positions( - [6, 4], - PieceColor::White, - board.board, - &[(None, "0000".to_string())], - false, - ); + let mut positions = + Pawn::authorized_positions([6, 4], PieceColor::White, board.board, &[], false); positions.sort(); assert_eq!(right_positions, positions); } @@ -288,13 +271,8 @@ mod tests { let mut right_positions = vec![vec![2, 3], vec![3, 3], vec![2, 4], vec![2, 2]]; right_positions.sort(); - let mut positions = Pawn::authorized_positions( - [1, 3], - PieceColor::Black, - board.board, - &[(None, "0000".to_string())], - false, - ); + let mut positions = + Pawn::authorized_positions([1, 3], PieceColor::Black, board.board, &[], false); positions.sort(); assert_eq!(right_positions, positions); } @@ -335,13 +313,8 @@ mod tests { let mut right_positions = vec![vec![2, 4], vec![2, 2]]; right_positions.sort(); - let mut positions = Pawn::authorized_positions( - [1, 3], - PieceColor::Black, - board.board, - &[(None, "0000".to_string())], - false, - ); + let mut positions = + Pawn::authorized_positions([1, 3], PieceColor::Black, board.board, &[], false); positions.sort(); assert_eq!(right_positions, positions); } @@ -377,7 +350,13 @@ mod tests { [3, 3], PieceColor::White, board.board, - &[(Some(PieceType::Pawn), "1232".to_string())], + &[(PieceMove { + piece_type: PieceType::Pawn, + from_y: 1, + from_x: 2, + to_y: 3, + to_x: 2, + })], false, ); positions.sort(); @@ -415,7 +394,13 @@ mod tests { [4, 2], PieceColor::Black, board.board, - &[(Some(PieceType::Pawn), "6343".to_string())], + &[(PieceMove { + piece_type: PieceType::Pawn, + from_y: 6, + from_x: 3, + to_y: 4, + to_x: 3, + })], false, ); positions.sort(); @@ -462,7 +447,13 @@ mod tests { [1, 1], PieceColor::Black, board.board, - &[(Some(PieceType::Pawn), "6343".to_string())], + &[(PieceMove { + piece_type: PieceType::Pawn, + from_y: 6, + from_x: 3, + to_y: 4, + to_x: 3, + })], false, ); positions.sort(); diff --git a/src/pieces/queen.rs b/src/pieces/queen.rs index 7fa9ad9..19ea8ed 100644 --- a/src/pieces/queen.rs +++ b/src/pieces/queen.rs @@ -1,5 +1,5 @@ use super::rook::Rook; -use super::{Movable, PieceColor, PieceType, Position}; +use super::{Movable, PieceColor, PieceMove, PieceType, Position}; use crate::board::DisplayMode; use crate::pieces::bishop::Bishop; use crate::utils::{cleaned_positions, impossible_positions_king_checked}; @@ -12,7 +12,7 @@ impl Movable for Queen { color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], allow_move_on_ally_positions: bool, - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { let mut positions: Vec> = vec![]; @@ -41,7 +41,7 @@ impl Position for Queen { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], _is_king_checked: bool, ) -> Vec> { impossible_positions_king_checked( @@ -56,7 +56,7 @@ impl Position for Queen { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { Self::piece_move(coordinates, color, board, true, move_history) } diff --git a/src/pieces/rook.rs b/src/pieces/rook.rs index 7a8ad35..873e63b 100644 --- a/src/pieces/rook.rs +++ b/src/pieces/rook.rs @@ -1,4 +1,4 @@ -use super::{Movable, PieceColor, PieceType, Position}; +use super::{Movable, PieceColor, PieceMove, PieceType, Position}; use crate::board::DisplayMode; use crate::utils::{ cleaned_positions, get_piece_color, impossible_positions_king_checked, is_cell_color_ally, @@ -12,7 +12,7 @@ impl Movable for Rook { color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], allow_move_on_ally_positions: bool, - _move_history: &[(Option, String)], + _move_history: &[PieceMove], ) -> Vec> { // Pawns can only move in one direction depending on their color let mut positions: Vec> = vec![]; @@ -170,7 +170,7 @@ impl Position for Rook { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], _is_king_checked: bool, ) -> Vec> { // If the king is not checked we get then normal moves @@ -188,7 +188,7 @@ impl Position for Rook { coordinates: [i8; 2], color: PieceColor, board: [[Option<(PieceType, PieceColor)>; 8]; 8], - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { Self::piece_move(coordinates, color, board, true, move_history) } diff --git a/src/utils.rs b/src/utils.rs index f0f3525..78945ef 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,7 @@ use crate::{ board::{Board, DisplayMode}, constants::UNDEFINED_POSITION, - pieces::{PieceColor, PieceType}, + pieces::{PieceColor, PieceMove, PieceType}, }; use ratatui::{ layout::{Alignment, Rect}, @@ -72,7 +72,7 @@ pub fn is_vec_in_array(array: Vec>, element: [i8; 2]) -> bool { pub fn get_all_protected_cells( board: [[Option<(PieceType, PieceColor)>; 8]; 8], player_turn: PieceColor, - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { let mut check_cells: Vec> = vec![]; for i in 0..8i8 { @@ -165,25 +165,21 @@ pub fn get_int_from_char(ch: Option) -> i8 { } } -pub fn get_latest_move( - move_history: &[(Option, String)], -) -> (Option, String) { +pub fn get_latest_move(move_history: &[PieceMove]) -> Option { if !move_history.is_empty() { - return move_history[move_history.len() - 1].clone(); + return Some(move_history[move_history.len() - 1].clone()); } - (None, "0000".to_string()) + None } pub fn did_piece_already_move( - move_history: &[(Option, String)], + move_history: &[PieceMove], original_piece: (Option, [i8; 2]), ) -> bool { for entry in move_history { - let position = entry.1.clone(); - let from_y = get_int_from_char(position.chars().next()); - let from_x = get_int_from_char(position.chars().nth(1)); - // Here there is an entry with the same piece type and the same original position, meaning it moved at some point - if entry.0 == original_piece.0 && [from_y, from_x] == original_piece.1 { + if Some(entry.piece_type) == original_piece.0 + && [entry.from_y, entry.from_x] == original_piece.1 + { return true; } } @@ -210,7 +206,7 @@ pub fn get_king_coordinates( pub fn is_getting_checked( board: [[Option<(PieceType, PieceColor)>; 8]; 8], player_turn: PieceColor, - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> bool { let coordinates = get_king_coordinates(board, player_turn); @@ -229,7 +225,7 @@ pub fn impossible_positions_king_checked( positions: Vec>, board: [[Option<(PieceType, PieceColor)>; 8]; 8], color: PieceColor, - move_history: &[(Option, String)], + move_history: &[PieceMove], ) -> Vec> { let mut cleaned_position: Vec> = vec![]; for position in positions {