rules: use generic bitboard move generation
For bishops, knights, rooks and queens that is.
This commit is contained in:
parent
5efdd5407b
commit
ce62d3ab3a
30
res/scripts/gen_king_rays.py
Executable file
30
res/scripts/gen_king_rays.py
Executable file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Pre-compute king ras bitboards for each square."""
|
||||||
|
|
||||||
|
TEMPLATE = """\
|
||||||
|
/// Pre-computed king rays.
|
||||||
|
const KING_RAYS: [Bitboard; 64] = [
|
||||||
|
{}
|
||||||
|
];
|
||||||
|
"""
|
||||||
|
|
||||||
|
DIRS = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)]
|
||||||
|
|
||||||
|
def bit_pos(square):
|
||||||
|
return 1 << square
|
||||||
|
|
||||||
|
def get_rays():
|
||||||
|
rays = []
|
||||||
|
for f in range(8):
|
||||||
|
for r in range(8):
|
||||||
|
bitboard = 0
|
||||||
|
for dir_f, dir_r in DIRS:
|
||||||
|
ray_f = f + dir_f
|
||||||
|
ray_r = r + dir_r
|
||||||
|
if ray_f < 0 or ray_f > 7 or ray_r < 0 or ray_r > 7:
|
||||||
|
continue
|
||||||
|
bitboard |= bit_pos(ray_f * 8 + ray_r)
|
||||||
|
rays.append(" 0b{:064b},".format(bitboard))
|
||||||
|
return rays
|
||||||
|
|
||||||
|
print(TEMPLATE.format("\n".join(get_rays())))
|
|
@ -2,6 +2,7 @@
|
||||||
"""Pre-compute knight ray bitboards for each square."""
|
"""Pre-compute knight ray bitboards for each square."""
|
||||||
|
|
||||||
TEMPLATE = """\
|
TEMPLATE = """\
|
||||||
|
/// Pre-computed knight rays.
|
||||||
const KNIGHT_RAYS: [Bitboard; 64] = [
|
const KNIGHT_RAYS: [Bitboard; 64] = [
|
||||||
{}
|
{}
|
||||||
];
|
];
|
||||||
|
|
79
src/board.rs
79
src/board.rs
|
@ -99,6 +99,7 @@ pub const H5: Square = 60;
|
||||||
pub const H6: Square = 61;
|
pub const H6: Square = 61;
|
||||||
pub const H7: Square = 62;
|
pub const H7: Square = 62;
|
||||||
pub const H8: Square = 63;
|
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]
|
||||||
|
@ -192,9 +193,8 @@ pub const fn after_on_file(file: i8, rank: i8) -> Bitboard {
|
||||||
FILES[file as usize] & bits_after(file, rank)
|
FILES[file as usize] & bits_after(file, rank)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Debug only: count positive bits of the bitboard.
|
/// Count positive bits of the bitboard.
|
||||||
#[allow(dead_code)]
|
pub fn count_bits(bitboard: Bitboard) -> u8 {
|
||||||
pub(crate) fn count_bits(bitboard: Bitboard) -> u8 {
|
|
||||||
let mut bitboard = bitboard;
|
let mut bitboard = bitboard;
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
while bitboard > 0 {
|
while bitboard > 0 {
|
||||||
|
@ -216,6 +216,75 @@ pub(crate) fn draw_bits(bitboard: Bitboard, f: &mut dyn std::io::Write) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.
|
// Generated by gen_knight_rays.py.
|
||||||
/// Pre-computed knight rays.
|
/// Pre-computed knight rays.
|
||||||
const KNIGHT_RAYS: [Bitboard; 64] = [
|
const KNIGHT_RAYS: [Bitboard; 64] = [
|
||||||
|
@ -477,6 +546,10 @@ impl Board {
|
||||||
KNIGHT_RAYS[square as usize] & !self.by_color(color)
|
KNIGHT_RAYS[square as usize] & !self.by_color(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
/// Debug only: write a text view of the board.
|
||||||
pub(crate) fn draw(&self, f: &mut dyn std::io::Write) {
|
pub(crate) fn draw(&self, f: &mut dyn std::io::Write) {
|
||||||
let cbb = self.combined();
|
let cbb = self.combined();
|
||||||
|
|
235
src/rules.rs
235
src/rules.rs
|
@ -178,37 +178,15 @@ fn get_bishop_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 views = [true; 4]; // Store diagonals where a piece blocks commit.
|
board,
|
||||||
let mut moves = Vec::with_capacity(8);
|
game_state,
|
||||||
for dist in 1..=7 {
|
board.get_bishop_rays(square, color),
|
||||||
for (dir, offset) in [(1, -1), (1, 1), (-1, 1), (-1, -1)].iter().enumerate() {
|
square,
|
||||||
if !views[dir] {
|
color,
|
||||||
continue
|
BISHOP,
|
||||||
}
|
pseudo_legal
|
||||||
|
)
|
||||||
// If this position is out of the board, stop looking in that direction.
|
|
||||||
let ray_f = f + offset.0 * dist;
|
|
||||||
if ray_f < POS_MIN || ray_f > POS_MAX {
|
|
||||||
views[dir] = false;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let ray_r = r + offset.1 * dist;
|
|
||||||
if ray_r < POS_MIN || ray_r > POS_MAX {
|
|
||||||
views[dir] = false;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let ray_square = sq(ray_f, ray_r);
|
|
||||||
|
|
||||||
match get_move_type(board, game_state, square, ray_square, color, pseudo_legal) {
|
|
||||||
MoveType::Simple(m) => { moves.push(m) }
|
|
||||||
MoveType::Capture(m) => { moves.push(m); views[dir] = false; }
|
|
||||||
MoveType::CantTakeFriend => { views[dir] = false; }
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moves
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_knight_moves(
|
fn get_knight_moves(
|
||||||
|
@ -218,25 +196,15 @@ fn get_knight_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::with_capacity(8);
|
board,
|
||||||
for offset in [(1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1, 2)].iter() {
|
game_state,
|
||||||
let ray_f = f + offset.0;
|
board.get_knight_rays(square, color),
|
||||||
if ray_f < POS_MIN || ray_f > POS_MAX {
|
square,
|
||||||
continue
|
color,
|
||||||
}
|
KNIGHT,
|
||||||
let ray_r = r + offset.1;
|
pseudo_legal
|
||||||
if ray_r < POS_MIN || ray_r > POS_MAX {
|
)
|
||||||
continue
|
|
||||||
}
|
|
||||||
let ray_square = sq(ray_f, ray_r);
|
|
||||||
|
|
||||||
match get_move_type(board, game_state, square, ray_square, color, pseudo_legal) {
|
|
||||||
MoveType::Simple(m) | MoveType::Capture(m) => moves.push(m),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moves
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_rook_moves(
|
fn get_rook_moves(
|
||||||
|
@ -246,36 +214,15 @@ fn get_rook_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::with_capacity(8);
|
board,
|
||||||
let mut views = [true; 4]; // Store lines where a piece blocks commit.
|
game_state,
|
||||||
for dist in 1..=7 {
|
board.get_rook_rays(square, color),
|
||||||
for (dir, offset) in [(0, 1), (1, 0), (0, -1), (-1, 0)].iter().enumerate() {
|
square,
|
||||||
if !views[dir] {
|
color,
|
||||||
continue
|
ROOK,
|
||||||
}
|
pseudo_legal
|
||||||
|
)
|
||||||
let ray_f = f + offset.0 * dist;
|
|
||||||
if ray_f < POS_MIN || ray_f > POS_MAX {
|
|
||||||
views[dir] = false;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let ray_r = r + offset.1 * dist;
|
|
||||||
if ray_r < POS_MIN || ray_r > POS_MAX {
|
|
||||||
views[dir] = false;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let ray_square = sq(ray_f, ray_r);
|
|
||||||
|
|
||||||
match get_move_type(board, game_state, square, ray_square, color, pseudo_legal) {
|
|
||||||
MoveType::Simple(m) => { moves.push(m) }
|
|
||||||
MoveType::Capture(m) => { moves.push(m); views[dir] = false; }
|
|
||||||
MoveType::CantTakeFriend => { views[dir] = false; }
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
moves
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_queen_moves(
|
fn get_queen_moves(
|
||||||
|
@ -285,11 +232,15 @@ fn get_queen_moves(
|
||||||
color: Color,
|
color: Color,
|
||||||
pseudo_legal: bool,
|
pseudo_legal: bool,
|
||||||
) -> Vec<Move> {
|
) -> Vec<Move> {
|
||||||
let mut moves = Vec::with_capacity(16);
|
get_moves_from_bb(
|
||||||
// Easy way to get queen moves, but may be a bit quicker if everything was rewritten here.
|
board,
|
||||||
moves.append(&mut get_bishop_moves(board, game_state, square, color, pseudo_legal));
|
game_state,
|
||||||
moves.append(&mut get_rook_moves(board, game_state, square, color, pseudo_legal));
|
board.get_queen_rays(square, color),
|
||||||
moves
|
square,
|
||||||
|
color,
|
||||||
|
QUEEN,
|
||||||
|
pseudo_legal
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_king_moves(
|
fn get_king_moves(
|
||||||
|
@ -299,24 +250,15 @@ fn get_king_moves(
|
||||||
color: Color,
|
color: Color,
|
||||||
pseudo_legal: bool,
|
pseudo_legal: bool,
|
||||||
) -> Vec<Move> {
|
) -> Vec<Move> {
|
||||||
let (f, r) = (sq_file(square), sq_rank(square));
|
let mut moves = get_moves_from_bb(
|
||||||
let mut moves = Vec::with_capacity(8);
|
board,
|
||||||
for offset in [(-1, 1), (0, 1), (1, 1), (-1, 0), (1, 0), (-1, -1), (0, -1), (1, -1)].iter() {
|
game_state,
|
||||||
let ray_f = f + offset.0;
|
board.get_king_rays(square, color),
|
||||||
if ray_f < POS_MIN || ray_f > POS_MAX {
|
square,
|
||||||
continue
|
color,
|
||||||
}
|
KING,
|
||||||
let ray_r = r + offset.1;
|
pseudo_legal
|
||||||
if ray_r < POS_MIN || ray_r > POS_MAX {
|
);
|
||||||
continue
|
|
||||||
}
|
|
||||||
let ray_square = sq(ray_f, ray_r);
|
|
||||||
|
|
||||||
match get_move_type(board, game_state, square, ray_square, color, pseudo_legal) {
|
|
||||||
MoveType::Simple(m) | MoveType::Capture(m) => moves.push(m),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop here for pseudo legal moves as castling is not considered along with them.
|
// Stop here for pseudo legal moves as castling is not considered along with them.
|
||||||
if pseudo_legal {
|
if pseudo_legal {
|
||||||
|
@ -338,6 +280,7 @@ fn get_king_moves(
|
||||||
(7, CASTLING_BL_MASK)
|
(7, CASTLING_BL_MASK)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let r = sq_rank(square);
|
||||||
// Check for castling if the king is on its castling rank (R1)
|
// Check for castling if the king is on its castling rank (R1)
|
||||||
// and is not in check (R4).
|
// and is not in check (R4).
|
||||||
if
|
if
|
||||||
|
@ -380,58 +323,58 @@ fn get_king_moves(
|
||||||
moves
|
moves
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get moves from this ray bitboard.
|
||||||
|
fn get_moves_from_bb(
|
||||||
|
board: &Board,
|
||||||
|
game_state: &GameState,
|
||||||
|
bitboard: Bitboard,
|
||||||
|
square: Square,
|
||||||
|
color: Color,
|
||||||
|
piece: Piece,
|
||||||
|
pseudo_legal: bool
|
||||||
|
) -> Vec<Move> {
|
||||||
|
let mut moves = Vec::with_capacity(count_bits(bitboard).into());
|
||||||
|
for ray_square in 0..NUM_SQUARES {
|
||||||
|
if ray_square == square || bitboard & bit_pos(ray_square) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if let Some(mut m) = inspect_move(board, game_state, square, ray_square, pseudo_legal) {
|
||||||
|
// Automatic queen promotion for pawns moving to the opposite rank.
|
||||||
|
if
|
||||||
|
piece == PAWN
|
||||||
|
&& (color == WHITE && sq_rank(ray_square) == RANK_8)
|
||||||
|
|| (color == BLACK && sq_rank(ray_square) == RANK_1)
|
||||||
|
{
|
||||||
|
m.promotion = Some(QUEEN);
|
||||||
|
}
|
||||||
|
moves.push(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moves
|
||||||
|
}
|
||||||
|
|
||||||
/// Accept or ignore a move from `square` to `ray_square`.
|
/// Accept or ignore a move from `square` to `ray_square`.
|
||||||
fn get_move_type(
|
///
|
||||||
|
/// This function checks that the move is legal, unless `pseudo_legal`
|
||||||
|
/// is true. It assumes that `ray_square` is either empty or an enemy
|
||||||
|
/// piece, but not a friend piece: they should have been filtered.
|
||||||
|
///
|
||||||
|
/// This function does not set promotions for pawns reaching last rank.
|
||||||
|
fn inspect_move(
|
||||||
board: &Board,
|
board: &Board,
|
||||||
game_state: &GameState,
|
game_state: &GameState,
|
||||||
square: Square,
|
square: Square,
|
||||||
ray_square: Square,
|
ray_square: Square,
|
||||||
color: Color,
|
pseudo_legal: bool
|
||||||
commit: bool
|
) -> Option<Move> {
|
||||||
) -> MoveType {
|
let m = Move::new(square, ray_square);
|
||||||
if board.is_empty(ray_square) {
|
if pseudo_legal || !is_illegal(board, game_state, &m) {
|
||||||
let m = Move::new(square, ray_square);
|
Some(m)
|
||||||
if is_legal(commit, board, game_state, &m) {
|
|
||||||
MoveType::Simple(m)
|
|
||||||
} else {
|
|
||||||
MoveType::CantRegister
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let ray_color = board.get_color_on(ray_square);
|
None
|
||||||
if let Some(m) = get_capture_move(color, square, ray_color, ray_square, false) {
|
|
||||||
if is_legal(commit, board, game_state, &m) {
|
|
||||||
MoveType::Capture(m)
|
|
||||||
} else {
|
|
||||||
MoveType::CantRegister
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MoveType::CantTakeFriend
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MoveType {
|
|
||||||
/// Move to an empty square.
|
|
||||||
Simple(Move),
|
|
||||||
/// Capture an enemy piece.
|
|
||||||
Capture(Move),
|
|
||||||
/// May be illegal, or should not be committed, e.g. to test rays.
|
|
||||||
CantRegister,
|
|
||||||
/// Can't capture a friend piece.
|
|
||||||
CantTakeFriend,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return true if `pseudo_legal` is true, or the move is not illegal,
|
|
||||||
///
|
|
||||||
/// Committing a move means that it can be safely played afterwards.
|
|
||||||
/// Sometimes it is not what is needed to accept a move in a collection
|
|
||||||
/// of moves, e.g. when simply checking if some moves would make a
|
|
||||||
/// previous move illegal.
|
|
||||||
#[inline]
|
|
||||||
fn is_legal(pseudo_legal: bool, board: &Board, game_state: &GameState, m: &Move) -> bool {
|
|
||||||
pseudo_legal || !is_illegal(board, game_state, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a move from `square1` to `square2` if colors are opposite.
|
/// Return a move from `square1` to `square2` if colors are opposite.
|
||||||
fn get_capture_move(
|
fn get_capture_move(
|
||||||
color1: Color,
|
color1: Color,
|
||||||
|
|
Reference in a new issue