- /* 
-  * tbprobe.c 
-  * Copyright (c) 2013-2015 Ronald de Man 
-  * This file may be redistributed and/or modified without restrictions. 
-  * 
-  * (C) 2015 basil, all rights reserved, 
-  * Permission is hereby granted, free of charge, to any person obtaining a 
-  * copy of this software and associated documentation files (the "Software"), 
-  * to deal in the Software without restriction, including without limitation 
-  * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
-  * and/or sell copies of the Software, and to permit persons to whom the 
-  * Software is furnished to do so, subject to the following conditions: 
-  *  
-  * The above copyright notice and this permission notice shall be included in 
-  * all copies or substantial portions of the Software. 
-  *  
-  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
-  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
-  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
-  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
-  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
-  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
-  * DEALINGS IN THE SOFTWARE. 
-  */ 
-   
- #include <assert.h> 
- #include <stdio.h> 
- #include <stdlib.h> 
-   
- #include "tbprobe.h" 
-   
- //#include <x86intrin.h> 
-   
- #define WHITE_KING              (TB_WPAWN + 5) 
- #define WHITE_QUEEN             (TB_WPAWN + 4) 
- #define WHITE_ROOK              (TB_WPAWN + 3) 
- #define WHITE_BISHOP            (TB_WPAWN + 2) 
- #define WHITE_KNIGHT            (TB_WPAWN + 1) 
- #define WHITE_PAWN              TB_WPAWN 
- #define BLACK_KING              (TB_BPAWN + 5) 
- #define BLACK_QUEEN             (TB_BPAWN + 4) 
- #define BLACK_ROOK              (TB_BPAWN + 3) 
- #define BLACK_BISHOP            (TB_BPAWN + 2) 
- #define BLACK_KNIGHT            (TB_BPAWN + 1) 
- #define BLACK_PAWN              TB_BPAWN 
-   
- #define PRIME_WHITE_QUEEN       11811845319353239651ull 
- #define PRIME_WHITE_ROOK        10979190538029446137ull 
- #define PRIME_WHITE_BISHOP      12311744257139811149ull 
- #define PRIME_WHITE_KNIGHT      15202887380319082783ull 
- #define PRIME_WHITE_PAWN        17008651141875982339ull 
- #define PRIME_BLACK_QUEEN       15484752644942473553ull 
- #define PRIME_BLACK_ROOK        18264461213049635989ull 
- #define PRIME_BLACK_BISHOP      15394650811035483107ull 
- #define PRIME_BLACK_KNIGHT      13469005675588064321ull 
- #define PRIME_BLACK_PAWN        11695583624105689831ull 
-   
- #define BOARD_RANK_EDGE         0x8181818181818181ull 
- #define BOARD_FILE_EDGE         0xFF000000000000FFull 
- #define BOARD_EDGE              (BOARD_RANK_EDGE | BOARD_FILE_EDGE) 
- #define BOARD_RANK_1            0x00000000000000FFull 
- #define BOARD_FILE_A            0x8080808080808080ull 
-   
- #define KEY_KvK                 0 
-   
- #define BEST_NONE               0xFFFF 
- #define SCORE_ILLEGAL           0x7FFF 
-   
- #define popcount(v) PopCnt(v) 
-   
- #define poplsb(x)               ((x) & ((x) - 1)) 
-   
- #define make_move(promote, from, to)                                    \ 
-     ((((promote) & 0x7) << 12) | (((from) & 0x3F) << 6) | ((to) & 0x3F)) 
- #define move_from(move)                                                 \ 
-     (((move) >> 6) & 0x3F) 
- #define move_to(move)                                                   \ 
-     ((move) & 0x3F) 
- #define move_promotes(move)                                             \ 
-     (((move) >> 12) & 0x7) 
-   
- #define MAX_MOVES               TB_MAX_MOVES 
- #define MOVE_STALEMATE          0xFFFF 
- #define MOVE_CHECKMATE          0xFFFE 
-   
- struct pos { 
-   uint64_t white; 
-   uint64_t black; 
-   uint64_t kings; 
-   uint64_t queens; 
-   uint64_t rooks; 
-   uint64_t bishops; 
-   uint64_t knights; 
-   uint64_t pawns; 
-   uint8_t rule50; 
-   uint8_t ep; 
-   bool turn; 
- }; 
-   
- static bool do_move(struct pos *pos, const struct pos *pos0, uint16_t move); 
- static int probe_dtz(const struct pos *pos, int *success); 
-   
- unsigned TB_LARGEST = 0; 
- #include "tbcore.c" 
-   
- #define rank(s)                 ((s) >> 3) 
- #define file(s)                 ((s) & 0x07) 
- #define board(s)                ((uint64_t)1 << (s)) 
- static inline unsigned _lsb(uint64_t b) { 
- #ifdef _WIN32 // Pierre-Marie Baty -- Win32 addition 
-   static const int index64[64] = { 
-      0, 47,  1, 56, 48, 27,  2, 60, 
-      57, 49, 41, 37, 28, 16,  3, 61, 
-      54, 58, 35, 52, 50, 42, 21, 44, 
-      38, 32, 29, 23, 17, 11,  4, 62, 
-      46, 55, 26, 59, 40, 36, 15, 53, 
-      34, 51, 20, 43, 31, 22, 10, 45, 
-      25, 39, 14, 33, 19, 30,  9, 24, 
-      13, 18,  8, 12,  7,  6,  5, 63 
-   }; 
-   /** 
-   * bitScanForward 
-   * @author Kim Walisch (2012) 
-   * @param bb bitboard to scan 
-   * @precondition bb != 0 
-   * @return index (0..63) of least significant one bit 
-   */ 
-    const uint64_t debruijn64 = 0x03f79d71b4cb0a89ULL; 
-    return index64[((b ^ (b - 1)) * debruijn64) >> 58]; 
- #else 
-   size_t idx; 
- __asm__("bsfq %1, %0": "=r"(idx):"rm"(b)); 
-   return idx; 
- #endif 
- } 
-   
- #define square(r, f)            (8 * (r) + (f)) 
-   
- #ifdef TB_KING_ATTACKS 
- #  define king_attacks(s)         TB_KING_ATTACKS(s) 
- #  define king_attacks_init() 
-                             /* NOP */ 
- #else                           /* TB_KING_ATTACKS */ 
-   
- static uint64_t king_attacks_table[64]; 
-   
- #  define king_attacks(s)         king_attacks_table[(s)] 
-   
- static void king_attacks_init(void) { 
-   for (unsigned s = 0; s < 64; s++) { 
-     unsigned r = rank(s); 
-     unsigned f = file(s); 
-     uint64_t b = 0; 
-     if (r != 0 && f != 0) 
-       b |= board(square(r - 1, f - 1)); 
-     if (r != 0) 
-       b |= board(square(r - 1, f)); 
-     if (r != 0 && f != 7) 
-       b |= board(square(r - 1, f + 1)); 
-     if (f != 7) 
-       b |= board(square(r, f + 1)); 
-     if (r != 7 && f != 7) 
-       b |= board(square(r + 1, f + 1)); 
-     if (r != 7) 
-       b |= board(square(r + 1, f)); 
-     if (r != 7 && f != 0) 
-       b |= board(square(r + 1, f - 1)); 
-     if (f != 0) 
-       b |= board(square(r, f - 1)); 
-     king_attacks_table[s] = b; 
-   } 
- } 
-   
- #endif                          /* TB_KING_ATTACKS */ 
-   
- #ifdef TB_KNIGHT_ATTACKS 
- #  define knight_attacks(s)       TB_KNIGHT_ATTACKS(s) 
- #  define knight_attacks_init() 
-                               /* NOP */ 
- #else                           /* TB_KNIGHT_ATTACKS */ 
-   
- static uint64_t knight_attacks_table[64]; 
-   
- #  define knight_attacks(s)       knight_attacks_table[(s)] 
-   
- static void knight_attacks_init(void) { 
-   for (unsigned s = 0; s < 64; s++) { 
-     int r1, r = rank(s); 
-     int f1, f = file(s); 
-     uint64_t b = 0; 
-     r1 = r - 1; 
-     f1 = f - 2; 
-     if (r1 >= 0 && f1 >= 0) 
-       b |= board(square(r1, f1)); 
-     r1 = r - 1; 
-     f1 = f + 2; 
-     if (r1 >= 0 && f1 <= 7) 
-       b |= board(square(r1, f1)); 
-     r1 = r - 2; 
-     f1 = f - 1; 
-     if (r1 >= 0 && f1 >= 0) 
-       b |= board(square(r1, f1)); 
-     r1 = r - 2; 
-     f1 = f + 1; 
-     if (r1 >= 0 && f1 <= 7) 
-       b |= board(square(r1, f1)); 
-     r1 = r + 1; 
-     f1 = f - 2; 
-     if (r1 <= 7 && f1 >= 0) 
-       b |= board(square(r1, f1)); 
-     r1 = r + 1; 
-     f1 = f + 2; 
-     if (r1 <= 7 && f1 <= 7) 
-       b |= board(square(r1, f1)); 
-     r1 = r + 2; 
-     f1 = f - 1; 
-     if (r1 <= 7 && f1 >= 0) 
-       b |= board(square(r1, f1)); 
-     r1 = r + 2; 
-     f1 = f + 1; 
-     if (r1 <= 7 && f1 <= 7) 
-       b |= board(square(r1, f1)); 
-     knight_attacks_table[s] = b; 
-   } 
- } 
-   
- #endif                          /* TB_KNIGHT_ATTACKS */ 
-   
- #ifdef TB_BISHOP_ATTACKS 
- #  define bishop_attacks(s, occ)  TB_BISHOP_ATTACKS(s, occ) 
- #  define bishop_attacks_init() 
-                               /* NOP */ 
- #else                           /* TB_BISHOP_ATTACKS */ 
-   
- static uint64_t diag_attacks_table[64][64]; 
- static uint64_t anti_attacks_table[64][64]; 
-   
- static const unsigned square2diag_table[64] = { 
-   0, 1, 2, 3, 4, 5, 6, 7, 
-   14, 0, 1, 2, 3, 4, 5, 6, 
-   13, 14, 0, 1, 2, 3, 4, 5, 
-   12, 13, 14, 0, 1, 2, 3, 4, 
-   11, 12, 13, 14, 0, 1, 2, 3, 
-   10, 11, 12, 13, 14, 0, 1, 2, 
-   9, 10, 11, 12, 13, 14, 0, 1, 
-   8, 9, 10, 11, 12, 13, 14, 0 
- }; 
-   
- static const unsigned square2anti_table[64] = { 
-   8, 9, 10, 11, 12, 13, 14, 0, 
-   9, 10, 11, 12, 13, 14, 0, 1, 
-   10, 11, 12, 13, 14, 0, 1, 2, 
-   11, 12, 13, 14, 0, 1, 2, 3, 
-   12, 13, 14, 0, 1, 2, 3, 4, 
-   13, 14, 0, 1, 2, 3, 4, 5, 
-   14, 0, 1, 2, 3, 4, 5, 6, 
-   0, 1, 2, 3, 4, 5, 6, 7 
- }; 
-   
- static const uint64_t diag2board_table[15] = { 
-   0x8040201008040201ull, 
-   0x0080402010080402ull, 
-   0x0000804020100804ull, 
-   0x0000008040201008ull, 
-   0x0000000080402010ull, 
-   0x0000000000804020ull, 
-   0x0000000000008040ull, 
-   0x0000000000000080ull, 
-   0x0100000000000000ull, 
-   0x0201000000000000ull, 
-   0x0402010000000000ull, 
-   0x0804020100000000ull, 
-   0x1008040201000000ull, 
-   0x2010080402010000ull, 
-   0x4020100804020100ull, 
- }; 
-   
- static const uint64_t anti2board_table[15] = { 
-   0x0102040810204080ull, 
-   0x0204081020408000ull, 
-   0x0408102040800000ull, 
-   0x0810204080000000ull, 
-   0x1020408000000000ull, 
-   0x2040800000000000ull, 
-   0x4080000000000000ull, 
-   0x8000000000000000ull, 
-   0x0000000000000001ull, 
-   0x0000000000000102ull, 
-   0x0000000000010204ull, 
-   0x0000000001020408ull, 
-   0x0000000102040810ull, 
-   0x0000010204081020ull, 
-   0x0001020408102040ull, 
- }; 
-   
- static inline size_t diag2index(uint64_t b, unsigned d) { 
-   b *= 0x0101010101010101ull; 
-   b >>= 56; 
-   b >>= 1; 
-   return (size_t) b; 
- } 
-   
- static inline size_t anti2index(uint64_t b, unsigned a) { 
-   return diag2index(b, a); 
- } 
-   
- #  define diag(s)                 square2diag_table[(s)] 
- #  define anti(s)                 square2anti_table[(s)] 
- #  define diag2board(d)           diag2board_table[(d)] 
- #  define anti2board(a)           anti2board_table[(a)] 
-   
- static uint64_t bishop_attacks(unsigned sq, uint64_t occ) { 
-   occ &= ~board(sq); 
-   unsigned d = diag(sq), a = anti(sq); 
-   uint64_t d_occ = occ & (diag2board(d) & ~BOARD_EDGE); 
-   uint64_t a_occ = occ & (anti2board(a) & ~BOARD_EDGE); 
-   size_t d_idx = diag2index(d_occ, d); 
-   size_t a_idx = anti2index(a_occ, a); 
-   uint64_t d_attacks = diag_attacks_table[sq][d_idx]; 
-   uint64_t a_attacks = anti_attacks_table[sq][a_idx]; 
-   return d_attacks | a_attacks; 
- } 
-   
- static void bishop_attacks_init(void) { 
-   for (unsigned idx = 0; idx < 64; idx++) { 
-     unsigned idx1 = idx << 1; 
-     for (unsigned s = 0; s < 64; s++) { 
-       int r = rank(s); 
-       int f = file(s); 
-       uint64_t b = 0; 
-       for (int i = -1; f + i >= 0 && r + i >= 0; i--) { 
-         unsigned occ = (1 << (f + i)); 
-         b |= board(square(r + i, f + i)); 
-         if (idx1 & occ) 
-           break; 
-       } 
-       for (int i = 1; f + i <= 7 && r + i <= 7; i++) { 
-         unsigned occ = (1 << (f + i)); 
-         b |= board(square(r + i, f + i)); 
-         if (idx1 & occ) 
-           break; 
-       } 
-       diag_attacks_table[s][idx] = b; 
-     } 
-   } 
-   
-   for (unsigned idx = 0; idx < 64; idx++) { 
-     unsigned idx1 = idx << 1; 
-     for (unsigned s = 0; s < 64; s++) { 
-       int r = rank(s); 
-       int f = file(s); 
-       uint64_t b = 0; 
-       for (int i = -1; f + i >= 0 && r - i <= 7; i--) { 
-         unsigned occ = (1 << (f + i)); 
-         b |= board(square(r - i, f + i)); 
-         if (idx1 & occ) 
-           break; 
-       } 
-       for (int i = 1; f + i <= 7 && r - i >= 0; i++) { 
-         unsigned occ = (1 << (f + i)); 
-         b |= board(square(r - i, f + i)); 
-         if (idx1 & occ) 
-           break; 
-       } 
-       anti_attacks_table[s][idx] = b; 
-     } 
-   } 
- } 
-   
- #endif                          /* TB_BISHOP_ATTACKS */ 
-   
- #ifdef TB_ROOK_ATTACKS 
- #  define rook_attacks(s, occ)    TB_ROOK_ATTACKS(s, occ) 
- #  define rook_attacks_init() 
-                             /* NOP */ 
- #else                           /* TB_ROOK_ATTACKS */ 
-   
- static uint64_t rank_attacks_table[64][64]; 
- static uint64_t file_attacks_table[64][64]; 
-   
- static inline size_t rank2index(uint64_t b, unsigned r) { 
-   b >>= (8 * r); 
-   b >>= 1; 
-   return (size_t) b; 
- } 
-   
- static inline size_t file2index(uint64_t b, unsigned f) { 
-   b >>= f; 
-   b *= 0x0102040810204080ull; 
-   b >>= 56; 
-   b >>= 1; 
-   return (size_t) b; 
- } 
-   
- #  define rank2board(r)           (0xFFull << (8 * (r))) 
- #  define file2board(f)           (0x0101010101010101ull << (f)) 
-   
- static uint64_t rook_attacks(unsigned sq, uint64_t occ) { 
-   occ &= ~board(sq); 
-   unsigned r = rank(sq), f = file(sq); 
-   uint64_t r_occ = occ & (rank2board(r) & ~BOARD_RANK_EDGE); 
-   uint64_t f_occ = occ & (file2board(f) & ~BOARD_FILE_EDGE); 
-   size_t r_idx = rank2index(r_occ, r); 
-   size_t f_idx = file2index(f_occ, f); 
-   uint64_t r_attacks = rank_attacks_table[sq][r_idx]; 
-   uint64_t f_attacks = file_attacks_table[sq][f_idx]; 
-   return r_attacks | f_attacks; 
- } 
-   
- static void rook_attacks_init(void) { 
-   for (unsigned idx = 0; idx < 64; idx++) { 
-     unsigned idx1 = idx << 1, occ; 
-     for (int f = 0; f <= 7; f++) { 
-       uint64_t b = 0; 
-       if (f > 0) { 
-         int i = f - 1; 
-         do { 
-           occ = (1 << i); 
-           b |= board(square(0, i)); 
-           i--; 
-         } 
-         while (!(idx1 & occ) && i >= 0); 
-       } 
-       if (f < 7) { 
-         int i = f + 1; 
-         do { 
-           occ = (1 << i); 
-           b |= board(square(0, i)); 
-           i++; 
-         } 
-         while (!(idx1 & occ) && i <= 7); 
-       } 
-       for (int r = 0; r <= 7; r++) { 
-         rank_attacks_table[square(r, f)][idx] = b; 
-         b <<= 8; 
-       } 
-     } 
-   } 
-   for (unsigned idx = 0; idx < 64; idx++) { 
-     unsigned idx1 = idx << 1, occ; 
-     for (int r = 0; r <= 7; r++) { 
-       uint64_t b = 0; 
-       if (r > 0) { 
-         int i = r - 1; 
-         do { 
-           occ = (1 << i); 
-           b |= board(square(i, 0)); 
-           i--; 
-         } 
-         while (!(idx1 & occ) && i >= 0); 
-       } 
-       if (r < 7) { 
-         int i = r + 1; 
-         do { 
-           occ = (1 << i); 
-           b |= board(square(i, 0)); 
-           i++; 
-         } 
-         while (!(idx1 & occ) && i <= 7); 
-       } 
-       for (int f = 0; f <= 7; f++) { 
-         file_attacks_table[square(r, f)][idx] = b; 
-         b <<= 1; 
-       } 
-     } 
-   } 
- } 
-   
- #endif                          /* TB_ROOK_ATTACKS */ 
-   
- #ifdef TB_QUEEN_ATTACKS 
- #  define queen_attacks(s, occ)   TB_QUEEN_ATTACKS(s, occ) 
- #else                           /* TB_QUEEN_ATTACKS */ 
- #  define queen_attacks(s, occ)   \ 
-     (rook_attacks((s), (occ)) | bishop_attacks((s), (occ))) 
- #endif                          /* TB_QUEEN_ATTACKS */ 
-   
- #ifdef TB_PAWN_ATTACKS 
- #  define pawn_attacks(s, c)      TB_PAWN_ATTACKS(s, c) 
- #  define pawn_attacks_init() 
-                             /* NOP */ 
- #else                           /* TB_PAWN_ATTACKS */ 
-   
- static uint64_t pawn_attacks_table[2][64]; 
-   
- #  define pawn_attacks(s, c)      pawn_attacks_table[(c)][(s)] 
-   
- static void pawn_attacks_init(void) { 
-   for (unsigned s = 0; s < 64; s++) { 
-     int r = rank(s); 
-     int f = file(s); 
-   
-     uint64_t b = 0; 
-     if (r != 7) { 
-       if (f != 0) 
-         b |= board(square(r + 1, f - 1)); 
-       if (f != 7) 
-         b |= board(square(r + 1, f + 1)); 
-     } 
-     pawn_attacks_table[1][s] = b; 
-   
-     b = 0; 
-     if (r != 0) { 
-       if (f != 0) 
-         b |= board(square(r - 1, f - 1)); 
-       if (f != 7) 
-         b |= board(square(r - 1, f + 1)); 
-     } 
-     pawn_attacks_table[0][s] = b; 
-   } 
- } 
-   
- #endif                          /* TB_PAWN_ATTACKS */ 
-   
- static void prt_str(const struct pos *pos, char *str, bool mirror) { 
-   uint64_t white = pos->white, black = pos->black; 
-   int i; 
-   if (mirror) { 
-     uint64_t tmp = white; 
-     white = black; 
-     black = tmp; 
-   } 
-   *str++ = 'K'; 
-   for (i = popcount(white & pos->queens); i > 0; i--) 
-     *str++ = 'Q'; 
-   for (i = popcount(white & pos->rooks); i > 0; i--) 
-     *str++ = 'R'; 
-   for (i = popcount(white & pos->bishops); i > 0; i--) 
-     *str++ = 'B'; 
-   for (i = popcount(white & pos->knights); i > 0; i--) 
-     *str++ = 'N'; 
-   for (i = popcount(white & pos->pawns); i > 0; i--) 
-     *str++ = 'P'; 
-   *str++ = 'v'; 
-   *str++ = 'K'; 
-   for (i = popcount(black & pos->queens); i > 0; i--) 
-     *str++ = 'Q'; 
-   for (i = popcount(black & pos->rooks); i > 0; i--) 
-     *str++ = 'R'; 
-   for (i = popcount(black & pos->bishops); i > 0; i--) 
-     *str++ = 'B'; 
-   for (i = popcount(black & pos->knights); i > 0; i--) 
-     *str++ = 'N'; 
-   for (i = popcount(black & pos->pawns); i > 0; i--) 
-     *str++ = 'P'; 
-   *str++ = '\0'; 
- } 
-   
- /* 
-  * Given a position, produce a 64-bit material signature key. 
-  */ 
- static uint64_t calc_key(const struct pos *pos, bool mirror) { 
-   uint64_t white = pos->white, black = pos->black; 
-   if (mirror) { 
-     uint64_t tmp = white; 
-     white = black; 
-     black = tmp; 
-   } 
-   return popcount(white & pos->queens) * PRIME_WHITE_QUEEN + 
-       popcount(white & pos->rooks) * PRIME_WHITE_ROOK + 
-       popcount(white & pos->bishops) * PRIME_WHITE_BISHOP + 
-       popcount(white & pos->knights) * PRIME_WHITE_KNIGHT + 
-       popcount(white & pos->pawns) * PRIME_WHITE_PAWN + 
-       popcount(black & pos->queens) * PRIME_BLACK_QUEEN + 
-       popcount(black & pos->rooks) * PRIME_BLACK_ROOK + 
-       popcount(black & pos->bishops) * PRIME_BLACK_BISHOP + 
-       popcount(black & pos->knights) * PRIME_BLACK_KNIGHT + 
-       popcount(black & pos->pawns) * PRIME_BLACK_PAWN; 
- } 
-   
- static uint64_t calc_key_from_pcs(int *pcs, int mirror) { 
-   mirror = (mirror ? 8 : 0); 
-   return pcs[WHITE_QUEEN ^ mirror] * PRIME_WHITE_QUEEN + 
-       pcs[WHITE_ROOK ^ mirror] * PRIME_WHITE_ROOK + 
-       pcs[WHITE_BISHOP ^ mirror] * PRIME_WHITE_BISHOP + 
-       pcs[WHITE_KNIGHT ^ mirror] * PRIME_WHITE_KNIGHT + 
-       pcs[WHITE_PAWN ^ mirror] * PRIME_WHITE_PAWN + 
-       pcs[BLACK_QUEEN ^ mirror] * PRIME_BLACK_QUEEN + 
-       pcs[BLACK_ROOK ^ mirror] * PRIME_BLACK_ROOK + 
-       pcs[BLACK_BISHOP ^ mirror] * PRIME_BLACK_BISHOP + 
-       pcs[BLACK_KNIGHT ^ mirror] * PRIME_BLACK_KNIGHT + 
-       pcs[BLACK_PAWN ^ mirror] * PRIME_BLACK_PAWN; 
- } 
-   
- static uint64_t get_pieces(const struct pos *pos, uint8_t code) { 
-   switch (code) { 
-     case WHITE_KING: 
-       return pos->kings & pos->white; 
-     case WHITE_QUEEN: 
-       return pos->queens & pos->white; 
-     case WHITE_ROOK: 
-       return pos->rooks & pos->white; 
-     case WHITE_BISHOP: 
-       return pos->bishops & pos->white; 
-     case WHITE_KNIGHT: 
-       return pos->knights & pos->white; 
-     case WHITE_PAWN: 
-       return pos->pawns & pos->white; 
-     case BLACK_KING: 
-       return pos->kings & pos->black; 
-     case BLACK_QUEEN: 
-       return pos->queens & pos->black; 
-     case BLACK_ROOK: 
-       return pos->rooks & pos->black; 
-     case BLACK_BISHOP: 
-       return pos->bishops & pos->black; 
-     case BLACK_KNIGHT: 
-       return pos->knights & pos->black; 
-     case BLACK_PAWN: 
-       return pos->pawns & pos->black; 
-     default: 
-       return 0; // Dummy. 
-   } 
- } 
-   
- static int probe_wdl_table(const struct pos *pos, int *success) { 
-   struct TBEntry *ptr; 
-   struct TBHashEntry *ptr2; 
-   uint64_t idx; 
-   uint64_t key; 
-   int i; 
-   uint8_t res; 
-   int p[TBPIECES]; 
-   
-  // Obtain the position's material signature key. 
-   key = calc_key(pos, false); 
-   
-  // Test for KvK. 
-   if (key == KEY_KvK) 
-     return 0; 
-   
-   ptr2 = TB_hash[key >> (64 - TBHASHBITS)]; 
-   for (i = 0; i < HSHMAX; i++) { 
-     if (ptr2[i].key == key) 
-       break; 
-   } 
-   if (i == HSHMAX) { 
-     *success = 0; 
-     return 0; 
-   } 
-   
-   ptr = ptr2[i].ptr; 
-   if (!ptr->ready) { 
-     LOCK(TB_MUTEX); 
-     if (!ptr->ready) { 
-       char str[16]; 
-       prt_str(pos, str, ptr->key != key); 
-       if (!init_table_wdl(ptr, str)) { 
-         ptr2[i].key = 0ULL; 
-         *success = 0; 
-         UNLOCK(TB_MUTEX); 
-         return 0; 
-       } 
-      // Memory barrier to ensure ptr->ready = 1 is not reordered. 
- #ifdef _MSC_VER 
-       MemoryBarrier (); // Pierre-Marie Baty -- Win32 equivalent 
- #else 
-       __asm__ __volatile__("":::"memory"); 
- #endif // _MSC_VER 
-       ptr->ready = 1; 
-     } 
-     UNLOCK(TB_MUTEX); 
-   } 
-   
-   int bside, mirror, cmirror; 
-   if (!ptr->symmetric) { 
-     if (key != ptr->key) { 
-       cmirror = 8; 
-       mirror = 0x38; 
-       bside = pos->turn; 
-     } else { 
-       cmirror = mirror = 0; 
-       bside = !pos->turn; 
-     } 
-   } else { 
-     cmirror = (pos->turn ? 0 : 8); 
-     mirror = (pos->turn ? 0 : 0x38); 
-     bside = 0; 
-   } 
-   
-  // p[i] is to contain the square 0-63 (A1-H8) for a piece of type 
-  // pc[i] ^ cmirror, where 1 = white pawn, ..., 14 = black king. 
-  // Pieces of the same type are guaranteed to be consecutive. 
-   if (!ptr->has_pawns) { 
-     struct TBEntry_piece *entry = (struct TBEntry_piece *) ptr; 
-     uint8_t *pc = entry->pieces[bside]; 
-     for (i = 0; i < entry->num;) { 
-       uint64_t bb = get_pieces(pos, pc[i] ^ cmirror); 
-       do { 
-         p[i++] = _lsb(bb); 
-         bb = poplsb(bb); 
-       } while (bb); 
-     } 
-     idx = encode_piece(entry, entry->norm[bside], p, entry->factor[bside]); 
-     res = decompress_pairs(entry->precomp[bside], idx); 
-   } else { 
-     struct TBEntry_pawn *entry = (struct TBEntry_pawn *) ptr; 
-     int k = entry->file[0].pieces[0][0] ^ cmirror; 
-     uint64_t bb = get_pieces(pos, k); 
-     i = 0; 
-     do { 
-       p[i++] = _lsb(bb) ^ mirror; 
-       bb = poplsb(bb); 
-     } while (bb); 
-     int f = pawn_file(entry, p); 
-     uint8_t *pc = entry->file[f].pieces[bside]; 
-     for (; i < entry->num;) { 
-       bb = get_pieces(pos, pc[i] ^ cmirror); 
-       do { 
-         p[i++] = _lsb(bb) ^ mirror; 
-         bb = poplsb(bb); 
-       } while (bb); 
-     } 
-     idx = 
-         encode_pawn(entry, entry->file[f].norm[bside], p, 
-         entry->file[f].factor[bside]); 
-     res = decompress_pairs(entry->file[f].precomp[bside], idx); 
-   } 
-   
-   return ((int) res) - 2; 
- } 
-   
- static int probe_dtz_table(const struct pos *pos, int wdl, int *success) { 
-   struct TBEntry *ptr; 
-   uint64_t idx; 
-   int i, res; 
-   int p[TBPIECES]; 
-   
-  // Obtain the position's material signature key. 
-   uint64_t key = calc_key(pos, false); 
-   
-   if (DTZ_table[0].key1 != key && DTZ_table[0].key2 != key) { 
-     for (i = 1; i < DTZ_ENTRIES; i++) { 
-       if (DTZ_table[i].key1 == key || DTZ_table[i].key2 == key) 
-         break; //new 
-      /*if (DTZ_table[i].key1 == key) 
-         break; *///mfb old 
-     } 
-     if (i < DTZ_ENTRIES) { 
-       struct DTZTableEntry table_entry = DTZ_table[i]; 
-       for (; i > 0; i--) 
-         DTZ_table[i] = DTZ_table[i - 1]; 
-       DTZ_table[0] = table_entry; 
-     } else { 
-       struct TBHashEntry *ptr2 = TB_hash[key >> (64 - TBHASHBITS)]; 
-       for (i = 0; i < HSHMAX; i++) { 
-         if (ptr2[i].key == key) 
-           break; 
-       } 
-       if (i == HSHMAX) { 
-         *success = 0; 
-         return 0; 
-       } 
-       ptr = ptr2[i].ptr; 
-       char str[16]; 
-       int mirror = (ptr->key != key); 
-       prt_str(pos, str, mirror); 
-       if (DTZ_table[DTZ_ENTRIES - 1].entry) 
-         free_dtz_entry(DTZ_table[DTZ_ENTRIES - 1].entry); 
-       for (i = DTZ_ENTRIES - 1; i > 0; i--) 
-         DTZ_table[i] = DTZ_table[i - 1]; 
-       uint64_t key1 = calc_key(pos, mirror); 
-       uint64_t key2 = calc_key(pos, !mirror); 
-       load_dtz_table(str, key1, key2); 
-     } 
-   } 
-   
-   ptr = DTZ_table[0].entry; 
-   if (!ptr) { 
-     *success = 0; 
-     return 0; 
-   } 
-   
-   int bside, mirror, cmirror; 
-   if (!ptr->symmetric) { 
-     if (key != ptr->key) { 
-       cmirror = 8; 
-       mirror = 0x38; 
-       bside = pos->turn; 
-     } else { 
-       cmirror = mirror = 0; 
-       bside = !pos->turn; 
-     } 
-   } else { 
-     cmirror = (pos->turn ? 0 : 8); 
-     mirror = (pos->turn ? 0 : 0x38); 
-     bside = 0; 
-   } 
-   
-   if (!ptr->has_pawns) { 
-     struct DTZEntry_piece *entry = (struct DTZEntry_piece *) ptr; 
-     if ((entry->flags & 1) != bside && !entry->symmetric) { 
-       *success = -1; 
-       return 0; 
-     } 
-     uint8_t *pc = entry->pieces; 
-     for (i = 0; i < entry->num;) { 
-       uint64_t bb = get_pieces(pos, pc[i] ^ cmirror); 
-       do { 
-         p[i++] = _lsb(bb); 
-         bb = poplsb(bb); 
-       } 
-       while (bb); 
-     } 
-     idx = 
-         encode_piece((struct TBEntry_piece *) entry, entry->norm, p, 
-         entry->factor); 
-     res = decompress_pairs(entry->precomp, idx); 
-   
-     if (entry->flags & 2) 
-       res = entry->map[entry->map_idx[wdl_to_map[wdl + 2]] + res]; 
-     if (!(entry->flags & pa_flags[wdl + 2]) || (wdl & 1)) 
-       res *= 2; 
-   } else { 
-     struct DTZEntry_pawn *entry = (struct DTZEntry_pawn *) ptr; 
-     int k = entry->file[0].pieces[0] ^ cmirror; 
-     uint64_t bb = get_pieces(pos, k); 
-     i = 0; 
-     do { 
-       p[i++] = _lsb(bb) ^ mirror; 
-       bb = poplsb(bb); 
-     } 
-     while (bb); 
-     int f = pawn_file((struct TBEntry_pawn *) entry, p); 
-     if ((entry->flags[f] & 1) != bside) { 
-       *success = -1; 
-       return 0; 
-     } 
-     uint8_t *pc = entry->file[f].pieces; 
-     for (; i < entry->num;) { 
-       bb = get_pieces(pos, pc[i] ^ cmirror); 
-       do { 
-         p[i++] = _lsb(bb) ^ mirror; 
-         bb = poplsb(bb); 
-       } 
-       while (bb); 
-     } 
-     idx = 
-         encode_pawn((struct TBEntry_pawn *) entry, entry->file[f].norm, p, 
-         entry->file[f].factor); 
-     res = decompress_pairs(entry->file[f].precomp, idx); 
-   
-     if (entry->flags[f] & 2) 
-       res = entry->map[entry->map_idx[f][wdl_to_map[wdl + 2]] + res]; 
-     if (!(entry->flags[f] & pa_flags[wdl + 2]) || (wdl & 1)) 
-       res *= 2; 
-   } 
-   
-   return res; 
- } 
-   
- static uint16_t *add_move(uint16_t * moves, bool promotes, unsigned from, 
-     unsigned to) { 
-   if (!promotes) 
-     *moves++ = make_move(TB_PROMOTES_NONE, from, to); 
-   else { 
-     *moves++ = make_move(TB_PROMOTES_QUEEN, from, to); 
-     *moves++ = make_move(TB_PROMOTES_KNIGHT, from, to); 
-     *moves++ = make_move(TB_PROMOTES_ROOK, from, to); 
-     *moves++ = make_move(TB_PROMOTES_BISHOP, from, to); 
-   } 
-   return moves; 
- } 
-   
- /* 
-  * Generate all captures or promotions. 
-  */ 
- static uint16_t *gen_captures_or_promotions(const struct pos *pos, 
-     uint16_t * moves) { 
-   uint64_t occ = pos->white | pos->black; 
-   uint64_t us = (pos->turn ? pos->white : pos->black), them = 
-       (pos->turn ? pos->black : pos->white); 
-   uint64_t b, att; 
-   { 
-     unsigned from = _lsb(pos->kings & us); 
-     for (att = king_attacks(from) & them; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->queens; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     for (att = queen_attacks(from, occ) & them; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->rooks; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     for (att = rook_attacks(from, occ) & them; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->bishops; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     for (att = bishop_attacks(from, occ) & them; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->knights; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     for (att = knight_attacks(from) & them; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->pawns; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     att = pawn_attacks(from, pos->turn); 
-     if (pos->ep != 0 && ((att & board(pos->ep)) != 0)) { 
-       unsigned to = pos->ep; 
-       moves = add_move(moves, false, from, to); 
-     } 
-     for (att = att & them; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, (rank(to) == 7 || rank(to) == 0), from, to); 
-     } 
-     if (pos->turn && rank(from) == 6) { 
-       unsigned to = from + 8; 
-       if ((board(to) & occ) == 0) 
-         moves = add_move(moves, true, from, to); 
-     } else if (!pos->turn && rank(from) == 1) { 
-       unsigned to = from - 8; 
-       if ((board(to) & occ) == 0) 
-         moves = add_move(moves, true, from, to); 
-     } 
-   } 
-   return moves; 
- } 
-   
- /* 
-  * Generate all non-capture pawn moves and promotions. 
-  */ 
- static uint16_t *gen_pawn_quiets_or_promotions(const struct pos *pos, 
-     uint16_t * moves) { 
-   uint64_t occ = pos->white | pos->black; 
-   uint64_t us = (pos->turn ? pos->white : pos->black); 
-   uint64_t b, att; 
-   
-   for (b = us & pos->pawns; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     unsigned next = from + (pos->turn ? 8 : -8); 
-     att = 0; 
-     if ((board(next) & occ) == 0) { 
-       att |= board(next); 
-       unsigned next2 = from + (pos->turn ? 16 : -16); 
-       if ((pos->turn ? rank(from) == 1 : rank(from) == 6) && 
-           ((board(next2) & occ) == 0)) 
-         att |= board(next2); 
-     } 
-     for (; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, (rank(to) == 7 || rank(to) == 0), from, to); 
-     } 
-   } 
-   return moves; 
- } 
-   
- /* 
-  * Generate all en passant captures. 
-  */ 
- static uint16_t *gen_pawn_ep_captures(const struct pos *pos, uint16_t * moves) { 
-   if (pos->ep == 0) 
-     return moves; 
-   uint64_t ep = board(pos->ep); 
-   unsigned to = pos->ep; 
-   uint64_t us = (pos->turn ? pos->white : pos->black); 
-   uint64_t b; 
-   for (b = us & pos->pawns; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     if ((pawn_attacks(from, pos->turn) & ep) != 0) 
-       moves = add_move(moves, false, from, to); 
-   } 
-   return moves; 
- } 
-   
- /* 
-  * Generate all moves. 
-  */ 
- static uint16_t *gen_moves(const struct pos *pos, uint16_t * moves) { 
-   uint64_t occ = pos->white | pos->black; 
-   uint64_t us = (pos->turn ? pos->white : pos->black), them = 
-       (pos->turn ? pos->black : pos->white); 
-   uint64_t b, att; 
-   
-   { 
-     unsigned from = _lsb(pos->kings & us); 
-     for (att = king_attacks(from) & ~us; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->queens; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     for (att = queen_attacks(from, occ) & ~us; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->rooks; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     for (att = rook_attacks(from, occ) & ~us; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->bishops; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     for (att = bishop_attacks(from, occ) & ~us; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->knights; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     for (att = knight_attacks(from) & ~us; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, false, from, to); 
-     } 
-   } 
-   for (b = us & pos->pawns; b; b = poplsb(b)) { 
-     unsigned from = _lsb(b); 
-     unsigned next = from + (pos->turn ? 8 : -8); 
-     att = pawn_attacks(from, pos->turn); 
-     if (pos->ep != 0 && ((att & board(pos->ep)) != 0)) { 
-       unsigned to = pos->ep; 
-       moves = add_move(moves, false, from, to); 
-     } 
-     att &= them; 
-     if ((board(next) & occ) == 0) { 
-       att |= board(next); 
-       unsigned next2 = from + (pos->turn ? 16 : -16); 
-       if ((pos->turn ? rank(from) == 1 : rank(from) == 6) && 
-           ((board(next2) & occ) == 0)) 
-         att |= board(next2); 
-     } 
-     for (; att; att = poplsb(att)) { 
-       unsigned to = _lsb(att); 
-       moves = add_move(moves, (rank(to) == 7 || rank(to) == 0), from, to); 
-     } 
-   } 
-   return moves; 
- } 
-   
- /* 
-  * Test if the given move is an en passant capture. 
-  */ 
- static bool is_en_passant(const struct pos *pos, uint16_t move) { 
-   uint16_t from = move_from(move); 
-   uint16_t to = move_to(move); 
-   uint64_t us = (pos->turn ? pos->white : pos->black); 
-   if (pos->ep == 0) 
-     return false; 
-   if (to != pos->ep) 
-     return false; 
-   if ((board(from) & us & pos->pawns) != 0) 
-     return false; 
-   return true; 
- } 
-   
- /* 
-  * Test if the given position is legal (can the king be captured?) 
-  */ 
- static bool is_legal(const struct pos *pos) { 
-   uint64_t occ = pos->white | pos->black; 
-   uint64_t us = (pos->turn ? pos->black : pos->white), them = 
-       (pos->turn ? pos->white : pos->black); 
-   uint64_t king = pos->kings & us; 
-   unsigned sq = _lsb(king); 
-   if (king_attacks(sq) & (pos->kings & them)) 
-     return false; 
-   uint64_t ratt = rook_attacks(sq, occ); 
-   uint64_t batt = bishop_attacks(sq, occ); 
-   if (ratt & (pos->rooks & them)) 
-     return false; 
-   if (batt & (pos->bishops & them)) 
-     return false; 
-   if ((ratt | batt) & (pos->queens & them)) 
-     return false; 
-   if (knight_attacks(sq) & (pos->knights & them)) 
-     return false; 
-   if (pawn_attacks(sq, !pos->turn) & (pos->pawns & them)) 
-     return false; 
-   return true; 
- } 
-   
- /* 
-  * Test if the king is in check. 
-  */ 
- static bool is_check(const struct pos *pos) { 
-   uint64_t occ = pos->white | pos->black; 
-   uint64_t us = (pos->turn ? pos->white : pos->black), them = 
-       (pos->turn ? pos->black : pos->white); 
-   uint64_t king = pos->kings & us; 
-   unsigned sq = _lsb(king); 
-   uint64_t ratt = rook_attacks(sq, occ); 
-   uint64_t batt = bishop_attacks(sq, occ); 
-   if (ratt & (pos->rooks & them)) 
-     return true; 
-   if (batt & (pos->bishops & them)) 
-     return true; 
-   if ((ratt | batt) & (pos->queens & them)) 
-     return true; 
-   if (knight_attacks(sq) & (pos->knights & them)) 
-     return true; 
-   if (pawn_attacks(sq, pos->turn) & (pos->pawns & them)) 
-     return true; 
-   return false; 
- } 
-   
- /* 
-  * Test if the king is in checkmate. 
-  */ 
- static bool is_mate(const struct pos *pos) { 
-   if (!is_check(pos)) 
-     return false; 
-   uint16_t moves0[MAX_MOVES]; 
-   uint16_t *moves = moves0; 
-   uint16_t *end = gen_moves(pos, moves); 
-   for (; moves < end; moves++) { 
-     struct pos pos1; 
-     if (do_move(&pos1, pos, *moves)) 
-       return false; 
-   } 
-   return true; 
- } 
-   
- /* 
-  * Test if the position is valid. 
-  */ 
- static bool is_valid(const struct pos *pos) { 
-   if (popcount(pos->kings) != 2) 
-     return false; 
-   if (popcount(pos->kings & pos->white) != 1) 
-     return false; 
-   if (popcount(pos->kings & pos->black) != 1) 
-     return false; 
-   if ((pos->white & pos->black) != 0) 
-     return false; 
-   if ((pos->kings & pos->queens) != 0) 
-     return false; 
-   if ((pos->kings & pos->rooks) != 0) 
-     return false; 
-   if ((pos->kings & pos->bishops) != 0) 
-     return false; 
-   if ((pos->kings & pos->knights) != 0) 
-     return false; 
-   if ((pos->kings & pos->pawns) != 0) 
-     return false; 
-   if ((pos->queens & pos->rooks) != 0) 
-     return false; 
-   if ((pos->queens & pos->bishops) != 0) 
-     return false; 
-   if ((pos->queens & pos->knights) != 0) 
-     return false; 
-   if ((pos->queens & pos->pawns) != 0) 
-     return false; 
-   if ((pos->rooks & pos->bishops) != 0) 
-     return false; 
-   if ((pos->rooks & pos->knights) != 0) 
-     return false; 
-   if ((pos->rooks & pos->pawns) != 0) 
-     return false; 
-   if ((pos->bishops & pos->knights) != 0) 
-     return false; 
-   if ((pos->bishops & pos->pawns) != 0) 
-     return false; 
-   if ((pos->knights & pos->pawns) != 0) 
-     return false; 
-   if ((pos->white | pos->black) != 
-       (pos->kings | pos->queens | pos->rooks | pos-> 
-           bishops | pos->knights | pos->pawns)) 
-     return false; 
-   return is_legal(pos); 
- } 
-   
- #define do_bb_move(b, from, to)                                         \ 
-     (((b) & (~board(to)) & (~board(from))) |                            \ 
-         ((((b) >> (from)) & 0x1) << (to))) 
-   
- static bool do_move(struct pos *pos, const struct pos *pos0, uint16_t move) { 
-   unsigned from = move_from(move); 
-   unsigned to = move_to(move); 
-   unsigned promotes = move_promotes(move); 
-   pos->turn = !pos0->turn; 
-   pos->white = do_bb_move(pos0->white, from, to); 
-   pos->black = do_bb_move(pos0->black, from, to); 
-   pos->kings = do_bb_move(pos0->kings, from, to); 
-   pos->queens = do_bb_move(pos0->queens, from, to); 
-   pos->rooks = do_bb_move(pos0->rooks, from, to); 
-   pos->bishops = do_bb_move(pos0->bishops, from, to); 
-   pos->knights = do_bb_move(pos0->knights, from, to); 
-   pos->pawns = do_bb_move(pos0->pawns, from, to); 
-   pos->ep = 0; 
-   if (promotes != TB_PROMOTES_NONE) { 
-     pos->pawns &= ~board(to); // Promotion 
-     switch (promotes) { 
-       case TB_PROMOTES_QUEEN: 
-         pos->queens |= board(to); 
-         break; 
-       case TB_PROMOTES_ROOK: 
-         pos->rooks |= board(to); 
-         break; 
-       case TB_PROMOTES_BISHOP: 
-         pos->bishops |= board(to); 
-         break; 
-       case TB_PROMOTES_KNIGHT: 
-         pos->knights |= board(to); 
-         break; 
-     } 
-     pos->rule50 = 0; 
-   } else if ((board(from) & pos0->pawns) != 0) { 
-     pos->rule50 = 0; // Pawn move 
-     if (rank(from) == 1 && rank(to) == 3 && 
-         (pawn_attacks(from + 8, true) & pos0->pawns & pos0->black) != 0) 
-       pos->ep = from + 8; 
-     else if (rank(from) == 6 && rank(to) == 4 && 
-         (pawn_attacks(from - 8, false) & pos0->pawns & pos0->white) != 0) 
-       pos->ep = from - 8; 
-     else if (to == pos0->ep) { 
-       unsigned ep_to = (pos0->turn ? to + 8 : to - 8); 
-       uint64_t ep_mask = ~board(ep_to); 
-       pos->white &= ep_mask; 
-       pos->black &= ep_mask; 
-       pos->pawns &= ep_mask; 
-     } 
-   } else if ((board(to) & (pos0->white | pos0->black)) != 0) 
-     pos->rule50 = 0; // Capture 
-   else 
-     pos->rule50 = pos0->rule50 + 1; // Normal move 
-   if (!is_legal(pos)) 
-     return false; 
-   return true; 
- } 
-   
- static int probe_ab(const struct pos *pos, int alpha, int beta, int *success) { 
-   int v; 
-   uint16_t moves0[64]; 
-   uint16_t *moves = moves0; 
-   uint16_t *end = gen_captures_or_promotions(pos, moves); 
-   for (; moves < end; moves++) { 
-     if (is_en_passant(pos, *moves)) 
-       continue; 
-     struct pos pos1; 
-     if (!do_move(&pos1, pos, *moves)) 
-       continue; 
-     v = -probe_ab(&pos1, -beta, -alpha, success); 
-     if (*success == 0) 
-       return 0; 
-     if (v > alpha) { 
-       if (v >= beta) { 
-         *success = 2; 
-         return v; 
-       } 
-       alpha = v; 
-     } 
-   } 
-   
-   v = probe_wdl_table(pos, success); 
-   if (*success == 0) 
-     return 0; 
-   if (alpha >= v) { 
-     *success = 1 + (alpha > 0); 
-     return alpha; 
-   } else { 
-     *success = 1; 
-     return v; 
-   } 
- } 
-   
- static int probe_wdl(const struct pos *pos, int *success) { 
-   *success = 1; 
-   int v = probe_ab(pos, -2, 2, success); 
-   if (*success == 0) 
-     return 0; 
-   
-  // If en passant is not possible, we are done. 
-   if (pos->ep == 0) 
-     return v; 
-   
-  // Now handle en passant. 
-   int v1 = -3; 
-   uint16_t moves0[2];           // Max=2 possible en-passant captures. 
-   uint16_t *moves = moves0; 
-   uint16_t *end = gen_pawn_ep_captures(pos, moves); 
-   for (; moves < end; moves++) { 
-     struct pos pos1; 
-     if (!do_move(&pos1, pos, *moves)) 
-       continue; 
-     int v0 = -probe_ab(pos, -2, 2, success); 
-     if (*success == 0) 
-       return 0; 
-     if (v0 > v1) 
-       v1 = v0; 
-   } 
-   if (v1 > -3) { 
-     if (v1 >= v) 
-       v = v1; 
-     else if (v == 0) { 
-      // Check whether there is at least one legal non-ep move. 
-       uint16_t moves0[MAX_MOVES]; 
-       uint16_t *moves = moves0; 
-       uint16_t *end = gen_moves(pos, moves); 
-       bool found = false; 
-       for (; moves < end; moves++) { 
-         if (is_en_passant(pos, *moves)) 
-           continue; 
-         struct pos pos1; 
-         if (do_move(&pos1, pos, *moves)) { 
-           found = true; 
-           break; 
-         } 
-       } 
-       if (!found) 
-         v = v1; // Forced to play the losing ep capture. 
-     } 
-   } 
-   
-   return v; 
- } 
-   
- static int probe_dtz_no_ep(const struct pos *pos, int *success) { 
-   int wdl, dtz; 
-   wdl = probe_ab(pos, -2, 2, success); 
-   if (wdl == 0) 
-     return 0; 
-   if (*success == 2) 
-     return wdl == 2 ? 1 : 101; 
-   
-   uint16_t moves0[MAX_MOVES]; 
-   uint16_t *moves = moves0, *end = NULL; 
-   
-   if (wdl > 0) { 
-    // Generate at least all legal non-capturing pawn moves 
-    // including non-capturing promotions. 
-     end = gen_pawn_quiets_or_promotions(pos, moves); 
-     for (; moves < end; moves++) { 
-       struct pos pos1; 
-       if (!do_move(&pos1, pos, *moves)) 
-         continue; 
-      //int v = pos.ep_square() == SQ_NONE ? -probe_ab(pos, -2, -wdl + 1, success) 
-      //                                   : -probe_wdl(pos, success); 
-      //int v = -probe_ab(&pos1, -2, -wdl + 1, success);removed mfb 
-       int v = (pos1.ep == 0 ? -probe_ab(&pos1, -2, -wdl + 1, success) : -probe_wdl(&pos1, success)); //added mfb 
-       if (*success == 0) 
-         return 0; 
-       if (v == wdl) 
-         return (v == 2 ? 1 : 101); 
-     } 
-   } 
-   
-   dtz = 1 + probe_dtz_table(pos, wdl, success); 
-   if (*success >= 0) { 
-     if (wdl & 1) 
-       dtz += 100; 
-     return (wdl >= 0 ? dtz : -dtz); 
-   } 
-   
-   if (wdl > 0) { 
-     int best = BEST_NONE; 
-     moves = moves0; 
-     end = gen_moves(pos, moves); 
-     for (; moves < end; moves++) { 
-       struct pos pos1; 
-       if (!do_move(&pos1, pos, *moves)) 
-         continue; 
-       if (pos1.rule50 == 0) 
-         continue; 
-       int v = -probe_dtz(&pos1, success); 
-       if (*success == 0) 
-         return 0; 
-       if (v > 0 && v + 1 < best) 
-         best = v + 1; 
-     } 
-     return best; 
-   } else { 
-     int best = -1; 
-     end = gen_moves(pos, moves); 
-     for (; moves < end; moves++) { 
-       int v; 
-       struct pos pos1; 
-       if (!do_move(&pos1, pos, *moves)) 
-         continue; 
-       if (pos1.rule50 == 0) { 
-         if (wdl == -2) 
-           v = -1; 
-         else { 
-           v = probe_ab(&pos1, 1, 2, success); 
-           v = (v == 2) ? 0 : -101; 
-         } 
-       } else 
-         v = -probe_dtz(&pos1, success) - 1; 
-       if (*success == 0) 
-         return 0; 
-       if (v < best) 
-         best = v; 
-     } 
-     return best; 
-   } 
- } 
-   
- static const int wdl_to_dtz[] = { 
-   -1, -101, 0, 101, 1 
- }; 
-   
- /* 
-  * Probe the DTZ table for a particular position. 
-  * If *success != 0, the probe was successful. 
-  * The return value is from the point of view of the side to move: 
-  *         n < -100 : loss, but draw under 50-move rule 
-  * -100 <= n < -1   : loss in n ply (assuming 50-move counter == 0) 
-  *         0            : draw 
-  *     1 < n <= 100 : win in n ply (assuming 50-move counter == 0) 
-  *   100 < n        : win, but draw under 50-move rule 
-  * 
-  * The return value n can be off by 1: a return value -n can mean a loss 
-  * in n+1 ply and a return value +n can mean a win in n+1 ply. This 
-  * cannot happen for tables with positions exactly on the "edge" of 
-  * the 50-move rule. 
-  * 
-  * This implies that if dtz > 0 is returned, the position is certainly 
-  * a win if dtz + 50-move-counter <= 99. Care must be taken that the engine 
-  * picks moves that preserve dtz + 50-move-counter <= 99. 
-  * 
-  * If n = 100 immediately after a capture or pawn move, then the position 
-  * is also certainly a win, and during the whole phase until the next 
-  * capture or pawn move, the inequality to be preserved is 
-  * dtz + 50-movecounter <= 100. 
-  * 
-  * In short, if a move is available resulting in dtz + 50-move-counter <= 99, 
-  * then do not accept moves leading to dtz + 50-move-counter == 100. 
-  */ 
- static int probe_dtz(const struct pos *pos, int *success) { 
-   *success = 1; 
-   int v = probe_dtz_no_ep(pos, success); 
-   if (*success == 0) 
-     return 0; 
-   
-   if (pos->ep == 0) 
-     return v; 
-   
-   int v1 = -3; 
-   uint16_t moves0[2];           // Max=2 possible en-passant captures. 
-   uint16_t *moves = moves0; 
-   uint16_t *end = gen_pawn_ep_captures(pos, moves); 
-   for (; moves < end; moves++) { 
-     struct pos pos1; 
-     if (!do_move(&pos1, pos, *moves)) 
-       continue; 
-     int v0 = -probe_ab(pos, -2, 2, success); 
-     if (*success == 0) 
-       return 0; 
-     if (v0 > v1) 
-       v1 = v0; 
-   } 
-   
-   if (v1 > -3) { 
-     v1 = wdl_to_dtz[v1 + 2]; 
-     if (v < -100) { 
-       if (v1 >= 0) 
-         v = v1; 
-     } else if (v < 0) { 
-       if (v1 >= 0 || v1 < -100) 
-         v = v1; 
-     } else if (v > 100) { 
-       if (v1 > 0) 
-         v = v1; 
-     } else if (v > 0) { 
-       if (v1 == 1) 
-         v = v1; 
-     } else if (v1 >= 0) 
-       v = v1; 
-     else { 
-       uint16_t moves0[MAX_MOVES]; 
-       uint16_t *moves = moves0; 
-       uint16_t *end = gen_moves(pos, moves); 
-       bool found = false; 
-       for (; moves < end; moves++) { 
-         if (is_en_passant(pos, *moves)) 
-           continue; 
-         struct pos pos1; 
-         if (do_move(&pos1, pos, *moves)) { 
-           found = true; 
-           break; 
-         } 
-       } 
-       if (!found) 
-         v = v1; // Forced to play the losing ep capture. 
-     } 
-   } 
-   
-   return v; 
- } 
-   
- unsigned dtz_to_wdl(int cnt50, int dtz) { 
-   int wdl = 0; 
-   if (dtz > 0) 
-     wdl = (dtz + cnt50 <= 100 ? 2 : 1); 
-   else if (dtz < 0) 
-     wdl = (-dtz + cnt50 <= 100 ? -2 : -1); 
-   return wdl + 2; 
- } 
-   
- static uint16_t probe_root(const struct pos *pos, int *score, 
-     unsigned *results) { 
-   int success; 
-   int dtz = probe_dtz(pos, &success); 
-   if (!success) 
-     return 0; 
-   
-   int16_t scores[MAX_MOVES]; 
-   uint16_t moves0[MAX_MOVES]; 
-   uint16_t *moves = moves0; 
-   uint16_t *end = gen_moves(pos, moves); 
-   size_t len = end - moves; 
-   size_t num_draw = 0; 
-   unsigned j = 0; 
-   unsigned i = 0;               //mfb 
-   for (i = 0; i < len; i++) { 
-     struct pos pos1; 
-     if (!do_move(&pos1, pos, moves[i])) { 
-       scores[i] = SCORE_ILLEGAL; 
-       continue; 
-     } 
-     int v = 0; 
-     if (dtz > 0 && is_mate(&pos1)) 
-       v = 1; 
-     else { 
-       if (pos1.rule50 != 0) { 
-         v = -probe_dtz(&pos1, &success); 
-         if (v > 0) 
-           v++; 
-         else if (v < 0) 
-           v--; 
-       } else { 
-         v = -probe_wdl(&pos1, &success); 
-         v = wdl_to_dtz[v + 2]; 
-       } 
-     } 
-     num_draw += (v == 0); 
-     if (!success) 
-       return 0; 
-     scores[i] = v; 
-     if (results != NULL) { 
-       unsigned res = 0; 
-       res = TB_SET_WDL(res, dtz_to_wdl(pos->rule50, v)); 
-       res = TB_SET_FROM(res, move_from(moves[i])); 
-       res = TB_SET_TO(res, move_to(moves[i])); 
-       res = TB_SET_PROMOTES(res, move_promotes(moves[i])); 
-       res = TB_SET_EP(res, is_en_passant(pos, moves[i])); 
-       res = TB_SET_DTZ(res, (dtz < 0 ? -dtz : dtz)); 
-       results[j++] = res; 
-     } 
-   } 
-   if (results != NULL) 
-     results[j++] = TB_RESULT_FAILED; 
-   if (score != NULL) 
-     *score = dtz; 
-   
-  // Now be a bit smart about filtering out moves. 
-   if (dtz > 0) // winning (or 50-move rule draw) 
-   { 
-     int best = BEST_NONE; 
-     uint16_t best_move = 0; 
-     for (i = 0; i < len; i++) { 
-       int v = scores[i]; 
-       if (v == SCORE_ILLEGAL) 
-         continue; 
-       if (v > 0 && v < best) { 
-         best = v; 
-         best_move = moves[i]; 
-       } 
-     } 
-     return (best == BEST_NONE ? 0 : best_move); 
-   } else if (dtz < 0) // losing (or 50-move rule draw) 
-   { 
-     int best = 0; 
-     uint16_t best_move = 0; 
-     for (i = 0; i < len; i++) { 
-       int v = scores[i]; 
-       if (v == SCORE_ILLEGAL) 
-         continue; 
-       if (v < best) { 
-         best = v; 
-         best_move = moves[i]; 
-       } 
-     } 
-     return (best == 0 ? MOVE_CHECKMATE : best_move); 
-   } else // drawing 
-   { 
-    // Check for stalemate: 
-     if (num_draw == 0) 
-       return MOVE_STALEMATE; 
-   
-    // Select a "random" move that preserves the draw. 
-    // Uses calc_key as the PRNG. 
-     size_t count = calc_key(pos, !pos->turn) % num_draw; 
-     for (i = 0; i < len; i++) { 
-       int v = scores[i]; 
-       if (v == SCORE_ILLEGAL) 
-         continue; 
-       if (v == 0) { 
-         if (count == 0) 
-           return moves[i]; 
-         count--; 
-       } 
-     } 
-     return 0; 
-   } 
- } 
-   
- extern bool tb_init_impl(const char *path) { 
-   if (sizeof(uint64_t) != 8 && // Paranoid check 
-       sizeof(uint32_t) != 4 && sizeof(uint16_t) != 2 && sizeof(uint8_t) != 1) 
-     return false; 
-   king_attacks_init(); 
-   knight_attacks_init(); 
-   bishop_attacks_init(); 
-   rook_attacks_init(); 
-   pawn_attacks_init(); 
-   if (path == NULL) 
-     path = ""; 
-   init_tablebases(path); 
-   return true; 
- } 
-   
- extern unsigned tb_probe_wdl_impl(uint64_t white, uint64_t black, 
-     uint64_t kings, uint64_t queens, uint64_t rooks, uint64_t bishops, 
-     uint64_t knights, uint64_t pawns, unsigned ep, bool turn, uint64_t hash) { 
-   struct pos pos = { 
-     white, 
-     black, 
-     kings, 
-     queens, 
-     rooks, 
-     bishops, 
-     knights, 
-     pawns, 
-     0, 
-     ep, 
-     turn 
-   }; 
-   static uint64_t cache[4096] = { 0 }; 
-   uint64_t idx = hash % 1024; 
-   if ((cache[idx] & ~0x7) == (hash & ~0x7)) { 
-    // Hit 
- //        FILE *F = fopen("debug.txt", "a"); 
- //        fprintf(F, "CACHE_HIT = %.16lX (result=%u)\n", cache[idx], 
- //            (unsigned)(cache[idx] & 0x7)); 
- //        fclose(F); 
-     return (cache[idx] & 0x7); 
-   } 
-  // Miss 
-   int success; 
-   int v = probe_wdl(&pos, &success); 
-   if (success == 0) 
-     return TB_RESULT_FAILED; 
-   unsigned result = (unsigned) (v + 2); 
-   hash &= ~0x7; 
-   hash |= (uint64_t) result; 
-   cache[idx] = hash; 
-   return result; 
- } 
-   
- extern unsigned tb_probe_root_impl(uint64_t white, uint64_t black, 
-     uint64_t kings, uint64_t queens, uint64_t rooks, uint64_t bishops, 
-     uint64_t knights, uint64_t pawns, unsigned rule50, unsigned ep, bool turn, 
-     unsigned *results) { 
-   struct pos pos = { 
-     white, 
-     black, 
-     kings, 
-     queens, 
-     rooks, 
-     bishops, 
-     knights, 
-     pawns, 
-     rule50, 
-     ep, 
-     turn 
-   }; 
-   int dtz; 
-   if (!is_valid(&pos)) 
-     return TB_RESULT_FAILED; 
-   uint16_t move = probe_root(&pos, &dtz, results); 
-   if (move == 0) 
-     return TB_RESULT_FAILED; 
-   if (move == MOVE_CHECKMATE) 
-     return TB_RESULT_CHECKMATE; 
-   if (move == MOVE_STALEMATE) 
-     return TB_RESULT_STALEMATE; 
-   unsigned res = 0; 
-   res = TB_SET_WDL(res, dtz_to_wdl(rule50, dtz)); 
-   res = TB_SET_FROM(res, move_from(move)); 
-   res = TB_SET_TO(res, move_to(move)); 
-   res = TB_SET_PROMOTES(res, move_promotes(move)); 
-   res = TB_SET_EP(res, is_en_passant(&pos, move)); 
-   return res; 
- } 
-   
- #ifndef TB_NO_HELPER_API 
-   
- unsigned tb_pop_count(uint64_t bb) { 
-   return popcount(bb); 
- } 
-   
- unsigned tb_lsb(uint64_t bb) { 
-   return _lsb(bb); 
- } 
-   
- uint64_t tb_pop_lsb(uint64_t bb) { 
-   return poplsb(bb); 
- } 
-   
- uint64_t tb_king_attacks(unsigned sq) { 
-   return king_attacks(sq); 
- } 
-   
- uint64_t tb_queen_attacks(unsigned sq, uint64_t occ) { 
-   return queen_attacks(sq, occ); 
- } 
-   
- uint64_t tb_rook_attacks(unsigned sq, uint64_t occ) { 
-   return rook_attacks(sq, occ); 
- } 
-   
- uint64_t tb_bishop_attacks(unsigned sq, uint64_t occ) { 
-   return bishop_attacks(sq, occ); 
- } 
-   
- uint64_t tb_knight_attacks(unsigned sq) { 
-   return knight_attacks(sq); 
- } 
-   
- uint64_t tb_pawn_attacks(unsigned sq, bool color) { 
-   return pawn_attacks(sq, color); 
- } 
-   
- #endif                          /* TB_NO_HELPER_API */ 
-