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 = """\
/// Pre-computed king rays.
const KING_RAYS: [Bitboard; 64] = [
pub const KING_RAYS: [Bitboard; 64] = [
{}
];
"""

View file

@ -3,7 +3,7 @@
TEMPLATE = """\
/// 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.
pub use crate::precomputed::*;
/// Color type, used to index `Board.color`.
pub type Color = usize;
@ -34,73 +36,6 @@ pub const NUM_PIECES: usize = 6;
/// Coords (file, rank) of a square on a board.
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.
#[inline]
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()
}
/// 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.
pub type Bitboard = u64;
@ -204,156 +144,18 @@ pub fn count_bits(bitboard: Bitboard) -> u8 {
count as u8
}
/// Debug only: pretty print a bitboard
/// Debug only: pretty-print a bitboard to stderr.
#[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() {
let mut rank_str = String::with_capacity(8);
for file in 0..8 {
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.
#[derive(Clone, PartialEq)]
pub struct Board {
@ -418,30 +220,31 @@ impl Board {
/// Get combined white/black pieces bitboard.
#[inline]
pub fn combined(&self) -> Bitboard {
pub const fn combined(&self) -> Bitboard {
self.colors[WHITE] | self.colors[BLACK]
}
/// Get the bitboard of a color.
#[inline]
pub fn by_color(&self, color: Color) -> Bitboard {
pub const fn by_color(&self, color: Color) -> Bitboard {
self.colors[color]
}
/// Get the bitboard of a piece type.
#[inline]
pub fn by_piece(&self, piece: Piece) -> Bitboard {
pub const fn by_piece(&self, piece: Piece) -> Bitboard {
self.pieces[piece]
}
/// Get the bitboard of a piece type for this color.
#[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)
}
/// 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
}
@ -466,25 +269,35 @@ impl Board {
}
/// Set a new value for the square at this position.
///
/// Clear opposite color bit, but not the previous piece bit.
#[inline]
pub fn set_square(&mut self, square: Square, color: Color, piece: Piece) {
self.colors[color] |= bit_pos(square);
self.colors[opposite(color)] &= !bit_pos(square);
self.pieces[piece] |= bit_pos(square);
let bp = bit_pos(square);
self.colors[color] |= bp;
self.colors[opposite(color)] &= !bp;
self.pieces[piece] |= bp;
}
/// Set the square empty at this position.
///
/// Clear both color and piece bitboards.
#[inline]
pub fn clear_square(&mut self, square: Square) {
for color in 0..NUM_COLORS { self.colors[color] &= !bit_pos(square); }
for piece in 0..NUM_PIECES { self.pieces[piece] &= !bit_pos(square); }
pub fn clear_square(&mut self, square: Square, color: Color, piece: Piece) {
let bp = bit_pos(square);
self.colors[color] &= !bp;
self.pieces[piece] &= !bp;
}
/// Move a piece from a position to another, clearing initial position.
#[inline]
/// Move a piece from a square to another, clearing initial 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));
self.clear_square(source);
let (source_color, source_piece) = (self.get_color_on(source), self.get_piece_on(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.
@ -498,20 +311,50 @@ impl Board {
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 {
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 {
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 {
self.get_blockable_rays(
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,
square: Square,
color: Color,
@ -542,16 +385,24 @@ impl Board {
rays_bb
}
/// Get knight rays: moves and captures bitboard.
pub fn get_knight_rays(&self, square: Square, color: Color) -> Bitboard {
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 {
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.
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();
for rank in (0..8).rev() {
let mut rank_str = String::with_capacity(8);
@ -699,6 +550,59 @@ mod tests {
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]
fn test_get_bishop_rays() {
let mut b = Board::new_empty();

View file

@ -62,6 +62,8 @@ pub enum Cmd {
WorkerInfo(Vec<analysis::AnalysisInfo>),
/// Send best move found by analysis worker.
WorkerBestMove(Option<Move>),
/// Draw board in logs.
DrawBoard,
// 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::WorkerInfo(infos) => self.reply(Cmd::Info(infos.to_vec())),
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),
}
}

View file

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

View file

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

View file

@ -52,7 +52,7 @@ impl fmt::Debug for Node {
impl fmt::Display for Node {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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();
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(
board: &Board,
game_state: &GameState,
@ -112,63 +178,16 @@ fn get_pawn_moves(
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
get_moves_from_bb(
board,
game_state,
board.get_pawn_progresses(square, color) | board.get_pawn_captures(square, color),
square,
color,
PAWN,
pseudo_legal
)
// TODO en passant
}
fn get_bishop_moves(
@ -324,6 +343,10 @@ fn get_king_moves(
}
/// 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(
board: &Board,
game_state: &GameState,
@ -480,7 +503,7 @@ mod tests {
let moves = get_piece_moves(&b, &gs, E2, WHITE, false);
assert_eq!(moves.len(), 0);
// 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);
assert_eq!(moves.len(), 0);

View file

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