Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better History System #68

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 153 additions & 72 deletions src/board.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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<PieceType>, String)>,
pub move_history: Vec<PieceMove>,
pub is_draw: bool,
pub is_checkmate: bool,
pub is_promotion: bool,
Expand Down Expand Up @@ -110,7 +110,7 @@ impl Board {
pub fn new(
board: [[Option<(PieceType, PieceColor)>; 8]; 8],
player_turn: PieceColor,
move_history: Vec<(Option<PieceType>, String)>,
move_history: Vec<PieceMove>,
) -> Self {
Self {
board,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(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));
if let Some(last_move) = self.move_history.last() {
let mut converted_move = String::new();

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(" -");
Expand All @@ -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));

let distance = (to_y - from_y).abs();
Some(last_move) => {
let distance = (last_move.to_y - last_move.from_y).abs();

if piece_type == &PieceType::Pawn && distance == 2 {
if last_move.piece_type == PieceType::Pawn && distance == 2 {
return true;
}
return false;
Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -506,20 +489,23 @@ 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;
}
_ => {
self.consecutive_non_pawn_or_capture += 1;
}
}

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
Expand Down Expand Up @@ -571,7 +557,13 @@ 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) {
Expand Down Expand Up @@ -634,19 +626,18 @@ 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]) {
if let Some(last_move) = self.move_history.last() {
if let Some(piece_type_to) = get_piece_type(self.board, [last_move.to_y, last_move.to_x])
{
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 {
if last_move.to_y == last_row && piece_type_to == PieceType::Pawn {
return true;
}
}
Expand All @@ -665,7 +656,7 @@ impl Board {

pub fn draw_by_repetition(&self) -> bool {
if self.move_history.len() >= 9 {
let last_ten: Vec<(Option<PieceType>, String)> =
let last_ten: Vec<PieceMove> =
self.move_history.iter().rev().take(9).cloned().collect();

if (last_ten[0].clone(), last_ten[1].clone())
Expand Down Expand Up @@ -807,22 +798,32 @@ impl Board {
let mut lines: Vec<Line> = 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))
}
Expand Down Expand Up @@ -866,7 +867,7 @@ impl Board {
mod tests {
use crate::{
board::Board,
pieces::{PieceColor, PieceType},
pieces::{PieceColor, PieceMove, PieceType},
utils::is_getting_checked,
};

Expand Down Expand Up @@ -1348,7 +1349,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());
Expand Down Expand Up @@ -1395,7 +1404,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());
Expand Down Expand Up @@ -1498,7 +1515,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());
Expand Down Expand Up @@ -1592,7 +1617,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());
}

Expand Down Expand Up @@ -1622,14 +1647,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,
}),
],
);

Expand Down Expand Up @@ -1720,7 +1793,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
Expand Down
Loading
Loading