Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify pieces color bb #100

Merged
merged 2 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
rustflags = ["-C", "target-cpu=native"]
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ opt-level = 1

[profile.release]
opt-level = 3
lto = true
lto = "fat"
codegen-units = 1
panic = "abort"
strip = "debuginfo"

[dev-dependencies]
criterion = { version = "0.5.1", features = ["html_reports"] }
Expand Down
10 changes: 5 additions & 5 deletions gauntlet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ readonly BOOK_FORMAT=epd
readonly THREADS=4
readonly BUILD_PATH=./target/release/$ENGINE_NAME
readonly MESSAGE_FILE=message.txt
readonly FAST_ROUNDS=500
readonly SLOW_ROUNDS=100
readonly FAST_TIME_CONTROL=1+0.1
readonly SLOW_TIME_CONTROL=30+0.3
readonly ELO_THRESHOLD=25
readonly FAST_ROUNDS=300
readonly SLOW_ROUNDS=150
readonly FAST_TIME_CONTROL=5+0.1
readonly SLOW_TIME_CONTROL=10+0.2
readonly ELO_THRESHOLD=20
readonly UPSTREAM=${1:-master} # Default to master if no argument is given

function run_gauntlet {
Expand Down
3 changes: 1 addition & 2 deletions src/evaluation/position/bishops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ pub fn evaluate_bishops(position: &Position) -> ValueScore {
let mut score = 0;

for color in Color::list() {
let our_bishops =
position.board.pieces_bb(Piece::Bishop) & position.board.occupancy_bb(*color);
let our_bishops = position.board.pieces_bb_color(Piece::Bishop, *color);

// Bishop pair
if our_bishops.count_ones() > 1 {
Expand Down
42 changes: 13 additions & 29 deletions src/evaluation/position/king.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
fn king_pawn_shelter(position: &Position, king_color: Color, king_square: Square) -> ValueScore {
let mut shelter = 0;

let our_pawns = position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(king_color);
let our_pawns = position.board.pieces_bb_color(Piece::Pawn, king_color);

let file_min = match king_square.file() {
0 => 0,
Expand Down Expand Up @@ -62,14 +62,10 @@ fn king_tropism(position: &Position, king_color: Color, king_square: Square) ->
}

pub fn evaluate_king_safety(position: &Position, midgame_ratio: u8) -> ValueScore {
let white_king_square = (position.board.occupancy_bb(Color::White)
& position.board.pieces_bb(Piece::King))
.into_iter()
.next();
let black_king_square = (position.board.occupancy_bb(Color::Black)
& position.board.pieces_bb(Piece::King))
.into_iter()
.next();
let white_king_square =
position.board.pieces_bb_color(Piece::King, Color::White).into_iter().next();
let black_king_square =
position.board.pieces_bb_color(Piece::King, Color::Black).into_iter().next();

if white_king_square.is_none() || black_king_square.is_none() {
return 0;
Expand Down Expand Up @@ -103,32 +99,20 @@ mod tests {
};

fn position_tropism(position: &Position) -> ValueScore {
let white_king_square = (position.board.occupancy_bb(Color::White)
& position.board.pieces_bb(Piece::King))
.into_iter()
.next()
.unwrap();
let black_king_square = (position.board.occupancy_bb(Color::Black)
& position.board.pieces_bb(Piece::King))
.into_iter()
.next()
.unwrap();
let white_king_square =
position.board.pieces_bb_color(Piece::King, Color::White).into_iter().next().unwrap();
let black_king_square =
position.board.pieces_bb_color(Piece::King, Color::Black).into_iter().next().unwrap();

king_tropism(position, Color::White, white_king_square)
- king_tropism(position, Color::Black, black_king_square)
}

fn position_shelter(position: &Position) -> ValueScore {
let white_king_square = (position.board.occupancy_bb(Color::White)
& position.board.pieces_bb(Piece::King))
.into_iter()
.next()
.unwrap();
let black_king_square = (position.board.occupancy_bb(Color::Black)
& position.board.pieces_bb(Piece::King))
.into_iter()
.next()
.unwrap();
let white_king_square =
position.board.pieces_bb_color(Piece::King, Color::White).into_iter().next().unwrap();
let black_king_square =
position.board.pieces_bb_color(Piece::King, Color::Black).into_iter().next().unwrap();

super::king_pawn_shelter(position, Color::White, white_king_square)
- super::king_pawn_shelter(position, Color::Black, black_king_square)
Expand Down
39 changes: 13 additions & 26 deletions src/evaluation/position/pawns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,8 @@ fn passed_pawns(us_direction: i8, us_bb: Bitboard, them_bb: Bitboard) -> Vec<Rel
pub fn evaluate_pawn_structure(position: &Position) -> ValueScore {
let mut score = 0;

let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let black_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::Black);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);
let black_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::Black);

const DOUBLED_PAWNS_PENALTY: ValueScore = -10;
score += doubled_pawns(white_pawns) as ValueScore * DOUBLED_PAWNS_PENALTY;
Expand Down Expand Up @@ -110,73 +108,64 @@ mod tests {
#[test]
fn doubled_pawns_1() {
let position = Position::from_fen("8/8/8/P7/P4P2/8/PPPP1PP1/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);

assert_eq!(super::doubled_pawns(white_pawns), 3);
}

#[test]
fn double_pawns_2() {
let position = Position::from_fen("8/8/7P/8/2P5/5PP1/PP1PP3/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);

assert_eq!(super::doubled_pawns(white_pawns), 0);
}

#[test]
fn pawn_islands_1() {
let position = Position::from_fen("8/8/7P/8/2P5/5PP1/PP1PP3/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);

assert_eq!(super::pawn_islands(white_pawns), 1);
}

#[test]
fn pawn_islands_2() {
let position = Position::from_fen("8/8/8/8/2P5/5PP1/1P1PP3/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);

assert_eq!(super::pawn_islands(white_pawns), 1);
}

#[test]
fn pawn_islands_3() {
let position = Position::from_fen("8/8/8/8/2P5/5PP1/1P1P4/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);

assert_eq!(super::pawn_islands(white_pawns), 2);
}

#[test]
fn pawn_islands_4() {
let position = Position::from_fen("8/8/8/8/8/P4PP1/1P1P4/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);

assert_eq!(super::pawn_islands(white_pawns), 3);
}

#[test]
fn pawn_islands_5() {
let position = Position::from_fen("8/8/8/8/8/P2P3P/8/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);

assert_eq!(super::pawn_islands(white_pawns), 3);
}

#[test]
fn passed_pawns_1() {
let position = Position::from_fen("8/1p6/8/1pPP4/5p2/7P/5P2/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let black_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::Black);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);
let black_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::Black);

assert_eq!(
passed_pawns(MoveDirection::pawn_direction(Color::White), white_pawns, black_pawns),
Expand All @@ -192,10 +181,8 @@ mod tests {
#[test]
fn passed_pawns_2() {
let position = Position::from_fen("8/8/8/1pPPp1P1/1p3pP1/7P/8/8 w - - 0 1").unwrap();
let white_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::White);
let black_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(Color::Black);
let white_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::White);
let black_pawns = position.board.pieces_bb_color(Piece::Pawn, Color::Black);

assert_eq!(
passed_pawns(MoveDirection::pawn_direction(Color::White), white_pawns, black_pawns),
Expand Down
8 changes: 3 additions & 5 deletions src/evaluation/position/rooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@ pub fn evaluate_rooks(position: &Position) -> ValueScore {
let mut score = 0;

for color in Color::list() {
let rooks = position.board.pieces_bb(Piece::Rook) & position.board.occupancy_bb(*color);
let rooks = position.board.pieces_bb_color(Piece::Rook, *color);

if let Some(rook) = rooks.into_iter().next() {
let occupancy = position.board.occupancy_bb_all();
let our_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(*color);
let their_pawns = position.board.pieces_bb(Piece::Pawn)
& position.board.occupancy_bb(color.opposite());
let our_pawns = position.board.pieces_bb_color(Piece::Pawn, *color);
let their_pawns = position.board.pieces_bb_color(Piece::Pawn, color.opposite());
let our_file = Bitboard::file_mask(rook.file());
let our_rank = Bitboard::rank_mask(rook.rank());

Expand Down
15 changes: 6 additions & 9 deletions src/moves/attacks/specials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const FIRST_ROW_WHITE: Bitboard = Bitboard::rank_mask(0);
const FIRST_ROW_BLACK: Bitboard = Bitboard::rank_mask(7);

pub fn pawn_attacks(board: &Board, color: Color) -> Bitboard {
let our_pawns = board.pieces_bb(Piece::Pawn) & board.occupancy_bb(color);
let our_pawns = board.pieces_bb_color(Piece::Pawn, color);
let direction = MoveDirection::pawn_direction(color);

(our_pawns & !PAWN_WEST_EDGE_FILE).shift(direction + MoveDirection::WEST)
Expand All @@ -31,8 +31,7 @@ pub fn pawn_attacks(board: &Board, color: Color) -> Bitboard {
pub fn generate_pawn_moves(stage: MoveStage, position: &Position, moves: &mut Vec<Move>) {
let occupancy = position.board.occupancy_bb_all();
let occupancy_them = position.board.occupancy_bb(position.side_to_move.opposite());
let our_pawns =
position.board.pieces_bb(Piece::Pawn) & position.board.occupancy_bb(position.side_to_move);
let our_pawns = position.board.pieces_bb_color(Piece::Pawn, position.side_to_move);

let direction = MoveDirection::pawn_direction(position.side_to_move);

Expand Down Expand Up @@ -176,9 +175,8 @@ pub fn generate_king_castles(position: &Position, moves: &mut Vec<Move>) {
}

fn generate_kingside_castle(color: Color, position: &Position, moves: &mut Vec<Move>) {
let rooks = position.board.pieces_bb(Piece::Rook) & position.board.occupancy_bb(color);
let king_square =
(position.board.pieces_bb(Piece::King) & position.board.occupancy_bb(color)).next();
let rooks = position.board.pieces_bb_color(Piece::Rook, color);
let king_square = (position.board.pieces_bb_color(Piece::King, color)).next();
let right_hand_side_rook_square = (match color {
Color::White => FIRST_ROW_WHITE,
Color::Black => FIRST_ROW_BLACK,
Expand Down Expand Up @@ -207,9 +205,8 @@ fn generate_kingside_castle(color: Color, position: &Position, moves: &mut Vec<M
}

fn generate_queenside_castle(color: Color, position: &Position, moves: &mut Vec<Move>) {
let rooks = position.board.pieces_bb(Piece::Rook) & position.board.occupancy_bb(color);
let king_square =
(position.board.pieces_bb(Piece::King) & position.board.occupancy_bb(color)).next();
let rooks = position.board.pieces_bb_color(Piece::Rook, color);
let king_square = (position.board.pieces_bb_color(Piece::King, color)).next();
let left_hand_side_rook_square = (match color {
Color::White => FIRST_ROW_WHITE,
Color::Black => FIRST_ROW_BLACK,
Expand Down
5 changes: 2 additions & 3 deletions src/moves/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl MoveDirection {
}

pub fn checked_by(board: &Board, color: Color) -> bool {
let checked_king = board.pieces_bb(Piece::King) & board.occupancy_bb(color.opposite());
let checked_king = board.pieces_bb_color(Piece::King, color.opposite());
checked_king
.into_iter()
.next()
Expand Down Expand Up @@ -167,8 +167,7 @@ pub fn generate_moves(stage: MoveStage, position: &Position) -> Vec<Move> {
}

let is_check = checked_by(board, side_to_move.opposite());
let king_square =
(board.pieces_bb(Piece::King) & board.occupancy_bb(side_to_move)).next().unwrap();
let king_square = board.pieces_bb_color(Piece::King, side_to_move).next().unwrap();

moves.retain(|mov| match mov.flag() {
MoveFlag::KingsideCastle | MoveFlag::QueensideCastle => true,
Expand Down
16 changes: 4 additions & 12 deletions src/moves/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,23 +238,15 @@ pub fn make_move<const UPDATE_METADATA: bool>(position: &Position, mov: Move) ->
&& matches!(mov.flag(), MoveFlag::Capture | MoveFlag::Quiet)
{
let king_square = match position.side_to_move {
Color::White => (position.board.pieces_bb(Piece::King)
& position.board.occupancy_bb(Color::White))
.next(),
Color::Black => (position.board.pieces_bb(Piece::King)
& position.board.occupancy_bb(Color::Black))
.next(),
Color::White => (position.board.pieces_bb_color(Piece::King, Color::White)).next(),
Color::Black => (position.board.pieces_bb_color(Piece::King, Color::Black)).next(),
};
let king_rank_rooks = match position.side_to_move {
Color::White => {
Bitboard::rank_mask(0)
& position.board.pieces_bb(Piece::Rook)
& position.board.occupancy_bb(Color::White)
Bitboard::rank_mask(0) & position.board.pieces_bb_color(Piece::Rook, Color::White)
}
Color::Black => {
Bitboard::rank_mask(7)
& position.board.pieces_bb(Piece::Rook)
& position.board.occupancy_bb(Color::Black)
Bitboard::rank_mask(7) & position.board.pieces_bb_color(Piece::Rook, Color::Black)
}
};
let left_hand_side_rook = king_rank_rooks
Expand Down
4 changes: 4 additions & 0 deletions src/position/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ impl Board {
pub fn pieces_bb(&self, piece: Piece) -> Bitboard {
self.pieces[piece as usize]
}

pub fn pieces_bb_color(&self, piece: Piece, color: Color) -> Bitboard {
self.pieces[piece as usize] & self.occupancy[color as usize]
}
}

impl std::fmt::Display for Board {
Expand Down
2 changes: 1 addition & 1 deletion src/position/fen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub fn position_from_fen(fen: &str) -> Option<Position> {
'h' => 7,
_ => return None,
};
let color_king_square = board.pieces_bb(Piece::King) & board.occupancy_bb(color);
let color_king_square = board.pieces_bb_color(Piece::King, color);
if let Some(color_king_square) = color_king_square.into_iter().next() {
let king_file = color_king_square.file();
if file > king_file {
Expand Down