engine: use rays for move generation

This commit is contained in:
dece 2020-06-21 15:57:58 +02:00
parent ce62d3ab3a
commit 9595d0f435
12 changed files with 799 additions and 295 deletions

View file

@ -3,7 +3,7 @@
TEMPLATE = """\ TEMPLATE = """\
/// Pre-computed king rays. /// Pre-computed king rays.
const KING_RAYS: [Bitboard; 64] = [ pub const KING_RAYS: [Bitboard; 64] = [
{} {}
]; ];
""" """

View file

@ -3,7 +3,7 @@
TEMPLATE = """\ TEMPLATE = """\
/// Pre-computed knight rays. /// Pre-computed knight rays.
const KNIGHT_RAYS: [Bitboard; 64] = [ pub const KNIGHT_RAYS: [Bitboard; 64] = [
{} {}
]; ];
""" """

View file

@ -0,0 +1,39 @@
#!/usr/bin/env python3
"""Pre-compute pawn captures bitboards for each square."""
TEMPLATE = """\
/// Pre-computed pawn captures.
pub const PAWN_CAPTURES: [[Bitboard; 64]; 2] = [
[
{}
],
[
{}
],
];
"""
def bit_pos(square):
return 1 << square
def get_captures():
both_captures = []
for direction in [1, -1]:
captures = []
for f in range(8):
for r in range(8):
bitboard = 0
prog_r = r + direction
if 0 < prog_r < 7:
prev_f = f - 1
if prev_f >= 0:
bitboard |= bit_pos(prev_f * 8 + prog_r)
next_f = f + 1
if next_f <= 7:
bitboard |= bit_pos(next_f * 8 + prog_r)
captures.append(" 0b{:064b},".format(bitboard))
both_captures.append(captures)
return both_captures
CAPTURES = get_captures()
print(TEMPLATE.format("\n".join(CAPTURES[0]), "\n".join(CAPTURES[1])))

View file

@ -0,0 +1,38 @@
#!/usr/bin/env python3
"""Pre-compute pawn progress bitboards for each square."""
TEMPLATE = """\
/// Pre-computed pawn progresses.
pub const PAWN_PROGRESSES: [[Bitboard; 64]; 2] = [
[
{}
],
[
{}
],
];
"""
def bit_pos(square):
return 1 << square
def get_progresses():
both_progresses = []
for direction in [1, -1]:
progresses = []
for f in range(8):
for r in range(8):
bitboard = 0
if 0 < r < 7:
prog_r = r + direction
bitboard |= bit_pos(f * 8 + prog_r)
if direction == 1 and r == 1:
bitboard |= bit_pos(f * 8 + prog_r + 1)
elif direction == -1 and r == 6:
bitboard |= bit_pos(f * 8 + (prog_r - 1))
progresses.append(" 0b{:064b},".format(bitboard))
both_progresses.append(progresses)
return both_progresses
PROGRESSES = get_progresses()
print(TEMPLATE.format("\n".join(PROGRESSES[0]), "\n".join(PROGRESSES[1])))

View file

