daily pastebin goal
38%
SHARE
TWEET

Untitled

a guest Jan 18th, 2019 60 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #[macro_use]
  2. extern crate lazy_static;
  3. extern crate rand;
  4.  
  5. mod game_state;
  6. mod misc;
  7. mod bitboards;
  8. mod movegen;
  9.  
  10. use self::game_state::GameState;
  11. use std::time::Instant;
  12.  
  13. fn main() {
  14.     let now = Instant::now();
  15.     bitboards::init_all();
  16.     println!("Should have initialized everything!");
  17.  
  18.     let new_now = Instant::now();
  19.     println!("Initialization Time: {}ms", new_now.duration_since(now).as_secs() * 1000 + new_now.duration_since(now).subsec_millis() as u64);
  20.     let now = Instant::now();
  21.  
  22.     let g = GameState::from_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
  23.     //let g= GameState::from_fen("r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 1");
  24.     let nodes = perft_div(&g, 6);
  25.     println!("{}", nodes);
  26.     //misc::STD_FEN);
  27.     let new_now = Instant::now();
  28.     let time_passed = new_now.duration_since(now).as_secs() as f64 + new_now.duration_since(now).subsec_millis() as f64 / 1000.0;
  29.     println!("Time: {}ms", new_now.duration_since(now).as_secs() * 1000 + new_now.duration_since(now).subsec_millis() as u64);
  30.     println!("NPS: {}", nodes as f64 / time_passed);
  31. }
  32.  
  33. pub fn perft_div(g: &GameState, depth: usize) -> u64 {
  34.     let mut count = 0u64;
  35.     let (valid_moves, in_check) = movegen::generate_moves(&g);
  36.     for mv in valid_moves {
  37.         let next_g = movegen::make_move(&g, &mv);
  38.         let res = perft(&next_g, depth - 1);
  39.         println!("{:?}: {}", mv, res);
  40.         count += res;
  41.     }
  42.     count
  43. }
  44.  
  45. pub fn perft(g: &GameState, depth: usize) -> u64 {
  46.     if depth == 1 {
  47.         let (vm, _ic) = movegen::generate_moves(&g);
  48.         return vm.len() as u64;
  49.     } else {
  50.         let mut res = 0;
  51.         let (valid_moves, incheck) = movegen::generate_moves(&g);
  52.         for mv in valid_moves {
  53.             res += perft(&movegen::make_move(&g, &mv), depth - 1);
  54.         }
  55.         res
  56.     }
  57. }
  58.    
  59. use std::fmt::{Formatter, Display, Result, Debug};
  60.  
  61. #[derive(Clone)]
  62. pub enum GameMoveType {
  63.     Quiet,
  64.     Capture,
  65.     EnPassant,
  66.     Castle,
  67.     Promotion(PieceType),
  68. }
  69.  
  70. #[derive(Clone, Debug)]
  71. pub enum PieceType {
  72.     King,
  73.     Pawn,
  74.     Knight,
  75.     Bishop,
  76.     Rook,
  77.     Queen,
  78. }
  79.  
  80. pub struct GameMove {
  81.     pub from: usize,
  82.     pub to: usize,
  83.     pub move_type: GameMoveType,
  84.     pub piece_type: PieceType,
  85. }
  86.  
  87. impl Debug for GameMove {
  88.     fn fmt(&self, formatter: &mut Formatter) -> Result {
  89.         let mut res_str: String = String::new();
  90.         res_str.push_str(&format!("{}{}{}{}", file_to_string(self.from % 8), self.from / 8 + 1, file_to_string(self.to % 8), self.to / 8 + 1));
  91.         match &self.move_type {
  92.             GameMoveType::Quiet => { res_str.push_str("") }
  93.             _ => {}
  94.         };
  95.         write!(formatter, "{}", res_str)
  96.     }
  97. }
  98.  
  99. fn file_to_string(file: usize) -> &'static str {
  100.     match file {
  101.         0 => "a",
  102.         1 => "b",
  103.         2 => "c",
  104.         3 => "d",
  105.         4 => "e",
  106.         5 => "f",
  107.         6 => "g",
  108.         7 => "h",
  109.         _ => panic!("invalid file")
  110.     }
  111. }
  112.  
  113. pub struct GameState {
  114.     // 0 = white
  115.     // 1 = black
  116.     pub color_to_move: usize,
  117.  
  118.     //Array saving all the bitboards
  119.     //Index 1:
  120.     // 0 -> Pawns
  121.     // 1 -> Knights
  122.     // 2 -> Bishops
  123.     // 3 -> Rooks
  124.     // 4 -> Queens
  125.     // 5 -> King
  126.     //Index 2:
  127.     // 0 -> White
  128.     // 1 -> Black
  129.     pub pieces: [[u64; 2]; 6],
  130.  
  131.     //Castle flags
  132.     pub castle_white_kingside: bool,
  133.     pub castle_white_queenside: bool,
  134.     pub castle_black_kingside: bool,
  135.     pub castle_black_queenside: bool,
  136.  
  137.     //En passant flag
  138.     pub en_passant: u64,
  139.     //50 move draw counter
  140.     pub half_moves: usize,
  141.     pub full_moves: usize,
  142.     //Move-Gen
  143.     //King/Knight lookup
  144.     //Sliding by magic
  145. }
  146.  
  147. impl GameState {
  148.     pub fn from_fen(fen: &str) -> GameState {
  149.         let vec: Vec<&str> = fen.split(" ").collect();
  150.         if vec.len() < 4 {
  151.             panic!("Invalid FEN");
  152.         }
  153.         //Parse through FEN
  154.         //Piecess
  155.         let pieces: Vec<&str> = vec[0].split("/").collect();
  156.         if pieces.len() != 8 {
  157.             panic!("Invalid FEN");
  158.         }
  159.         //Iterate over all 8 ranks
  160.         let mut pieces_arr: [[u64; 2]; 6] = [[0u64; 2]; 6];
  161.         for rank in 0..8 {
  162.             let rank_str = pieces[rank];
  163.             let mut file: usize = 0;
  164.             let mut rank_str_idx: usize = 0;
  165.             while file < 8 {
  166.                 let idx = (7 - rank) * 8 + file;
  167.                 let next_char = rank_str.chars().nth(rank_str_idx);
  168.                 rank_str_idx += 1;
  169.                 match next_char {
  170.                     Some(x) => {
  171.                         match x {
  172.                             'P' => {
  173.                                 pieces_arr[0][0] |= 1u64 << idx;
  174.                                 file += 1;
  175.                             }
  176.                             'p' => {
  177.                                 pieces_arr[0][1] |= 1u64 << idx;
  178.                                 file += 1;
  179.                             }
  180.                             'N' => {
  181.                                 pieces_arr[1][0] |= 1u64 << idx;
  182.                                 file += 1;
  183.                             }
  184.                             'n' => {
  185.                                 pieces_arr[1][1] |= 1u64 << idx;
  186.                                 file += 1;
  187.                             }
  188.                             'B' => {
  189.                                 pieces_arr[2][0] |= 1u64 << idx;
  190.                                 file += 1;
  191.                             }
  192.                             'b' => {
  193.                                 pieces_arr[2][1] |= 1u64 << idx;
  194.                                 file += 1;
  195.                             }
  196.                             'R' => {
  197.                                 pieces_arr[3][0] |= 1u64 << idx;
  198.                                 file += 1;
  199.                             }
  200.                             'r' => {
  201.                                 pieces_arr[3][1] |= 1u64 << idx;
  202.                                 file += 1;
  203.                             }
  204.                             'Q' => {
  205.                                 pieces_arr[4][0] |= 1u64 << idx;
  206.                                 file += 1;
  207.                             }
  208.                             'q' => {
  209.                                 pieces_arr[4][1] |= 1u64 << idx;
  210.                                 file += 1;
  211.                             }
  212.                             'K' => {
  213.                                 pieces_arr[5][0] |= 1u64 << idx;
  214.                                 file += 1;
  215.                             }
  216.                             'k' => {
  217.                                 pieces_arr[5][1] |= 1u64 << idx;
  218.                                 file += 1;
  219.                             }
  220.                             '1' => {
  221.                                 file += 1;
  222.                             }
  223.                             '2' => {
  224.                                 file += 2;
  225.                             }
  226.                             '3' => {
  227.                                 file += 3;
  228.                             }
  229.                             '4' => {
  230.                                 file += 4;
  231.                             }
  232.                             '5' => {
  233.                                 file += 5;
  234.                             }
  235.                             '6' => {
  236.                                 file += 6;
  237.                             }
  238.                             '7' => {
  239.                                 file += 7;
  240.                             }
  241.                             '8' => {
  242.                                 file += 8;
  243.                             }
  244.                             _ => {
  245.                                 panic!("Invalid FEN");
  246.                             }
  247.                         }
  248.                     }
  249.                     None => panic!("Invalid FEN"),
  250.                 }
  251.             }
  252.         }
  253.  
  254.         //Side to move
  255.         let color_to_move = match vec[1] {
  256.             "w" => 0,
  257.             "b" => 1,
  258.             _ => panic!("Invalid FEN!")
  259.         };
  260.  
  261.         //CastlingAbilities
  262.         let castle_white_kingside = vec[2].contains("K");
  263.         let castle_white_queenside = vec[2].contains("Q");
  264.         let castle_black_kingside = vec[2].contains("k");
  265.         let castle_black_queenside = vec[2].contains("q");
  266.  
  267.         //En Passant target square //Ignore
  268.         let mut en_passant: u64 = 0u64;
  269.         if vec[3] != "-" {
  270.             let mut idx: usize = 0usize;
  271.             let file = vec[3].chars().nth(0);
  272.             let rank = vec[3].chars().nth(1);
  273.             match file {
  274.                 Some(x) => {
  275.                     match x {
  276.                         'a' | 'A' => {}
  277.                         'b' | 'B' => {
  278.                             idx += 1;
  279.                         }
  280.                         'c' | 'C' => {
  281.                             idx += 2;
  282.                         }
  283.                         'd' | 'D' => {
  284.                             idx += 3;
  285.                         }
  286.                         'e' | 'E' => {
  287.                             idx += 4;
  288.                         }
  289.                         'f' | 'F' => {
  290.                             idx += 5;
  291.                         }
  292.                         'g' | 'G' => {
  293.                             idx += 6;
  294.                         }
  295.                         'h' | 'H' => {
  296.                             idx += 7;
  297.                         }
  298.                         _ => {
  299.                             panic!("Invalid FEN!");
  300.                         }
  301.                     }
  302.                 }
  303.                 None => { panic!("Invalid FEN!"); }
  304.             }
  305.             match rank {
  306.                 Some(x) => {
  307.                     match x {
  308.                         '1' => {}
  309.                         '2' => {
  310.                             idx += 8;
  311.                         }
  312.                         '3' => {
  313.                             idx += 16;
  314.                         }
  315.                         '4' => {
  316.                             idx += 24;
  317.                         }
  318.                         '5' => {
  319.                             idx += 32;
  320.                         }
  321.                         '6' => {
  322.                             idx += 40;
  323.                         }
  324.                         '7' => {
  325.                             idx += 48;
  326.                         }
  327.                         '8' => {
  328.                             idx += 56;
  329.                         }
  330.                         _ => {
  331.                             panic!("Invalid FEN!");
  332.                         }
  333.                     }
  334.                 }
  335.                 None => {
  336.                     panic!("Invalid FEN!");
  337.                 }
  338.             }
  339.             en_passant = 1u64 << idx;
  340.         }
  341.         let mut half_moves = 0;
  342.         let mut full_moves = 0;
  343.         if vec.len() > 4 {
  344.             //HalfMoveClock
  345.             half_moves = vec[4].parse().unwrap();
  346.  
  347.             full_moves = vec[5].parse().unwrap();
  348.         }
  349.         GameState {
  350.             color_to_move,
  351.             pieces: pieces_arr,
  352.             castle_white_kingside,
  353.             castle_white_queenside,
  354.             castle_black_kingside,
  355.             castle_black_queenside,
  356.             half_moves,
  357.             full_moves,
  358.             en_passant,
  359.         }
  360.     }
  361.     pub fn standard() -> GameState {
  362.         GameState {
  363.             color_to_move: 0usize,
  364.             pieces: [[0xff00u64, 0xff000000000000u64], [0x42u64, 0x4200000000000000u64], [0x24u64, 0x2400000000000000u64], [0x81u64, 0x8100000000000000u64],
  365.                 [0x8u64, 0x800000000000000u64], [0x10u64, 0x1000000000000000u64]],
  366.             castle_white_kingside: true,
  367.             castle_white_queenside: true,
  368.             castle_black_kingside: true,
  369.             castle_black_queenside: true,
  370.             en_passant: 0u64,
  371.             half_moves: 0usize,
  372.             full_moves: 1usize,
  373.         }
  374.     }
  375. }
  376.    
  377. pub const STD_FEN:&str ="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
  378.    
  379. use rand::Rng;
  380.  
  381. static mut ROOK_BITS: [usize; 64] = [
  382.     12, 11, 11, 11, 11, 11, 11, 12,
  383.     11, 10, 10, 10, 10, 10, 10, 11,
  384.     11, 10, 10, 10, 10, 10, 10, 11,
  385.     11, 10, 10, 10, 10, 10, 10, 11,
  386.     11, 10, 10, 10, 10, 10, 10, 11,
  387.     11, 10, 10, 10, 10, 10, 10, 11,
  388.     11, 10, 10, 10, 10, 10, 10, 11,
  389.     12, 11, 11, 11, 11, 11, 11, 12
  390. ];
  391. static mut BISHOP_BITS: [usize; 64] = [
  392.     6, 5, 5, 5, 5, 5, 5, 6,
  393.     5, 5, 5, 5, 5, 5, 5, 5,
  394.     5, 5, 7, 7, 7, 7, 5, 5,
  395.     5, 5, 7, 9, 9, 7, 5, 5,
  396.     5, 5, 7, 9, 9, 7, 5, 5,
  397.     5, 5, 7, 7, 7, 7, 5, 5,
  398.     5, 5, 5, 5, 5, 5, 5, 5,
  399.     6, 5, 5, 5, 5, 5, 5, 6
  400. ];
  401. const MAGIC_NUMS_ROOKS: [u64; 64] = [
  402.     0x2180028011204008u64, 0x21400190002000c0u64, 0x8480100020000b80u64, 0x80100080061800u64, 0xc100080004030010u64, 0x200084430120001u64, 0x1880110006800200u64, 0x100006200804100u64, 0x4084800280400020u64, 0x8400400050002000u64, 0xd001020010342u64, 0x20040102008040u64, 0x8000802400810800u64, 0x2922002804100a01u64, 0x4109002a0099000cu64, 0x40020000840e0841u64, 0x800848000204011u64, 0x900444000201008u64, 0x5201010020049142u64, 0x80620009c20030u64, 0x45310004080100u64, 0x808002001400u64, 0x1090840002100328u64, 0x8022000184085bu64, 0x401080028020u64, 0x4910400080802000u64, 0x1400403100200100u64, 0x910008080180450u64, 0x200040080800800u64, 0x1052000200100429u64, 0x2004e80c000a1110u64, 0x1423000100005282u64, 0x8088834000800aa0u64, 0x10080c000806000u64, 0x8010200082805002u64, 0x82101003000u64, 0x7040080280800400u64, 0x610c004100401200u64, 0x5700010804001002u64, 0x1000008042000904u64, 0x21049460c0008000u64, 0x410014020004002u64, 0x20100a001410013u64, 0x401000810010020u64, 0x4008012400808008u64, 0x808200440480110u64, 0x1b81040200010100u64, 0x8020040040820003u64, 0x80002108508100u64, 0x10242082b008200u64, 0x801004090200100u64, 0x4003002008100100u64, 0x8180080440080u64, 0x890c0004800a0080u64, 0x104020108102400u64, 0x41111040840200u64, 0x1010201601008042u64, 0x127002440013181u64, 0x102104209220082u64, 0xa011009001242009u64, 0x81000228001085u64, 0x5022001008011c02u64, 0x100821000810804u64, 0x100002280d601u64, ];
  403. const MAGIC_NUMS_BISHOPS: [u64; 64] = [
  404.     0x6040422a14086080u64, 0x4084800408020u64, 0x400c080210440010u64, 0x44042080000000u64, 0x2610882002100a00u64, 0x9030080c0080u64, 0xc140841048148004u64, 0x200844c100442u64, 0x40042004042682u64, 0x4200100608410a28u64, 0x802010052a202108u64, 0x800c080601410802u64, 0xc001011040020004u64, 0x488811002902400u64, 0xa008024210106808u64, 0x1004a100e9042004u64, 0x2030002102e20800u64, 0x510a5810210042u64, 0x68010408089830u64, 0x41c800802044200u64, 0x4004080a04000u64, 0x4004080203040a00u64, 0x830642382040u64, 0x8200401101c23040u64, 0x8400248108110u64, 0x4440020289080u64, 0x3008040408004050u64, 0x8004004004010002u64, 0x921004024044016u64, 0x201840802020a00u64, 0x20222c0000414811u64, 0x5802068602404810u64, 0x2791200810a29848u64, 0x2650821000081000u64, 0x415000480322u64, 0x2041401820060200u64, 0x1020200240104u64, 0x10802000c2212u64, 0xe002880a00005200u64, 0x2001062200402100u64, 0x52105044000850u64, 0x204590820800818u64, 0x1201410082a00u64, 0x440004200810800u64, 0x20080100442401u64, 0x200b200214100880u64, 0x2810108100400100u64, 0x8824640052011048u64, 0x4281040114400060u64, 0x988824040208001du64, 0x806081c40c040909u64, 0x20090084110014u64, 0x304006022440118u64, 0x1011400304010004u64, 0xa1020010410a048u64, 0x8110020809002809u64, 0x40010022100c0413u64, 0x2800020125011014u64, 0x46082400u64, 0x60408400840401u64, 0x8001020010021204u64, 0x4c00100812084200u64, 0x20000420440c1098u64, 0x802200c01120060u64, ];
  405. lazy_static! {
  406.     pub static ref FILES: [u64;8] = initialize_files();
  407.     pub static ref NOT_FILES: [u64;8] = initialize_not_files();
  408.     pub static ref RANKS: [u64;8] = initialize_ranks();
  409.     pub static ref SQUARES: [u64;64]= initialize_squares();
  410.     pub static ref NOT_SQUARES: [u64;64]= initialize_not_squares();
  411.     pub static ref MAGICS_ROOKS: Vec<Magic>= init_magics_rooks();
  412.     pub static ref MAGICS_BISHOPS:Vec<Magic>= init_magics_bishops();
  413.     pub static ref KING_ATTACKS:[u64;64] = init_king_attacks();
  414.     pub static ref KNIGHT_ATTACKS:[u64;64] = init_knight_attacks();
  415.     pub static ref FILES_LESS_THAN:[u64;8]= init_files_less_than();
  416.     pub static ref FILES_GREATER_THAN:[u64;8]= init_files_greater_than();
  417.     pub static ref RANKS_LESS_THAN:[u64;8]= init_ranks_less_than();
  418.     pub static ref RANKS_GREATER_THAN:[u64;8]= init_ranks_greater_than();
  419. }
  420. pub struct Magic {
  421.     pub occupancy_mask: u64,
  422.     pub shift: usize,
  423.     pub magic_num: u64,
  424.     pub lookup_table: Vec<u64>,
  425. }
  426.  
  427. impl Magic {
  428.     pub fn get_attacks(&self, all_pieces_board: u64) -> u64 {
  429.         self.lookup_table[(((all_pieces_board & self.occupancy_mask).wrapping_mul(self.magic_num)) >> (64 - self.shift)) as usize]
  430.     }
  431. }
  432.  
  433. pub fn init_all() {
  434.     FILES.len();
  435.     NOT_FILES.len();
  436.     RANKS.len();
  437.     SQUARES.len();
  438.     NOT_SQUARES.len();
  439.     //Override Magics with better magic nums
  440.     MAGICS_ROOKS.len();
  441.     MAGICS_BISHOPS.len();
  442.     KING_ATTACKS.len();
  443.     KNIGHT_ATTACKS.len();
  444.     FILES_LESS_THAN.len();
  445.     FILES_GREATER_THAN.len();
  446.     RANKS_LESS_THAN.len();
  447.     RANKS_GREATER_THAN.len();
  448. }
  449.  
  450. //Rook-specific magic
  451. pub fn init_magics_rooks() -> Vec<Magic> {
  452.     let mut res: Vec<Magic> = Vec::with_capacity(64);
  453.     for square in 0..64 {
  454.         let shift;
  455.         unsafe {
  456.             shift = ROOK_BITS[square];
  457.         }
  458.         let occupancy_mask = occupancy_mask_rooks(square);
  459.         if occupancy_mask.count_ones() as usize != shift {
  460.             panic!("Not good!");
  461.         }
  462.         let mut blockers_by_index: Vec<u64> = Vec::with_capacity(1 << shift);
  463.         let mut attack_table: Vec<u64> = Vec::with_capacity(1 << shift);
  464.         //Initialize lookup table
  465.         for i in 0..(1 << shift) {
  466.             //i is index of lookup table
  467.             blockers_by_index.push(blockers_to_bitboard(i, shift, occupancy_mask));
  468.             attack_table.push(rook_attacks_slow(square, blockers_by_index[i]));
  469.         }
  470.         let magic_num = MAGIC_NUMS_ROOKS[square];
  471.         let mut lookup_table = Vec::with_capacity(1 << shift);
  472.         for _i in 0..(1 << shift) {
  473.             lookup_table.push(0u64);
  474.         }
  475.         //Calculate look-up table
  476.         for i in 0..(1 << shift) {
  477.             let j = transform(blockers_by_index[i], magic_num, shift);
  478.             if lookup_table[j] == 0u64 {
  479.                 lookup_table[j] = attack_table[i];
  480.             } else {
  481.                 panic!("Isn't valid num!")
  482.             }
  483.         }
  484.         res.push(Magic {
  485.             occupancy_mask,
  486.             shift,
  487.             magic_num,
  488.             lookup_table,
  489.         })
  490.     }
  491.     println!("Finished Initializing Rook Attacks!");
  492.     res
  493. }
  494.  
  495. pub fn occupancy_mask_rooks(square: usize) -> u64 {
  496.     (((RANKS[square / 8] & !(FILES[0] | FILES[7])) | (FILES[square % 8] & !(RANKS[0] | RANKS[7]))) & NOT_SQUARES[square])
  497. }
  498.  
  499. pub fn rook_attacks_slow(square: usize, blocks: u64) -> u64 {
  500.     let mut res = 0u64;
  501.     let rank: isize = (square / 8) as isize;
  502.     let file: isize = (square % 8) as isize;
  503.     let dirs: [(isize, isize); 4] = [(0, 1), (0, -1), (1, 0), (-1, 0)];
  504.     for dir in dirs.iter() {
  505.         let (file_i, rank_i) = dir;
  506.         let mut rn = rank + rank_i;
  507.         let mut fnn = file + file_i;
  508.         while rn >= 0 && rn <= 7 && fnn >= 0 && fnn <= 7 {
  509.             res |= 1u64 << (rn * 8 + fnn);
  510.             if (blocks & (1u64 << (rn * 8 + fnn))) != 0 {
  511.                 break;
  512.             }
  513.             rn += rank_i;
  514.             fnn += file_i;
  515.         }
  516.     }
  517.     res
  518. }
  519. //Bishop-specific magic
  520. pub fn init_magics_bishops() -> Vec<Magic> {
  521.     let mut res: Vec<Magic> = Vec::with_capacity(64);
  522.     for square in 0..64 {
  523.         let shift;
  524.         unsafe {
  525.             shift = BISHOP_BITS[square];
  526.         }
  527.  
  528.         let occupancy_mask = occupancy_mask_bishops(square);
  529.         if occupancy_mask.count_ones() as usize != shift {
  530.             panic!("Not good!");
  531.         }
  532.  
  533.         let mut blockers_by_index: Vec<u64> = Vec::with_capacity(1 << shift);
  534.         let mut attack_table: Vec<u64> = Vec::with_capacity(1 << shift);
  535.         //Initialize lookup table
  536.         for i in 0..(1 << shift) {
  537.             //i is index of lookup table
  538.             blockers_by_index.push(blockers_to_bitboard(i, shift, occupancy_mask));
  539.             attack_table.push(bishop_attacks_slow(square, blockers_by_index[i]));
  540.         }
  541.  
  542.         let magic_num = MAGIC_NUMS_BISHOPS[square];
  543.         let mut lookup_table = Vec::with_capacity(1 << shift);
  544.         for _i in 0..(1 << shift) {
  545.             lookup_table.push(0u64);
  546.         }
  547.         //Calculate look-up table
  548.         for i in 0..(1 << shift) {
  549.             let j = transform(blockers_by_index[i], magic_num, shift);
  550.             if lookup_table[j] == 0u64 {
  551.                 lookup_table[j] = attack_table[i];
  552.             } else {
  553.                 panic!("Isn't valid num!")
  554.             }
  555.         }
  556.         res.push(Magic {
  557.             occupancy_mask,
  558.             shift,
  559.             magic_num,
  560.             lookup_table,
  561.         })
  562.     }
  563.     println!("Finished Initializing Bishop Attacks!");
  564.     res
  565. }
  566.  
  567. pub fn occupancy_mask_bishops(square: usize) -> u64 {
  568.     let mut res = 0u64;
  569.     let rk = (square / 8) as isize;
  570.     let fl = (square % 8) as isize;
  571.     let dirs: [(isize, isize); 4] = [(1, 1), (-1, -1), (1, -1), (-1, 1)];
  572.     for dir in dirs.iter() {
  573.         let (file_i, rank_i) = dir;
  574.         let mut rn = rk + rank_i;
  575.         let mut fnn = fl + file_i;
  576.         while rn >= 1 && rn <= 6 && fnn >= 1 && fnn <= 6 {
  577.             res |= 1u64 << (rn * 8 + fnn);
  578.             rn += rank_i;
  579.             fnn += file_i;
  580.         }
  581.     }
  582.     res
  583. }
  584.  
  585. pub fn bishop_attacks_slow(square: usize, blocks: u64) -> u64 {
  586.     let mut res = 0u64;
  587.     let rank: isize = (square / 8) as isize;
  588.     let file: isize = (square % 8) as isize;
  589.     let dirs: [(isize, isize); 4] = [(1, 1), (-1, -1), (1, -1), (-1, 1)];
  590.     for dir in dirs.iter() {
  591.         let (file_i, rank_i) = dir;
  592.         let mut rn = rank + rank_i;
  593.         let mut fnn = file + file_i;
  594.         while rn >= 0 && rn <= 7 && fnn >= 0 && fnn <= 7 {
  595.             res |= 1u64 << (rn * 8 + fnn);
  596.             if (blocks & (1u64 << (rn * 8 + fnn))) != 0 {
  597.                 break;
  598.             }
  599.             rn += rank_i;
  600.             fnn += file_i;
  601.         }
  602.     }
  603.     res
  604. }
  605. //General Magic stuff
  606. pub fn transform(blockers: u64, magic: u64, n_bits: usize) -> usize {
  607.     ((blockers.wrapping_mul(magic)) >> (64 - n_bits)) as usize
  608. }
  609.  
  610. pub fn generate_magic(blockers_by_index: &Vec<u64>, attack_table: &Vec<u64>, n_bits: usize, occ_mask: u64) -> u64 {
  611.     for _iterations in 0..100000000 {
  612.         let random_magic = random_u64_fewbits();
  613.         if ((occ_mask.wrapping_mul(random_magic)) & 0xFF00000000000000u64) < 6 {
  614.             continue;
  615.         }
  616.         if is_valid_magic(random_magic, n_bits, blockers_by_index, attack_table) {
  617.             return random_magic;
  618.         }
  619.     }
  620.     panic!("No Magic found!");
  621. }
  622.  
  623. pub fn is_valid_magic(magic: u64, n_bits: usize, blockers_by_index: &Vec<u64>, attack_table: &Vec<u64>) -> bool {
  624.     let mut used = Vec::with_capacity(1 << n_bits);
  625.     for _i in 0..(1 << n_bits) {
  626.         used.push(0u64);
  627.     }
  628.     for i in 0..(1 << n_bits) {
  629.         let j = transform(blockers_by_index[i], magic, n_bits);
  630.         if used[j] == 0u64 {
  631.             used[j] = attack_table[i];
  632.         } else if used[j] != attack_table[i] {
  633.             return false;
  634.         }
  635.     }
  636.     return true;
  637. }
  638.  
  639. pub fn random_u64() -> u64 {
  640.     rand::thread_rng().gen::<u64>()
  641. }
  642.  
  643. pub fn random_u64_fewbits() -> u64 {
  644.     random_u64() & random_u64() & random_u64()
  645. }
  646.  
  647. pub fn blockers_to_bitboard(block_index: usize, n_bits: usize, mut mask: u64) -> u64 {
  648.     let mut res = 0u64;
  649.     for i in 0..n_bits {
  650.         let j = mask.trailing_zeros();
  651.         mask &= !(1 << j);
  652.         if (block_index & (1 << i)) != 0 {
  653.             res |= 1u64 << j;
  654.         }
  655.     }
  656.     res
  657. }
  658.  
  659. //Initializing General BitBoards
  660.  
  661. pub fn initialize_files() -> [u64; 8] {
  662.     let mut res = [0u64; 8];
  663.     for file in 0..8 {
  664.         if file == 0 {
  665.             res[0] = 1u64 << 0 | 1u64 << 8 | 1u64 << 16 | 1u64 << 24 | 1u64 << 32 | 1u64 << 40 | 1u64 << 48 | 1u64 << 56;
  666.         } else {
  667.             res[file] = res[file - 1] << 1;
  668.         }
  669.     }
  670.     println!("Finished Initializing Files!");
  671.     res
  672. }
  673.  
  674. pub fn initialize_not_files() -> [u64; 8] {
  675.     let mut res = [0u64; 8];
  676.     for file in 0..8 {
  677.         res[file] = !FILES[file];
  678.     }
  679.     println!("Finished Initializing NOT Files!");
  680.     res
  681. }
  682.  
  683. pub fn initialize_ranks() -> [u64; 8] {
  684.     let mut res = [0u64; 8];
  685.     for rank in 0..8 {
  686.         if rank == 0 {
  687.             res[0] = 1u64 << 0 | 1u64 << 1 | 1u64 << 2 | 1u64 << 3 | 1u64 << 4 | 1u64 << 5 | 1u64 << 6 | 1u64 << 7;
  688.         } else {
  689.             res[rank] = res[rank - 1] << 8;
  690.         }
  691.     }
  692.     println!("Finished Initializing Ranks!");
  693.     res
  694. }
  695.  
  696. pub fn initialize_squares() -> [u64; 64] {
  697.     let mut res = [0u64; 64];
  698.     for squares in 0..64 {
  699.         res[squares] = 1u64 << squares;
  700.     }
  701.     println!("Finished Initializing Squares!");
  702.     res
  703. }
  704.  
  705. pub fn initialize_not_squares() -> [u64; 64] {
  706.     let mut res = [0u64; 64];
  707.     for squares in 0..64 {
  708.         res[squares] = !(1u64 << squares);
  709.     }
  710.     println!("Finished Initializing NOT_Squares!");
  711.     res
  712. }
  713.  
  714. pub fn north_one(board: u64) -> u64 {
  715.     board << 8
  716. }
  717.  
  718. pub fn north_east_one(board: u64) -> u64 {
  719.     (board & NOT_FILES[7]) << 9
  720. }
  721.  
  722. pub fn north_west_one(board: u64) -> u64 {
  723.     (board & NOT_FILES[0]) << 7
  724. }
  725.  
  726. pub fn south_one(board: u64) -> u64 {
  727.     board >> 8
  728. }
  729.  
  730. pub fn south_east_one(board: u64) -> u64 {
  731.     (board & NOT_FILES[7]) >> 7
  732. }
  733.  
  734. pub fn south_west_one(board: u64) -> u64 {
  735.     (board & NOT_FILES[0]) >> 9
  736. }
  737.  
  738. pub fn west_one(board: u64) -> u64 {
  739.     (board & NOT_FILES[0]) >> 1
  740. }
  741.  
  742. pub fn east_one(board: u64) -> u64 {
  743.     (board & NOT_FILES[7]) << 1
  744. }
  745.  
  746. pub fn king_attack(mut king_board: u64) -> u64 {
  747.     let mut attacks = east_one(king_board) | west_one(king_board);
  748.     king_board |= attacks;
  749.     attacks |= south_one(king_board) | north_one(king_board);
  750.     attacks
  751. }
  752.  
  753. pub fn init_king_attacks() -> [u64; 64] {
  754.     let mut res = [0u64; 64];
  755.     for square in 0..64 {
  756.         res[square] = king_attack(1u64 << square);
  757.     }
  758.     println!("Finished Initializing King Attacks!");
  759.     res
  760. }
  761.  
  762. pub fn knight_attack(knight: u64) -> u64 {
  763.     let mut attacks;
  764.     let mut east = east_one(knight);
  765.     let mut west = west_one(knight);
  766.     attacks = (east | west) << 16;
  767.     attacks |= (east | west) >> 16;
  768.     east = east_one(east);
  769.     west = west_one(west);
  770.     attacks |= (east | west) << 8;
  771.     attacks |= (east | west) >> 8;
  772.     attacks
  773. }
  774.  
  775. pub fn init_knight_attacks() -> [u64; 64] {
  776.     let mut res = [0u64; 64];
  777.     for square in 0..64 {
  778.         res[square] = knight_attack(1u64 << square);
  779.     }
  780.     println!("Finished Initializing Knight Attacks!");
  781.     res
  782. }
  783.  
  784. pub fn init_files_less_than() -> [u64; 8] {
  785.     let mut res = [0u64; 8];
  786.     for files in 0..8 {
  787.         for files_less_than in 0..files {
  788.             res[files] |= FILES[files_less_than];
  789.         }
  790.     }
  791.     println!("Finished Initializing FilesLessThan!");
  792.     res
  793. }
  794.  
  795. pub fn init_ranks_less_than() -> [u64; 8] {
  796.     let mut res = [0u64; 8];
  797.     for ranks in 0..8 {
  798.         for ranks_less_than in 0..ranks {
  799.             res[ranks] |= RANKS[ranks_less_than];
  800.         }
  801.     }
  802.     println!("Finished Initializing RanksLessThan!");
  803.     res
  804. }
  805.  
  806. pub fn init_files_greater_than() -> [u64; 8] {
  807.     let mut res = [0u64; 8];
  808.     for files in 0..8 {
  809.         res[files] = !FILES_LESS_THAN[files] & !FILES[files];
  810.     }
  811.     println!("Finished Initializing FilesGreaterThan!");
  812.     res
  813. }
  814.  
  815. pub fn init_ranks_greater_than() -> [u64; 8] {
  816.     let mut res = [0u64; 8];
  817.     for ranks in 0..8 {
  818.         res[ranks] = !RANKS_LESS_THAN[ranks] & !RANKS[ranks];
  819.     }
  820.     println!("Finished Initializing FilesGreaterThan!");
  821.     res
  822. }
  823.  
  824. //Misc
  825. pub fn to_string_board(board: u64) -> String {
  826.     let mut res_str: String = String::new();
  827.     res_str.push_str("+---+---+---+---+---+---+---+---+n");
  828.     for rank in 0..8 {
  829.         res_str.push_str("| ");
  830.         for file in 0..8 {
  831.             let idx = 8 * (7 - rank) + file;
  832.             if ((board >> idx) & 1) != 0 {
  833.                 res_str.push_str("X");
  834.             } else {
  835.                 res_str.push_str(" ");
  836.             }
  837.             res_str.push_str(" | ");
  838.         }
  839.         res_str.push_str("n+---+---+---+---+---+---+---+---+n");
  840.     }
  841.     res_str
  842. }
  843.    
  844. use super::bitboards;
  845. use super::game_state::{self, GameMove, GameMoveType, PieceType};
  846.  
  847. //Move GEn
  848. //King- Piece-Wise by lookup
  849. //Knight-Piece-Wise by lookup
  850. //Bishop/Queen/Rook - Piece-Wise by lookup in Magic
  851. //Pawn-SetWise by shift
  852. pub fn king_attack(square: usize) -> u64 {
  853.     bitboards::KING_ATTACKS[square]
  854. }
  855.  
  856. pub fn bishop_attack(square: usize, all_pieces: u64) -> u64 {
  857.     bitboards::Magic::get_attacks(&bitboards::MAGICS_BISHOPS[square], all_pieces)
  858. }
  859.  
  860. pub fn rook_attack(square: usize, all_pieces: u64) -> u64 {
  861.     bitboards::Magic::get_attacks(&bitboards::MAGICS_ROOKS[square], all_pieces)
  862. }
  863.  
  864. pub fn knight_attack(square: usize) -> u64 {
  865.     bitboards::KNIGHT_ATTACKS[square]
  866. }
  867.  
  868. pub fn w_single_push_pawn_targets(pawns: u64, empty: u64) -> u64 {
  869.     bitboards::north_one(pawns) & empty
  870. }
  871.  
  872. pub fn w_double_push_pawn_targets(pawns: u64, empty: u64) -> u64 {
  873.     bitboards::north_one(bitboards::north_one(pawns & bitboards::RANKS[1]) & empty) & empty
  874. }
  875.  
  876. pub fn b_single_push_pawn_targets(pawns: u64, empty: u64) -> u64 {
  877.     bitboards::south_one(pawns) & empty
  878. }
  879.  
  880. pub fn b_double_push_pawn_targets(pawns: u64, empty: u64) -> u64 {
  881.     bitboards::south_one(bitboards::south_one(pawns & bitboards::RANKS[6]) & empty) & empty
  882. }
  883.  
  884. //NorthEast = +9
  885. pub fn w_pawn_east_targets(pawns: u64) -> u64 {
  886.     bitboards::north_east_one(pawns)
  887. }
  888.  
  889. //NorthWest = +7
  890. pub fn w_pawn_west_targets(pawns: u64) -> u64 {
  891.     bitboards::north_west_one(pawns)
  892. }
  893.  
  894. //SouthEast = -7
  895. pub fn b_pawn_east_targets(pawns: u64) -> u64 {
  896.     bitboards::south_west_one(pawns)
  897. }
  898.  
  899. //NorthWest = -9
  900. pub fn b_pawn_west_targets(pawns: u64) -> u64 {
  901.     bitboards::south_east_one(pawns)
  902. }
  903.  
  904. pub fn add_moves(move_list: &mut Vec<GameMove>, from: usize, mut to_board: u64, piece_type: &PieceType, move_type: GameMoveType) {
  905.     while to_board != 0u64 {
  906.         let idx = to_board.trailing_zeros() as usize;
  907.         let  move_t_cl = move_type.clone();
  908.         let pt_cl= piece_type.clone();
  909.         move_list.push(GameMove {
  910.             from,
  911.             to: idx,
  912.             move_type: move_t_cl,
  913.             piece_type: pt_cl
  914.         });
  915.         to_board ^= 1u64 << idx;
  916.         //to_board&= to_board-1;
  917.     }
  918. }
  919.  
  920. pub fn add_quiet_pawn_single_pushes(mut single_push_board: u64, color_to_move: &usize, move_list: &mut Vec<GameMove>) {
  921.     while single_push_board != 0u64 {
  922.         let idx = single_push_board.trailing_zeros() as usize;
  923.         move_list.push(GameMove {
  924.             from: if *color_to_move == 0 { idx - 8 } else { idx + 8 },
  925.             to: idx,
  926.             move_type: GameMoveType::Quiet,
  927.             piece_type: PieceType::Pawn,
  928.         });
  929.         single_push_board ^= 1 << idx;
  930.     }
  931. }
  932.  
  933. pub fn add_quiet_pawn_double_pushes(mut double_push_board: u64, color_to_move: &usize, move_list: &mut Vec<GameMove>) {
  934.     while double_push_board != 0u64 {
  935.         let idx = double_push_board.trailing_zeros() as usize;
  936.         move_list.push(GameMove {
  937.             from: if *color_to_move == 0 { idx - 16 } else { idx + 16 },
  938.             to: idx,
  939.             move_type: GameMoveType::Quiet,
  940.             piece_type: PieceType::Pawn,
  941.         });
  942.         double_push_board ^= 1 << idx;
  943.     }
  944. }
  945.  
  946. pub fn add_promotion_push(mut promotion_board: u64, color_to_move: &usize, move_list: &mut Vec<GameMove>, source_shift: usize) {
  947.     while promotion_board != 0u64 {
  948.         let idx = promotion_board.trailing_zeros() as usize;
  949.         move_list.push(GameMove {
  950.             from: if *color_to_move == 0 { idx - source_shift } else { idx + source_shift },
  951.             to: idx,
  952.             move_type: GameMoveType::Promotion(PieceType::Queen),
  953.             piece_type: PieceType::Pawn,
  954.         });
  955.         move_list.push(GameMove {
  956.             from: if *color_to_move == 0 { idx - source_shift } else { idx + source_shift },
  957.             to: idx,
  958.             move_type: GameMoveType::Promotion(PieceType::Rook),
  959.             piece_type: PieceType::Pawn,
  960.         });
  961.         move_list.push(GameMove {
  962.             from: if *color_to_move == 0 { idx - source_shift } else { idx + source_shift },
  963.             to: idx,
  964.             move_type: GameMoveType::Promotion(PieceType::Bishop),
  965.             piece_type: PieceType::Pawn,
  966.         });
  967.         move_list.push(GameMove {
  968.             from: if *color_to_move == 0 { idx - source_shift } else { idx + source_shift },
  969.             to: idx,
  970.             move_type: GameMoveType::Promotion(PieceType::Knight),
  971.             piece_type: PieceType::Pawn,
  972.         });
  973.         promotion_board ^= 1 << idx;
  974.     }
  975. }
  976.  
  977. pub fn add_pawn_capture(mut capture_board: u64, color_to_move: &usize, move_list: &mut Vec<GameMove>, source_shift: usize) {
  978.     while capture_board != 0u64 {
  979.         let idx = capture_board.trailing_zeros() as usize;
  980.         move_list.push(GameMove {
  981.             from: if *color_to_move == 0 { idx - source_shift } else { idx + source_shift },
  982.             to: idx,
  983.             move_type: GameMoveType::Capture,
  984.             piece_type: PieceType::Pawn,
  985.         });
  986.         capture_board ^= 1 << idx;
  987.     }
  988. }
  989.  
  990. pub fn add_en_passants(mut enpassant_board: u64, color_to_move: &usize, move_list: &mut Vec<GameMove>, source_shift: usize, all_pieces_without_my_king: u64, enemy_rooks: u64, my_king_idx: usize) {
  991.     while enpassant_board != 0u64 {
  992.         let index = enpassant_board.trailing_zeros() as usize;
  993.         enpassant_board ^= 1u64 << index;
  994.         //Check if rare case didn't happen
  995.         //Remove t-7,t-8 or t+7,t+8
  996.         let all_pieces_without_en_passants = all_pieces_without_my_king & !bitboards::SQUARES[if *color_to_move == 0 { index - source_shift } else { index + source_shift }]
  997.             & !bitboards::SQUARES[if *color_to_move == 0 { index - 8 } else { index + 8 }];
  998.         if rook_attack(my_king_idx, all_pieces_without_en_passants) & (!bitboards::FILES[my_king_idx % 8]) & enemy_rooks != 0 {
  999.             continue;
  1000.         }
  1001.         move_list.push(GameMove {
  1002.             from: if *color_to_move == 0 { index - source_shift } else { index + source_shift },
  1003.             to: index,
  1004.             move_type: GameMoveType::EnPassant,
  1005.             piece_type: PieceType::Pawn,
  1006.         });
  1007.     }
  1008. }
  1009.  
  1010. //Make moves
  1011. pub fn make_move(g: &game_state::GameState, mv: &game_state::GameMove) -> game_state::GameState {
  1012.     match mv.move_type {
  1013.         GameMoveType::Quiet => make_quiet_move(&g, &mv),
  1014.         GameMoveType::Capture => make_capture_move(&g, &mv),
  1015.         GameMoveType::EnPassant => make_enpassant_move(&g, &mv),
  1016.         GameMoveType::Castle => make_castle_move(&g, &mv),
  1017.         GameMoveType::Promotion(PieceType::Queen) | GameMoveType::Promotion(PieceType::Rook) | GameMoveType::Promotion(PieceType::Bishop) | GameMoveType::Promotion(PieceType::Knight)
  1018.         => make_promotion_move(&g, &mv),
  1019.         _ => panic!("Invalid move type")
  1020.     }
  1021. }
  1022.  
  1023. pub fn move_piece(pieces: &mut [[u64; 2]; 6], mv: &game_state::GameMove, move_color: usize) {
  1024.     let index = match mv.piece_type {
  1025.         PieceType::Pawn => 0,
  1026.         PieceType::Knight => 1,
  1027.         PieceType::Bishop => 2,
  1028.         PieceType::Rook => 3,
  1029.         PieceType::Queen => 4,
  1030.         PieceType::King => 5,
  1031.     };
  1032.     pieces[index][move_color] ^= bitboards::SQUARES[mv.from];
  1033.     pieces[index][move_color] |= bitboards::SQUARES[mv.to];
  1034.     //pieces[index][move_color] ^= 1u64<<mv.from;
  1035.     //pieces[index][move_color] |= 1u64<<mv.to;
  1036. }
  1037.  
  1038. pub fn delete_piece(pieces: &mut [[u64; 2]; 6], delete_square: usize, delete_color: usize) {
  1039.     pieces[0][delete_color] &= bitboards::NOT_SQUARES[delete_square];
  1040.     pieces[1][delete_color] &= bitboards::NOT_SQUARES[delete_square];
  1041.     pieces[2][delete_color] &= bitboards::NOT_SQUARES[delete_square];
  1042.     pieces[3][delete_color] &= bitboards::NOT_SQUARES[delete_square];
  1043.     pieces[4][delete_color] &= bitboards::NOT_SQUARES[delete_square];
  1044. }
  1045.  
  1046. pub fn check_castle_flags(ck: bool, cq: bool, mv: &game_state::GameMove, color_to_move: usize, pieces: [[u64; 2]; 6]) -> (bool, bool) {
  1047.     match mv.piece_type {
  1048.         PieceType::King => (false, false),
  1049.         PieceType::Rook => {
  1050.             let mut new_ck = ck;
  1051.             if ck {
  1052.                 if color_to_move == 0 {
  1053.                     if pieces[3][0] & bitboards::SQUARES[7] == 0 {
  1054.                         new_ck = false;
  1055.                     }
  1056.                 } else {
  1057.                     if pieces[3][1] & bitboards::SQUARES[63] == 0 {
  1058.                         new_ck = false;
  1059.                     }
  1060.                 }
  1061.             }
  1062.             let mut new_cq = cq;
  1063.             if cq {
  1064.                 if color_to_move == 0 {
  1065.                     if pieces[3][0] & bitboards::SQUARES[0] == 0 {
  1066.                         new_cq = false;
  1067.                     }
  1068.                 } else {
  1069.                     if pieces[3][1] & bitboards::SQUARES[56] == 0 {
  1070.                         new_cq = false;
  1071.                     }
  1072.                 }
  1073.             }
  1074.             (new_ck, new_cq)
  1075.         }
  1076.         _ => (ck, cq)
  1077.     }
  1078. }
  1079.  
  1080. pub fn make_quiet_move(g: &game_state::GameState, mv: &game_state::GameMove) -> game_state::GameState {
  1081.     let color_to_move = 1 - g.color_to_move;
  1082.     let mut pieces = g.pieces.clone();
  1083.     //Make the move
  1084.     move_piece(&mut pieces, &mv, g.color_to_move);
  1085.  
  1086.     //Check new castle rights
  1087.     //The enemies castle right's can't change on a quiet move
  1088.     let (castle_white_kingside, castle_white_queenside) = if g.color_to_move == 0 {
  1089.         check_castle_flags(g.castle_white_kingside, g.castle_white_queenside, &mv, g.color_to_move, pieces)
  1090.     } else { (g.castle_white_kingside, g.castle_white_queenside) };
  1091.     let (castle_black_kingside, castle_black_queenside) = if g.color_to_move == 0 {
  1092.         (g.castle_black_kingside, g.castle_black_queenside)
  1093.     } else { check_castle_flags(g.castle_black_kingside, g.castle_black_queenside, &mv, g.color_to_move, pieces) };
  1094.  
  1095.     //This will be taken care of later
  1096.     let mut en_passant = 0u64;
  1097.  
  1098.     let mut half_moves = g.half_moves + 1;
  1099.  
  1100.     //Reset half moves if its a pawn move and also check if its a double pawn move, if so, set en passant flag
  1101.     match mv.piece_type {
  1102.         PieceType::Pawn => {
  1103.             half_moves = 0;
  1104.             if g.color_to_move == 0 && mv.to - mv.from == 16 {
  1105.                 en_passant = bitboards::SQUARES[mv.to - 8];
  1106.             } else if g.color_to_move == 1 && mv.from - mv.to == 16 {
  1107.                 en_passant = bitboards::SQUARES[mv.to + 8];
  1108.             }
  1109.         }
  1110.         _ => {}
  1111.     };
  1112.  
  1113.     //If black was to move, increase full moves by one
  1114.     let full_moves = g.full_moves + g.color_to_move;
  1115.     //Create new game state object
  1116.     game_state::GameState {
  1117.         color_to_move,
  1118.         pieces,
  1119.         castle_white_kingside,
  1120.         castle_white_queenside,
  1121.         castle_black_kingside,
  1122.         castle_black_queenside,
  1123.         en_passant,
  1124.         half_moves,
  1125.         full_moves,
  1126.     }
  1127. }
  1128.  
  1129. pub fn make_capture_move(g: &game_state::GameState, mv: &game_state::GameMove) -> game_state::GameState {
  1130.     let color_to_move = 1 - g.color_to_move;
  1131.     let mut pieces = g.pieces.clone();
  1132.     //Make the move
  1133.     move_piece(&mut pieces, &mv, g.color_to_move);
  1134.     //Delete to from enemy pieces
  1135.     delete_piece(&mut pieces, mv.to, color_to_move);
  1136.  
  1137.     let (mut castle_white_kingside, mut castle_white_queenside) = if g.color_to_move == 0 {
  1138.         check_castle_flags(g.castle_white_kingside, g.castle_white_queenside, &mv, g.color_to_move, pieces)
  1139.     } else { (g.castle_white_kingside, g.castle_white_queenside) };
  1140.     let (mut castle_black_kingside, mut castle_black_queenside) = if g.color_to_move == 0 {
  1141.         (g.castle_black_kingside, g.castle_black_queenside)
  1142.     } else { check_castle_flags(g.castle_black_kingside, g.castle_black_queenside, &mv, g.color_to_move, pieces) };
  1143.  
  1144.     if g.color_to_move == 0 {
  1145.         //Check that blacks rook didn't get captured
  1146.         if pieces[3][1] & bitboards::SQUARES[56] == 0 {
  1147.             castle_black_queenside = false;
  1148.         }
  1149.         if pieces[3][1] & bitboards::SQUARES[63] == 0 {
  1150.             castle_black_kingside = false;
  1151.         }
  1152.     } else {
  1153.         if pieces[3][0] & bitboards::SQUARES[0] == 0 {
  1154.             castle_white_queenside = false;
  1155.         }
  1156.         if pieces[3][0] & bitboards::SQUARES[7] == 0 {
  1157.             castle_white_kingside = false;
  1158.         }
  1159.     }
  1160.     let en_passant = 0u64;
  1161.  
  1162.     let half_moves = 0usize;
  1163.     let full_moves = g.full_moves + g.color_to_move;
  1164.  
  1165.     game_state::GameState {
  1166.         color_to_move,
  1167.         pieces,
  1168.         castle_white_kingside,
  1169.         castle_white_queenside,
  1170.         castle_black_kingside,
  1171.         castle_black_queenside,
  1172.         en_passant,
  1173.         half_moves,
  1174.         full_moves,
  1175.     }
  1176. }
  1177.  
  1178. pub fn make_enpassant_move(g: &game_state::GameState, mv: &game_state::GameMove) -> game_state::GameState {
  1179.     let color_to_move = 1 - g.color_to_move;
  1180.     let mut pieces = g.pieces.clone();
  1181.     //Make the move
  1182.     move_piece(&mut pieces, &mv, g.color_to_move);
  1183.     //Delete enemy pawn
  1184.     delete_piece(&mut pieces, if g.color_to_move == 0 { mv.to - 8 } else { mv.to + 8 }, color_to_move);
  1185.  
  1186.     let castle_white_kingside = g.castle_white_kingside;
  1187.     let castle_white_queenside = g.castle_white_queenside;
  1188.     let castle_black_kingside = g.castle_black_kingside;
  1189.     let castle_black_queenside = g.castle_black_queenside;
  1190.  
  1191.     let en_passant = 0u64;
  1192.  
  1193.     let half_moves = 0usize;
  1194.     let full_moves = g.full_moves + g.color_to_move;
  1195.  
  1196.     game_state::GameState {
  1197.         color_to_move,
  1198.         pieces,
  1199.         castle_white_kingside,
  1200.         castle_white_queenside,
  1201.         castle_black_kingside,
  1202.         castle_black_queenside,
  1203.         en_passant,
  1204.         half_moves,
  1205.         full_moves,
  1206.     }
  1207. }
  1208.  
  1209. pub fn make_castle_move(g: &game_state::GameState, mv: &game_state::GameMove) -> game_state::GameState {
  1210.     let color_to_move = 1 - g.color_to_move;
  1211.     let mut pieces = g.pieces.clone();
  1212.     //Move the king
  1213.     move_piece(&mut pieces, &mv, g.color_to_move);
  1214.  
  1215.     //Move the rook
  1216.     //Determine if its kingside or queenside castle
  1217.     //Kingside
  1218.     if mv.to == 58 {
  1219.         pieces[3][1] ^= bitboards::SQUARES[56];
  1220.         pieces[3][1] |= bitboards::SQUARES[59];
  1221.     } else if mv.to == 2 {
  1222.         pieces[3][0] ^= bitboards::SQUARES[0];
  1223.         pieces[3][0] |= bitboards::SQUARES[3];
  1224.     } else if mv.to == 62 {//Queenside
  1225.         pieces[3][1] ^= bitboards::SQUARES[63];
  1226.         pieces[3][1] |= bitboards::SQUARES[61];
  1227.     } else if mv.to == 6 {
  1228.         pieces[3][0] ^= bitboards::SQUARES[7];
  1229.         pieces[3][0] |= bitboards::SQUARES[5];
  1230.     }
  1231.  
  1232.     let (castle_white_kingside, castle_white_queenside) = if g.color_to_move == 0 { (false, false) } else {
  1233.         (g.castle_white_kingside, g.castle_white_queenside)
  1234.     };
  1235.     let (castle_black_kingside, castle_black_queenside) = if g.color_to_move == 1 { (false, false) } else {
  1236.         (g.castle_black_kingside, g.castle_black_queenside)
  1237.     };
  1238.  
  1239.     let en_passant = 0u64;
  1240.  
  1241.     let half_moves = g.half_moves + 1;
  1242.     let full_moves = g.full_moves + g.color_to_move;
  1243.  
  1244.     game_state::GameState {
  1245.         color_to_move,
  1246.         pieces,
  1247.         castle_white_kingside,
  1248.         castle_white_queenside,
  1249.         castle_black_kingside,
  1250.         castle_black_queenside,
  1251.         en_passant,
  1252.         half_moves,
  1253.         full_moves,
  1254.     }
  1255. }
  1256.  
  1257. pub fn make_promotion_move(g: &game_state::GameState, mv: &game_state::GameMove) -> game_state::GameState {
  1258.     let color_to_move = 1 - g.color_to_move;
  1259.     let mut pieces = g.pieces.clone();
  1260.     //Make the move
  1261.     move_piece(&mut pieces, &mv, g.color_to_move);
  1262.     //Delete enemy piece if any on there
  1263.     delete_piece(&mut pieces, mv.to, color_to_move);
  1264.     //Delete my pawn
  1265.     pieces[0][g.color_to_move] ^= bitboards::SQUARES[mv.to];
  1266.     //Add piece respectivly
  1267.     pieces[match mv.move_type {
  1268.         GameMoveType::Promotion(PieceType::Queen) => { 4 }
  1269.         GameMoveType::Promotion(PieceType::Knight) => { 1 }
  1270.         GameMoveType::Promotion(PieceType::Bishop) => { 2 }
  1271.         GameMoveType::Promotion(PieceType::Rook) => { 3 }
  1272.         _ => panic!("Invalid Type")
  1273.     }][g.color_to_move] |= bitboards::SQUARES[mv.to];
  1274.  
  1275.     let mut castle_white_kingside = g.castle_white_kingside;
  1276.     let mut castle_white_queenside = g.castle_white_queenside;
  1277.     let mut castle_black_kingside = g.castle_black_kingside;
  1278.     let mut castle_black_queenside = g.castle_black_queenside;
  1279.  
  1280.     if g.color_to_move == 0 {
  1281.         //Check that blacks rook didn't get captured
  1282.         if pieces[3][1] & bitboards::SQUARES[56] == 0 {
  1283.             castle_black_queenside = false;
  1284.         }
  1285.         if pieces[3][1] & bitboards::SQUARES[63] == 0 {
  1286.             castle_black_kingside = false;
  1287.         }
  1288.     } else {
  1289.         if pieces[3][0] & bitboards::SQUARES[0] == 0 {
  1290.             castle_white_queenside = false;
  1291.         }
  1292.         if pieces[3][0] & bitboards::SQUARES[7] == 0 {
  1293.             castle_white_kingside = false;
  1294.         }
  1295.     }
  1296.  
  1297.     let en_passant = 0u64;
  1298.  
  1299.     let half_moves = 0usize;
  1300.     let full_moves = g.full_moves + g.color_to_move;
  1301.  
  1302.     game_state::GameState {
  1303.         color_to_move,
  1304.         pieces,
  1305.         castle_white_kingside,
  1306.         castle_white_queenside,
  1307.         castle_black_kingside,
  1308.         castle_black_queenside,
  1309.         en_passant,
  1310.         half_moves,
  1311.         full_moves,
  1312.     }
  1313. }
  1314.  
  1315. pub fn generate_moves(g: &game_state::GameState) -> (Vec<GameMove>, bool) {
  1316.     //Following this guide:
  1317.     // https://peterellisjones.com/posts/generating-legal-chess-moves-efficiently/
  1318.  
  1319.     let mut move_list: Vec<GameMove> = Vec::with_capacity(60);
  1320.     let color_to_move = g.color_to_move;
  1321.     let enemy_color = 1 - color_to_move;
  1322.  
  1323.     //Get my pieces
  1324.     let my_king = g.pieces[5][color_to_move];
  1325.     let my_king_idx = my_king.trailing_zeros() as usize;
  1326.  
  1327.     let mut my_pawns = g.pieces[0][color_to_move];
  1328.  
  1329.     let mut my_knights = g.pieces[1][color_to_move];
  1330.  
  1331.     let mut my_bishops = g.pieces[2][color_to_move] | g.pieces[4][color_to_move];
  1332.  
  1333.     let mut my_rooks = g.pieces[3][color_to_move] | g.pieces[4][color_to_move];
  1334.     //Need this to xor out queens later, when we look at pinned pieces
  1335.     let my_queens = g.pieces[4][color_to_move];
  1336.  
  1337.     //Get enemy pieces
  1338.     let enemy_king = g.pieces[5][enemy_color];
  1339.     let enemy_king_idx = enemy_king.trailing_zeros() as usize;
  1340.  
  1341.     let enemy_pawns = g.pieces[0][enemy_color];
  1342.  
  1343.     let enemy_knights = g.pieces[1][enemy_color];
  1344.  
  1345.     let enemy_bishops = g.pieces[2][enemy_color] | g.pieces[4][enemy_color];
  1346.  
  1347.     let enemy_rooks = g.pieces[3][enemy_color] | g.pieces[4][enemy_color];
  1348.  
  1349.     let my_pieces = my_king | my_pawns | my_knights | my_bishops | my_rooks;
  1350.     let not_my_pieces = !my_pieces;
  1351.     let enemy_sliders = enemy_bishops | enemy_rooks;
  1352.     let enemy_pieces = enemy_pawns | enemy_knights | enemy_sliders | enemy_king;
  1353.     let not_enemy_pieces = !enemy_pieces;
  1354.     let all_pieces_without_my_king = enemy_pieces | (my_pieces & !my_king);
  1355.     let all_pieces = all_pieces_without_my_king | my_king;
  1356.     let empty = !all_pieces;
  1357.  
  1358.     let unsafe_white_squares = if color_to_move == 0 {
  1359.         get_b_attacked_squares(enemy_king_idx, enemy_pawns, enemy_knights, enemy_bishops, enemy_rooks
  1360.                                , all_pieces_without_my_king)
  1361.     } else {
  1362.         get_w_attacked_squares(enemy_king_idx, enemy_pawns, enemy_knights, enemy_bishops, enemy_rooks
  1363.                                , all_pieces_without_my_king)
  1364.     };
  1365.     let possible_king_moves = king_attack(my_king_idx) & !unsafe_white_squares & not_my_pieces;
  1366.     add_moves(&mut move_list, my_king_idx, possible_king_moves & not_enemy_pieces, &PieceType::King, GameMoveType::Quiet);
  1367.     add_moves(&mut move_list, my_king_idx, possible_king_moves & enemy_pieces, &PieceType::King, GameMoveType::Capture);
  1368.     let (king_attackers_board, checking_piece_is_slider, checking_piece_slider_is_bishop) = if unsafe_white_squares & my_king == 0 {
  1369.         (0u64, false, false)
  1370.     } else {
  1371.         if color_to_move == 0 {
  1372.             attackers_from_black(my_king, my_king_idx, enemy_pawns, enemy_knights
  1373.                                  , enemy_bishops, enemy_rooks, all_pieces)
  1374.         } else {
  1375.             attackers_from_white(my_king, my_king_idx, enemy_pawns, enemy_knights
  1376.                                  , enemy_bishops, enemy_rooks, all_pieces)
  1377.         }
  1378.     };
  1379.  
  1380.     let num_checkers = king_attackers_board.count_ones();
  1381.     //Double check
  1382.     if num_checkers > 1 { //Then only king moves are possible anyway
  1383.         return (move_list, true);
  1384.     }
  1385.     //Calculate capture and push mask
  1386.     let mut capture_mask = 0xFFFFFFFFFFFFFFFFu64;
  1387.     let mut push_mask = 0xFFFFFFFFFFFFFFFFu64;
  1388.     //Single-Check
  1389.     {
  1390.         if num_checkers == 1 {
  1391.             capture_mask = king_attackers_board;
  1392.             if checking_piece_is_slider {
  1393.                 let checking_piece_square = king_attackers_board.trailing_zeros() as usize;
  1394.                 if checking_piece_slider_is_bishop {
  1395.                     push_mask = get_bishop_ray(bishop_attack(checking_piece_square, 0u64), my_king_idx, checking_piece_square);
  1396.                 } else {
  1397.                     push_mask = get_rook_ray(rook_attack(checking_piece_square, 0u64), my_king_idx, checking_piece_square);
  1398.                 }
  1399.             } else {
  1400.                 push_mask = 0u64;
  1401.             }
  1402.         }
  1403.     }
  1404.  
  1405.     //Pinned pieces
  1406.     {//Pinned by rook
  1407.         let rook_attacks_from_my_king_postion = rook_attack(my_king_idx, all_pieces);
  1408.         //See one layer through my pieces
  1409.         //If a rook is found seeing through one piece, the piece is pinned
  1410.         let xray_rooks = xray_rook_attacks(rook_attacks_from_my_king_postion, all_pieces, my_pieces, my_king_idx);
  1411.         //Go through all directions
  1412.         //Find the rooks with xray
  1413.         let mut rooks_on_xray = xray_rooks & enemy_rooks;
  1414.         while rooks_on_xray != 0 {
  1415.             let rook_position = rooks_on_xray.trailing_zeros() as usize;
  1416.             rooks_on_xray &= rooks_on_xray - 1;
  1417.             let ray = get_rook_ray(rook_attacks_from_my_king_postion | xray_rooks, rook_position, my_king_idx);
  1418.             let pinned_piece = ray & my_pieces;
  1419.             let pinned_piece_position = pinned_piece.trailing_zeros() as usize;
  1420.             if pinned_piece & my_rooks != 0 {
  1421.                 let mut piece_type = PieceType::Rook;
  1422.                 if pinned_piece & my_queens != 0 {
  1423.                     my_bishops ^= pinned_piece;
  1424.                     piece_type = PieceType::Queen;
  1425.                 }
  1426.                 my_rooks ^= pinned_piece;
  1427.                 add_moves(&mut move_list, pinned_piece_position, ray & !pinned_piece & push_mask, &piece_type, GameMoveType::Quiet);
  1428.                 //Don't forget that we can capture the rook aswell
  1429.                 add_moves(&mut move_list, pinned_piece_position, bitboards::SQUARES[rook_position] & capture_mask, &piece_type, GameMoveType::Capture);
  1430.                 continue;
  1431.             }
  1432.             if pinned_piece & my_pawns != 0 {
  1433.                 my_pawns ^= pinned_piece;
  1434.                 let pawn_push_once = if color_to_move == 0 { w_single_push_pawn_targets(pinned_piece, empty) } else { b_single_push_pawn_targets(pinned_piece, empty) } & ray;
  1435.                 let pawn_push_twice = if color_to_move == 0 { w_double_push_pawn_targets(pinned_piece, empty) } else { b_double_push_pawn_targets(pinned_piece, empty) } & ray;
  1436.                 add_moves(&mut move_list, pinned_piece_position, (pawn_push_once | pawn_push_twice) & push_mask, &PieceType::Pawn, GameMoveType::Quiet);
  1437.                 continue;
  1438.             }
  1439.             if pinned_piece & my_knights != 0 {
  1440.                 my_knights ^= pinned_piece;
  1441.                 continue;
  1442.             }
  1443.             if pinned_piece & my_bishops != 0 {
  1444.                 my_bishops ^= pinned_piece;
  1445.             }
  1446.         }
  1447.         //Pinned by bishop
  1448.         let bishop_attacks_from_my_king_position = bishop_attack(my_king_idx, all_pieces);
  1449.         let xray_bishops = xray_bishop_attacks(bishop_attacks_from_my_king_position, all_pieces, my_pieces, my_king_idx);
  1450.         let mut bishops_on_xray = xray_bishops & enemy_bishops;
  1451.         while bishops_on_xray != 0 {
  1452.             let bishop_position = bishops_on_xray.trailing_zeros() as usize;
  1453.             bishops_on_xray &= bishops_on_xray - 1;
  1454.             let ray = get_bishop_ray(bishop_attacks_from_my_king_position | xray_bishops, bishop_position, my_king_idx);
  1455.             let pinned_piece = ray & my_pieces;
  1456.             let pinned_piece_position = pinned_piece.trailing_zeros() as usize;
  1457.             if pinned_piece & my_bishops != 0 {
  1458.                 let mut piece_type = PieceType::Bishop;
  1459.                 if pinned_piece & my_queens != 0 {
  1460.                     my_rooks ^= pinned_piece;
  1461.                     piece_type = PieceType::Queen;
  1462.                 }
  1463.                 my_bishops ^= pinned_piece;
  1464.  
  1465.                 add_moves(&mut move_list, pinned_piece_position, ray & !pinned_piece & push_mask, &piece_type, GameMoveType::Quiet);
  1466.                 add_moves(&mut move_list, pinned_piece_position, bitboards::SQUARES[bishop_position] & capture_mask, &piece_type, GameMoveType::Capture);
  1467.                 continue;
  1468.             }
  1469.             if pinned_piece & my_pawns != 0 {
  1470.                 my_pawns ^= pinned_piece;
  1471.                 let pawn_targets = if color_to_move == 0 { w_pawn_east_targets(pinned_piece) } else { b_pawn_east_targets(pinned_piece) } | if color_to_move == 0 { w_pawn_west_targets(pinned_piece) } else { b_pawn_west_targets(pinned_piece) };
  1472.                 let pawn_captures = pawn_targets & bitboards::SQUARES[bishop_position] & capture_mask;
  1473.                 //let pawn_enpassants = pawn_targets & g.en_passant;
  1474.                 add_moves(&mut move_list, pinned_piece_position, pawn_captures, &PieceType::Pawn, GameMoveType::Capture);
  1475.                 //add_moves(&mut move_list, pinned_piece_position, pawn_enpassants, &PieceType::Pawn, GameMoveType::EnPassant);
  1476.                 continue;
  1477.             }
  1478.             if pinned_piece & my_knights != 0 {
  1479.                 my_knights ^= pinned_piece;
  1480.                 continue;
  1481.             }
  1482.             if pinned_piece & my_rooks != 0 {
  1483.                 my_rooks ^= pinned_piece;
  1484.             }
  1485.         }
  1486.     }
  1487.     //Calculate normal moves
  1488.     //Pawns
  1489.     {
  1490.         //Single push
  1491.         {
  1492.             let my_pawns_single_push = if color_to_move == 0 { w_single_push_pawn_targets(my_pawns, empty) } else { b_single_push_pawn_targets(my_pawns, empty) } & push_mask;
  1493.             let my_pawns_no_promotion = my_pawns_single_push & !bitboards::RANKS[if color_to_move == 0 { 7 } else { 0 }];
  1494.             let my_pawns_promotion = my_pawns_single_push & bitboards::RANKS[if color_to_move == 0 { 7 } else { 0 }];
  1495.             add_quiet_pawn_single_pushes(my_pawns_no_promotion, &color_to_move, &mut move_list);
  1496.             add_promotion_push(my_pawns_promotion, &color_to_move, &mut move_list, 8usize);
  1497.         }
  1498.         //Double push
  1499.         {
  1500.             let my_pawns_double_push = if color_to_move == 0 { w_double_push_pawn_targets(my_pawns, empty) } else { b_double_push_pawn_targets(my_pawns, empty) } & push_mask;
  1501.             add_quiet_pawn_double_pushes(my_pawns_double_push, &color_to_move, &mut move_list);
  1502.         }
  1503.         //Capture west
  1504.         {
  1505.             let my_pawns_west_targets = if color_to_move == 0 { w_pawn_west_targets(my_pawns) } else { b_pawn_west_targets(my_pawns) };
  1506.             let my_pawns_west_normal_captures = my_pawns_west_targets & capture_mask & enemy_pieces;
  1507.             //Checking for promotion on capture
  1508.             let my_pawns_no_promotion = my_pawns_west_normal_captures & !bitboards::RANKS[if color_to_move == 0 { 7 } else { 0 }];
  1509.             let my_pawns_promotion = my_pawns_west_normal_captures & bitboards::RANKS[if color_to_move == 0 { 7 } else { 0 }];
  1510.             //Capture
  1511.             add_pawn_capture(my_pawns_no_promotion, &color_to_move, &mut move_list, 7usize);
  1512.             //Promotion capture
  1513.             add_promotion_push(my_pawns_promotion, &color_to_move, &mut move_list, 7usize);
  1514.  
  1515.  
  1516.             //En passant
  1517.             //We can capture en passant, if its in capture mask aswell
  1518.             let my_pawns_west_enpassants = my_pawns_west_targets & g.en_passant & if color_to_move == 0 { capture_mask << 8 } else { capture_mask >> 8 };
  1519.             add_en_passants(my_pawns_west_enpassants, &color_to_move, &mut move_list, 7usize, all_pieces_without_my_king, enemy_rooks, my_king_idx);
  1520.         }
  1521.         //Capture east
  1522.         {
  1523.             let my_pawns_east_targets = if color_to_move == 0 { w_pawn_east_targets(my_pawns) } else { b_pawn_east_targets(my_pawns) };
  1524.             let my_pawns_east_normal_captures = my_pawns_east_targets & capture_mask & enemy_pieces;
  1525.             //Checking for promotion on capture
  1526.             let my_pawns_no_promotion = my_pawns_east_normal_captures & !bitboards::RANKS[if color_to_move == 0 { 7 } else { 0 }];
  1527.             let my_pawns_promotion = my_pawns_east_normal_captures & bitboards::RANKS[if color_to_move == 0 { 7 } else { 0 }];
  1528.  
  1529.             add_pawn_capture(my_pawns_no_promotion, &color_to_move, &mut move_list, 9usize);
  1530.             add_promotion_push(my_pawns_promotion, &color_to_move, &mut move_list, 9usize);
  1531.             //En passants
  1532.             let  my_pawns_east_enpassants = my_pawns_east_targets & g.en_passant & if color_to_move == 0 { capture_mask << 8 } else { capture_mask >> 8 };
  1533.             add_en_passants(my_pawns_east_enpassants, &color_to_move, &mut move_list, 9usize, all_pieces_without_my_king, enemy_rooks, my_king_idx);
  1534.         }
  1535.     }
  1536.     //Knights
  1537.     {
  1538.         while my_knights != 0u64 {
  1539.             let index = if color_to_move == 0 { 63usize - my_knights.leading_zeros() as usize } else { my_knights.trailing_zeros() as usize };
  1540.             let my_knight_attacks = knight_attack(index) & not_my_pieces;
  1541.             let my_knight_captures = my_knight_attacks & enemy_pieces & capture_mask;
  1542.             add_moves(&mut move_list, index, my_knight_captures, &PieceType::Knight, GameMoveType::Capture);
  1543.             let my_knight_quiets = my_knight_attacks & !enemy_pieces & push_mask;
  1544.             add_moves(&mut move_list, index, my_knight_quiets, &PieceType::Knight, GameMoveType::Quiet);
  1545.             my_knights ^= 1u64 << index;
  1546.         }
  1547.     }
  1548.     //Bishops
  1549.     {
  1550.         while my_bishops != 0u64 {
  1551.             let index = if color_to_move == 0 { 63usize - my_bishops.leading_zeros() as usize } else { my_bishops.trailing_zeros() as usize };
  1552.             let my_bishop_attack = bishop_attack(index, all_pieces) & not_my_pieces;
  1553.             let my_bishop_capture = my_bishop_attack & enemy_pieces & capture_mask;
  1554.             let piece_type = if bitboards::SQUARES[index] & my_queens != 0 { PieceType::Queen } else { PieceType::Bishop };
  1555.             add_moves(&mut move_list, index, my_bishop_capture, &piece_type, GameMoveType::Capture);
  1556.             let my_bishop_quiet = my_bishop_attack & !enemy_pieces & push_mask;
  1557.             add_moves(&mut move_list, index, my_bishop_quiet, &piece_type, GameMoveType::Quiet);
  1558.             my_bishops ^= 1u64 << index;
  1559.         }
  1560.     }
  1561.     //Rooks
  1562.     {
  1563.         while my_rooks != 0u64 {
  1564.             let index = if color_to_move == 0 { 63usize - my_rooks.leading_zeros() as usize } else { my_rooks.trailing_zeros() as usize };
  1565.             let my_rook_attack = rook_attack(index, all_pieces) & not_my_pieces;
  1566.             let my_rook_capture = my_rook_attack & enemy_pieces & capture_mask;
  1567.             let piece_type = if bitboards::SQUARES[index] & my_queens != 0 { PieceType::Queen } else { PieceType::Rook };
  1568.             add_moves(&mut move_list, index, my_rook_capture, &piece_type, GameMoveType::Capture);
  1569.             let my_rook_quiets = my_rook_attack & !enemy_pieces & push_mask;
  1570.             add_moves(&mut move_list, index, my_rook_quiets, &piece_type, GameMoveType::Quiet);
  1571.             my_rooks ^= 1u64 << index;
  1572.         }
  1573.     }
  1574.     //Castles
  1575.     if num_checkers == 0 {
  1576.         if g.color_to_move == 0 {
  1577.             //Make sure there is no piece in between and safe squares
  1578.             if g.castle_white_kingside {
  1579.                 if (all_pieces | unsafe_white_squares) & (bitboards::SQUARES[5] | bitboards::SQUARES[6]) == 0 {
  1580.                     move_list.push(GameMove {
  1581.                         from: my_king_idx,
  1582.                         to: 6usize,
  1583.                         move_type: GameMoveType::Castle,
  1584.                         piece_type: PieceType::King,
  1585.                     });
  1586.                 }
  1587.             }
  1588.             if g.castle_white_queenside {
  1589.                 if ((all_pieces | unsafe_white_squares) & (bitboards::SQUARES[2] | bitboards::SQUARES[3]) | all_pieces & bitboards::SQUARES[1]) == 0 {
  1590.                     move_list.push(GameMove {
  1591.                         from: my_king_idx,
  1592.                         to: 2usize,
  1593.                         move_type: GameMoveType::Castle,
  1594.                         piece_type: PieceType::King,
  1595.                     });
  1596.                 }
  1597.             }
  1598.         } else {
  1599.             if g.castle_black_kingside {
  1600.                 if (all_pieces | unsafe_white_squares) & (bitboards::SQUARES[61] | bitboards::SQUARES[62]) == 0 {
  1601.                     move_list.push(GameMove {
  1602.                         from: my_king_idx,
  1603.                         to: 62usize,
  1604.                         move_type: GameMoveType::Castle,
  1605.                         piece_type: PieceType::King,
  1606.                     });
  1607.                 }
  1608.             }
  1609.             if g.castle_black_queenside {
  1610.                 if ((all_pieces | unsafe_white_squares) & (bitboards::SQUARES[58] | bitboards::SQUARES[59]) | all_pieces & bitboards::SQUARES[57]) == 0 {
  1611.                     move_list.push(GameMove {
  1612.                         from: my_king_idx,
  1613.                         to: 58usize,
  1614.                         move_type: GameMoveType::Castle,
  1615.                         piece_type: PieceType::King,
  1616.                     });
  1617.                 }
  1618.             }
  1619.         }
  1620.     }
  1621.     (move_list, num_checkers > 0)
  1622. }
  1623.  
  1624. pub fn xray_rook_attacks(attacks: u64, occupied_square: u64, one_time_blockers: u64, rook_square: usize) -> u64 {
  1625.     return attacks ^ rook_attack(rook_square, occupied_square ^ (one_time_blockers & attacks));
  1626. }
  1627.  
  1628. pub fn xray_bishop_attacks(attacks: u64, occupied_square: u64, one_time_blockers: u64, bishop_square: usize) -> u64 {
  1629.     return attacks ^ bishop_attack(bishop_square, occupied_square ^ (one_time_blockers & attacks));
  1630. }
  1631.  
  1632. //Gets the ray of one rook into a specific direction
  1633. pub fn get_rook_ray(rook_attacks_in_all_directions: u64, target_square: usize, rook_square: usize) -> u64 {
  1634.     let diff = target_square as isize - rook_square as isize;
  1635.     let target_rank = target_square / 8;
  1636.     let target_file = target_square % 8;
  1637.     let rook_rank = rook_square / 8;
  1638.     let rook_file = rook_square % 8;
  1639.     if diff > 0 {
  1640.         //Same vertical
  1641.         if target_rank == rook_rank {
  1642.             return bitboards::FILES_LESS_THAN[target_file] & bitboards::FILES_GREATER_THAN[rook_file] & rook_attacks_in_all_directions;
  1643.         } else {
  1644.             return bitboards::RANKS_LESS_THAN[target_rank] & bitboards::RANKS_GREATER_THAN[rook_rank] & rook_attacks_in_all_directions;
  1645.         }
  1646.     } else {
  1647.         if target_rank == rook_rank {
  1648.             return bitboards::FILES_GREATER_THAN[target_file] & bitboards::FILES_LESS_THAN[rook_file] & rook_attacks_in_all_directions;
  1649.         } else {
  1650.             return bitboards::RANKS_GREATER_THAN[target_rank] & bitboards::RANKS_LESS_THAN[rook_rank] & rook_attacks_in_all_directions;
  1651.         }
  1652.     }
  1653. }
  1654.  
  1655. //Gets the rof of one bishop into a specific direction
  1656. pub fn get_bishop_ray(bishop_attack_in_all_directions: u64, target_square: usize, bishop_square: usize) -> u64 {
  1657.     let diff = target_square as isize - bishop_square as isize;
  1658.     let target_rank = target_square / 8;
  1659.     let target_file = target_square % 8;
  1660.     let bishop_rank = bishop_square / 8;
  1661.     let bishop_file = bishop_square % 8;
  1662.     if diff > 0 {
  1663.         if diff % 7 == 0 {
  1664.             return bitboards::FILES_GREATER_THAN[target_file] & bitboards::FILES_LESS_THAN[bishop_file]
  1665.                 & bitboards::RANKS_LESS_THAN[target_rank] & bitboards::RANKS_GREATER_THAN[bishop_rank]
  1666.                 & bishop_attack_in_all_directions;
  1667.         } else {
  1668.             return bitboards::FILES_LESS_THAN[target_file] & bitboards::FILES_GREATER_THAN[bishop_file]
  1669.                 & bitboards::RANKS_LESS_THAN[target_rank] & bitboards::RANKS_GREATER_THAN[bishop_rank]
  1670.                 & bishop_attack_in_all_directions;
  1671.         }
  1672.     } else {
  1673.         if diff % -7 == 0 {
  1674.             return bitboards::FILES_LESS_THAN[target_file] & bitboards::FILES_GREATER_THAN[bishop_file]
  1675.                 & bitboards::RANKS_GREATER_THAN[target_rank] & bitboards::RANKS_LESS_THAN[bishop_rank]
  1676.                 & bishop_attack_in_all_directions;
  1677.         } else {
  1678.             return bitboards::FILES_GREATER_THAN[target_file] & bitboards::FILES_LESS_THAN[bishop_file]
  1679.                 & bitboards::RANKS_GREATER_THAN[target_rank] & bitboards::RANKS_LESS_THAN[bishop_rank]
  1680.                 & bishop_attack_in_all_directions;
  1681.         }
  1682.     }
  1683. }
  1684.  
  1685. pub fn attackers_from_white(square_board: u64, square: usize, white_pawns: u64, white_knights: u64, white_bishops: u64, white_rooks: u64, blockers: u64) -> (u64, bool, bool) {
  1686.     let mut attackers = 0u64;
  1687.     let mut slider_flag = false;
  1688.     let mut bishop_slider = false;
  1689.     attackers |= knight_attack(square) & white_knights;
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top