|  | @@ -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");
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 |