stockfish-core 0.2.0

Core types for implementing a fast chess engine
Documentation
use stockfish_core::prelude::*;
use stockfish_core::accelerate::computed;
use stockfish_core::arch::{self, TARGET_BITS, TARGET_ENDIAN};
use stockfish_core::bitboard::magic::Magic;

use std::io::prelude::Write;
use std::fs::{self, File};
use std::path::{Path, PathBuf};

fn main() -> std::io::Result<()> {
    let output_root = PathBuf::from("./stockfish-core/share/cached");

    let pext = Some(arch::pext_status());

    fs::create_dir_all(&output_root)?;

    accelerate("square_distance", None, &output_root, &generate_square_distance());
    accelerate("line",            None, &output_root, &generate_line());
    accelerate("between",         None, &output_root, &generate_between());
    accelerate("pseudo_attacks",  None, &output_root, &generate_pseudo_attacks());
    accelerate("pawn_attacks",    None, &output_root, &generate_pawn_attacks());

    let bishop_magics = Magic::new_bishop();
    accelerate("bishop_magic_numbers", pext, &output_root, &bishop_magics.magics);
    accelerate("bishop_magic_attacks", pext, &output_root, &bishop_magics.attacks);

    let rook_magics = Magic::new_rook();
    accelerate("rook_magic_numbers", pext, &output_root, &rook_magics.magics);
    accelerate("rook_magic_attacks", pext, &output_root, &rook_magics.attacks);

    Ok(())
}

fn accelerate<P: AsRef<Path>, T: bytemuck::Pod>(
    name: &str,
    tag:  Option<&str>,
    root: P,
    data: &T
) {
    let tag      = tag.map_or("".into(), |t| format!("-{t}"));
    let filename = format!("{name}.{TARGET_ENDIAN}{TARGET_BITS}{tag}.bin");
    let path     = root.as_ref().join(filename);
    let bytes    = bytemuck::bytes_of(data);

    File::options()
        .create(true)
        .write(true)
        .truncate(true)
        .open(path).unwrap()
        .write_all(bytes).unwrap();
}

fn generate_square_distance() -> [[u8; Square::COUNT]; Square::COUNT] {
    let mut distances = [[0; Square::COUNT]; Square::COUNT];

    for s1 in Square::iter() {
        for s2 in Square::iter() {
            distances[s1][s2] = computed::square_distance(s1, s2);
        }
    }

    distances
}

fn generate_line() -> [[Bitboard; Square::COUNT]; Square::COUNT] {
    let mut line = [[Bitboard::EMPTY; Square::COUNT]; Square::COUNT];

    for s1 in Square::iter() {
        for s2 in Square::iter() {
            line[s1][s2] = computed::line(s1, s2);
        }
    }

    line
}

fn generate_between() -> [[Bitboard; Square::COUNT]; Square::COUNT] {
    let mut between = [[Bitboard::EMPTY; Square::COUNT]; Square::COUNT];

    for s1 in Square::iter() {
        for s2 in Square::iter() {
            between[s1][s2] = computed::between(s1, s2);
        }
    }

    between
}

fn generate_pseudo_attacks() -> [[Bitboard; Square::COUNT]; Token::COUNT] {
    let mut pseudo_attacks = [[Bitboard::EMPTY; Square::COUNT]; Token::COUNT];

    for token in Token::iter().skip(1) {
        for square in Square::iter() {
            pseudo_attacks[token][square] = computed::pseudo_attacks(token, square);
        }
    }

    pseudo_attacks
}

fn generate_pawn_attacks() -> [[Bitboard; Square::COUNT]; Color::COUNT] {
    let mut pawn_attacks = [[Bitboard::EMPTY; Square::COUNT]; Color::COUNT];

    for color in Color::iter() {
        for square in Square::iter() {
            pawn_attacks[color][square] = computed::pawn_attacks(color, square);
        }
    }

    pawn_attacks
}