123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- use std::{io::{Write}, fs::File};
- extern crate rand;
- use rand::*;
- fn main() {
- println!("cargo:rerun-if-changed=build.rs");
- let mut file = std::fs::File::create("src/magic/tables.rs").unwrap();
- create_tables(&mut file);
- }
- type Bitboard = u64;
- type Square = u8;
- pub const FILE_A: Bitboard = 0x_8080_8080_8080_8080;
- pub const FILE_B: Bitboard = FILE_A >> 1;
- pub const FILE_C: Bitboard = FILE_A >> 2;
- pub const FILE_D: Bitboard = FILE_A >> 3;
- pub const FILE_E: Bitboard = FILE_A >> 4;
- pub const FILE_F: Bitboard = FILE_A >> 5;
- pub const FILE_G: Bitboard = FILE_A >> 6;
- pub const FILE_H: Bitboard = FILE_A >> 7;
- pub const ROW_1: Bitboard = 0x_0000_0000_0000_00FF;
- pub const ROW_2: Bitboard = 0x_0000_0000_0000_FF00;
- pub const ROW_3: Bitboard = 0x_0000_0000_00FF_0000;
- pub const ROW_4: Bitboard = 0x_0000_0000_FF00_0000;
- pub const ROW_5: Bitboard = 0x_0000_00FF_0000_0000;
- pub const ROW_6: Bitboard = 0x_0000_FF00_0000_0000;
- pub const ROW_7: Bitboard = 0x_00FF_0000_0000_0000;
- pub const ROW_8: Bitboard = 0x_FF00_0000_0000_0000;
- pub fn print_board(b: Bitboard) -> String {
- (0..8).map(
- |i| (0..8).map(
- |j| if bit_at(b, i, j) { "x " }
- else { ". " }
- ).collect::<String>() + "\n"
- ).collect::<String>()
- }
- pub fn bit_at(b: Bitboard, i: i32, j: i32) -> bool {
- ((b >> (7 - i) * 8 + 7 - j) & 1) == 1
- }
- pub fn from_square(s: Square) -> Bitboard {
- return 1_u64 << s;
- }
- pub fn north_one(b: Bitboard) -> Bitboard {
- b << 8
- }
- pub fn south_one(b: Bitboard) -> Bitboard {
- b >> 8
- }
- pub fn west_one(b: Bitboard) -> Bitboard {
- (b << 1) & !FILE_H
- }
- pub fn east_one(b: Bitboard) -> Bitboard {
- (b >> 1) & !FILE_A
- }
- pub fn northeast_one(b: Bitboard) -> Bitboard {
- (b << 7) & !FILE_A
- }
- pub fn northwest_one(b: Bitboard) -> Bitboard {
- (b << 9) & !FILE_H
- }
- pub fn southwest_one(b: Bitboard) -> Bitboard {
- (b >> 7) & !FILE_H
- }
- pub fn southeast_one(b: Bitboard) -> Bitboard {
- (b >> 9) & !FILE_A
- }
- pub fn generate_sliding_destinations(occupied: Bitboard,
- piece: Bitboard, straight: bool,
- diagonal: bool,
- only_occ: bool) -> Bitboard {
- let straights = [north_one, south_one, east_one, west_one];
- let diagonals = [northeast_one, southeast_one, northwest_one, southwest_one];
- let mut result: Bitboard = 0;
- if straight {
- for direction in straights.iter() {
- result |= generate_direction(piece, *direction, occupied, only_occ);
- }
- }
- if diagonal {
- for direction in diagonals.iter() {
- result |= generate_direction(piece, *direction, occupied, only_occ);
- }
- }
- return result;
- }
- fn generate_direction(piece: Bitboard, direction: fn(Bitboard) -> Bitboard, occupied: Bitboard, only_occ: bool) -> Bitboard {
- let mut result: Bitboard = 0;
- let mut b = piece;
- loop {
- b = direction(b);
- if only_occ && direction(b) == 0 {
- break;
- }
- result |= b;
- if b & occupied != 0 || b == 0 {
- break;
- }
- }
- return result;
- }
- fn extract(mut mask: Bitboard, index: u32) -> Bitboard {
- let required_bits = mask.count_ones();
- let mut result: Bitboard = 0;
- for bit in 0..required_bits {
- let idx = mask.trailing_zeros();
- if (1 << bit) & index != 0 {
- result |= 1 << idx;
- }
- mask = mask & !(1 << idx);
- }
- return result;
- }
- pub fn low_one_random() -> u64 {
- let mut rng = rand::thread_rng();
- rng.next_u64() & rng.next_u64() & rng.next_u64()
- }
- fn create_magic_slider(s: Square, diagonal: bool) -> Option<(u64, u64, Vec<Bitboard>)> {
- let bitboard = from_square(s);
- let patt = generate_sliding_destinations(0, bitboard, !diagonal, diagonal, true);
- if !diagonal {
- println!("{}", print_board(bitboard));
- println!("{}\n\n", print_board(patt));
- //panic!("asas");
- }
- let required_bits = patt.count_ones();
- let mut correct_results: [Bitboard; 4096] = [!0_u64; 4096];
- for i in 0..4096_usize {
- let b = extract(patt, i as _);
- correct_results[i] = generate_sliding_destinations(b, bitboard, !diagonal, diagonal, false);
- }
- for _ in 0..10000000 {
- let mut table: [Bitboard; 4096] = [0; 4096];
- let magic = low_one_random();
- let mut failed = false;
- if magic.wrapping_mul(patt).wrapping_shr(48).count_ones() < 6 {
- continue;
- }
- for i in 0..(1 << required_bits) {
- let b = extract(patt, i as _);
- let correct_result =
- if correct_results[i] != !0_u64 {
- correct_results[i]
- }
- else {
- correct_results[i] = generate_sliding_destinations(b, bitboard, !diagonal, diagonal, false);
- correct_results[i]
- };
- let index = magic.wrapping_mul(b).wrapping_shr(64 - required_bits) as usize;
- if index >= 4096 {
- println!("{}", print_board(patt));
- panic!("asas");
- }
- if table[index] == 0 {
- table[index] = correct_result;
- }
- else if table[index] != correct_result {
- failed = true;
- break;
- }
- //println!("{}", print_board(b));
- }
- if !failed {
- return Some((patt, magic, table.to_vec()));
- }
- }
- println!("OH NOO\n{}", print_board(patt));
- return None;
- }
- fn create_tables(file: &mut File) {
- create(file, false, "ROOK");
- create(file, true, "BISHOP");
- }
- fn create(file: &mut File, diagonal: bool, prefix: &str) {
- let mut masks: Vec<u64> = Vec::new();
- let mut magics: Vec<u64> = Vec::new();
- let mut tables: Vec<Vec<u64>> = Vec::new();
- // bishops:
- for square in 0..64 {
- let res = create_magic_slider(square, diagonal);
- if let Some((mask, magic, table)) = res {
- masks.push(mask);
- magics.push(magic);
- tables.push(table);
- }
- else {
- panic!("NO");
- }
- }
- writeln!(file, "use crate::bitboard::*;").unwrap();
- write!(file, "pub const {}_MASKS_AND_MAGICS: [(Bitboard, Bitboard); 64] = [", prefix).unwrap();
- for square in 0..64 {
- write!(file, "({}, {}), ", masks[square], magics[square]).unwrap();
- }
- writeln!(file, "];").unwrap();
- write!(file, "pub const {}_BITS: [u8; 64] = [", prefix).unwrap();
- for square in 0..64 {
- write!(file, "{}, ", masks[square].count_ones()).unwrap();
- }
- writeln!(file, "];").unwrap();
- let max_tablesize = 1_usize << masks.iter().map(|x| x.count_ones()).max().unwrap_or(12);
- write!(file, "pub const {}_TABLES: [[Bitboard; {}]; 64] = [", prefix, max_tablesize).unwrap();
- for square in 0..64 {
- write!(file, "[").unwrap();
- //for result in &tables[square] {
- for i in 0..max_tablesize {
- write!(file, "{}, ", tables[square][i]).unwrap();
- }
- writeln!(file, "], ").unwrap();
- }
- writeln!(file, "];").unwrap();
- //panic!("asas");
- }
|