Skip to content

Commit

Permalink
Add castling support
Browse files Browse the repository at this point in the history
  • Loading branch information
oriolarcas committed Sep 2, 2023
1 parent bdafdcb commit b90fcbf
Show file tree
Hide file tree
Showing 7 changed files with 588 additions and 244 deletions.
2 changes: 2 additions & 0 deletions src-tauri/benches/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ fn search(bench: &mut Bencher) {
board: *initial_board(),
player: Player::White,
last_move: None,
info: Default::default(),
};

let best_branch = get_best_move_recursive(&mut game, 3).unwrap();
Expand All @@ -30,6 +31,7 @@ fn game_benchmark() -> u64 {
board: *initial_board(),
player: Player::White,
last_move: None,
info: Default::default(),
};
let get_best_move_helper = |game: &mut Game| {
let best_branch = get_best_move_recursive(game, 3).unwrap();
Expand Down
129 changes: 89 additions & 40 deletions src-tauri/src/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ impl Board {
self.rows[source.row][source.col] = None;
}

pub fn home_rank(player: &Player) -> usize {
match player {
Player::White => 0,
Player::Black => 7,
}
}

pub fn promotion_rank(player: &Player) -> usize {
match player {
Player::White => 7,
Expand All @@ -169,20 +176,20 @@ impl Board {
}
}

fn get_unicode_piece(piece: PieceType, player: Player) -> &'static str {
fn get_unicode_piece(piece: PieceType, player: Player) -> char {
match (player, piece) {
(Player::White, PieceType::Pawn) => "♙",
(Player::White, PieceType::Knight) => "♘",
(Player::White, PieceType::Bishop) => "♗",
(Player::White, PieceType::Rook) => "♖",
(Player::White, PieceType::Queen) => "♕",
(Player::White, PieceType::King) => "♔",
(Player::Black, PieceType::Pawn) => "♟︎",
(Player::Black, PieceType::Knight) => "♞",
(Player::Black, PieceType::Bishop) => "♝",
(Player::Black, PieceType::Rook) => "♜",
(Player::Black, PieceType::Queen) => "♛",
(Player::Black, PieceType::King) => "♚",
(Player::White, PieceType::Pawn) => '♙',
(Player::White, PieceType::Knight) => '♘',
(Player::White, PieceType::Bishop) => '♗',
(Player::White, PieceType::Rook) => '♖',
(Player::White, PieceType::Queen) => '♕',
(Player::White, PieceType::King) => '♔',
(Player::Black, PieceType::Pawn) => '♟',
(Player::Black, PieceType::Knight) => '♞',
(Player::Black, PieceType::Bishop) => '♝',
(Player::Black, PieceType::Rook) => '♜',
(Player::Black, PieceType::Queen) => '♛',
(Player::Black, PieceType::King) => '♚',
}
}

Expand Down Expand Up @@ -292,36 +299,10 @@ const INITIAL_BOARD: Board = Board {
],
};

const CHECK_MATE_BOARD: Board = Board {
rows: [
[
p!(rw),
p!(nw),
p!(bw),
p!(qw),
p!(kw),
p!(bw),
p!(nw),
p!(rw),
],
[p!(); 8],
[p!(); 8],
[p!(); 8],
[p!(); 8],
[p!(); 8],
[p!(); 8],
[p!(), p!(), p!(), p!(), p!(kb), p!(), p!(), p!()],
],
};

pub const fn initial_board() -> &'static Board {
&INITIAL_BOARD
}

pub const fn check_mate_board() -> &'static Board {
&CHECK_MATE_BOARD
}

