Skip to content

Commit 240aa31

Browse files
committed
use u64 for occupancy
1 parent 056684f commit 240aa31

1 file changed

Lines changed: 136 additions & 21 deletions

File tree

check-buddy/src/board.rs

Lines changed: 136 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub struct BoardMap {
2626
white_kingside_rook_moved: bool,
2727
white_king_pos: Position,
2828
black_king_pos: Position,
29+
white_occupancy: u64,
30+
black_occupancy: u64,
2931
}
3032

3133
impl Default for BoardMap {
@@ -43,6 +45,8 @@ impl Default for BoardMap {
4345
white_kingside_rook_moved: false,
4446
white_king_pos: [0, 0],
4547
black_king_pos: [0, 0],
48+
white_occupancy: 0,
49+
black_occupancy: 0,
4650
}
4751
}
4852
}
@@ -80,6 +84,13 @@ impl BoardMap {
8084
let pos = [index / 8, index % 8];
8185
board.squares[pos[0]][pos[1]] = Piece(color | rank);
8286

87+
let bit = 1u64 << index;
88+
if color == WHITE {
89+
board.white_occupancy |= bit;
90+
} else {
91+
board.black_occupancy |= bit;
92+
}
93+
8394
// track king position
8495
if rank == KING {
8596
if color == WHITE {
@@ -824,13 +835,25 @@ impl BoardMap {
824835
promotion,
825836
..
826837
} = position_move;
838+
839+
let from_bit = 1u64 << (from[0] * 8 + from[1]);
840+
let to_bit = 1u64 << (to[0] * 8 + to[1]);
841+
827842
if en_passant {
828843
let shift = if self.get_piece(from).get_color() == PieceColor::Black {
829844
1
830845
} else {
831846
-1
832847
};
833848
let to_step = [(to[0] as isize - shift) as usize, to[1]];
849+
let ep_bit = 1u64 << (to_step[0] * 8 + to_step[1]);
850+
851+
// remove captured pawn from occupancy
852+
if self.get_piece(from).get_color() == PieceColor::White {
853+
self.black_occupancy ^= ep_bit;
854+
} else {
855+
self.white_occupancy ^= ep_bit;
856+
}
834857
self.set_piece(to_step, 0);
835858
}
836859

@@ -887,17 +910,51 @@ impl BoardMap {
887910
// kingside castle - move rook from h-file to f-file
888911
let rook_from = [from[0], 7];
889912
let rook_to = [from[0], 5];
913+
let rook_from_bit = 1u64 << (rook_from[0] * 8 + rook_from[1]);
914+
let rook_to_bit = 1u64 << (rook_to[0] * 8 + rook_to[1]);
915+
if piece.get_color() == PieceColor::White {
916+
self.white_occupancy ^= rook_from_bit;
917+
self.white_occupancy |= rook_to_bit;
918+
} else {
919+
self.black_occupancy ^= rook_from_bit;
920+
self.black_occupancy |= rook_to_bit;
921+
}
890922
self.set_piece(rook_to, self.get_piece(rook_from).0);
891923
self.set_piece(rook_from, 0);
892924
} else if from[1] == 4 && to[1] == 2 {
893925
// queenside castle - move rook from a-file to d-file
894926
let rook_from = [from[0], 0];
895927
let rook_to = [from[0], 3];
928+
let rook_from_bit = 1u64 << (rook_from[0] * 8 + rook_from[1]);
929+
let rook_to_bit = 1u64 << (rook_to[0] * 8 + rook_to[1]);
930+
if piece.get_color() == PieceColor::White {
931+
self.white_occupancy ^= rook_from_bit;
932+
self.white_occupancy |= rook_to_bit;
933+
} else {
934+
self.black_occupancy ^= rook_from_bit;
935+
self.black_occupancy |= rook_to_bit;
936+
}
896937
self.set_piece(rook_to, self.get_piece(rook_from).0);
897938
self.set_piece(rook_from, 0);
898939
}
899940
}
900941

942+
let target_piece = self.get_piece(to);
943+
if piece.get_color() == PieceColor::White {
944+
self.white_occupancy ^= from_bit;
945+
self.white_occupancy |= to_bit;
946+
947+
if target_piece.is_piece() {
948+
self.black_occupancy ^= to_bit;
949+
}
950+
} else {
951+
self.black_occupancy ^= from_bit;
952+
self.black_occupancy |= to_bit;
953+
if target_piece.is_piece() {
954+
self.white_occupancy ^= to_bit;
955+
}
956+
}
957+
901958
if promotion {
902959
let color = match self.get_piece(from).get_color() {
903960
PieceColor::Black => BLACK,
@@ -929,24 +986,60 @@ impl BoardMap {
929986
..
930987
} = piece_move;
931988

989+
let from_bit = 1u64 << (from[0] * 8 + from[1]);
990+
let to_bit = 1u64 << (to[0] * 8 + to[1]);
991+
932992
// undo castling rook movement if this was a castling move
933993
let piece = self.get_piece(to);
934994
if let Some(PieceType::King) = piece.get_type() {
935995
if from[1] == 4 && to[1] == 6 {
936996
// undo kingside castle - move rook back from f-file to h-file
937997
let rook_from = [from[0], 5];
938998
let rook_to = [from[0], 7];
999+
let rook_from_bit = 1u64 << (rook_from[0] * 8 + rook_from[1]);
1000+
let rook_to_bit = 1u64 << (rook_to[0] * 8 + rook_to[1]);
1001+
if piece.get_color() == PieceColor::White {
1002+
self.white_occupancy ^= rook_from_bit;
1003+
self.white_occupancy |= rook_to_bit;
1004+
} else {
1005+
self.black_occupancy ^= rook_from_bit;
1006+
self.black_occupancy |= rook_to_bit;
1007+
}
9391008
self.set_piece(rook_to, self.get_piece(rook_from).0);
9401009
self.set_piece(rook_from, 0);
9411010
} else if from[1] == 4 && to[1] == 2 {
9421011
// undo queenside castle - move rook back from d-file to a-file
9431012
let rook_from = [from[0], 3];
9441013
let rook_to = [from[0], 0];
1014+
let rook_from_bit = 1u64 << (rook_from[0] * 8 + rook_from[1]);
1015+
let rook_to_bit = 1u64 << (rook_to[0] * 8 + rook_to[1]);
1016+
if piece.get_color() == PieceColor::White {
1017+
self.white_occupancy ^= rook_from_bit;
1018+
self.white_occupancy |= rook_to_bit;
1019+
} else {
1020+
self.black_occupancy ^= rook_from_bit;
1021+
self.black_occupancy |= rook_to_bit;
1022+
}
9451023
self.set_piece(rook_to, self.get_piece(rook_from).0);
9461024
self.set_piece(rook_from, 0);
9471025
}
9481026
}
9491027

1028+
if piece.get_color() == PieceColor::White {
1029+
self.white_occupancy ^= to_bit;
1030+
self.white_occupancy |= from_bit;
1031+
1032+
if last_piece != 0 {
1033+
self.black_occupancy |= to_bit;
1034+
}
1035+
} else {
1036+
self.black_occupancy ^= to_bit;
1037+
self.black_occupancy |= from_bit;
1038+
if last_piece != 0 {
1039+
self.white_occupancy |= to_bit;
1040+
}
1041+
}
1042+
9501043
self.set_piece(from, self.get_piece(to).0);
9511044
self.set_piece(to, last_piece);
9521045

@@ -959,6 +1052,13 @@ impl BoardMap {
9591052
-1
9601053
};
9611054
let captured_pawn_pos = [(to[0] as isize - shift) as usize, to[1]];
1055+
let ep_bit = 1u64 << (captured_pawn_pos[0] * 8 + captured_pawn_pos[1]);
1056+
// Restore captured pawn in occupancy
1057+
if moving_piece.get_color() == PieceColor::White {
1058+
self.black_occupancy |= ep_bit;
1059+
} else {
1060+
self.white_occupancy |= ep_bit;
1061+
}
9621062
// restore the captured pawn (it was the opponent's pawn with en-passant flag)
9631063
let opponent_color = if moving_piece.get_color() == PieceColor::Black {
9641064
WHITE
@@ -971,33 +1071,48 @@ impl BoardMap {
9711071
/// generates all moves based on active color.
9721072
pub fn gen_all_legal_moves(&self) -> Vec<PositionMove> {
9731073
let mut legal_moves = vec![];
974-
for rank in 0..8 {
975-
for file in 0..8 {
976-
let piece = self.squares[rank][file];
977-
if piece.is_piece() && piece.get_color() == self.active_color {
978-
let from_move = [rank, file];
979-
let to_moves = self.gen_legal_positions([rank, file]);
980-
let moves = to_moves
981-
.iter()
982-
.map(|&to| PositionMove::new(from_move, to))
983-
.collect::<Vec<_>>();
984-
legal_moves.extend(moves);
985-
}
986-
}
1074+
1075+
let mut active_bits = if self.active_color == PieceColor::White {
1076+
self.white_occupancy
1077+
} else {
1078+
self.black_occupancy
1079+
};
1080+
1081+
while active_bits != 0 {
1082+
let square_idx = active_bits.trailing_zeros() as usize;
1083+
active_bits ^= 1u64 << square_idx; // Clear the bit
1084+
1085+
let from_move = [square_idx / 8, square_idx % 8];
1086+
let to_moves = self.gen_legal_positions(from_move);
1087+
let moves = to_moves
1088+
.iter()
1089+
.map(|&to| PositionMove::new(from_move, to))
1090+
.collect::<Vec<_>>();
1091+
legal_moves.extend(moves);
9871092
}
1093+
9881094
legal_moves
9891095
}
9901096
pub fn gen_all_opponent_positions(&self) -> Vec<Position> {
9911097
let mut opponent_positions = vec![];
992-
for rank in 0..8 {
993-
for file in 0..8 {
994-
let piece = self.squares[rank][file];
995-
if piece.is_piece() && piece.get_color() != self.active_color {
996-
let positions = self.gen_to_positions([rank, file]);
997-
opponent_positions.extend(positions);
998-
}
999-
}
1098+
1099+
// Use bitboard to iterate only over opponent pieces
1100+
let mut opponent_bits = if self.active_color == PieceColor::White {
1101+
self.black_occupancy
1102+
} else {
1103+
self.white_occupancy
1104+
};
1105+
1106+
// Iterate through set bits (opponent pieces)
1107+
while opponent_bits != 0 {
1108+
let square_idx = opponent_bits.trailing_zeros() as usize;
1109+
opponent_bits ^= 1u64 << square_idx; // Clear the bit
1110+
1111+
let pos = [square_idx / 8, square_idx % 8];
1112+
let positions = self.gen_to_positions(pos);
1113+
opponent_positions.extend(positions);
10001114
}
1115+
10011116
opponent_positions
10021117
}
10031118
pub fn is_en_passant(&self, from: Position, to: Position) -> bool {

0 commit comments

Comments
 (0)