Use lsb and have_common_bit fn's for readability
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bitboard::{
|
bitboard::{
|
||||||
intersect, lsb, square_to_bitboard, square_to_bitboard_wrapping, EMPTY, NOT_FILE_A,
|
have_common_bit, lsb, square_to_bitboard, square_to_bitboard_wrapping, EMPTY, NOT_FILE_A,
|
||||||
NOT_FILE_AB, NOT_FILE_GH, NOT_FILE_H,
|
NOT_FILE_AB, NOT_FILE_GH, NOT_FILE_H,
|
||||||
},
|
},
|
||||||
board::Color,
|
board::Color,
|
||||||
@@ -152,7 +152,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo
|
|||||||
for (rank, file) in (rank..=7).zip(file..=7) {
|
for (rank, file) in (rank..=7).zip(file..=7) {
|
||||||
let attack_square = square_to_bitboard(coords_to_square(rank, file));
|
let attack_square = square_to_bitboard(coords_to_square(rank, file));
|
||||||
attacks |= attack_square;
|
attacks |= attack_square;
|
||||||
if attack_square & blocker != 0 {
|
if have_common_bit(attack_square, blocker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo
|
|||||||
for (rank, file) in (0..target_rank).rev().zip(file..=7) {
|
for (rank, file) in (0..target_rank).rev().zip(file..=7) {
|
||||||
let attack_square = square_to_bitboard(coords_to_square(rank, file));
|
let attack_square = square_to_bitboard(coords_to_square(rank, file));
|
||||||
attacks |= attack_square;
|
attacks |= attack_square;
|
||||||
if attack_square & blocker != 0 {
|
if have_common_bit(attack_square, blocker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo
|
|||||||
for (rank, file) in (rank..=7).zip((0..target_file).rev()) {
|
for (rank, file) in (rank..=7).zip((0..target_file).rev()) {
|
||||||
let attack_square = square_to_bitboard(coords_to_square(rank, file));
|
let attack_square = square_to_bitboard(coords_to_square(rank, file));
|
||||||
attacks |= attack_square;
|
attacks |= attack_square;
|
||||||
if attack_square & blocker != 0 {
|
if have_common_bit(attack_square, blocker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ pub fn bishop_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitbo
|
|||||||
for (rank, file) in (0..target_rank).rev().zip((0..target_file).rev()) {
|
for (rank, file) in (0..target_rank).rev().zip((0..target_file).rev()) {
|
||||||
let attack_square = square_to_bitboard(coords_to_square(rank, file));
|
let attack_square = square_to_bitboard(coords_to_square(rank, file));
|
||||||
attacks |= attack_square;
|
attacks |= attack_square;
|
||||||
if attack_square & blocker != 0 {
|
if have_common_bit(attack_square, blocker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,14 +197,14 @@ pub fn rook_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboar
|
|||||||
for rank in rank..=7 {
|
for rank in rank..=7 {
|
||||||
let attack_square = square_to_bitboard(coords_to_square(rank, target_file));
|
let attack_square = square_to_bitboard(coords_to_square(rank, target_file));
|
||||||
attacks |= attack_square;
|
attacks |= attack_square;
|
||||||
if attack_square & blocker != 0 {
|
if have_common_bit(attack_square, blocker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for file in file..=7 {
|
for file in file..=7 {
|
||||||
let attack_square = square_to_bitboard(coords_to_square(target_rank, file));
|
let attack_square = square_to_bitboard(coords_to_square(target_rank, file));
|
||||||
attacks |= attack_square;
|
attacks |= attack_square;
|
||||||
if attack_square & blocker != 0 {
|
if have_common_bit(attack_square, blocker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,14 +213,14 @@ pub fn rook_attacks_on_the_fly(bitboard: Bitboard, blocker: Bitboard) -> Bitboar
|
|||||||
for rank in (0..=rank).rev() {
|
for rank in (0..=rank).rev() {
|
||||||
let attack_square = square_to_bitboard(coords_to_square(rank, target_file));
|
let attack_square = square_to_bitboard(coords_to_square(rank, target_file));
|
||||||
attacks |= attack_square;
|
attacks |= attack_square;
|
||||||
if attack_square & blocker != 0 {
|
if have_common_bit(attack_square, blocker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for file in (0..=file).rev() {
|
for file in (0..=file).rev() {
|
||||||
let attack_square = square_to_bitboard(coords_to_square(target_rank, file));
|
let attack_square = square_to_bitboard(coords_to_square(target_rank, file));
|
||||||
attacks |= attack_square;
|
attacks |= attack_square;
|
||||||
if attack_square & blocker != 0 {
|
if have_common_bit(attack_square, blocker) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,7 +234,7 @@ pub fn set_occupancy(index: u64, relevant_bits: usize, mut attack_mask: Bitboard
|
|||||||
for bit in 0..relevant_bits {
|
for bit in 0..relevant_bits {
|
||||||
let square = lsb(attack_mask);
|
let square = lsb(attack_mask);
|
||||||
attack_mask &= !square_to_bitboard(square);
|
attack_mask &= !square_to_bitboard(square);
|
||||||
if intersect(index, square_to_bitboard(bit)) {
|
if have_common_bit(index, square_to_bitboard(bit)) {
|
||||||
occupancy |= square_to_bitboard(square);
|
occupancy |= square_to_bitboard(square);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,15 @@ use u64 as Bitboard;
|
|||||||
pub const EMPTY: Bitboard = 0x0;
|
pub const EMPTY: Bitboard = 0x0;
|
||||||
pub const FULL: Bitboard = 0xffffffffffffffff;
|
pub const FULL: Bitboard = 0xffffffffffffffff;
|
||||||
pub const NOT_FILE_A: Bitboard = 0xfefefefefefefefe;
|
pub const NOT_FILE_A: Bitboard = 0xfefefefefefefefe;
|
||||||
pub const NOT_FILE_AB: Bitboard = 0xfcfcfcfcfcfcfcfc;
|
|
||||||
pub const NOT_FILE_H: Bitboard = 0x7f7f7f7f7f7f7f7f;
|
pub const NOT_FILE_H: Bitboard = 0x7f7f7f7f7f7f7f7f;
|
||||||
|
pub const NOT_FILE_AB: Bitboard = 0xfcfcfcfcfcfcfcfc;
|
||||||
pub const NOT_FILE_GH: Bitboard = 0x3f3f3f3f3f3f3f3f;
|
pub const NOT_FILE_GH: Bitboard = 0x3f3f3f3f3f3f3f3f;
|
||||||
pub const RANK_8: Bitboard = 0x0ff00000000000000;
|
pub const RANK_1: Bitboard = 0xff;
|
||||||
|
pub const RANK_2: Bitboard = 0xff00;
|
||||||
|
pub const RANK_4: Bitboard = 0xff000000;
|
||||||
|
pub const RANK_5: Bitboard = 0xff00000000;
|
||||||
|
pub const RANK_7: Bitboard = 0xff000000000000;
|
||||||
|
pub const RANK_8: Bitboard = 0xff00000000000000;
|
||||||
|
|
||||||
pub const fn square_to_bitboard(square: usize) -> Bitboard {
|
pub const fn square_to_bitboard(square: usize) -> Bitboard {
|
||||||
1_u64 << square
|
1_u64 << square
|
||||||
@@ -24,6 +29,6 @@ pub const fn bit_count(bitboard: Bitboard) -> usize {
|
|||||||
bitboard.count_ones() as usize
|
bitboard.count_ones() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn intersect(bitboard_a: Bitboard, bitboard_b: Bitboard) -> bool {
|
pub const fn have_common_bit(bitboard_a: Bitboard, bitboard_b: Bitboard) -> bool {
|
||||||
bitboard_a & bitboard_b != 0
|
bitboard_a & bitboard_b != 0
|
||||||
}
|
}
|
||||||
|
|||||||
93
src/board.rs
93
src/board.rs
@@ -4,6 +4,7 @@ use crate::attack::{
|
|||||||
get_bishop_attacks, get_king_attacks, get_knight_attacks, get_pawn_attacks, get_queen_attacks,
|
get_bishop_attacks, get_king_attacks, get_knight_attacks, get_pawn_attacks, get_queen_attacks,
|
||||||
get_rook_attacks,
|
get_rook_attacks,
|
||||||
};
|
};
|
||||||
|
use crate::bitboard::{have_common_bit, lsb, square_to_bitboard};
|
||||||
use crate::game::{Castle, State};
|
use crate::game::{Castle, State};
|
||||||
use crate::movegen::{
|
use crate::movegen::{
|
||||||
bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves,
|
bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves,
|
||||||
@@ -93,12 +94,23 @@ impl Board {
|
|||||||
Color::White => (&self.white_pieces, Color::Black),
|
Color::White => (&self.white_pieces, Color::Black),
|
||||||
};
|
};
|
||||||
|
|
||||||
enemy[Kind::Pawn.idx()].bitboard & get_pawn_attacks(sq, own_color) != 0
|
have_common_bit(
|
||||||
|| enemy[Kind::Knight.idx()].bitboard & get_knight_attacks(sq) != 0
|
enemy[Kind::Pawn.idx()].bitboard,
|
||||||
|| enemy[Kind::Bishop.idx()].bitboard & get_bishop_attacks(all_occupancies, sq) != 0
|
get_pawn_attacks(sq, own_color),
|
||||||
|| enemy[Kind::Rook.idx()].bitboard & get_rook_attacks(all_occupancies, sq) != 0
|
) || have_common_bit(enemy[Kind::Knight.idx()].bitboard, get_knight_attacks(sq))
|
||||||
|| enemy[Kind::Queen.idx()].bitboard & get_queen_attacks(all_occupancies, sq) != 0
|
|| have_common_bit(
|
||||||
|| enemy[Kind::King.idx()].bitboard & get_king_attacks(sq) != 0
|
enemy[Kind::Bishop.idx()].bitboard,
|
||||||
|
get_bishop_attacks(all_occupancies, sq),
|
||||||
|
)
|
||||||
|
|| have_common_bit(
|
||||||
|
enemy[Kind::Rook.idx()].bitboard,
|
||||||
|
get_rook_attacks(all_occupancies, sq),
|
||||||
|
)
|
||||||
|
|| have_common_bit(
|
||||||
|
enemy[Kind::Queen.idx()].bitboard,
|
||||||
|
get_queen_attacks(all_occupancies, sq),
|
||||||
|
)
|
||||||
|
|| have_common_bit(enemy[Kind::King.idx()].bitboard, get_king_attacks(sq))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_move_legit(&self, square: usize, opponent_color: Color) -> bool {
|
pub fn is_move_legit(&self, square: usize, opponent_color: Color) -> bool {
|
||||||
@@ -162,13 +174,12 @@ impl Board {
|
|||||||
Color::Black => &self.black_pieces,
|
Color::Black => &self.black_pieces,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.state.update_castling_state_quiet(mv.source, color);
|
||||||
self.state
|
self.state
|
||||||
.update_castling_state_quiet(mv.source as u8, color);
|
.update_castling_state_capture(mv.target, Color::opponent_color(color));
|
||||||
self.state
|
|
||||||
.update_castling_state_capture(mv.target as u8, Color::opponent_color(color));
|
|
||||||
self.state.change_side();
|
self.state.change_side();
|
||||||
|
|
||||||
let own_king_square = pieces[Kind::King.idx()].bitboard.trailing_zeros() as usize;
|
let own_king_square = lsb(pieces[Kind::King.idx()].bitboard);
|
||||||
self.is_move_legit(own_king_square, Color::opponent_color(color))
|
self.is_move_legit(own_king_square, Color::opponent_color(color))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,58 +191,58 @@ impl Board {
|
|||||||
|
|
||||||
match &mv.move_type {
|
match &mv.move_type {
|
||||||
MoveType::Quiet => {
|
MoveType::Quiet => {
|
||||||
Self::move_piece(mv.source as u8, mv.target as u8, own_pieces);
|
Self::move_piece(mv.source, mv.target, own_pieces);
|
||||||
self.state.set_en_passant_target_square(None);
|
self.state.set_en_passant_target_square(None);
|
||||||
}
|
}
|
||||||
MoveType::Capture => {
|
MoveType::Capture => {
|
||||||
Self::move_piece(mv.source as u8, mv.target as u8, own_pieces);
|
Self::move_piece(mv.source, mv.target, own_pieces);
|
||||||
Self::remove_piece(mv.target as u8, opponent_pieces);
|
Self::remove_piece(mv.target, opponent_pieces);
|
||||||
self.state.set_en_passant_target_square(None);
|
self.state.set_en_passant_target_square(None);
|
||||||
}
|
}
|
||||||
MoveType::EnPassant => {
|
MoveType::EnPassant => {
|
||||||
Self::move_piece(mv.source as u8, mv.target as u8, own_pieces);
|
Self::move_piece(mv.source, mv.target, own_pieces);
|
||||||
Self::remove_pawn_enpassant(mv.target as u8, opponent_pieces, color);
|
Self::remove_pawn_enpassant(mv.target, opponent_pieces, color);
|
||||||
self.state.set_en_passant_target_square(None);
|
self.state.set_en_passant_target_square(None);
|
||||||
}
|
}
|
||||||
MoveType::DoublePush => {
|
MoveType::DoublePush => {
|
||||||
Self::move_piece(mv.source as u8, mv.target as u8, own_pieces);
|
Self::move_piece(mv.source, mv.target, own_pieces);
|
||||||
let en_passant = match color {
|
let en_passant = match color {
|
||||||
Color::White => Some((mv.source + 8) as u8),
|
Color::White => Some(mv.source + 8),
|
||||||
Color::Black => Some((mv.source - 8) as u8),
|
Color::Black => Some(mv.source - 8),
|
||||||
};
|
};
|
||||||
self.state.set_en_passant_target_square(en_passant);
|
self.state.set_en_passant_target_square(en_passant);
|
||||||
}
|
}
|
||||||
MoveType::Promotion(promote) => {
|
MoveType::Promotion(promote) => {
|
||||||
Self::remove_piece(mv.source as u8, own_pieces);
|
Self::remove_piece(mv.source, own_pieces);
|
||||||
Self::promote_piece(mv.target as u8, own_pieces, *promote);
|
Self::promote_piece(mv.target, own_pieces, *promote);
|
||||||
self.state.set_en_passant_target_square(None);
|
self.state.set_en_passant_target_square(None);
|
||||||
}
|
}
|
||||||
MoveType::PromotionCapture(promote) => {
|
MoveType::PromotionCapture(promote) => {
|
||||||
Self::remove_piece(mv.source as u8, own_pieces);
|
Self::remove_piece(mv.source, own_pieces);
|
||||||
Self::remove_piece(mv.target as u8, opponent_pieces);
|
Self::remove_piece(mv.target, opponent_pieces);
|
||||||
Self::promote_piece(mv.target as u8, own_pieces, *promote);
|
Self::promote_piece(mv.target, own_pieces, *promote);
|
||||||
self.state.set_en_passant_target_square(None);
|
self.state.set_en_passant_target_square(None);
|
||||||
}
|
}
|
||||||
MoveType::Castle => {
|
MoveType::Castle => {
|
||||||
Self::move_piece(mv.source as u8, mv.target as u8, own_pieces);
|
Self::move_piece(mv.source, mv.target, own_pieces);
|
||||||
Self::move_rook_castle(mv.target as u8, own_pieces);
|
Self::move_rook_castle(mv.target, own_pieces);
|
||||||
self.state.set_en_passant_target_square(None);
|
self.state.set_en_passant_target_square(None);
|
||||||
self.state.set_castling_ability(color, Castle::None)
|
self.state.set_castling_ability(color, Castle::None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_piece(source: u8, target: u8, pieces: &mut [Piece; 6]) {
|
fn move_piece(source: usize, target: usize, pieces: &mut [Piece; 6]) {
|
||||||
for p in pieces.iter_mut() {
|
for p in pieces.iter_mut() {
|
||||||
if p.bitboard & (1_u64 << source) != 0 {
|
if have_common_bit(p.bitboard, square_to_bitboard(source)) {
|
||||||
p.bitboard &= !(1_u64 << source);
|
p.bitboard &= !square_to_bitboard(source);
|
||||||
p.bitboard |= 1_u64 << target;
|
p.bitboard |= square_to_bitboard(target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_rook_castle(square: u8, pieces: &mut [Piece; 6]) {
|
fn move_rook_castle(square: usize, pieces: &mut [Piece; 6]) {
|
||||||
let (rook_source, rook_target) = match square {
|
let (rook_source, rook_target) = match square {
|
||||||
2 | 58 => (square - 2, square + 1),
|
2 | 58 => (square - 2, square + 1),
|
||||||
6 | 62 => (square + 1, square - 1),
|
6 | 62 => (square + 1, square - 1),
|
||||||
@@ -241,33 +252,33 @@ impl Board {
|
|||||||
Self::move_piece(rook_source, rook_target, pieces);
|
Self::move_piece(rook_source, rook_target, pieces);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn promote_piece(square: u8, pieces: &mut [Piece; 6], promote: Promote) {
|
fn promote_piece(square: usize, pieces: &mut [Piece; 6], promote: Promote) {
|
||||||
match promote {
|
match promote {
|
||||||
Promote::Knight => pieces[Kind::Knight.idx()].bitboard |= 1_u64 << square,
|
Promote::Knight => pieces[Kind::Knight.idx()].bitboard |= square_to_bitboard(square),
|
||||||
Promote::Bishop => pieces[Kind::Bishop.idx()].bitboard |= 1_u64 << square,
|
Promote::Bishop => pieces[Kind::Bishop.idx()].bitboard |= square_to_bitboard(square),
|
||||||
Promote::Rook => pieces[Kind::Rook.idx()].bitboard |= 1_u64 << square,
|
Promote::Rook => pieces[Kind::Rook.idx()].bitboard |= square_to_bitboard(square),
|
||||||
Promote::Queen => pieces[Kind::Queen.idx()].bitboard |= 1_u64 << square,
|
Promote::Queen => pieces[Kind::Queen.idx()].bitboard |= square_to_bitboard(square),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_piece(square: u8, pieces: &mut [Piece; 6]) {
|
fn remove_piece(square: usize, pieces: &mut [Piece; 6]) {
|
||||||
for p in pieces.iter_mut() {
|
for p in pieces.iter_mut() {
|
||||||
if p.bitboard & (1_u64 << square) != 0 {
|
if have_common_bit(p.bitboard, square_to_bitboard(square)) {
|
||||||
p.bitboard &= !(1_u64 << square);
|
p.bitboard &= !(square_to_bitboard(square));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_pawn_enpassant(square: u8, pieces: &mut [Piece; 6], color: Color) {
|
fn remove_pawn_enpassant(square: usize, pieces: &mut [Piece; 6], color: Color) {
|
||||||
let piece_to_remove = match color {
|
let piece_to_remove = match color {
|
||||||
Color::White => square - 8,
|
Color::White => square - 8,
|
||||||
Color::Black => square + 8,
|
Color::Black => square + 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
for p in pieces.iter_mut() {
|
for p in pieces.iter_mut() {
|
||||||
if p.bitboard & (1_u64 << piece_to_remove) != 0 {
|
if have_common_bit(p.bitboard, square_to_bitboard(piece_to_remove)) {
|
||||||
p.bitboard &= !(1_u64 << piece_to_remove);
|
p.bitboard &= !(square_to_bitboard(piece_to_remove));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,10 +122,10 @@ fn castling_ability(castling: &str) -> Result<[Castle; 2], FenError> {
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
fn en_passant_target_square(square: &str) -> Result<Option<u8>, FenError> {
|
fn en_passant_target_square(square: &str) -> Result<Option<usize>, FenError> {
|
||||||
let mut sqr = square.chars();
|
let mut sqr = square.chars();
|
||||||
|
|
||||||
let mut files: HashMap<char, u8> = HashMap::new();
|
let mut files: HashMap<char, usize> = HashMap::new();
|
||||||
files.insert('a', 0);
|
files.insert('a', 0);
|
||||||
files.insert('b', 1);
|
files.insert('b', 1);
|
||||||
files.insert('c', 2);
|
files.insert('c', 2);
|
||||||
@@ -135,7 +135,7 @@ fn en_passant_target_square(square: &str) -> Result<Option<u8>, FenError> {
|
|||||||
files.insert('g', 6);
|
files.insert('g', 6);
|
||||||
files.insert('h', 7);
|
files.insert('h', 7);
|
||||||
|
|
||||||
let mut ranks: HashMap<char, u8> = HashMap::new();
|
let mut ranks: HashMap<char, usize> = HashMap::new();
|
||||||
ranks.insert('3', 2);
|
ranks.insert('3', 2);
|
||||||
ranks.insert('6', 5);
|
ranks.insert('6', 5);
|
||||||
|
|
||||||
|
|||||||
12
src/game.rs
12
src/game.rs
@@ -35,7 +35,7 @@ impl Default for Game {
|
|||||||
pub struct State {
|
pub struct State {
|
||||||
side_to_move: Color,
|
side_to_move: Color,
|
||||||
castling_ability: [Castle; 2],
|
castling_ability: [Castle; 2],
|
||||||
en_passant_target_square: Option<u8>,
|
en_passant_target_square: Option<usize>,
|
||||||
halfmove_clock: u8,
|
halfmove_clock: u8,
|
||||||
fullmove_counter: u8,
|
fullmove_counter: u8,
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ impl State {
|
|||||||
pub const fn load_state(
|
pub const fn load_state(
|
||||||
side_to_move: Color,
|
side_to_move: Color,
|
||||||
castling_ability: [Castle; 2],
|
castling_ability: [Castle; 2],
|
||||||
en_passant_target_square: Option<u8>,
|
en_passant_target_square: Option<usize>,
|
||||||
halfmove_clock: u8,
|
halfmove_clock: u8,
|
||||||
fullmove_counter: u8,
|
fullmove_counter: u8,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@@ -67,7 +67,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn get_en_passant_target_square(&self) -> Option<u8> {
|
pub const fn get_en_passant_target_square(&self) -> Option<usize> {
|
||||||
self.en_passant_target_square
|
self.en_passant_target_square
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_castling_state_quiet(&mut self, source: u8, color: Color) {
|
pub fn update_castling_state_quiet(&mut self, source: usize, color: Color) {
|
||||||
self.update_castling_state_capture(source, color);
|
self.update_castling_state_capture(source, color);
|
||||||
|
|
||||||
match (source, color) {
|
match (source, color) {
|
||||||
@@ -88,7 +88,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_castling_state_capture(&mut self, target: u8, color: Color) {
|
pub fn update_castling_state_capture(&mut self, target: usize, color: Color) {
|
||||||
let (short_square, long_square) = match color {
|
let (short_square, long_square) = match color {
|
||||||
Color::White => (7, 0),
|
Color::White => (7, 0),
|
||||||
Color::Black => (63, 56),
|
Color::Black => (63, 56),
|
||||||
@@ -122,7 +122,7 @@ impl State {
|
|||||||
self.side_to_move
|
self.side_to_move
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_en_passant_target_square(&mut self, sq: Option<u8>) {
|
pub fn set_en_passant_target_square(&mut self, sq: Option<usize>) {
|
||||||
self.en_passant_target_square = sq;
|
self.en_passant_target_square = sq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ pub enum MoveType {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||||
pub struct Move {
|
pub struct Move {
|
||||||
pub source: u32,
|
pub source: usize,
|
||||||
pub target: u32,
|
pub target: usize,
|
||||||
pub move_type: MoveType,
|
pub move_type: MoveType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Move {
|
impl Move {
|
||||||
pub const fn new(source: u32, target: u32) -> Self {
|
pub const fn new(source: usize, target: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
source,
|
source,
|
||||||
target,
|
target,
|
||||||
@@ -33,7 +33,7 @@ impl Move {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn new_with_type(source: u32, target: u32, move_type: MoveType) -> Self {
|
pub const fn new_with_type(source: usize, target: usize, move_type: MoveType) -> Self {
|
||||||
Self {
|
Self {
|
||||||
source,
|
source,
|
||||||
target,
|
target,
|
||||||
|
|||||||
105
src/movegen.rs
105
src/movegen.rs
@@ -2,21 +2,20 @@ use crate::attack::{
|
|||||||
get_bishop_attacks, get_king_attacks, get_knight_attacks, get_pawn_attacks, get_queen_attacks,
|
get_bishop_attacks, get_king_attacks, get_knight_attacks, get_pawn_attacks, get_queen_attacks,
|
||||||
get_rook_attacks,
|
get_rook_attacks,
|
||||||
};
|
};
|
||||||
|
use crate::bitboard::{
|
||||||
|
have_common_bit, lsb, square_to_bitboard, NOT_FILE_A, NOT_FILE_H, RANK_1, RANK_2, RANK_4,
|
||||||
|
RANK_5, RANK_7, RANK_8,
|
||||||
|
};
|
||||||
use crate::board::{Board, Color};
|
use crate::board::{Board, Color};
|
||||||
use crate::game::Castle;
|
use crate::game::Castle;
|
||||||
use crate::r#move::{Move, MoveType, Promote};
|
use crate::r#move::{Move, MoveType, Promote};
|
||||||
use u64 as Bitboard;
|
use u64 as Bitboard;
|
||||||
|
|
||||||
const NOT_A_FILE: Bitboard = 0xfefefefefefefefe;
|
|
||||||
const NOT_H_FILE: Bitboard = 0x7f7f7f7f7f7f7f7f;
|
|
||||||
const RANK_4: Bitboard = 0x00000000ff000000;
|
|
||||||
const RANK_5: Bitboard = 0x000000ff00000000;
|
|
||||||
|
|
||||||
pub fn pawn_pseudo_moves(
|
pub fn pawn_pseudo_moves(
|
||||||
pawns: Bitboard,
|
pawns: Bitboard,
|
||||||
all_occupancies: Bitboard,
|
all_occupancies: Bitboard,
|
||||||
enemy_occupancies: Bitboard,
|
enemy_occupancies: Bitboard,
|
||||||
en_passant_square: Option<u8>,
|
en_passant_square: Option<usize>,
|
||||||
color: Color,
|
color: Color,
|
||||||
) -> Vec<Move> {
|
) -> Vec<Move> {
|
||||||
let mut moves = vec![];
|
let mut moves = vec![];
|
||||||
@@ -47,10 +46,10 @@ fn white_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec<Move> {
|
|||||||
|
|
||||||
let mut single_push_targets = (pawns << 8) & empty;
|
let mut single_push_targets = (pawns << 8) & empty;
|
||||||
while single_push_targets != 0 {
|
while single_push_targets != 0 {
|
||||||
let to = single_push_targets.trailing_zeros();
|
let to = lsb(single_push_targets);
|
||||||
let from = to - 8;
|
let from = to - 8;
|
||||||
|
|
||||||
if 1_u64 << from as u64 & 0xff000000000000 != 0 {
|
if have_common_bit(square_to_bitboard(from), RANK_7) {
|
||||||
moves.extend([
|
moves.extend([
|
||||||
Move::new_with_type(from, to, MoveType::Promotion(Promote::Knight)),
|
Move::new_with_type(from, to, MoveType::Promotion(Promote::Knight)),
|
||||||
Move::new_with_type(from, to, MoveType::Promotion(Promote::Bishop)),
|
Move::new_with_type(from, to, MoveType::Promotion(Promote::Bishop)),
|
||||||
@@ -62,10 +61,11 @@ fn white_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec<Move> {
|
|||||||
}
|
}
|
||||||
single_push_targets &= single_push_targets - 1;
|
single_push_targets &= single_push_targets - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let single_push_targets = (pawns << 8) & empty;
|
let single_push_targets = (pawns << 8) & empty;
|
||||||
let mut double_push_targets = (single_push_targets << 8) & empty & RANK_4;
|
let mut double_push_targets = (single_push_targets << 8) & empty & RANK_4;
|
||||||
while double_push_targets != 0 {
|
while double_push_targets != 0 {
|
||||||
let to = double_push_targets.trailing_zeros();
|
let to = lsb(double_push_targets);
|
||||||
let from = to - 16;
|
let from = to - 16;
|
||||||
moves.push(Move::new_with_type(from, to, MoveType::DoublePush));
|
moves.push(Move::new_with_type(from, to, MoveType::DoublePush));
|
||||||
double_push_targets &= double_push_targets - 1;
|
double_push_targets &= double_push_targets - 1;
|
||||||
@@ -79,10 +79,10 @@ fn black_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec<Move> {
|
|||||||
|
|
||||||
let mut single_push_targets = (pawns >> 8) & empty;
|
let mut single_push_targets = (pawns >> 8) & empty;
|
||||||
while single_push_targets != 0 {
|
while single_push_targets != 0 {
|
||||||
let to = single_push_targets.trailing_zeros();
|
let to = lsb(single_push_targets);
|
||||||
let from = to + 8;
|
let from = to + 8;
|
||||||
|
|
||||||
if 1_u64 << from as u64 & 0xff00 != 0 {
|
if have_common_bit(square_to_bitboard(from), RANK_2) {
|
||||||
moves.extend([
|
moves.extend([
|
||||||
Move::new_with_type(from, to, MoveType::Promotion(Promote::Knight)),
|
Move::new_with_type(from, to, MoveType::Promotion(Promote::Knight)),
|
||||||
Move::new_with_type(from, to, MoveType::Promotion(Promote::Bishop)),
|
Move::new_with_type(from, to, MoveType::Promotion(Promote::Bishop)),
|
||||||
@@ -98,7 +98,7 @@ fn black_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec<Move> {
|
|||||||
let single_push_targets = (pawns >> 8) & empty;
|
let single_push_targets = (pawns >> 8) & empty;
|
||||||
let mut double_push_targets = (single_push_targets >> 8) & empty & RANK_5;
|
let mut double_push_targets = (single_push_targets >> 8) & empty & RANK_5;
|
||||||
while double_push_targets != 0 {
|
while double_push_targets != 0 {
|
||||||
let to = double_push_targets.trailing_zeros();
|
let to = lsb(double_push_targets);
|
||||||
let from = to + 16;
|
let from = to + 16;
|
||||||
moves.push(Move::new_with_type(from, to, MoveType::DoublePush));
|
moves.push(Move::new_with_type(from, to, MoveType::DoublePush));
|
||||||
double_push_targets &= double_push_targets - 1;
|
double_push_targets &= double_push_targets - 1;
|
||||||
@@ -109,17 +109,17 @@ fn black_pawn_quiet_moves(pawns: Bitboard, occupancies: Bitboard) -> Vec<Move> {
|
|||||||
fn white_pawn_capture_moves(
|
fn white_pawn_capture_moves(
|
||||||
pawns: Bitboard,
|
pawns: Bitboard,
|
||||||
enemy_occupancies: Bitboard,
|
enemy_occupancies: Bitboard,
|
||||||
en_passant_square: Option<u8>,
|
en_passant_square: Option<usize>,
|
||||||
) -> Vec<Move> {
|
) -> Vec<Move> {
|
||||||
let mut moves = vec![];
|
let mut moves = vec![];
|
||||||
let mut w_pawns_capture_east = pawns & ((enemy_occupancies >> 9) & NOT_H_FILE);
|
let mut w_pawns_capture_east = pawns & ((enemy_occupancies >> 9) & NOT_FILE_H);
|
||||||
let mut w_pawns_capture_west = pawns & ((enemy_occupancies >> 7) & NOT_A_FILE);
|
let mut w_pawns_capture_west = pawns & ((enemy_occupancies >> 7) & NOT_FILE_A);
|
||||||
|
|
||||||
while w_pawns_capture_east != 0 {
|
while w_pawns_capture_east != 0 {
|
||||||
let from = w_pawns_capture_east.trailing_zeros();
|
let from = lsb(w_pawns_capture_east);
|
||||||
let to = from + 9;
|
let to = from + 9;
|
||||||
|
|
||||||
if 1_u64 << to as u64 & 0xff00000000000000 != 0 {
|
if have_common_bit(square_to_bitboard(to), RANK_8) {
|
||||||
moves.extend([
|
moves.extend([
|
||||||
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)),
|
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)),
|
||||||
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)),
|
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)),
|
||||||
@@ -132,10 +132,10 @@ fn white_pawn_capture_moves(
|
|||||||
w_pawns_capture_east &= w_pawns_capture_east - 1;
|
w_pawns_capture_east &= w_pawns_capture_east - 1;
|
||||||
}
|
}
|
||||||
while w_pawns_capture_west != 0 {
|
while w_pawns_capture_west != 0 {
|
||||||
let from = w_pawns_capture_west.trailing_zeros();
|
let from = lsb(w_pawns_capture_west);
|
||||||
let to = from + 7;
|
let to = from + 7;
|
||||||
|
|
||||||
if 1_u64 << to as u64 & 0xff00000000000000 != 0 {
|
if have_common_bit(square_to_bitboard(to), RANK_8) {
|
||||||
moves.extend([
|
moves.extend([
|
||||||
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)),
|
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)),
|
||||||
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)),
|
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)),
|
||||||
@@ -149,12 +149,12 @@ fn white_pawn_capture_moves(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(en_passant_square) = en_passant_square {
|
if let Some(en_passant_square) = en_passant_square {
|
||||||
let attacked_from = get_pawn_attacks(en_passant_square as usize, Color::Black);
|
let attacked_from = get_pawn_attacks(en_passant_square, Color::Black);
|
||||||
let mut result = attacked_from & pawns;
|
let mut result = attacked_from & pawns;
|
||||||
while result != 0 {
|
while result != 0 {
|
||||||
moves.push(Move::new_with_type(
|
moves.push(Move::new_with_type(
|
||||||
result.trailing_zeros(),
|
lsb(result),
|
||||||
en_passant_square as u32,
|
en_passant_square,
|
||||||
MoveType::EnPassant,
|
MoveType::EnPassant,
|
||||||
));
|
));
|
||||||
result &= result - 1;
|
result &= result - 1;
|
||||||
@@ -166,16 +166,17 @@ fn white_pawn_capture_moves(
|
|||||||
fn black_pawn_capture_moves(
|
fn black_pawn_capture_moves(
|
||||||
pawns: Bitboard,
|
pawns: Bitboard,
|
||||||
enemy_occupancies: Bitboard,
|
enemy_occupancies: Bitboard,
|
||||||
en_passant_square: Option<u8>,
|
en_passant_square: Option<usize>,
|
||||||
) -> Vec<Move> {
|
) -> Vec<Move> {
|
||||||
let mut moves = vec![];
|
let mut moves = vec![];
|
||||||
let mut b_pawns_capture_east = pawns & ((enemy_occupancies << 7) & NOT_H_FILE);
|
let mut b_pawns_capture_east = pawns & ((enemy_occupancies << 7) & NOT_FILE_H);
|
||||||
let mut b_pawns_capture_west = pawns & ((enemy_occupancies << 9) & NOT_A_FILE);
|
let mut b_pawns_capture_west = pawns & ((enemy_occupancies << 9) & NOT_FILE_A);
|
||||||
|
|
||||||
while b_pawns_capture_east != 0 {
|
while b_pawns_capture_east != 0 {
|
||||||
let from = b_pawns_capture_east.trailing_zeros();
|
let from = lsb(b_pawns_capture_east);
|
||||||
let to = from - 7;
|
let to = from - 7;
|
||||||
if 1_u64 << to as u64 & 0xff != 0 {
|
|
||||||
|
if have_common_bit(square_to_bitboard(to), RANK_1) {
|
||||||
moves.extend([
|
moves.extend([
|
||||||
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)),
|
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)),
|
||||||
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)),
|
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)),
|
||||||
@@ -189,9 +190,9 @@ fn black_pawn_capture_moves(
|
|||||||
}
|
}
|
||||||
|
|
||||||
while b_pawns_capture_west != 0 {
|
while b_pawns_capture_west != 0 {
|
||||||
let from = b_pawns_capture_west.trailing_zeros();
|
let from = lsb(b_pawns_capture_west);
|
||||||
let to = from - 9;
|
let to = from - 9;
|
||||||
if 1_u64 << to as u64 & 0xff != 0 {
|
if have_common_bit(square_to_bitboard(to), RANK_1) {
|
||||||
moves.extend([
|
moves.extend([
|
||||||
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)),
|
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Knight)),
|
||||||
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)),
|
Move::new_with_type(from, to, MoveType::PromotionCapture(Promote::Bishop)),
|
||||||
@@ -205,12 +206,12 @@ fn black_pawn_capture_moves(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(en_passant_square) = en_passant_square {
|
if let Some(en_passant_square) = en_passant_square {
|
||||||
let attacked_from = get_pawn_attacks(en_passant_square as usize, Color::White);
|
let attacked_from = get_pawn_attacks(en_passant_square, Color::White);
|
||||||
let mut result = attacked_from & pawns;
|
let mut result = attacked_from & pawns;
|
||||||
while result != 0 {
|
while result != 0 {
|
||||||
moves.push(Move::new_with_type(
|
moves.push(Move::new_with_type(
|
||||||
result.trailing_zeros(),
|
lsb(result),
|
||||||
en_passant_square as u32,
|
en_passant_square,
|
||||||
MoveType::EnPassant,
|
MoveType::EnPassant,
|
||||||
));
|
));
|
||||||
result &= result - 1;
|
result &= result - 1;
|
||||||
@@ -228,13 +229,13 @@ pub fn knight_pseudo_moves(
|
|||||||
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
||||||
|
|
||||||
while knights != 0 {
|
while knights != 0 {
|
||||||
let knight_square = knights.trailing_zeros() as usize;
|
let knight_square = lsb(knights);
|
||||||
let from = knight_square as u32;
|
let from = knight_square;
|
||||||
let mut attacks = get_knight_attacks(knight_square) & !own_occupancies;
|
let mut attacks = get_knight_attacks(knight_square) & !own_occupancies;
|
||||||
|
|
||||||
while attacks != 0 {
|
while attacks != 0 {
|
||||||
let attack_sq = attacks.trailing_zeros();
|
let attack_sq = lsb(attacks);
|
||||||
if (1_u64 << attack_sq) & enemy_occupancies != 0 {
|
if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) {
|
||||||
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
||||||
} else {
|
} else {
|
||||||
moves.push(Move::new(from, attack_sq));
|
moves.push(Move::new(from, attack_sq));
|
||||||
@@ -255,13 +256,13 @@ pub fn bishop_pseudo_moves(
|
|||||||
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
||||||
|
|
||||||
while bishops != 0 {
|
while bishops != 0 {
|
||||||
let bishop_square = bishops.trailing_zeros() as usize;
|
let bishop_square = lsb(bishops);
|
||||||
let from = bishop_square as u32;
|
let from = bishop_square;
|
||||||
let mut attacks = get_bishop_attacks(all_occupancies, bishop_square) & !own_occupancies;
|
let mut attacks = get_bishop_attacks(all_occupancies, bishop_square) & !own_occupancies;
|
||||||
|
|
||||||
while attacks != 0 {
|
while attacks != 0 {
|
||||||
let attack_sq = attacks.trailing_zeros();
|
let attack_sq = lsb(attacks);
|
||||||
if (1_u64 << attack_sq) & enemy_occupancies != 0 {
|
if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) {
|
||||||
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
||||||
} else {
|
} else {
|
||||||
moves.push(Move::new(from, attack_sq));
|
moves.push(Move::new(from, attack_sq));
|
||||||
@@ -282,13 +283,13 @@ pub fn rook_pseudo_moves(
|
|||||||
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
||||||
|
|
||||||
while rooks != 0 {
|
while rooks != 0 {
|
||||||
let rook_square = rooks.trailing_zeros() as usize;
|
let rook_square = lsb(rooks);
|
||||||
let from = rook_square as u32;
|
let from = rook_square;
|
||||||
let mut attacks = get_rook_attacks(all_occupancies, rook_square) & !own_occupancies;
|
let mut attacks = get_rook_attacks(all_occupancies, rook_square) & !own_occupancies;
|
||||||
|
|
||||||
while attacks != 0 {
|
while attacks != 0 {
|
||||||
let attack_sq = attacks.trailing_zeros();
|
let attack_sq = lsb(attacks);
|
||||||
if (1_u64 << attack_sq) & enemy_occupancies != 0 {
|
if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) {
|
||||||
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
||||||
} else {
|
} else {
|
||||||
moves.push(Move::new(from, attack_sq));
|
moves.push(Move::new(from, attack_sq));
|
||||||
@@ -309,13 +310,13 @@ pub fn queen_pseudo_moves(
|
|||||||
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
||||||
|
|
||||||
while queens != 0 {
|
while queens != 0 {
|
||||||
let queen_square = queens.trailing_zeros() as usize;
|
let queen_square = lsb(queens);
|
||||||
let from = queen_square as u32;
|
let from = queen_square;
|
||||||
let mut attacks = get_queen_attacks(all_occupancies, queen_square) & !own_occupancies;
|
let mut attacks = get_queen_attacks(all_occupancies, queen_square) & !own_occupancies;
|
||||||
|
|
||||||
while attacks != 0 {
|
while attacks != 0 {
|
||||||
let attack_sq = attacks.trailing_zeros();
|
let attack_sq = lsb(attacks);
|
||||||
if (1_u64 << attack_sq) & enemy_occupancies != 0 {
|
if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) {
|
||||||
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
||||||
} else {
|
} else {
|
||||||
moves.push(Move::new(from, attack_sq));
|
moves.push(Move::new(from, attack_sq));
|
||||||
@@ -335,14 +336,14 @@ pub fn king_pseudo_moves(
|
|||||||
color: Color,
|
color: Color,
|
||||||
) -> Vec<Move> {
|
) -> Vec<Move> {
|
||||||
let mut moves = vec![];
|
let mut moves = vec![];
|
||||||
let king_square = king.trailing_zeros() as usize;
|
let king_square = lsb(king);
|
||||||
let from = king_square as u32;
|
let from = king_square;
|
||||||
let mut attacks = get_king_attacks(king_square) & !own_occupancies;
|
let mut attacks = get_king_attacks(king_square) & !own_occupancies;
|
||||||
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
let enemy_occupancies = all_occupancies ^ own_occupancies;
|
||||||
|
|
||||||
while attacks != 0 {
|
while attacks != 0 {
|
||||||
let attack_sq = attacks.trailing_zeros();
|
let attack_sq = lsb(attacks);
|
||||||
if (1_u64 << attack_sq) & enemy_occupancies != 0 {
|
if have_common_bit(square_to_bitboard(attack_sq), enemy_occupancies) {
|
||||||
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
moves.push(Move::new_with_type(from, attack_sq, MoveType::Capture));
|
||||||
} else {
|
} else {
|
||||||
moves.push(Move::new(from, attack_sq));
|
moves.push(Move::new(from, attack_sq));
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ pub fn perftree_script() {
|
|||||||
let mut game = crate::fen::from_fen(fen).expect("Invalid FEN string");
|
let mut game = crate::fen::from_fen(fen).expect("Invalid FEN string");
|
||||||
let (mut nodes, depth): (u64, u8) = (0, MAX_DEPTH);
|
let (mut nodes, depth): (u64, u8) = (0, MAX_DEPTH);
|
||||||
driver(&mut game, &mut nodes, depth);
|
driver(&mut game, &mut nodes, depth);
|
||||||
println!();
|
|
||||||
println!("{}", nodes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|||||||
Reference in New Issue
Block a user