diff --git a/Cargo.toml b/Cargo.toml index 756e025..52a2217 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,19 +2,8 @@ name = "seer" version = "0.1.0" edition = "2021" -build = "src/build.rs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] random = "0.12.2" - -[build-dependencies] -random = "0.12.2" - -# Optimize build scripts to shorten compile times. -[profile.dev.build-override] -opt-level = 3 - -[profile.release.build-override] -opt-level = 3 diff --git a/src/build.rs b/src/build.rs deleted file mode 100644 index 10d7a94..0000000 --- a/src/build.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::io::{Result, Write}; - -pub mod board; -pub mod movegen; -pub mod utils; - -use crate::{ - board::{Bitboard, Color, File, Square}, - movegen::{ - naive::{ - king::king_moves, - knight::knight_moves, - pawn::{pawn_captures, pawn_moves}, - }, - wizardry::generation::{generate_bishop_magics, generate_rook_magics}, - Magic, - }, -}; - -fn print_magics(out: &mut dyn Write, var_name: &str, magics: &[Magic]) -> Result<()> { - writeln!(out, "static {}: [Magic; {}] = [", var_name, magics.len())?; - for magic in magics.iter() { - writeln!( - out, - " Magic{{magic: {}, offset: {}, mask: Bitboard({}), shift: {},}},", - magic.magic, magic.offset, magic.mask.0, magic.shift - )?; - } - writeln!(out, "];")?; - Ok(()) -} - -fn print_boards(out: &mut dyn Write, var_name: &str, boards: &[Bitboard]) -> Result<()> { - writeln!(out, "static {}: [Bitboard; {}] = [", var_name, boards.len())?; - for board in boards.iter().cloned() { - writeln!(out, " Bitboard({}),", board.0)?; - } - writeln!(out, "];")?; - Ok(()) -} - -fn print_double_sided_boards( - out: &mut dyn Write, - var_name: &str, - white_boards: &[Bitboard], - black_boards: &[Bitboard], -) -> Result<()> { - assert_eq!(white_boards.len(), black_boards.len()); - writeln!( - out, - "static {}: [[Bitboard; {}]; 2] = [", - var_name, - white_boards.len() - )?; - for color in Color::iter() { - let boards = if color == Color::White { - white_boards - } else { - black_boards - }; - writeln!(out, " [")?; - for square in Square::iter() { - writeln!(out, " Bitboard({}),", boards[square.index()].0)?; - } - writeln!(out, " ],")?; - } - writeln!(out, "];")?; - Ok(()) -} - -#[allow(clippy::redundant_clone)] -fn main() -> Result<()> { - // FIXME: rerun-if-changed directives - - let out_dir = std::env::var_os("OUT_DIR").unwrap(); - let magic_path = std::path::Path::new(&out_dir).join("magic_tables.rs"); - let mut out = std::fs::File::create(&magic_path).unwrap(); - - let rng = random::default().seed([12, 27]); - - { - let (magics, moves) = generate_bishop_magics(&mut rng.clone()); - print_magics(&mut out, "BISHOP_MAGICS", &magics)?; - print_boards(&mut out, "BISHOP_MOVES", &moves)?; - } - - { - let (magics, moves) = generate_rook_magics(&mut rng.clone()); - print_magics(&mut out, "ROOK_MAGICS", &magics)?; - print_boards(&mut out, "ROOK_MOVES", &moves)?; - } - - { - let moves: Vec<_> = Square::iter().map(knight_moves).collect(); - print_boards(&mut out, "KNIGHT_MOVES", &moves)?; - } - - { - let white_moves: Vec<_> = Square::iter() - .map(|square| pawn_moves(Color::White, square, Bitboard::EMPTY)) - .collect(); - let black_moves: Vec<_> = Square::iter() - .map(|square| pawn_moves(Color::Black, square, Bitboard::EMPTY)) - .collect(); - print_double_sided_boards(&mut out, "PAWN_MOVES", &white_moves, &black_moves)?; - let white_attacks: Vec<_> = Square::iter() - .map(|square| pawn_captures(Color::White, square)) - .collect(); - let black_attacks: Vec<_> = Square::iter() - .map(|square| pawn_captures(Color::Black, square)) - .collect(); - print_double_sided_boards(&mut out, "PAWN_ATTACKS", &white_attacks, &black_attacks)?; - } - - { - let moves: Vec<_> = Square::iter().map(king_moves).collect(); - print_boards(&mut out, "KING_MOVES", &moves)?; - let king_blockers: Vec<_> = Color::iter() - .map(|color| { - Square::new(File::F, color.first_rank()) | Square::new(File::G, color.first_rank()) - }) - .collect(); - let queen_blockers: Vec<_> = Color::iter() - .map(|color| { - Square::new(File::B, color.first_rank()) - | Square::new(File::C, color.first_rank()) - | Square::new(File::D, color.first_rank()) - }) - .collect(); - print_boards(&mut out, "KING_SIDE_CASTLE_BLOCKERS", &king_blockers)?; - print_boards(&mut out, "QUEEN_SIDE_CASTLE_BLOCKERS", &queen_blockers)?; - } - - // Include the generated files now that the build script has run. - println!("cargo:rustc-cfg=generated_boards"); - - // Run the build script only if something in move generation might have changed. - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-changed=movegen/naive/"); - println!("cargo:rerun-if-changed=movegen/wizardry/"); - - Ok(()) -} diff --git a/src/movegen/naive/bishop.rs b/src/movegen/bishop.rs similarity index 99% rename from src/movegen/naive/bishop.rs rename to src/movegen/bishop.rs index 0806077..0fe0247 100644 --- a/src/movegen/naive/bishop.rs +++ b/src/movegen/bishop.rs @@ -1,5 +1,6 @@ use crate::board::{Bitboard, Direction, Square}; +#[allow(unused)] pub fn bishop_moves(square: Square, blockers: Bitboard) -> Bitboard { Direction::iter_bishop() .map(|dir| dir.slide_board_with_blockers(square.into_bitboard(), blockers)) diff --git a/src/movegen/naive/king.rs b/src/movegen/king.rs similarity index 99% rename from src/movegen/naive/king.rs rename to src/movegen/king.rs index 6e98df7..932b4f4 100644 --- a/src/movegen/naive/king.rs +++ b/src/movegen/king.rs @@ -1,6 +1,7 @@ use crate::board::{Bitboard, CastleRights, Color, Direction, File, Square}; // No castling moves included +#[allow(unused)] pub fn king_moves(square: Square) -> Bitboard { let board = square.into_bitboard(); @@ -9,6 +10,7 @@ pub fn king_moves(square: Square) -> Bitboard { .fold(Bitboard::EMPTY, |lhs, rhs| lhs | rhs) } +#[allow(unused)] pub fn king_castling_moves(color: Color, castle_rights: CastleRights) -> Bitboard { let rank = color.first_rank(); diff --git a/src/movegen/naive/knight.rs b/src/movegen/knight.rs similarity index 99% rename from src/movegen/naive/knight.rs rename to src/movegen/knight.rs index f850d71..4783bde 100644 --- a/src/movegen/naive/knight.rs +++ b/src/movegen/knight.rs @@ -1,5 +1,6 @@ use crate::board::{Bitboard, Direction, Square}; +#[allow(unused)] pub fn knight_moves(square: Square) -> Bitboard { let board = square.into_bitboard(); diff --git a/src/movegen/magic/mod.rs b/src/movegen/magic/mod.rs index b31abeb..f59bde2 100644 --- a/src/movegen/magic/mod.rs +++ b/src/movegen/magic/mod.rs @@ -19,8 +19,3 @@ impl Magic { base_index + self.offset } } - -#[cfg(generated_boards)] -mod moves; -#[cfg(generated_boards)] -pub use moves::*; diff --git a/src/movegen/magic/moves.rs b/src/movegen/magic/moves.rs deleted file mode 100644 index 2901b28..0000000 --- a/src/movegen/magic/moves.rs +++ /dev/null @@ -1,71 +0,0 @@ -use super::Magic; -use crate::board::{Bitboard, Color, Square}; - -include!(concat!(env!("OUT_DIR"), "/magic_tables.rs")); - -pub fn quiet_pawn_moves(color: Color, square: Square, blockers: Bitboard) -> Bitboard { - // If there is a piece in front of the pawn, it can't advance - if !(color.backward_direction().move_board(blockers) & square).is_empty() { - return Bitboard::EMPTY; - } - // SAFETY: we know the values are in-bounds - unsafe { - *PAWN_MOVES - .get_unchecked(color.index()) - .get_unchecked(square.index()) - } -} - -pub fn pawn_moves(color: Color, square: Square, blockers: Bitboard) -> Bitboard { - // SAFETY: we know the values are in-bounds - let attacks = unsafe { - *PAWN_ATTACKS - .get_unchecked(color.index()) - .get_unchecked(square.index()) - }; - quiet_pawn_moves(color, square, blockers) | attacks -} - -pub fn knight_moves(square: Square) -> Bitboard { - // SAFETY: we know the values are in-bounds - unsafe { *KNIGHT_MOVES.get_unchecked(square.index()) } -} - -pub fn bishop_moves(square: Square, blockers: Bitboard) -> Bitboard { - // SAFETY: we know the values are in-bounds - unsafe { - let index = BISHOP_MAGICS - .get_unchecked(square.index()) - .get_index(blockers); - *BISHOP_MOVES.get_unchecked(index) - } -} - -pub fn rook_moves(square: Square, blockers: Bitboard) -> Bitboard { - // SAFETY: we know the values are in-bounds - unsafe { - let index = ROOK_MAGICS - .get_unchecked(square.index()) - .get_index(blockers); - *ROOK_MOVES.get_unchecked(index) - } -} - -pub fn queen_moves(square: Square, blockers: Bitboard) -> Bitboard { - bishop_moves(square, blockers) | rook_moves(square, blockers) -} - -pub fn king_moves(square: Square) -> Bitboard { - // SAFETY: we know the values are in-bounds - unsafe { *KING_MOVES.get_unchecked(square.index()) } -} - -pub fn king_side_castle_blockers(color: Color) -> Bitboard { - // SAFETY: we know the values are in-bounds - unsafe { *KING_SIDE_CASTLE_BLOCKERS.get_unchecked(color.index()) } -} - -pub fn queen_side_castle_blockers(color: Color) -> Bitboard { - // SAFETY: we know the values are in-bounds - unsafe { *QUEEN_SIDE_CASTLE_BLOCKERS.get_unchecked(color.index()) } -} diff --git a/src/movegen/mod.rs b/src/movegen/mod.rs index 9ddbf36..26b60a3 100644 --- a/src/movegen/mod.rs +++ b/src/movegen/mod.rs @@ -2,8 +2,12 @@ pub mod magic; pub use magic::*; -// Naive move generation -pub mod naive; +// Move generation implementation details +pub(crate) mod bishop; +pub(crate) mod king; +pub(crate) mod knight; +pub(crate) mod pawn; +pub(crate) mod rook; // Magic bitboard generation pub(crate) mod wizardry; diff --git a/src/movegen/naive/mod.rs b/src/movegen/naive/mod.rs deleted file mode 100644 index f1bbe3e..0000000 --- a/src/movegen/naive/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod bishop; -pub mod king; -pub mod knight; -pub mod pawn; -pub mod rook; diff --git a/src/movegen/naive/pawn.rs b/src/movegen/pawn.rs similarity index 98% rename from src/movegen/naive/pawn.rs rename to src/movegen/pawn.rs index 55b5bf6..5c929fa 100644 --- a/src/movegen/naive/pawn.rs +++ b/src/movegen/pawn.rs @@ -1,5 +1,6 @@ use crate::board::{Bitboard, Color, Direction, Rank, Square}; +#[allow(unused)] pub fn pawn_moves(color: Color, square: Square, blockers: Bitboard) -> Bitboard { if (square.rank() == Rank::First) || (square.rank() == Rank::Eighth) { return Bitboard::EMPTY; @@ -21,6 +22,7 @@ pub fn pawn_moves(color: Color, square: Square, blockers: Bitboard) -> Bitboard } } +#[allow(unused)] pub fn pawn_captures(color: Color, square: Square) -> Bitboard { if (square.rank() == Rank::First) || (square.rank() == Rank::Eighth) { return Bitboard::EMPTY; @@ -36,6 +38,7 @@ pub fn pawn_captures(color: Color, square: Square) -> Bitboard { attack_west | attack_east } +#[allow(unused)] pub fn en_passant_origins(square: Square) -> Bitboard { let board = square.into_bitboard(); diff --git a/src/movegen/naive/rook.rs b/src/movegen/rook.rs similarity index 99% rename from src/movegen/naive/rook.rs rename to src/movegen/rook.rs index 0b06cef..31fd7d8 100644 --- a/src/movegen/naive/rook.rs +++ b/src/movegen/rook.rs @@ -1,5 +1,6 @@ use crate::board::{Bitboard, Direction, Square}; +#[allow(unused)] pub fn rook_moves(square: Square, blockers: Bitboard) -> Bitboard { Direction::iter_rook() .map(|dir| dir.slide_board_with_blockers(square.into_bitboard(), blockers)) diff --git a/src/movegen/wizardry/generation.rs b/src/movegen/wizardry/generation.rs index 173eef0..ee75d57 100644 --- a/src/movegen/wizardry/generation.rs +++ b/src/movegen/wizardry/generation.rs @@ -1,5 +1,6 @@ use crate::board::{Bitboard, Square}; -use crate::movegen::naive::{bishop::bishop_moves, rook::rook_moves}; +use crate::movegen::bishop::bishop_moves; +use crate::movegen::rook::rook_moves; use crate::movegen::Magic; use super::mask::{generate_bishop_mask, generate_rook_mask}; diff --git a/src/movegen/wizardry/mask.rs b/src/movegen/wizardry/mask.rs index eed93a0..0c0bbdf 100644 --- a/src/movegen/wizardry/mask.rs +++ b/src/movegen/wizardry/mask.rs @@ -1,5 +1,6 @@ use crate::board::{Bitboard, File, Rank, Square}; -use crate::movegen::naive::{bishop::bishop_moves, rook::rook_moves}; +use crate::movegen::bishop::bishop_moves; +use crate::movegen::rook::rook_moves; pub fn generate_bishop_mask(square: Square) -> Bitboard { let rays = bishop_moves(square, Bitboard::EMPTY);