@ -1,5 +1,7 @@
//! Basic type definitions and functions. //! Basic type definitions and functions.
pub use crate::precomputed::*;
/// Color type, used to index `Board.color`. /// Color type, used to index `Board.color`.
pub type Color = usize; pub type Color = usize;
@ -34,73 +36,6 @@ pub const NUM_PIECES: usize = 6;
/// Coords (file, rank) of a square on a board. /// Coords (file, rank) of a square on a board.
pub type Square = i8; pub type Square = i8;
// Generated by gen_squares.py.
pub const A1: Square = 0;
pub const A2: Square = 1;
pub const A3: Square = 2;
pub const A4: Square = 3;
pub const A5: Square = 4;
pub const A6: Square = 5;
pub const A7: Square = 6;
pub const A8: Square = 7;
pub const B1: Square = 8;
pub const B2: Square = 9;
pub const B3: Square = 10;
pub const B4: Square = 11;
pub const B5: Square = 12;
pub const B6: Square = 13;
pub const B7: Square = 14;
pub const B8: Square = 15;
pub const C1: Square = 16;
pub const C2: Square = 17;
pub const C3: Square = 18;
pub const C4: Square = 19;
pub const C5: Square = 20;
pub const C6: Square = 21;
pub const C7: Square = 22;
pub const C8: Square = 23;
pub const D1: Square = 24;
pub const D2: Square = 25;
pub const D3: Square = 26;
pub const D4: Square = 27;
pub const D5: Square = 28;
pub const D6: Square = 29;
pub const D7: Square = 30;
pub const D8: Square = 31;
pub const E1: Square = 32;
pub const E2: Square = 33;
pub const E3: Square = 34;
pub const E4: Square = 35;
pub const E5: Square = 36;
pub const E6: Square = 37;
pub const E7: Square = 38;
pub const E8: Square = 39;
pub const F1: Square = 40;
pub const F2: Square = 41;
pub const F3: Square = 42;
pub const F4: Square = 43;
pub const F5: Square = 44;
pub const F6: Square = 45;
pub const F7: Square = 46;
pub const F8: Square = 47;
pub const G1: Square = 48;
pub const G2: Square = 49;
pub const G3: Square = 50;
pub const G4: Square = 51;
pub const G5: Square = 52;
pub const G6: Square = 53;
pub const G7: Square = 54;
pub const G8: Square = 55;
pub const H1: Square = 56;
pub const H2: Square = 57;
pub const H3: Square = 58;
pub const H4: Square = 59;
pub const H5: Square = 60;
pub const H6: Square = 61;
pub const H7: Square = 62;
pub const H8: Square = 63;
pub const NUM_SQUARES: Square = 64;
/// Get square from file and rank, both starting from 0. /// Get square from file and rank, both starting from 0.
#[inline] #[inline]
pub const fn sq(file: i8, rank: i8) -> Square { file * 8 + rank } pub const fn sq(file: i8, rank: i8) -> Square { file * 8 + rank }
@ -135,6 +70,11 @@ pub fn sq_to_string(square: Square) -> String {
String::from_utf8_lossy(&bytes).to_string() String::from_utf8_lossy(&bytes).to_string()
} }
/// Return the forward square for either white or black.
pub fn forward_square(square: Square, color: Color) -> Square {
sq(sq_file(square), sq_rank(square) + (if color == WHITE { 1 } else { -1 }))
}
/// Bitboard for color or piece bits. /// Bitboard for color or piece bits.
pub type Bitboard = u64; pub type Bitboard = u64;
@ -204,156 +144,18 @@ pub fn count_bits(bitboard: Bitboard) -> u8 {
count as u8 count as u8
} }
/// Debug only: pretty print a bitboard /// Debug only: pretty-print a bitboard to stderr.
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn draw_bits(bitboard: Bitboard, f: &mut dyn std::io::Write) { pub(crate) fn draw_bits(bitboard: Bitboard) {
for rank in (0..8).rev() { for rank in (0..8).rev() {
let mut rank_str = String::with_capacity(8); let mut rank_str = String::with_capacity(8);
for file in 0..8 { for file in 0..8 {
rank_str.push(if bitboard & bit_pos(sq(file, rank)) == 0 { '.' } else { '1' }); rank_str.push(if bitboard & bit_pos(sq(file, rank)) == 0 { '.' } else { '1' });
} }
writeln!(f, "{}", rank_str).unwrap(); eprintln!("{}", rank_str);
} }
} }
// Generated by gen_king_rays.py.
/// Pre-computed king rays.
const KING_RAYS: [Bitboard; 64] = [
0b00000000_00000000_00000000_00000000_00000000_00000000_00000011_00000010,
0b00000000_00000000_00000000_00000000_00000000_00000000_00000111_00000101,
0b00000000_00000000_00000000_00000000_00000000_00000000_00001110_00001010,
0b00000000_00000000_00000000_00000000_00000000_00000000_00011100_00010100,
0b00000000_00000000_00000000_00000000_00000000_00000000_00111000_00101000,
0b00000000_00000000_00000000_00000000_00000000_00000000_01110000_01010000,
0b00000000_00000000_00000000_00000000_00000000_00000000_11100000_10100000,
0b00000000_00000000_00000000_00000000_00000000_00000000_11000000_01000000,
0b00000000_00000000_00000000_00000000_00000000_00000011_00000010_00000011,
0b00000000_00000000_00000000_00000000_00000000_00000111_00000101_00000111,
0b00000000_00000000_00000000_00000000_00000000_00001110_00001010_00001110,
0b00000000_00000000_00000000_00000000_00000000_00011100_00010100_00011100,
0b00000000_00000000_00000000_00000000_00000000_00111000_00101000_00111000,
0b00000000_00000000_00000000_00000000_00000000_01110000_01010000_01110000,
0b00000000_00000000_00000000_00000000_00000000_11100000_10100000_11100000,
0b00000000_00000000_00000000_00000000_00000000_11000000_01000000_11000000,
0b00000000_00000000_00000000_00000000_00000011_00000010_00000011_00000000,
0b00000000_00000000_00000000_00000000_00000111_00000101_00000111_00000000,
0b00000000_00000000_00000000_00000000_00001110_00001010_00001110_00000000,
0b00000000_00000000_00000000_00000000_00011100_00010100_00011100_00000000,
0b00000000_00000000_00000000_00000000_00111000_00101000_00111000_00000000,
0b00000000_00000000_00000000_00000000_01110000_01010000_01110000_00000000,
0b00000000_00000000_00000000_00000000_11100000_10100000_11100000_00000000,
0b00000000_00000000_00000000_00000000_11000000_01000000_11000000_00000000,
0b00000000_00000000_00000000_00000011_00000010_00000011_00000000_00000000,
0b00000000_00000000_00000000_00000111_00000101_00000111_00000000_00000000,
0b00000000_00000000_00000000_00001110_00001010_00001110_00000000_00000000,
0b00000000_00000000_00000000_00011100_00010100_00011100_00000000_00000000,
0b00000000_00000000_00000000_00111000_00101000_00111000_00000000_00000000,
0b00000000_00000000_00000000_01110000_01010000_01110000_00000000_00000000,
0b00000000_00000000_00000000_11100000_10100000_11100000_00000000_00000000,
0b00000000_00000000_00000000_11000000_01000000_11000000_00000000_00000000,
0b00000000_00000000_00000011_00000010_00000011_00000000_00000000_00000000,
0b00000000_00000000_00000111_00000101_00000111_00000000_00000000_00000000,
0b00000000_00000000_00001110_00001010_00001110_00000000_00000000_00000000,
0b00000000_00000000_00011100_00010100_00011100_00000000_00000000_00000000,
0b00000000_00000000_00111000_00101000_00111000_00000000_00000000_00000000,
0b00000000_00000000_01110000_01010000_01110000_00000000_00000000_00000000,
0b00000000_00000000_11100000_10100000_11100000_00000000_00000000_00000000,
0b00000000_00000000_11000000_01000000_11000000_00000000_00000000_00000000,
0b00000000_00000011_00000010_00000011_00000000_00000000_00000000_00000000,
0b00000000_00000111_00000101_00000111_00000000_00000000_00000000_00000000,
0b00000000_00001110_00001010_00001110_00000000_00000000_00000000_00000000,
0b00000000_00011100_00010100_00011100_00000000_00000000_00000000_00000000,
0b00000000_00111000_00101000_00111000_00000000_00000000_00000000_00000000,
0b00000000_01110000_01010000_01110000_00000000_00000000_00000000_00000000,
0b00000000_11100000_10100000_11100000_00000000_00000000_00000000_00000000,
0b00000000_11000000_01000000_11000000_00000000_00000000_00000000_00000000,
0b00000011_00000010_00000011_00000000_00000000_00000000_00000000_00000000,
0b00000111_00000101_00000111_00000000_00000000_00000000_00000000_00000000,
0b00001110_00001010_00001110_00000000_00000000_00000000_00000000_00000000,
0b00011100_00010100_00011100_00000000_00000000_00000000_00000000_00000000,
0b00111000_00101000_00111000_00000000_00000000_00000000_00000000_00000000,
0b01110000_01010000_01110000_00000000_00000000_00000000_00000000_00000000,
0b11100000_10100000_11100000_00000000_00000000_00000000_00000000_00000000,
0b11000000_01000000_11000000_00000000_00000000_00000000_00000000_00000000,
0b00000010_00000011_00000000_00000000_00000000_00000000_00000000_00000000,
0b00000101_00000111_00000000_00000000_00000000_00000000_00000000_00000000,
0b00001010_00001110_00000000_00000000_00000000_00000000_00000000_00000000,
0b00010100_00011100_00000000_00000000_00000000_00000000_00000000_00000000,
0b00101000_00111000_00000000_00000000_00000000_00000000_00000000_00000000,
0b01010000_01110000_00000000_00000000_00000000_00000000_00000000_00000000,
0b10100000_11100000_00000000_00000000_00000000_00000000_00000000_00000000,
0b01000000_11000000_00000000_00000000_00000000_00000000_00000000_00000000,
];
// Generated by gen_knight_rays.py.
/// Pre-computed knight rays.
const KNIGHT_RAYS: [Bitboard; 64] = [
0b00000000_00000000_00000000_00000000_00000000_00000010_00000100_00000000,
0b00000000_00000000_00000000_00000000_00000000_00000101_00001000_00000000,
0b00000000_00000000_00000000_00000000_00000000_00001010_00010001_00000000,
0b00000000_00000000_00000000_00000000_00000000_00010100_00100010_00000000,
0b00000000_00000000_00000000_00000000_00000000_00101000_01000100_00000000,
0b00000000_00000000_00000000_00000000_00000000_01010000_10001000_00000000,
0b00000000_00000000_00000000_00000000_00000000_10100000_00010000_00000000,
0b00000000_00000000_00000000_00000000_00000000_01000000_00100000_00000000,
0b00000000_00000000_00000000_00000000_00000010_00000100_00000000_00000100,
0b00000000_00000000_00000000_00000000_00000101_00001000_00000000_00001000,
0b00000000_00000000_00000000_00000000_00001010_00010001_00000000_00010001,
0b00000000_00000000_00000000_00000000_00010100_00100010_00000000_00100010,
0b00000000_00000000_00000000_00000000_00101000_01000100_00000000_01000100,
0b00000000_00000000_00000000_00000000_01010000_10001000_00000000_10001000,
0b00000000_00000000_00000000_00000000_10100000_00010000_00000000_00010000,
0b00000000_00000000_00000000_00000000_01000000_00100000_00000000_00100000,
0b00000000_00000000_00000000_00000010_00000100_00000000_00000100_00000010,
0b00000000_00000000_00000000_00000101_00001000_00000000_00001000_00000101,
0b00000000_00000000_00000000_00001010_00010001_00000000_00010001_00001010,
0b00000000_00000000_00000000_00010100_00100010_00000000_00100010_00010100,
0b00000000_00000000_00000000_00101000_01000100_00000000_01000100_00101000,
0b00000000_00000000_00000000_01010000_10001000_00000000_10001000_01010000,
0b00000000_00000000_00000000_10100000_00010000_00000000_00010000_10100000,
0b00000000_00000000_00000000_01000000_00100000_00000000_00100000_01000000,
0b00000000_00000000_00000010_00000100_00000000_00000100_00000010_00000000,
0b00000000_00000000_00000101_00001000_00000000_00001000_00000101_00000000,
0b00000000_00000000_00001010_00010001_00000000_00010001_00001010_00000000,
0b00000000_00000000_00010100_00100010_00000000_00100010_00010100_00000000,
0b00000000_00000000_00101000_01000100_00000000_01000100_00101000_00000000,
0b00000000_00000000_01010000_10001000_00000000_10001000_01010000_00000000,
0b00000000_00000000_10100000_00010000_00000000_00010000_10100000_00000000,
0b00000000_00000000_01000000_00100000_00000000_00100000_01000000_00000000,
0b00000000_00000010_00000100_00000000_00000100_00000010_00000000_00000000,
0b00000000_00000101_00001000_00000000_00001000_00000101_00000000_00000000,
0b00000000_00001010_00010001_00000000_00010001_00001010_00000000_00000000,
0b00000000_00010100_00100010_00000000_00100010_00010100_00000000_00000000,
0b00000000_00101000_01000100_00000000_01000100_00101000_00000000_00000000,
0b00000000_01010000_10001000_00000000_10001000_01010000_00000000_00000000,
0b00000000_10100000_00010000_00000000_00010000_10100000_00000000_00000000,
0b00000000_01000000_00100000_00000000_00100000_01000000_00000000_00000000,
0b00000010_00000100_00000000_00000100_00000010_00000000_00000000_00000000,
0b00000101_00001000_00000000_00001000_00000101_00000000_00000000_00000000,
0b00001010_00010001_00000000_00010001_00001010_00000000_00000000_00000000,
0b00010100_00100010_00000000_00100010_00010100_00000000_00000000_00000000,
0b00101000_01000100_00000000_01000100_00101000_00000000_00000000_00000000,
0b01010000_10001000_00000000_10001000_01010000_00000000_00000000_00000000,
0b10100000_00010000_00000000_00010000_10100000_00000000_00000000_00000000,
0b01000000_00100000_00000000_00100000_01000000_00000000_00000000_00000000,
0b00000100_00000000_00000100_00000010_00000000_00000000_00000000_00000000,
0b00001000_00000000_00001000_00000101_00000000_00000000_00000000_00000000,
0b00010001_00000000_00010001_00001010_00000000_00000000_00000000_00000000,
0b00100010_00000000_00100010_00010100_00000000_00000000_00000000_00000000,
0b01000100_00000000_01000100_00101000_00000000_00000000_00000000_00000000,
0b10001000_00000000_10001000_01010000_00000000_00000000_00000000_00000000,
0b00010000_00000000_00010000_10100000_00000000_00000000_00000000_00000000,
0b00100000_00000000_00100000_01000000_00000000_00000000_00000000_00000000,
0b00000000_00000100_00000010_00000000_00000000_00000000_00000000_00000000,
0b00000000_00001000_00000101_00000000_00000000_00000000_00000000_00000000,
0b00000000_00010001_00001010_00000000_00000000_00000000_00000000_00000000,
0b00000000_00100010_00010100_00000000_00000000_00000000_00000000_00000000,
0b00000000_01000100_00101000_00000000_00000000_00000000_00000000_00000000,
0b00000000_10001000_01010000_00000000_00000000_00000000_00000000_00000000,
0b00000000_00010000_10100000_00000000_00000000_00000000_00000000_00000000,
0b00000000_00100000_01000000_00000000_00000000_00000000_00000000_00000000,
];
/// Board representation with color/piece bitboards. /// Board representation with color/piece bitboards.
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct Board { pub struct Board {
@ -418,30 +220,31 @@ impl Board {
/// Get combined white/black pieces bitboard. /// Get combined white/black pieces bitboard.
#[inline] #[inline]
pub fn combined(&self) -> Bitboard { pub const fn combined(&self) -> Bitboard {
self.colors[WHITE] | self.colors[BLACK] self.colors[WHITE] | self.colors[BLACK]
} }
/// Get the bitboard of a color. /// Get the bitboard of a color.
#[inline] #[inline]
pub fn by_color(&self, color: Color) -> Bitboard { pub const fn by_color(&self, color: Color) -> Bitboard {
self.colors[color] self.colors[color]
} }
/// Get the bitboard of a piece type. /// Get the bitboard of a piece type.
#[inline] #[inline]
pub fn by_piece(&self, piece: Piece) -> Bitboard { pub const fn by_piece(&self, piece: Piece) -> Bitboard {
self.pieces[piece] self.pieces[piece]
} }
/// Get the bitboard of a piece type for this color. /// Get the bitboard of a piece type for this color.
#[inline] #[inline]
pub fn by_color_and_piece(&self, color: Color, piece: Piece) -> Bitboard { pub const fn by_color_and_piece(&self, color: Color, piece: Piece) -> Bitboard {
self.by_color(color) & self.by_piece(piece) self.by_color(color) & self.by_piece(piece)
} }
/// True if this square is empty. /// True if this square is empty.
pub fn is_empty(&self, square: Square) -> bool { #[inline]
pub const fn is_empty(&self, square: Square) -> bool {
self.combined() & bit_pos(square) == 0 self.combined() & bit_pos(square) == 0
} }
@ -466,25 +269,35 @@ impl Board {
} }
/// Set a new value for the square at this position. /// Set a new value for the square at this position.
///
/// Clear opposite color bit, but not the previous piece bit.
#[inline] #[inline]
pub fn set_square(&mut self, square: Square, color: Color, piece: Piece) { pub fn set_square(&mut self, square: Square, color: Color, piece: Piece) {
self.colors[color] |= bit_pos(square); let bp = bit_pos(square);
self.colors[opposite(color)] &= !bit_pos(square); self.colors[color] |= bp;
self.pieces[piece] |= bit_pos(square); self.colors[opposite(color)] &= !bp;
self.pieces[piece] |= bp;
} }
/// Set the square empty at this position. /// Set the square empty at this position.
///
/// Clear both color and piece bitboards.
#[inline] #[inline]
pub fn clear_square(&mut self, square: Square) { pub fn clear_square(&mut self, square: Square, color: Color, piece: Piece) {
for color in 0..NUM_COLORS { self.colors[color] &= !bit_pos(square); } let bp = bit_pos(square);
for piece in 0..NUM_PIECES { self.pieces[piece] &= !bit_pos(square); } self.colors[color] &= !bp;
self.pieces[piece] &= !bp;
} }
/// Move a piece from a position to another, clearing initial position. /// Move a piece from a square to another, clearing initial square.
#[inline]
pub fn move_square(&mut self, source: Square, dest: Square) { pub fn move_square(&mut self, source: Square, dest: Square) {
self.set_square(dest, self.get_color_on(source), self.get_piece_on(source)); let (source_color, source_piece) = (self.get_color_on(source), self.get_piece_on(source));
self.clear_square(source); self.clear_square(source, source_color, source_piece);
if !self.is_empty(dest) {
let (dest_color, dest_piece) = (self.get_color_on(dest), self.get_piece_on(dest));
self.clear_square(dest, dest_color, dest_piece);
}
self.set_square(dest, source_color, source_piece);
} }
/// Find position of this king. /// Find position of this king.
@ -498,20 +311,50 @@ impl Board {
None None
} }
/// Get pawn progress: only forward moves.
pub fn get_pawn_progresses(&self, square: Square, color: Color) -> Bitboard {
let mut progress_bb = PAWN_PROGRESSES[color][square as usize] & !self.combined();
// Check that we do not jump over a piece when on a starting position.
if color == WHITE && sq_rank(square) == RANK_2 {
if self.combined() & bit_pos(sq(sq_file(square), sq_rank(square) + 1)) != 0 {
progress_bb &= !bit_pos(sq(sq_file(square), sq_rank(square) + 2));
}
}
else if color == BLACK && sq_rank(square) == RANK_7 {
if self.combined() & bit_pos(sq(sq_file(square), sq_rank(square) - 1)) != 0 {
progress_bb &= !bit_pos(sq(sq_file(square), sq_rank(square) - 2));
}
}
progress_bb
}
/// Get pawn captures: only moves capturing enemy pieces.
pub const fn get_pawn_captures(&self, square: Square, color: Color) -> Bitboard {
PAWN_CAPTURES[color][square as usize] & self.by_color(opposite(color))
}
/// Get bishop rays: moves and captures bitboard.
pub fn get_bishop_rays(&self, square: Square, color: Color) -> Bitboard { pub fn get_bishop_rays(&self, square: Square, color: Color) -> Bitboard {
self.get_blockable_rays(square, color, &[(1, 1), (1, -1), (-1, -1), (-1, 1)]) self.get_blockable_rays(square, color, &[(1, 1), (1, -1), (-1, -1), (-1, 1)])
} }
/// Get rook rays: moves and captures bitboard.
pub fn get_rook_rays(&self, square: Square, color: Color) -> Bitboard { pub fn get_rook_rays(&self, square: Square, color: Color) -> Bitboard {
self.get_blockable_rays(square, color, &[(1, 0), (0, 1), (-1, 0), (0, -1)]) self.get_blockable_rays(square, color, &[(1, 0), (0, 1), (-1, 0), (0, -1)])
} }
/// Get queen rays: moves and captures bitboard.
pub fn get_queen_rays(&self, square: Square, color: Color) -> Bitboard { pub fn get_queen_rays(&self, square: Square, color: Color) -> Bitboard {
self.get_blockable_rays( self.get_blockable_rays(
square, color, &[(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)] square, color, &[(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)]
) )
} }
/// Get rays for piece that can move how far they want.
///
/// Used for bishops, rooks and queens. A ray bitboard is the
/// combination of squares either empty or occupied by an enemy
/// piece they can reach.
fn get_blockable_rays(&self, fn get_blockable_rays(&self,
square: Square, square: Square,
color: Color, color: Color,
@ -542,16 +385,24 @@ impl Board {
rays_bb rays_bb
} }
/// Get knight rays: moves and captures bitboard.
pub fn get_knight_rays(&self, square: Square, color: Color) -> Bitboard { pub fn get_knight_rays(&self, square: Square, color: Color) -> Bitboard {
KNIGHT_RAYS[square as usize] & !self.by_color(color) KNIGHT_RAYS[square as usize] & !self.by_color(color)
} }
/// Get king rays: moves and captures bitboard.
pub fn get_king_rays(&self, square: Square, color: Color) -> Bitboard { pub fn get_king_rays(&self, square: Square, color: Color) -> Bitboard {
KING_RAYS[square as usize] & !self.by_color(color) KING_RAYS[square as usize] & !self.by_color(color)
} }
/// Debug only: write a text view of the board to stderr.
#[allow(dead_code)] // For tests only.
pub(crate) fn draw(&self) {
self.draw_to(&mut std::io::stderr());
}
/// Debug only: write a text view of the board. /// Debug only: write a text view of the board.
pub(crate) fn draw(&self, f: &mut dyn std::io::Write) { pub(crate) fn draw_to(&self, f: &mut dyn std::io::Write) {
let cbb = self.combined(); let cbb = self.combined();
for rank in (0..8).rev() { for rank in (0..8).rev() {
let mut rank_str = String::with_capacity(8); let mut rank_str = String::with_capacity(8);
@ -699,6 +550,59 @@ mod tests {
assert_eq!(b.find_king(BLACK), Some(E8)); assert_eq!(b.find_king(BLACK), Some(E8));
} }
#[test]
fn test_get_pawn_progresses() {
let mut b = Board::new_empty();
// Check for simple or double move for white and black.
b.set_square(A2, WHITE, PAWN);
assert_eq!(count_bits(b.get_pawn_progresses(A2, WHITE)), 2);
b.set_square(B2, WHITE, PAWN);
assert_eq!(count_bits(b.get_pawn_progresses(B2, WHITE)), 2);
b.set_square(B3, WHITE, PAWN);
assert_eq!(count_bits(b.get_pawn_progresses(B3, WHITE)), 1);
assert!(b.get_pawn_progresses(B3, WHITE) & bit_pos(B4) != 0);
b.set_square(H7, WHITE, PAWN);
assert_eq!(count_bits(b.get_pawn_progresses(H7, WHITE)), 1);
b.set_square(A7, BLACK, PAWN);
assert_eq!(count_bits(b.get_pawn_progresses(A7, BLACK)), 2);
assert!(b.get_pawn_progresses(A7, BLACK) & bit_pos(A6) != 0);
assert!(b.get_pawn_progresses(A7, BLACK) & bit_pos(A5) != 0);
// Check that a starting pawn cannot jump over another piece.
// Here, b2 is still blocked by another pawn on b3.
assert_eq!(count_bits(b.get_pawn_progresses(B2, WHITE)), 0);
// Move the blocking pawn to b4: one move is freed.
b.move_square(B3, B4);
let progress_bb = b.get_pawn_progresses(B2, WHITE);
assert_eq!(count_bits(progress_bb), 1);
assert!(progress_bb & bit_pos(B3) != 0);
}
#[test]
fn test_get_pawn_captures() {
let mut b = Board::new_empty();
// No capture by default.
b.set_square(A2, WHITE, PAWN);
assert_eq!(count_bits(b.get_pawn_captures(A2, WHITE)), 0);
// Can't capture forward.
b.set_square(A3, BLACK, PAWN);
assert_eq!(count_bits(b.get_pawn_captures(A2, WHITE)), 0);
// Can't capture a frendly piece.
b.set_square(B3, WHITE, KNIGHT);
assert_eq!(count_bits(b.get_pawn_captures(A2, WHITE)), 0);
// Capture that pawn...
b.set_square(B3, BLACK, PAWN);
assert_eq!(count_bits(b.get_pawn_captures(A2, WHITE)), 1);
// But it can capture you back!
assert_eq!(count_bits(b.get_pawn_captures(B3, BLACK)), 1);
// This one can capture both b3 and d3 black pawns.
b.set_square(C2, WHITE, PAWN);
b.set_square(D3, BLACK, PAWN);
assert_eq!(count_bits(b.get_pawn_captures(C2, WHITE)), 2);
}
#[test] #[test]
fn test_get_bishop_rays() { fn test_get_bishop_rays() {
let mut b = Board::new_empty(); let mut b = Board::new_empty();

View file

@ -62,6 +62,8 @@ pub enum Cmd {
WorkerInfo(Vec<analysis::AnalysisInfo>), WorkerInfo(Vec<analysis::AnalysisInfo>),
/// Send best move found by analysis worker. /// Send best move found by analysis worker.
WorkerBestMove(Option<Move>), WorkerBestMove(Option<Move>),
/// Draw board in logs.
DrawBoard,
// Commands that can be sent by the engine. // Commands that can be sent by the engine.
@ -124,6 +126,13 @@ impl Engine {
Cmd::Log(s) => self.reply(Cmd::Log(s.to_string())), Cmd::Log(s) => self.reply(Cmd::Log(s.to_string())),
Cmd::WorkerInfo(infos) => self.reply(Cmd::Info(infos.to_vec())), Cmd::WorkerInfo(infos) => self.reply(Cmd::Info(infos.to_vec())),
Cmd::WorkerBestMove(m) => self.reply(Cmd::BestMove(m.clone())), Cmd::WorkerBestMove(m) => self.reply(Cmd::BestMove(m.clone())),
// Other commands.
Cmd::DrawBoard => {
let mut s = vec!();
self.node.board.draw_to(&mut s);
let s = format!("Current board:\n{}", String::from_utf8_lossy(&s));
self.reply(Cmd::Log(s));
}
_ => eprintln!("Not an engine input command: {:?}", cmd), _ => eprintln!("Not an engine input command: {:?}", cmd),
} }
} }

View file

@ -7,6 +7,7 @@ pub mod engine;
pub mod fen; pub mod fen;
pub mod movement; pub mod movement;
pub mod node; pub mod node;
pub mod precomputed;
pub mod rules; pub mod rules;
pub mod stats; pub mod stats;
pub mod uci; pub mod uci;

View file

@ -167,16 +167,16 @@ mod tests {
assert_eq!(gs.castling, CASTLING_MASK); assert_eq!(gs.castling, CASTLING_MASK);
// On a starting board, start by making place for all castles. // On a starting board, start by making place for all castles.
b.clear_square(B1); b.clear_square(B1, WHITE, KNIGHT);
b.clear_square(C1); b.clear_square(C1, WHITE, BISHOP);
b.clear_square(D1); b.clear_square(D1, WHITE, QUEEN);
b.clear_square(F1); b.clear_square(F1, WHITE, BISHOP);
b.clear_square(G1); b.clear_square(G1, WHITE, KNIGHT);
b.clear_square(B8); b.clear_square(B8, BLACK, KNIGHT);
b.clear_square(C8); b.clear_square(C8, BLACK, BISHOP);
b.clear_square(D8); b.clear_square(D8, BLACK, QUEEN);
b.clear_square(F8); b.clear_square(F8, BLACK, BISHOP);
b.clear_square(G8); b.clear_square(G8, BLACK, KNIGHT);
// White queen-side castling. // White queen-side castling.
Move::new(E1, C1).apply_to(&mut b, &mut gs); Move::new(E1, C1).apply_to(&mut b, &mut gs);
assert_eq!(b.get_color_on(C1), WHITE); assert_eq!(b.get_color_on(C1), WHITE);

View file

@ -52,7 +52,7 @@ impl fmt::Debug for Node {
impl fmt::Display for Node { impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut s = vec!(); let mut s = vec!();
self.board.draw(&mut s); self.board.draw_to(&mut s);
let board_drawing = String::from_utf8_lossy(&s).to_string(); let board_drawing = String::from_utf8_lossy(&s).to_string();
write!(f, "* Board:\n{}\nGame state: {}", board_drawing, self.game_state) write!(f, "* Board:\n{}\nGame state: {}", board_drawing, self.game_state)
} }

482
src/precomputed.rs Normal file
View file

@ -0,0 +1,482 @@
//! Ugly module with all kind of precomputed stuff.
use crate::board::{Square, Bitboard};
// Generated by gen_squares.py.
pub const A1: Square = 0;
pub const A2: Square = 1;
pub const A3: Square = 2;
pub const A4: Square = 3;
pub const A5: Square = 4;
pub const A6: Square = 5;
pub const A7: Square = 6;
pub const A8: Square = 7;
pub const B1: Square = 8;
pub const B2: Square = 9;
pub const B3: Square = 10;
pub const B4: Square = 11;
pub const B5: Square = 12;
pub const B6: Square = 13;
pub const B7: Square = 14;
pub const B8: Square = 15;
pub const C1: Square = 16;
pub const C2: Square = 17;
pub const C3: Square = 18;
pub const C4: Square = 19;
pub const C5: Square = 20;
pub const C6: Square = 21;
pub const C7: Square = 22;
pub const C8: Square = 23;
pub const D1: Square = 24;
pub const D2: Square = 25;
pub const D3: Square = 26;
pub const D4: Square = 27;
pub const D5: Square = 28;
pub const D6: Square = 29;
pub const D7: Square = 30;
pub const D8: Square = 31;
pub const E1: Square = 32;
pub const E2: Square = 33;
pub const E3: Square = 34;
pub const E4: Square = 35;
pub const E5: Square = 36;
pub const E6: Square = 37;
pub const E7: Square = 38;
pub const E8: Square = 39;
pub const F1: Square = 40;
pub const F2: Square = 41;
pub const F3: Square = 42;
pub const F4: Square = 43;
pub const F5: Square = 44;
pub const F6: Square = 45;
pub const F7: Square = 46;
pub const F8: Square = 47;
pub const G1: Square = 48;
pub const G2: Square = 49;
pub const G3: Square = 50;
pub const G4: Square = 51;
pub const G5: Square = 52;
pub const G6: Square = 53;
pub const G7: Square = 54;
pub const G8: Square = 55;
pub const H1: Square = 56;
pub const H2: Square = 57;
pub const H3: Square = 58;
pub const H4: Square = 59;
pub const H5: Square = 60;
pub const H6: Square = 61;
pub const H7: Square = 62;
pub const H8: Square = 63;
pub const NUM_SQUARES: Square = 64;
// Generated by gen_pawn_progresses.py.
/// Pre-computed pawn progress (for white and black).
pub const PAWN_PROGRESSES: [[Bitboard; 64]; 2] = [
[
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000001100,
0b0000000000000000000000000000000000000000000000000000000000001000,
0b0000000000000000000000000000000000000000000000000000000000010000,
0b0000000000000000000000000000000000000000000000000000000000100000,
0b0000000000000000000000000000000000000000000000000000000001000000,
0b0000000000000000000000000000000000000000000000000000000010000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000110000000000,
0b0000000000000000000000000000000000000000000000000000100000000000,
0b0000000000000000000000000000000000000000000000000001000000000000,
0b0000000000000000000000000000000000000000000000000010000000000000,
0b0000000000000000000000000000000000000000000000000100000000000000,
0b0000000000000000000000000000000000000000000000001000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000011000000000000000000,
0b0000000000000000000000000000000000000000000010000000000000000000,
0b0000000000000000000000000000000000000000000100000000000000000000,
0b0000000000000000000000000000000000000000001000000000000000000000,
0b0000000000000000000000000000000000000000010000000000000000000000,
0b0000000000000000000000000000000000000000100000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000001100000000000000000000000000,
0b0000000000000000000000000000000000001000000000000000000000000000,
0b0000000000000000000000000000000000010000000000000000000000000000,
0b0000000000000000000000000000000000100000000000000000000000000000,
0b0000000000000000000000000000000001000000000000000000000000000000,
0b0000000000000000000000000000000010000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000110000000000000000000000000000000000,
0b0000000000000000000000000000100000000000000000000000000000000000,
0b0000000000000000000000000001000000000000000000000000000000000000,
0b0000000000000000000000000010000000000000000000000000000000000000,
0b0000000000000000000000000100000000000000000000000000000000000000,
0b0000000000000000000000001000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000011000000000000000000000000000000000000000000,
0b0000000000000000000010000000000000000000000000000000000000000000,
0b0000000000000000000100000000000000000000000000000000000000000000,
0b0000000000000000001000000000000000000000000000000000000000000000,
0b0000000000000000010000000000000000000000000000000000000000000000,
0b0000000000000000100000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000001100000000000000000000000000000000000000000000000000,
0b0000000000001000000000000000000000000000000000000000000000000000,
0b0000000000010000000000000000000000000000000000000000000000000000,
0b0000000000100000000000000000000000000000000000000000000000000000,
0b0000000001000000000000000000000000000000000000000000000000000000,
0b0000000010000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000110000000000000000000000000000000000000000000000000000000000,
0b0000100000000000000000000000000000000000000000000000000000000000,
0b0001000000000000000000000000000000000000000000000000000000000000,
0b0010000000000000000000000000000000000000000000000000000000000000,
0b0100000000000000000000000000000000000000000000000000000000000000,
0b1000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
],
[
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000001,
0b0000000000000000000000000000000000000000000000000000000000000010,
0b0000000000000000000000000000000000000000000000000000000000000100,
0b0000000000000000000000000000000000000000000000000000000000001000,
0b0000000000000000000000000000000000000000000000000000000000010000,
0b0000000000000000000000000000000000000000000000000000000000110000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000100000000,
0b0000000000000000000000000000000000000000000000000000001000000000,
0b0000000000000000000000000000000000000000000000000000010000000000,
0b0000000000000000000000000000000000000000000000000000100000000000,
0b0000000000000000000000000000000000000000000000000001000000000000,
0b0000000000000000000000000000000000000000000000000011000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000010000000000000000,
0b0000000000000000000000000000000000000000000000100000000000000000,
0b0000000000000000000000000000000000000000000001000000000000000000,
0b0000000000000000000000000000000000000000000010000000000000000000,
0b0000000000000000000000000000000000000000000100000000000000000000,
0b0000000000000000000000000000000000000000001100000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000001000000000000000000000000,
0b0000000000000000000000000000000000000010000000000000000000000000,
0b0000000000000000000000000000000000000100000000000000000000000000,
0b0000000000000000000000000000000000001000000000000000000000000000,
0b0000000000000000000000000000000000010000000000000000000000000000,
0b0000000000000000000000000000000000110000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000100000000000000000000000000000000,
0b0000000000000000000000000000001000000000000000000000000000000000,
0b0000000000000000000000000000010000000000000000000000000000000000,
0b0000000000000000000000000000100000000000000000000000000000000000,
0b0000000000000000000000000001000000000000000000000000000000000000,
0b0000000000000000000000000011000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000010000000000000000000000000000000000000000,
0b0000000000000000000000100000000000000000000000000000000000000000,
0b0000000000000000000001000000000000000000000000000000000000000000,
0b0000000000000000000010000000000000000000000000000000000000000000,
0b0000000000000000000100000000000000000000000000000000000000000000,
0b0000000000000000001100000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000001000000000000000000000000000000000000000000000000,
0b0000000000000010000000000000000000000000000000000000000000000000,
0b0000000000000100000000000000000000000000000000000000000000000000,
0b0000000000001000000000000000000000000000000000000000000000000000,
0b0000000000010000000000000000000000000000000000000000000000000000,
0b0000000000110000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000100000000000000000000000000000000000000000000000000000000,
0b0000001000000000000000000000000000000000000000000000000000000000,
0b0000010000000000000000000000000000000000000000000000000000000000,
0b0000100000000000000000000000000000000000000000000000000000000000,
0b0001000000000000000000000000000000000000000000000000000000000000,
0b0011000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
],
];
// Generated by gen_pawn_captures.py.
/// Pre-computed pawn captures (for white and black).
pub const PAWN_CAPTURES: [[Bitboard; 64]; 2] = [
[
0b0000000000000000000000000000000000000000000000000000001000000000,
0b0000000000000000000000000000000000000000000000000000010000000000,
0b0000000000000000000000000000000000000000000000000000100000000000,
0b0000000000000000000000000000000000000000000000000001000000000000,
0b0000000000000000000000000000000000000000000000000010000000000000,
0b0000000000000000000000000000000000000000000000000100000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000100000000000000010,
0b0000000000000000000000000000000000000000000001000000000000000100,
0b0000000000000000000000000000000000000000000010000000000000001000,
0b0000000000000000000000000000000000000000000100000000000000010000,
0b0000000000000000000000000000000000000000001000000000000000100000,
0b0000000000000000000000000000000000000000010000000000000001000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000010000000000000001000000000,
0b0000000000000000000000000000000000000100000000000000010000000000,
0b0000000000000000000000000000000000001000000000000000100000000000,
0b0000000000000000000000000000000000010000000000000001000000000000,
0b0000000000000000000000000000000000100000000000000010000000000000,
0b0000000000000000000000000000000001000000000000000100000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000001000000000000000100000000000000000,
0b0000000000000000000000000000010000000000000001000000000000000000,
0b0000000000000000000000000000100000000000000010000000000000000000,
0b0000000000000000000000000001000000000000000100000000000000000000,
0b0000000000000000000000000010000000000000001000000000000000000000,
0b0000000000000000000000000100000000000000010000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000100000000000000010000000000000000000000000,
0b0000000000000000000001000000000000000100000000000000000000000000,
0b0000000000000000000010000000000000001000000000000000000000000000,
0b0000000000000000000100000000000000010000000000000000000000000000,
0b0000000000000000001000000000000000100000000000000000000000000000,
0b0000000000000000010000000000000001000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000010000000000000001000000000000000000000000000000000,
0b0000000000000100000000000000010000000000000000000000000000000000,
0b0000000000001000000000000000100000000000000000000000000000000000,
0b0000000000010000000000000001000000000000000000000000000000000000,
0b0000000000100000000000000010000000000000000000000000000000000000,
0b0000000001000000000000000100000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000001000000000000000100000000000000000000000000000000000000000,
0b0000010000000000000001000000000000000000000000000000000000000000,
0b0000100000000000000010000000000000000000000000000000000000000000,
0b0001000000000000000100000000000000000000000000000000000000000000,
0b0010000000000000001000000000000000000000000000000000000000000000,
0b0100000000000000010000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000010000000000000000000000000000000000000000000000000,
0b0000000000000100000000000000000000000000000000000000000000000000,
0b0000000000001000000000000000000000000000000000000000000000000000,
0b0000000000010000000000000000000000000000000000000000000000000000,
0b0000000000100000000000000000000000000000000000000000000000000000,
0b0000000001000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
],
[
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000001000000000,
0b0000000000000000000000000000000000000000000000000000010000000000,
0b0000000000000000000000000000000000000000000000000000100000000000,
0b0000000000000000000000000000000000000000000000000001000000000000,
0b0000000000000000000000000000000000000000000000000010000000000000,
0b0000000000000000000000000000000000000000000000000100000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000100000000000000010,
0b0000000000000000000000000000000000000000000001000000000000000100,
0b0000000000000000000000000000000000000000000010000000000000001000,
0b0000000000000000000000000000000000000000000100000000000000010000,
0b0000000000000000000000000000000000000000001000000000000000100000,
0b0000000000000000000000000000000000000000010000000000000001000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000010000000000000001000000000,
0b0000000000000000000000000000000000000100000000000000010000000000,
0b0000000000000000000000000000000000001000000000000000100000000000,
0b0000000000000000000000000000000000010000000000000001000000000000,
0b0000000000000000000000000000000000100000000000000010000000000000,
0b0000000000000000000000000000000001000000000000000100000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000001000000000000000100000000000000000,
0b0000000000000000000000000000010000000000000001000000000000000000,
0b0000000000000000000000000000100000000000000010000000000000000000,
0b0000000000000000000000000001000000000000000100000000000000000000,
0b0000000000000000000000000010000000000000001000000000000000000000,
0b0000000000000000000000000100000000000000010000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000100000000000000010000000000000000000000000,
0b0000000000000000000001000000000000000100000000000000000000000000,
0b0000000000000000000010000000000000001000000000000000000000000000,
0b0000000000000000000100000000000000010000000000000000000000000000,
0b0000000000000000001000000000000000100000000000000000000000000000,
0b0000000000000000010000000000000001000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000010000000000000001000000000000000000000000000000000,
0b0000000000000100000000000000010000000000000000000000000000000000,
0b0000000000001000000000000000100000000000000000000000000000000000,
0b0000000000010000000000000001000000000000000000000000000000000000,
0b0000000000100000000000000010000000000000000000000000000000000000,
0b0000000001000000000000000100000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000001000000000000000100000000000000000000000000000000000000000,
0b0000010000000000000001000000000000000000000000000000000000000000,
0b0000100000000000000010000000000000000000000000000000000000000000,
0b0001000000000000000100000000000000000000000000000000000000000000,
0b0010000000000000001000000000000000000000000000000000000000000000,
0b0100000000000000010000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000000000000000000000000000000000000000000000000000000,
0b0000000000000010000000000000000000000000000000000000000000000000,
0b0000000000000100000000000000000000000000000000000000000000000000,
0b0000000000001000000000000000000000000000000000000000000000000000,
0b0000000000010000000000000000000000000000000000000000000000000000,
0b0000000000100000000000000000000000000000000000000000000000000000,
0b0000000001000000000000000000000000000000000000000000000000000000,
],
];
// Generated by gen_king_rays.py.
/// Pre-computed king rays.
pub const KING_RAYS: [Bitboard; 64] = [
0b00000000_00000000_00000000_00000000_00000000_00000000_00000011_00000010,
0b00000000_00000000_00000000_00000000_00000000_00000000_00000111_00000101,
0b00000000_00000000_00000000_00000000_00000000_00000000_00001110_00001010,
0b00000000_00000000_00000000_00000000_00000000_00000000_00011100_00010100,
0b00000000_00000000_00000000_00000000_00000000_00000000_00111000_00101000,
0b00000000_00000000_00000000_00000000_00000000_00000000_01110000_01010000,
0b00000000_00000000_00000000_00000000_00000000_00000000_11100000_10100000,
0b00000000_00000000_00000000_00000000_00000000_00000000_11000000_01000000,
0b00000000_00000000_00000000_00000000_00000000_00000011_00000010_00000011,
0b00000000_00000000_00000000_00000000_00000000_00000111_00000101_00000111,
0b00000000_00000000_00000000_00000000_00000000_00001110_00001010_00001110,
0b00000000_00000000_00000000_00000000_00000000_00011100_00010100_00011100,
0b00000000_00000000_00000000_00000000_00000000_00111000_00101000_00111000,
0b00000000_00000000_00000000_00000000_00000000_01110000_01010000_01110000,
0b00000000_00000000_00000000_00000000_00000000_11100000_10100000_11100000,
0b00000000_00000000_00000000_00000000_00000000_11000000_01000000_11000000,
0b00000000_00000000_00000000_00000000_00000011_00000010_00000011_00000000,
0b00000000_00000000_00000000_00000000_00000111_00000101_00000111_00000000,
0b00000000_00000000_00000000_00000000_00001110_00001010_00001110_00000000,
0b00000000_00000000_00000000_00000000_00011100_00010100_00011100_00000000,
0b00000000_00000000_00000000_00000000_00111000_00101000_00111000_00000000,
0b00000000_00000000_00000000_00000000_01110000_01010000_01110000_00000000,
0b00000000_00000000_00000000_00000000_11100000_10100000_11100000_00000000,
0b00000000_00000000_00000000_00000000_11000000_01000000_11000000_00000000,
0b00000000_00000000_00000000_00000011_00000010_00000011_00000000_00000000,
0b00000000_00000000_00000000_00000111_00000101_00000111_00000000_00000000,
0b00000000_00000000_00000000_00001110_00001010_00001110_00000000_00000000,
0b00000000_00000000_00000000_00011100_00010100_00011100_00000000_00000000,
0b00000000_00000000_00000000_00111000_00101000_00111000_00000000_00000000,
0b00000000_00000000_00000000_01110000_01010000_01110000_00000000_00000000,
0b00000000_00000000_00000000_11100000_10100000_11100000_00000000_00000000,
0b00000000_00000000_00000000_11000000_01000000_11000000_00000000_00000000,
0b00000000_00000000_00000011_00000010_00000011_00000000_00000000_00000000,
0b00000000_00000000_00000111_00000101_00000111_00000000_00000000_00000000,
0b00000000_00000000_00001110_00001010_00001110_00000000_00000000_00000000,
0b00000000_00000000_00011100_00010100_00011100_00000000_00000000_00000000,
0b00000000_00000000_00111000_00101000_00111000_00000000_00000000_00000000,
0b00000000_00000000_01110000_01010000_01110000_00000000_00000000_00000000,
0b00000000_00000000_11100000_10100000_11100000_00000000_00000000_00000000,
0b00000000_00000000_11000000_01000000_11000000_00000000_00000000_00000000,
0b00000000_00000011_00000010_00000011_00000000_00000000_00000000_00000000,
0b00000000_00000111_00000101_00000111_00000000_00000000_00000000_00000000,
0b00000000_00001110_00001010_00001110_00000000_00000000_00000000_00000000,
0b00000000_00011100_00010100_00011100_00000000_00000000_00000000_00000000,
0b00000000_00111000_00101000_00111000_00000000_00000000_00000000_00000000,
0b00000000_01110000_01010000_01110000_00000000_00000000_00000000_00000000,
0b00000000_11100000_10100000_11100000_00000000_00000000_00000000_00000000,
0b00000000_11000000_01000000_11000000_00000000_00000000_00000000_00000000,
0b00000011_00000010_00000011_00000000_00000000_00000000_00000000_00000000,
0b00000111_00000101_00000111_00000000_00000000_00000000_00000000_00000000,
0b00001110_00001010_00001110_00000000_00000000_00000000_00000000_00000000,
0b00011100_00010100_00011100_00000000_00000000_00000000_00000000_00000000,
0b00111000_00101000_00111000_00000000_00000000_00000000_00000000_00000000,
0b01110000_01010000_01110000_00000000_00000000_00000000_00000000_00000000,
0b11100000_10100000_11100000_00000000_00000000_00000000_00000000_00000000,
0b11000000_01000000_11000000_00000000_00000000_00000000_00000000_00000000,
0b00000010_00000011_00000000_00000000_00000000_00000000_00000000_00000000,
0b00000101_00000111_00000000_00000000_00000000_00000000_00000000_00000000,
0b00001010_00001110_00000000_00000000_00000000_00000000_00000000_00000000,
0b00010100_00011100_00000000_00000000_00000000_00000000_00000000_00000000,
0b00101000_00111000_00000000_00000000_00000000_00000000_00000000_00000000,
0b01010000_01110000_00000000_00000000_00000000_00000000_00000000_00000000,
0b10100000_11100000_00000000_00000000_00000000_00000000_00000000_00000000,
0b01000000_11000000_00000000_00000000_00000000_00000000_00000000_00000000,
];
// Generated by gen_knight_rays.py.
/// Pre-computed knight rays.
pub const KNIGHT_RAYS: [Bitboard; 64] = [
0b00000000_00000000_00000000_00000000_00000000_00000010_00000100_00000000,
0b00000000_00000000_00000000_00000000_00000000_00000101_00001000_00000000,
0b00000000_00000000_00000000_00000000_00000000_00001010_00010001_00000000,
0b00000000_00000000_00000000_00000000_00000000_00010100_00100010_00000000,
0b00000000_00000000_00000000_00000000_00000000_00101000_01000100_00000000,
0b00000000_00000000_00000000_00000000_00000000_01010000_10001000_00000000,
0b00000000_00000000_00000000_00000000_00000000_10100000_00010000_00000000,
0b00000000_00000000_00000000_00000000_00000000_01000000_00100000_00000000,
0b00000000_00000000_00000000_00000000_00000010_00000100_00000000_00000100,
0b00000000_00000000_00000000_00000000_00000101_00001000_00000000_00001000,
0b00000000_00000000_00000000_00000000_00001010_00010001_00000000_00010001,
0b00000000_00000000_00000000_00000000_00010100_00100010_00000000_00100010,
0b00000000_00000000_00000000_00000000_00101000_01000100_00000000_01000100,
0b00000000_00000000_00000000_00000000_01010000_10001000_00000000_10001000,
0b00000000_00000000_00000000_00000000_10100000_00010000_00000000_00010000,
0b00000000_00000000_00000000_00000000_01000000_00100000_00000000_00100000,
0b00000000_00000000_00000000_00000010_00000100_00000000_00000100_00000010,
0b00000000_00000000_00000000_00000101_00001000_00000000_00001000_00000101,
0b00000000_00000000_00000000_00001010_00010001_00000000_00010001_00001010,
0b00000000_00000000_00000000_00010100_00100010_00000000_00100010_00010100,
0b00000000_00000000_00000000_00101000_01000100_00000000_01000100_00101000,
0b00000000_00000000_00000000_01010000_10001000_00000000_10001000_01010000,
0b00000000_00000000_00000000_10100000_00010000_00000000_00010000_10100000,
0b00000000_00000000_00000000_01000000_00100000_00000000_00100000_01000000,
0b00000000_00000000_00000010_00000100_00000000_00000100_00000010_00000000,
0b00000000_00000000_00000101_00001000_00000000_00001000_00000101_00000000,
0b00000000_00000000_00001010_00010001_00000000_00010001_00001010_00000000,
0b00000000_00000000_00010100_00100010_00000000_00100010_00010100_00000000,
0b00000000_00000000_00101000_01000100_00000000_01000100_00101000_00000000,
0b00000000_00000000_01010000_10001000_00000000_10001000_01010000_00000000,
0b00000000_00000000_10100000_00010000_00000000_00010000_10100000_00000000,
0b00000000_00000000_01000000_00100000_00000000_00100000_01000000_00000000,
0b00000000_00000010_00000100_00000000_00000100_00000010_00000000_00000000,
0b00000000_00000101_00001000_00000000_00001000_00000101_00000000_00000000,
0b00000000_00001010_00010001_00000000_00010001_00001010_00000000_00000000,
0b00000000_00010100_00100010_00000000_00100010_00010100_00000000_00000000,
0b00000000_00101000_01000100_00000000_01000100_00101000_00000000_00000000,
0b00000000_01010000_10001000_00000000_10001000_01010000_00000000_00000000,
0b00000000_10100000_00010000_00000000_00010000_10100000_00000000_00000000,
0b00000000_01000000_00100000_00000000_00100000_01000000_00000000_00000000,
0b00000010_00000100_00000000_00000100_00000010_00000000_00000000_00000000,
0b00000101_00001000_00000000_00001000_00000101_00000000_00000000_00000000,
0b00001010_00010001_00000000_00010001_00001010_00000000_00000000_00000000,
0b00010100_00100010_00000000_00100010_00010100_00000000_00000000_00000000,
0b00101000_01000100_00000000_01000100_00101000_00000000_00000000_00000000,
0b01010000_10001000_00000000_10001000_01010000_00000000_00000000_00000000,
0b10100000_00010000_00000000_00010000_10100000_00000000_00000000_00000000,
0b01000000_00100000_00000000_00100000_01000000_00000000_00000000_00000000,
0b00000100_00000000_00000100_00000010_00000000_00000000_00000000_00000000,
0b00001000_00000000_00001000_00000101_00000000_00000000_00000000_00000000,
0b00010001_00000000_00010001_00001010_00000000_00000000_00000000_00000000,
0b00100010_00000000_00100010_00010100_00000000_00000000_00000000_00000000,
0b01000100_00000000_01000100_00101000_00000000_00000000_00000000_00000000,
0b10001000_00000000_10001000_01010000_00000000_00000000_00000000_00000000,
0b00010000_00000000_00010000_10100000_00000000_00000000_00000000_00000000,
0b00100000_00000000_00100000_01000000_00000000_00000000_00000000_00000000,
0b00000000_00000100_00000010_00000000_00000000_00000000_00000000_00000000,
0b00000000_00001000_00000101_00000000_00000000_00000000_00000000_00000000,
0b00000000_00010001_00001010_00000000_00000000_00000000_00000000_00000000,
0b00000000_00100010_00010100_00000000_00000000_00000000_00000000_00000000,
0b00000000_01000100_00101000_00000000_00000000_00000000_00000000_00000000,
0b00000000_10001000_01010000_00000000_00000000_00000000_00000000_00000000,
0b00000000_00010000_10100000_00000000_00000000_00000000_00000000_00000000,
0b00000000_00100000_01000000_00000000_00000000_00000000_00000000_00000000,
];

View file

@ -105,6 +105,72 @@ fn get_piece_moves(
} }
} }
// fn get_pawn_moves(
// board: &Board,
// game_state: &GameState,
// square: Square,
// color: Color,
// pseudo_legal: bool,
// ) -> Vec<Move> {
// let (f, r) = (sq_file(square), sq_rank(square));
// let mut moves = vec!();
// // Direction: positive for white, negative for black.
// let dir = if color == WHITE { 1 } else { -1 };
// // Check 1 or 2 square forward.
// let move_len = if (color == WHITE && r == 1) || (color == BLACK && r == 6) { 2 } else { 1 };
// for i in 1..=move_len {
// let forward_r = r + dir * i;
// if dir > 0 && forward_r > POS_MAX {
// return moves
// }
// if dir < 0 && forward_r < POS_MIN {
// return moves
// }
// let forward: Square = sq(f, forward_r);
// // If forward square is empty (and we are not jumping over an occupied square), add it.
// if board.is_empty(forward) && (i == 1 || board.is_empty(sq(f, forward_r - dir))) {
// let mut m = Move::new(square, forward);
// // Pawns that get to the opposite rank automatically promote as queens.
// if (dir > 0 && forward_r == POS_MAX) || (dir < 0 && forward_r == POS_MIN) {
// m.promotion = Some(QUEEN)
// }
// if pseudo_legal || !is_illegal(board, game_state, &m) {
// moves.push(m);
// }
// }
// // Check diagonals for pieces to attack.
// if i == 1 {
// // First diagonal.
// if f - 1 >= POS_MIN {
// let diag = sq(f - 1, forward_r);
// if !board.is_empty(diag) {
// let diag_color = board.get_color_on(diag);
// if let Some(m) = get_capture_move(color, square, diag_color, diag, true) {
// if pseudo_legal || !is_illegal(board, game_state, &m) {
// moves.push(m);
// }
// }
// }
// }
// // Second diagonal.
// if f + 1 <= POS_MAX {
// let diag = sq(f + 1, forward_r);
// if !board.is_empty(diag) {
// let diag_color = board.get_color_on(diag);
// if let Some(m) = get_capture_move(color, square, diag_color, diag, true) {
// if pseudo_legal || !is_illegal(board, game_state, &m) {
// moves.push(m);
// }
// }
// }
// }
// }
// // TODO en passant
// }
// moves
// }
fn get_pawn_moves( fn get_pawn_moves(
board: &Board, board: &Board,
game_state: &GameState, game_state: &GameState,
@ -112,64 +178,17 @@ fn get_pawn_moves(
color: Color, color: Color,
pseudo_legal: bool, pseudo_legal: bool,
) -> Vec<Move> { ) -> Vec<Move> {
let (f, r) = (sq_file(square), sq_rank(square)); get_moves_from_bb(
let mut moves = vec!(); board,
// Direction: positive for white, negative for black. game_state,
let dir = if color == WHITE { 1 } else { -1 }; board.get_pawn_progresses(square, color) | board.get_pawn_captures(square, color),
// Check 1 or 2 square forward. square,
let move_len = if (color == WHITE && r == 1) || (color == BLACK && r == 6) { 2 } else { 1 }; color,
for i in 1..=move_len { PAWN,
let forward_r = r + dir * i; pseudo_legal
if dir > 0 && forward_r > POS_MAX { )
return moves
}
if dir < 0 && forward_r < POS_MIN {
return moves
}
let forward: Square = sq(f, forward_r);
// If forward square is empty (and we are not jumping over an occupied square), add it.
if board.is_empty(forward) && (i == 1 || board.is_empty(sq(f, forward_r - dir))) {
let mut m = Move::new(square, forward);
// Pawns that get to the opposite rank automatically promote as queens.
if (dir > 0 && forward_r == POS_MAX) || (dir < 0 && forward_r == POS_MIN) {
m.promotion = Some(QUEEN)
}
if pseudo_legal || !is_illegal(board, game_state, &m) {
moves.push(m);
}
}
// Check diagonals for pieces to attack.
if i == 1 {
// First diagonal.
if f - 1 >= POS_MIN {
let diag = sq(f - 1, forward_r);
if !board.is_empty(diag) {
let diag_color = board.get_color_on(diag);
if let Some(m) = get_capture_move(color, square, diag_color, diag, true) {
if pseudo_legal || !is_illegal(board, game_state, &m) {
moves.push(m);
}
}
}
}
// Second diagonal.
if f + 1 <= POS_MAX {
let diag = sq(f + 1, forward_r);
if !board.is_empty(diag) {
let diag_color = board.get_color_on(diag);
if let Some(m) = get_capture_move(color, square, diag_color, diag, true) {
if pseudo_legal || !is_illegal(board, game_state, &m) {
moves.push(m);
}
}
}
}
}
// TODO en passant // TODO en passant
} }
moves
}
fn get_bishop_moves( fn get_bishop_moves(
board: &Board, board: &Board,
@ -324,6 +343,10 @@ fn get_king_moves(
} }
/// Get moves from this ray bitboard. /// Get moves from this ray bitboard.
///
/// Inspect all moves from the bitboard and produce a Move for each
/// legal move, or all moves if `pseudo_legal` is true. Pawns that
/// reach the last rank are promoted as queens.
fn get_moves_from_bb( fn get_moves_from_bb(
board: &Board, board: &Board,
game_state: &GameState, game_state: &GameState,
@ -480,7 +503,7 @@ mod tests {
let moves = get_piece_moves(&b, &gs, E2, WHITE, false); let moves = get_piece_moves(&b, &gs, E2, WHITE, false);
assert_eq!(moves.len(), 0); assert_eq!(moves.len(), 0);
// 3. remove the e4 black pawn; the white pawn should not be able to jump above e3 pawn. // 3. remove the e4 black pawn; the white pawn should not be able to jump above e3 pawn.
b.clear_square(E4); b.clear_square(E4, BLACK, PAWN);
let moves = get_piece_moves(&b, &gs, E2, WHITE, false); let moves = get_piece_moves(&b, &gs, E2, WHITE, false);
assert_eq!(moves.len(), 0); assert_eq!(moves.len(), 0);

View file

@ -57,6 +57,10 @@ pub enum UciCmd {
Position(Vec<PositionArgs>), Position(Vec<PositionArgs>),
Go(Vec<GoArgs>), Go(Vec<GoArgs>),
Quit, Quit,
// Unofficial commands mostly for debugging.
VatuDraw,
Unknown(String), Unknown(String),
} }
@ -198,6 +202,9 @@ impl Uci {
self.send_engine_command(engine::Cmd::Stop); self.send_engine_command(engine::Cmd::Stop);
}, },
UciCmd::Quit => return false, UciCmd::Quit => return false,
UciCmd::VatuDraw => {
self.send_engine_command(engine::Cmd::DrawBoard);
}
UciCmd::Unknown(c) => { self.log(format!("Unknown command: {}", c)); } UciCmd::Unknown(c) => { self.log(format!("Unknown command: {}", c)); }
} }
true true
@ -305,6 +312,7 @@ fn parse_command(s: &str) -> UciCmd {
"position" => parse_position_command(&fields[1..]), "position" => parse_position_command(&fields[1..]),
"go" => parse_go_command(&fields[1..]), "go" => parse_go_command(&fields[1..]),
"quit" => UciCmd::Quit, "quit" => UciCmd::Quit,
"vatudraw" => UciCmd::VatuDraw,
c => UciCmd::Unknown(c.to_string()), c => UciCmd::Unknown(c.to_string()),
} }
} }