|
@@ -1,303 +1,34 @@
|
|
use bitboard::*;
|
|
use bitboard::*;
|
|
use movegen::*;
|
|
use movegen::*;
|
|
|
|
|
|
|
|
+enum MoveUndo {
|
|
|
|
+ Default {
|
|
|
|
+ piece_type: PieceType,
|
|
|
|
+ before: Bitboard,
|
|
|
|
+ captured_type: PieceType,
|
|
|
|
+ captured_before: Bitboard,
|
|
|
|
+ },
|
|
|
|
+ Castling { rooks_before: Bitboard, king_before: Bitboard },
|
|
|
|
+ Promotion {
|
|
|
|
+ promoted_to: PieceType,
|
|
|
|
+ promoted_to_before: Bitboard,
|
|
|
|
|
|
-pub struct Game
|
|
|
|
-{
|
|
|
|
- pub pieces: [Bitboard; 12],
|
|
|
|
- en_passant: u8,
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-impl Default for Game {
|
|
|
|
- fn default () -> Game {
|
|
|
|
- Game {
|
|
|
|
- pieces: [
|
|
|
|
- ROW_2,
|
|
|
|
- 0x42,
|
|
|
|
- 0x24,
|
|
|
|
- 0x81,
|
|
|
|
- 0x10,
|
|
|
|
- 0x08,
|
|
|
|
- ROW_7,
|
|
|
|
- 0x42 << 56,
|
|
|
|
- 0x24 << 56,
|
|
|
|
- 0x81 << 56,
|
|
|
|
- 0x10 << 56,
|
|
|
|
- 0x08 << 56,
|
|
|
|
- ],
|
|
|
|
- en_passant: 0,
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-impl Game {
|
|
|
|
-
|
|
|
|
- pub fn from_fen(fen: &str) -> Option<Game> {
|
|
|
|
- let mut game: Game = Game::default();
|
|
|
|
- let example = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
|
|
|
- let mut fen_parts = fen.split_whitespace();
|
|
|
|
-
|
|
|
|
- match fen_parts.next() {
|
|
|
|
- Some(position) => {
|
|
|
|
- let rows = position.split('/');
|
|
|
|
- let mut row_index = 0;
|
|
|
|
- for row in rows {
|
|
|
|
- if row_index >= 8 {
|
|
|
|
- return None;
|
|
|
|
- }
|
|
|
|
- let mut col_index = 0;
|
|
|
|
- for c in row.chars() {
|
|
|
|
-
|
|
|
|
- if col_index >= 8 {
|
|
|
|
- return None;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- let bit_to_set = single_bit_board(col_index, row_index);
|
|
|
|
- match c {
|
|
|
|
- 'p' => { *game.pawns_mut(BLACK) |= bit_to_set },
|
|
|
|
- 'k' => { *game.knights_mut(BLACK) |= bit_to_set },
|
|
|
|
- 'b' => { *game.bishops_mut(BLACK) |= bit_to_set },
|
|
|
|
- 'r' => { *game.rooks_mut(BLACK) |= bit_to_set },
|
|
|
|
- 'q' => { *game.queens_mut(BLACK) |= bit_to_set },
|
|
|
|
- 'k' => { *game.kings_mut(BLACK) |= bit_to_set },
|
|
|
|
- 'P' => { *game.pawns_mut(WHITE) |= bit_to_set },
|
|
|
|
- 'K' => { *game.knights_mut(WHITE) |= bit_to_set },
|
|
|
|
- 'B' => { *game.bishops_mut(WHITE) |= bit_to_set },
|
|
|
|
- 'R' => { *game.rooks_mut(WHITE) |= bit_to_set },
|
|
|
|
- 'Q' => { *game.queens_mut(WHITE) |= bit_to_set },
|
|
|
|
- 'K' => { *game.kings_mut(WHITE) |= bit_to_set },
|
|
|
|
- num => {
|
|
|
|
- col_index += match num.to_digit(10) { Some(x) => x, None => {
|
|
|
|
- return None;
|
|
|
|
- }} as u8 - 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- col_index += 1;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- None => return None
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- None
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn bitboard(&self, pt: PieceType, side: Side) -> Bitboard {
|
|
|
|
- if side == BLACK {
|
|
|
|
- self.pieces[(pt + 6) as usize]
|
|
|
|
- } else {
|
|
|
|
- self.pieces[pt as usize]
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * \return bitboard containig all occupied squares
|
|
|
|
- */
|
|
|
|
- pub fn occupied(&self) -> Bitboard {
|
|
|
|
- self.pieces.into_iter().fold(0, |a, b| { a | b } )
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn pawns(&self, side: Side) -> Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => self.pieces[0],
|
|
|
|
- BLACK => self.pieces[6],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn knights(&self, side: Side) -> Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => self.pieces[1],
|
|
|
|
- BLACK => self.pieces[7],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn bishops(&self, side: Side) -> Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => self.pieces[2],
|
|
|
|
- BLACK => self.pieces[8],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn rooks(&self, side: Side) -> Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => self.pieces[3],
|
|
|
|
- BLACK => self.pieces[9],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn queens(&self, side: Side) -> Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => self.pieces[4],
|
|
|
|
- BLACK => self.pieces[10],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn kings(&self, side: Side) -> Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => self.pieces[5],
|
|
|
|
- BLACK => self.pieces[11],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn pawns_mut(&mut self, side: Side) -> &mut Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => &mut self.pieces[0],
|
|
|
|
- BLACK => &mut self.pieces[6],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn knights_mut(&mut self, side: Side) -> &mut Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => &mut self.pieces[1],
|
|
|
|
- BLACK => &mut self.pieces[7],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn bishops_mut(&mut self, side: Side) -> &mut Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => &mut self.pieces[2],
|
|
|
|
- BLACK => &mut self.pieces[8],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn rooks_mut(&mut self, side: Side) -> &mut Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => &mut self.pieces[3],
|
|
|
|
- BLACK => &mut self.pieces[9],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn queens_mut(&mut self, side: Side) -> &mut Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => &mut self.pieces[4],
|
|
|
|
- BLACK => &mut self.pieces[10],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn kings_mut(&mut self, side: Side) -> &mut Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => &mut self.pieces[5],
|
|
|
|
- BLACK => &mut self.pieces[11],
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn get_all_side(&self, side: Side) -> Bitboard {
|
|
|
|
- match side {
|
|
|
|
- WHITE => self.pieces[0] | self.pieces[1] | self.pieces[2] | self.pieces[3] |
|
|
|
|
- self.pieces[4] | self.pieces[5],
|
|
|
|
- BLACK => self.pieces[6] | self.pieces[7] | self.pieces[8] | self.pieces[9] |
|
|
|
|
- self.pieces[10] | self.pieces[11]
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn get_square(&self, square: Square) -> (PieceType, Side) {
|
|
|
|
- let square_mask = 1 << square;
|
|
|
|
- for i in 0..6 {
|
|
|
|
- if self.pieces[i] & square_mask != 0 {
|
|
|
|
- return (i as PieceType, WHITE);
|
|
|
|
- }
|
|
|
|
- if self.pieces[i + 6] & square_mask != 0 {
|
|
|
|
- return (i as PieceType, BLACK);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return (NO_PIECE, WHITE);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @brief creates a unicode string containing the board
|
|
|
|
- *
|
|
|
|
- * Example:
|
|
|
|
- *
|
|
|
|
- * ┌───┬───┬───┬───┬───┬───┬───┬───┐
|
|
|
|
- * 8 │ ♜ │ ♞ │ ♝ │ ♛ │ ♚ │ ♝ │ ♞ │ ♜ │
|
|
|
|
- * ├───┼───┼───┼───┼───┼───┼───┼───┤
|
|
|
|
- * 7 │ ♟ │ ♟ │ ♟ │ ♟ │ ♟ │ ♟ │ ♟ │ ♟ │
|
|
|
|
- * ├───┼───┼───┼───┼───┼───┼───┼───┤
|
|
|
|
- * 6 │ │ │ │ │ │ │ │ │
|
|
|
|
- * ├───┼───┼───┼───┼───┼───┼───┼───┤
|
|
|
|
- * 5 │ │ │ │ │ │ │ │ │
|
|
|
|
- * ├───┼───┼───┼───┼───┼───┼───┼───┤
|
|
|
|
- * 4 │ │ │ │ │ │ │ │ │
|
|
|
|
- * ├───┼───┼───┼───┼───┼───┼───┼───┤
|
|
|
|
- * 3 │ │ │ │ │ │ │ │ │
|
|
|
|
- * ├───┼───┼───┼───┼───┼───┼───┼───┤
|
|
|
|
- * 2 │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │ ♙ │
|
|
|
|
- * ├───┼───┼───┼───┼───┼───┼───┼───┤
|
|
|
|
- * 1 │ ♖ │ ♘ │ ♗ │ ♕ │ ♔ │ ♗ │ ♘ │ ♖ │
|
|
|
|
- * └───┴───┴───┴───┴───┴───┴───┴───┘
|
|
|
|
- * a b c d e f g h
|
|
|
|
- *
|
|
|
|
- */
|
|
|
|
- pub fn beautiful_print(&self) -> String {
|
|
|
|
- let chars = ['─', '│', '┌', '┐', '└', '┘', '├', '┤', '┬', '┴', '┼'];
|
|
|
|
- let figures = ['♙', '♘', '♗', '♖', '♕', '♔', '♟', '♞', '♝', '♜', '♛', '♚'];
|
|
|
|
- let mut board: String = String::new();
|
|
|
|
-
|
|
|
|
- #[derive(Copy, Clone)]
|
|
|
|
- struct GridLine {
|
|
|
|
- left: char,
|
|
|
|
- center: char,
|
|
|
|
- right: char,
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- let top = GridLine { left: chars[2], center: chars[8], right: chars[3] };
|
|
|
|
- let center = GridLine { left: chars[6], center: chars[10], right: chars[7] };
|
|
|
|
- let bot = GridLine { left: chars[4], center: chars[9], right: chars[5] };
|
|
|
|
-
|
|
|
|
- let generate_line = |gl: GridLine| {
|
|
|
|
- let mut line = String::new();
|
|
|
|
- for i in 0..33 {
|
|
|
|
- match i {
|
|
|
|
- 0 => { line.push(gl.left) }
|
|
|
|
- 32 => { line.push(gl.right) }
|
|
|
|
- x => { line.push(if x % 4 == 0 { gl.center } else { chars[0] }) }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return line;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- let piece_line = |row: u8| {
|
|
|
|
- let mut line = String::new();
|
|
|
|
- line.push(chars[1]);
|
|
|
|
- line.push(' ');
|
|
|
|
- for i in 0..8 {
|
|
|
|
- let (pt, side) = self.get_square(square_from_indices(i, row));
|
|
|
|
- if pt == NO_PIECE {
|
|
|
|
- line.push(' ');
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- let fig_index = pt as usize + if side == BLACK { 6 } else { 0 };
|
|
|
|
- line.push(figures[fig_index]);
|
|
|
|
- }
|
|
|
|
- line.push(' '); line.push(chars[1]); line.push(' ');
|
|
|
|
- }
|
|
|
|
- return line;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- board.push_str(" ");
|
|
|
|
- board.push_str(&generate_line(top));
|
|
|
|
- board.push('\n');
|
|
|
|
- for i in 0..8 {
|
|
|
|
- board.push_str(&(8 - i).to_string());
|
|
|
|
- board.push(' ');
|
|
|
|
- board.push_str(&piece_line(i));
|
|
|
|
- board.push('\n');
|
|
|
|
- if i != 7 {
|
|
|
|
- board.push_str(" ");
|
|
|
|
- board.push_str(&generate_line(center));
|
|
|
|
- board.push('\n');
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- board.push_str(" ");
|
|
|
|
- board.push_str(&generate_line(bot));
|
|
|
|
- board.push_str("\n a b c d e f g h");
|
|
|
|
-
|
|
|
|
- return board;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+//01 function negamax(node, depth, color)
|
|
|
|
+//02 if depth = 0 or node is a terminal node
|
|
|
|
+//03 return color * the heuristic value of node
|
|
|
|
+//
|
|
|
|
+//04 bestValue := −∞
|
|
|
|
+//05 foreach child of node
|
|
|
|
+//06 v := −negamax(child, depth − 1, −color)
|
|
|
|
+//07 bestValue := max( bestValue, v )
|
|
|
|
+//08 return bestValue
|
|
pub fn search() {
|
|
pub fn search() {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*fn negamax(game: &Game, depth: i32) {
|
|
|
|
|
|
|
|
+}*/
|