Explorar el Código

adding magic generator

Nicolas Winkler hace 2 años
padre
commit
2577f06131
Se han modificado 1 ficheros con 256 adiciones y 0 borrados
  1. 256 0
      build.rs

+ 256 - 0
build.rs

@@ -0,0 +1,256 @@
+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");
+}
+