#[derive(Copy, Clone, PartialEq, Serialize)]
pub struct Position {
pub row: usize,
Expand Down Expand Up @@ -573,7 +554,8 @@ pub enum MoveExtraInfo {
Promotion(PieceType),
Passed,
EnPassant,
// Castle,
CastleKingside,
CastleQueenside,
}

#[derive(Copy, Clone, Serialize)]
Expand All @@ -582,9 +564,76 @@ pub struct MoveInfo {
pub info: MoveExtraInfo,
}

#[derive(Copy, Clone, Serialize)]
pub struct GameInfo {
white_kingside_castling_allowed: bool,
white_queenside_castling_allowed: bool,
black_kingside_castling_allowed: bool,
black_queenside_castling_allowed: bool,
}

impl GameInfo {
pub const fn new() -> GameInfo {
Self {
white_kingside_castling_allowed: true,
white_queenside_castling_allowed: true,
black_kingside_castling_allowed: true,
black_queenside_castling_allowed: true,
}
}

pub fn can_castle_kingside(&self, player: &Player) -> bool {
match player {
Player::White => self.white_kingside_castling_allowed,
Player::Black => self.black_kingside_castling_allowed,
}
}

pub fn can_castle_queenside(&self, player: &Player) -> bool {
match player {
Player::White => self.white_queenside_castling_allowed,
Player::Black => self.black_queenside_castling_allowed,
}
}

pub fn disable_castle_kingside(&mut self, player: &Player) {
match player {
Player::White => self.white_kingside_castling_allowed = false,
Player::Black => self.black_kingside_castling_allowed = false,
}
}

pub fn disable_castle_queenside(&mut self, player: &Player) {
match player {
Player::White => self.white_queenside_castling_allowed = false,
Player::Black => self.black_queenside_castling_allowed = false,
}
}
}

impl fmt::Display for GameInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{{white: {{kingside: {}, queenside: {}}}, black: {{kingside: {}, queenside: {}}}",
self.white_kingside_castling_allowed,
self.white_queenside_castling_allowed,
self.black_kingside_castling_allowed,
self.black_queenside_castling_allowed
)
}
}

impl Default for GameInfo {
fn default() -> Self {
GameInfo::new()
}
}

#[derive(Copy, Clone, Serialize)]
pub struct Game {
pub board: Board,
pub player: Player,
pub last_move: Option<MoveInfo>,
pub info: GameInfo,
}
29 changes: 17 additions & 12 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use chusst::board::{initial_board, Game, Move, Piece, Player, Position};
use chusst::board::{initial_board, Game, GameInfo, Move, Piece, Player, Position};
use chusst::moves;
use chusst::moves::MateType;

Expand Down Expand Up @@ -33,6 +33,7 @@ static GAME: Mutex<GameData> = Mutex::new(GameData {
board: *initial_board(),
player: Player::White,
last_move: None,
info: GameInfo::new(),
},
history: vec![],
});
Expand All @@ -52,14 +53,15 @@ fn get_history() -> Vec<TurnDescription> {
fn get_possible_moves(row: usize, col: usize) -> Vec<Position> {
let position = Position { row, col };
let game = &mut GAME.lock().unwrap().game;
let possible_moves = moves::get_possible_moves(&game.board, &game.last_move, position);
let possible_moves =
moves::get_possible_moves(&game.board, &game.last_move, &game.info, position);
possible_moves
}

#[tauri::command]
fn get_possible_captures() -> moves::BoardCaptures {
let game = &mut GAME.lock().unwrap().game;
moves::get_possible_captures(&game.board, &game.last_move)
moves::get_possible_captures(&game.board, &game.last_move, &game.info)
}

#[tauri::command(rename_all = "snake_case")]
Expand All @@ -77,13 +79,14 @@ fn do_move(source_row: usize, source_col: usize, target_row: usize, target_col:
let game_data = &mut GAME.lock().unwrap();
let game = &mut game_data.game;

let white_move = match moves::move_name(&game.board, &game.last_move, &game.player, &mv) {
Some(name) => name,
None => {
println!("Invalid move: {}", mv);
return false;
}
};
let white_move =
match moves::move_name(&game.board, &game.last_move, &game.info, &game.player, &mv) {
Some(name) => name,
None => {
println!("Invalid move: {}", mv);
return false;
}
};

let white_captures = match moves::do_move(game, &mv) {
Some(captures) => captures,
Expand All @@ -95,12 +98,13 @@ fn do_move(source_row: usize, source_col: usize, target_row: usize, target_col:

let (black_move_opt, black_captures, mate) = match moves::get_best_move(game, 3) {
moves::GameMove::Normal(mv) => {
let description = moves::move_name(&game.board, &game.last_move, &game.player, &mv);
let description =
moves::move_name(&game.board, &game.last_move, &game.info, &game.player, &mv);

let black_captures = moves::do_move(game, &mv);
assert!(black_captures.is_some());

let black_mate = moves::is_mate(&game.board, &game.player, &game.last_move);
let black_mate = moves::is_mate(&game.board, &game.player, &game.last_move, &game.info);

(description, black_captures.unwrap(), black_mate)
}
Expand Down Expand Up @@ -155,6 +159,7 @@ fn restart() {
board: *initial_board(),
player: Player::White,
last_move: None,
info: Default::default(),
};

data.history.clear();
Expand Down
Loading

0 comments on commit b90fcbf

Please sign in to comment.