Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * tbprobe.c
  3.  * Copyright (c) 2013-2015 Ronald de Man
  4.  * This file may be redistributed and/or modified without restrictions.
  5.  *
  6.  * (C) 2015 basil, all rights reserved,
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included in
  15.  * all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23.  * DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. #include <assert.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29.  
  30. #include "tbprobe.h"
  31.  
  32. //#include <x86intrin.h>
  33.  
  34. #define WHITE_KING              (TB_WPAWN + 5)
  35. #define WHITE_QUEEN             (TB_WPAWN + 4)
  36. #define WHITE_ROOK              (TB_WPAWN + 3)
  37. #define WHITE_BISHOP            (TB_WPAWN + 2)
  38. #define WHITE_KNIGHT            (TB_WPAWN + 1)
  39. #define WHITE_PAWN              TB_WPAWN
  40. #define BLACK_KING              (TB_BPAWN + 5)
  41. #define BLACK_QUEEN             (TB_BPAWN + 4)
  42. #define BLACK_ROOK              (TB_BPAWN + 3)
  43. #define BLACK_BISHOP            (TB_BPAWN + 2)
  44. #define BLACK_KNIGHT            (TB_BPAWN + 1)
  45. #define BLACK_PAWN              TB_BPAWN
  46.  
  47. #define PRIME_WHITE_QUEEN       11811845319353239651ull
  48. #define PRIME_WHITE_ROOK        10979190538029446137ull
  49. #define PRIME_WHITE_BISHOP      12311744257139811149ull
  50. #define PRIME_WHITE_KNIGHT      15202887380319082783ull
  51. #define PRIME_WHITE_PAWN        17008651141875982339ull
  52. #define PRIME_BLACK_QUEEN       15484752644942473553ull
  53. #define PRIME_BLACK_ROOK        18264461213049635989ull
  54. #define PRIME_BLACK_BISHOP      15394650811035483107ull
  55. #define PRIME_BLACK_KNIGHT      13469005675588064321ull
  56. #define PRIME_BLACK_PAWN        11695583624105689831ull
  57.  
  58. #define BOARD_RANK_EDGE         0x8181818181818181ull
  59. #define BOARD_FILE_EDGE         0xFF000000000000FFull
  60. #define BOARD_EDGE              (BOARD_RANK_EDGE | BOARD_FILE_EDGE)
  61. #define BOARD_RANK_1            0x00000000000000FFull
  62. #define BOARD_FILE_A            0x8080808080808080ull
  63.  
  64. #define KEY_KvK                 0
  65.  
  66. #define BEST_NONE               0xFFFF
  67. #define SCORE_ILLEGAL           0x7FFF
  68.  
  69. #define popcount(v) PopCnt(v)
  70.  
  71. #define poplsb(x)               ((x) & ((x) - 1))
  72.  
  73. #define make_move(promote, from, to)                                    \
  74.     ((((promote) & 0x7) << 12) | (((from) & 0x3F) << 6) | ((to) & 0x3F))
  75. #define move_from(move)                                                 \
  76.     (((move) >> 6) & 0x3F)
  77. #define move_to(move)                                                   \
  78.     ((move) & 0x3F)
  79. #define move_promotes(move)                                             \
  80.     (((move) >> 12) & 0x7)
  81.  
  82. #define MAX_MOVES               TB_MAX_MOVES
  83. #define MOVE_STALEMATE          0xFFFF
  84. #define MOVE_CHECKMATE          0xFFFE
  85.  
  86. struct pos {
  87.   uint64_t white;
  88.   uint64_t black;
  89.   uint64_t kings;
  90.   uint64_t queens;
  91.   uint64_t rooks;
  92.   uint64_t bishops;
  93.   uint64_t knights;
  94.   uint64_t pawns;
  95.   uint8_t rule50;
  96.   uint8_t ep;
  97.   bool turn;
  98. };
  99.  
  100. static bool do_move(struct pos *pos, const struct pos *pos0, uint16_t move);
  101. static int probe_dtz(const struct pos *pos, int *success);
  102.  
  103. unsigned TB_LARGEST = 0;
  104. #include "tbcore.c"
  105.  
  106. #define rank(s)                 ((s) >> 3)
  107. #define file(s)                 ((s) & 0x07)
  108. #define board(s)                ((uint64_t)1 << (s))
  109. static inline unsigned _lsb(uint64_t b) {
  110. #ifdef _WIN32 // Pierre-Marie Baty -- Win32 addition
  111.   static const int index64[64] = {
  112.      0, 47,  1, 56, 48, 27,  2, 60,
  113.      57, 49, 41, 37, 28, 16,  3, 61,
  114.      54, 58, 35, 52, 50, 42, 21, 44,
  115.      38, 32, 29, 23, 17, 11,  4, 62,
  116.      46, 55, 26, 59, 40, 36, 15, 53,
  117.      34, 51, 20, 43, 31, 22, 10, 45,
  118.      25, 39, 14, 33, 19, 30,  9, 24,
  119.      13, 18,  8, 12,  7,  6,  5, 63
  120.   };
  121.   /**
  122.   * bitScanForward
  123.   * @author Kim Walisch (2012)
  124.   * @param bb bitboard to scan
  125.   * @precondition bb != 0
  126.   * @return index (0..63) of least significant one bit
  127.   */
  128.    const uint64_t debruijn64 = 0x03f79d71b4cb0a89ULL;
  129.    assert (b != 0);
  130.    return index64[((b ^ (b - 1)) * debruijn64) >> 58];
  131. #else
  132.   size_t idx;
  133. __asm__("bsfq %1, %0": "=r"(idx):"rm"(b));
  134.   return idx;
  135. #endif
  136. }
  137.  
  138. #define square(r, f)            (8 * (r) + (f))
  139.  
  140. #ifdef TB_KING_ATTACKS
  141. #  define king_attacks(s)         TB_KING_ATTACKS(s)
  142. #  define king_attacks_init()
  143.                             /* NOP */
  144. #else                           /* TB_KING_ATTACKS */
  145.  
  146. static uint64_t king_attacks_table[64];
  147.  
  148. #  define king_attacks(s)         king_attacks_table[(s)]
  149.  
  150. static void king_attacks_init(void) {
  151.   for (unsigned s = 0; s < 64; s++) {
  152.     unsigned r = rank(s);
  153.     unsigned f = file(s);
  154.     uint64_t b = 0;
  155.     if (r != 0 && f != 0)
  156.       b |= board(square(r - 1, f - 1));
  157.     if (r != 0)
  158.       b |= board(square(r - 1, f));
  159.     if (r != 0 && f != 7)
  160.       b |= board(square(r - 1, f + 1));
  161.     if (f != 7)
  162.       b |= board(square(r, f + 1));
  163.     if (r != 7 && f != 7)
  164.       b |= board(square(r + 1, f + 1));
  165.     if (r != 7)
  166.       b |= board(square(r + 1, f));
  167.     if (r != 7 && f != 0)
  168.       b |= board(square(r + 1, f - 1));
  169.     if (f != 0)
  170.       b |= board(square(r, f - 1));
  171.     king_attacks_table[s] = b;
  172.   }
  173. }
  174.  
  175. #endif                          /* TB_KING_ATTACKS */
  176.  
  177. #ifdef TB_KNIGHT_ATTACKS
  178. #  define knight_attacks(s)       TB_KNIGHT_ATTACKS(s)
  179. #  define knight_attacks_init()
  180.                               /* NOP */
  181. #else                           /* TB_KNIGHT_ATTACKS */
  182.  
  183. static uint64_t knight_attacks_table[64];
  184.  
  185. #  define knight_attacks(s)       knight_attacks_table[(s)]
  186.  
  187. static void knight_attacks_init(void) {
  188.   for (unsigned s = 0; s < 64; s++) {
  189.     int r1, r = rank(s);
  190.     int f1, f = file(s);
  191.     uint64_t b = 0;
  192.     r1 = r - 1;
  193.     f1 = f - 2;
  194.     if (r1 >= 0 && f1 >= 0)
  195.       b |= board(square(r1, f1));
  196.     r1 = r - 1;
  197.     f1 = f + 2;
  198.     if (r1 >= 0 && f1 <= 7)
  199.       b |= board(square(r1, f1));
  200.     r1 = r - 2;
  201.     f1 = f - 1;
  202.     if (r1 >= 0 && f1 >= 0)
  203.       b |= board(square(r1, f1));
  204.     r1 = r - 2;
  205.     f1 = f + 1;
  206.     if (r1 >= 0 && f1 <= 7)
  207.       b |= board(square(r1, f1));
  208.     r1 = r + 1;
  209.     f1 = f - 2;
  210.     if (r1 <= 7 && f1 >= 0)
  211.       b |= board(square(r1, f1));
  212.     r1 = r + 1;
  213.     f1 = f + 2;
  214.     if (r1 <= 7 && f1 <= 7)
  215.       b |= board(square(r1, f1));
  216.     r1 = r + 2;
  217.     f1 = f - 1;
  218.     if (r1 <= 7 && f1 >= 0)
  219.       b |= board(square(r1, f1));
  220.     r1 = r + 2;
  221.     f1 = f + 1;
  222.     if (r1 <= 7 && f1 <= 7)
  223.       b |= board(square(r1, f1));
  224.     knight_attacks_table[s] = b;
  225.   }
  226. }
  227.  
  228. #endif                          /* TB_KNIGHT_ATTACKS */
  229.  
  230. #ifdef TB_BISHOP_ATTACKS
  231. #  define bishop_attacks(s, occ)  TB_BISHOP_ATTACKS(s, occ)
  232. #  define bishop_attacks_init()
  233.                               /* NOP */
  234. #else                           /* TB_BISHOP_ATTACKS */
  235.  
  236. static uint64_t diag_attacks_table[64][64];
  237. static uint64_t anti_attacks_table[64][64];
  238.  
  239. static const unsigned square2diag_table[64] = {
  240.   0, 1, 2, 3, 4, 5, 6, 7,
  241.   14, 0, 1, 2, 3, 4, 5, 6,
  242.   13, 14, 0, 1, 2, 3, 4, 5,
  243.   12, 13, 14, 0, 1, 2, 3, 4,
  244.   11, 12, 13, 14, 0, 1, 2, 3,
  245.   10, 11, 12, 13, 14, 0, 1, 2,
  246.   9, 10, 11, 12, 13, 14, 0, 1,
  247.   8, 9, 10, 11, 12, 13, 14, 0
  248. };
  249.  
  250. static const unsigned square2anti_table[64] = {
  251.   8, 9, 10, 11, 12, 13, 14, 0,
  252.   9, 10, 11, 12, 13, 14, 0, 1,
  253.   10, 11, 12, 13, 14, 0, 1, 2,
  254.   11, 12, 13, 14, 0, 1, 2, 3,
  255.   12, 13, 14, 0, 1, 2, 3, 4,
  256.   13, 14, 0, 1, 2, 3, 4, 5,
  257.   14, 0, 1, 2, 3, 4, 5, 6,
  258.   0, 1, 2, 3, 4, 5, 6, 7
  259. };
  260.  
  261. static const uint64_t diag2board_table[15] = {
  262.   0x8040201008040201ull,
  263.   0x0080402010080402ull,
  264.   0x0000804020100804ull,
  265.   0x0000008040201008ull,
  266.   0x0000000080402010ull,
  267.   0x0000000000804020ull,
  268.   0x0000000000008040ull,
  269.   0x0000000000000080ull,
  270.   0x0100000000000000ull,
  271.   0x0201000000000000ull,
  272.   0x0402010000000000ull,
  273.   0x0804020100000000ull,
  274.   0x1008040201000000ull,
  275.   0x2010080402010000ull,
  276.   0x4020100804020100ull,
  277. };
  278.  
  279. static const uint64_t anti2board_table[15] = {
  280.   0x0102040810204080ull,
  281.   0x0204081020408000ull,
  282.   0x0408102040800000ull,
  283.   0x0810204080000000ull,
  284.   0x1020408000000000ull,
  285.   0x2040800000000000ull,
  286.   0x4080000000000000ull,
  287.   0x8000000000000000ull,
  288.   0x0000000000000001ull,
  289.   0x0000000000000102ull,
  290.   0x0000000000010204ull,
  291.   0x0000000001020408ull,
  292.   0x0000000102040810ull,
  293.   0x0000010204081020ull,
  294.   0x0001020408102040ull,
  295. };
  296.  
  297. static inline size_t diag2index(uint64_t b, unsigned d) {
  298.   b *= 0x0101010101010101ull;
  299.   b >>= 56;
  300.   b >>= 1;
  301.   return (size_t) b;
  302. }
  303.  
  304. static inline size_t anti2index(uint64_t b, unsigned a) {
  305.   return diag2index(b, a);
  306. }
  307.  
  308. #  define diag(s)                 square2diag_table[(s)]
  309. #  define anti(s)                 square2anti_table[(s)]
  310. #  define diag2board(d)           diag2board_table[(d)]
  311. #  define anti2board(a)           anti2board_table[(a)]
  312.  
  313. static uint64_t bishop_attacks(unsigned sq, uint64_t occ) {
  314.   occ &= ~board(sq);
  315.   unsigned d = diag(sq), a = anti(sq);
  316.   uint64_t d_occ = occ & (diag2board(d) & ~BOARD_EDGE);
  317.   uint64_t a_occ = occ & (anti2board(a) & ~BOARD_EDGE);
  318.   size_t d_idx = diag2index(d_occ, d);
  319.   size_t a_idx = anti2index(a_occ, a);
  320.   uint64_t d_attacks = diag_attacks_table[sq][d_idx];
  321.   uint64_t a_attacks = anti_attacks_table[sq][a_idx];
  322.   return d_attacks | a_attacks;
  323. }
  324.  
  325. static void bishop_attacks_init(void) {
  326.   for (unsigned idx = 0; idx < 64; idx++) {
  327.     unsigned idx1 = idx << 1;
  328.     for (unsigned s = 0; s < 64; s++) {
  329.       int r = rank(s);
  330.       int f = file(s);
  331.       uint64_t b = 0;
  332.       for (int i = -1; f + i >= 0 && r + i >= 0; i--) {
  333.         unsigned occ = (1 << (f + i));
  334.         b |= board(square(r + i, f + i));
  335.         if (idx1 & occ)
  336.           break;
  337.       }
  338.       for (int i = 1; f + i <= 7 && r + i <= 7; i++) {
  339.         unsigned occ = (1 << (f + i));
  340.         b |= board(square(r + i, f + i));
  341.         if (idx1 & occ)
  342.           break;
  343.       }
  344.       diag_attacks_table[s][idx] = b;
  345.     }
  346.   }
  347.  
  348.   for (unsigned idx = 0; idx < 64; idx++) {
  349.     unsigned idx1 = idx << 1;
  350.     for (unsigned s = 0; s < 64; s++) {
  351.       int r = rank(s);
  352.       int f = file(s);
  353.       uint64_t b = 0;
  354.       for (int i = -1; f + i >= 0 && r - i <= 7; i--) {
  355.         unsigned occ = (1 << (f + i));
  356.         b |= board(square(r - i, f + i));
  357.         if (idx1 & occ)
  358.           break;
  359.       }
  360.       for (int i = 1; f + i <= 7 && r - i >= 0; i++) {
  361.         unsigned occ = (1 << (f + i));
  362.         b |= board(square(r - i, f + i));
  363.         if (idx1 & occ)
  364.           break;
  365.       }
  366.       anti_attacks_table[s][idx] = b;
  367.     }
  368.   }
  369. }
  370.  
  371. #endif                          /* TB_BISHOP_ATTACKS */
  372.  
  373. #ifdef TB_ROOK_ATTACKS
  374. #  define rook_attacks(s, occ)    TB_ROOK_ATTACKS(s, occ)
  375. #  define rook_attacks_init()
  376.                             /* NOP */
  377. #else                           /* TB_ROOK_ATTACKS */
  378.  
  379. static uint64_t rank_attacks_table[64][64];
  380. static uint64_t file_attacks_table[64][64];
  381.  
  382. static inline size_t rank2index(uint64_t b, unsigned r) {
  383.   b >>= (8 * r);
  384.   b >>= 1;
  385.   return (size_t) b;
  386. }
  387.  
  388. static inline size_t file2index(uint64_t b, unsigned f) {
  389.   b >>= f;
  390.   b *= 0x0102040810204080ull;
  391.   b >>= 56;
  392.   b >>= 1;
  393.   return (size_t) b;
  394. }
  395.  
  396. #  define rank2board(r)           (0xFFull << (8 * (r)))
  397. #  define file2board(f)           (0x0101010101010101ull << (f))
  398.  
  399. static uint64_t rook_attacks(unsigned sq, uint64_t occ) {
  400.   occ &= ~board(sq);
  401.   unsigned r = rank(sq), f = file(sq);
  402.   uint64_t r_occ = occ & (rank2board(r) & ~BOARD_RANK_EDGE);
  403.   uint64_t f_occ = occ & (file2board(f) & ~BOARD_FILE_EDGE);
  404.   size_t r_idx = rank2index(r_occ, r);
  405.   size_t f_idx = file2index(f_occ, f);
  406.   uint64_t r_attacks = rank_attacks_table[sq][r_idx];
  407.   uint64_t f_attacks = file_attacks_table[sq][f_idx];
  408.   return r_attacks | f_attacks;
  409. }
  410.  
  411. static void rook_attacks_init(void) {
  412.   for (unsigned idx = 0; idx < 64; idx++) {
  413.     unsigned idx1 = idx << 1, occ;
  414.     for (int f = 0; f <= 7; f++) {
  415.       uint64_t b = 0;
  416.       if (f > 0) {
  417.         int i = f - 1;
  418.         do {
  419.           occ = (1 << i);
  420.           b |= board(square(0, i));
  421.           i--;
  422.         }
  423.         while (!(idx1 & occ) && i >= 0);
  424.       }
  425.       if (f < 7) {
  426.         int i = f + 1;
  427.         do {
  428.           occ = (1 << i);
  429.           b |= board(square(0, i));
  430.           i++;
  431.         }
  432.         while (!(idx1 & occ) && i <= 7);
  433.       }
  434.       for (int r = 0; r <= 7; r++) {
  435.         rank_attacks_table[square(r, f)][idx] = b;
  436.         b <<= 8;
  437.       }
  438.     }
  439.   }
  440.   for (unsigned idx = 0; idx < 64; idx++) {
  441.     unsigned idx1 = idx << 1, occ;
  442.     for (int r = 0; r <= 7; r++) {
  443.       uint64_t b = 0;
  444.       if (r > 0) {
  445.         int i = r - 1;
  446.         do {
  447.           occ = (1 << i);
  448.           b |= board(square(i, 0));
  449.           i--;
  450.         }
  451.         while (!(idx1 & occ) && i >= 0);
  452.       }
  453.       if (r < 7) {
  454.         int i = r + 1;
  455.         do {
  456.           occ = (1 << i);
  457.           b |= board(square(i, 0));
  458.           i++;
  459.         }
  460.         while (!(idx1 & occ) && i <= 7);
  461.       }
  462.       for (int f = 0; f <= 7; f++) {
  463.         file_attacks_table[square(r, f)][idx] = b;
  464.         b <<= 1;
  465.       }
  466.     }
  467.   }
  468. }
  469.  
  470. #endif                          /* TB_ROOK_ATTACKS */
  471.  
  472. #ifdef TB_QUEEN_ATTACKS
  473. #  define queen_attacks(s, occ)   TB_QUEEN_ATTACKS(s, occ)
  474. #else                           /* TB_QUEEN_ATTACKS */
  475. #  define queen_attacks(s, occ)   \
  476.     (rook_attacks((s), (occ)) | bishop_attacks((s), (occ)))
  477. #endif                          /* TB_QUEEN_ATTACKS */
  478.  
  479. #ifdef TB_PAWN_ATTACKS
  480. #  define pawn_attacks(s, c)      TB_PAWN_ATTACKS(s, c)
  481. #  define pawn_attacks_init()
  482.                             /* NOP */
  483. #else                           /* TB_PAWN_ATTACKS */
  484.  
  485. static uint64_t pawn_attacks_table[2][64];
  486.  
  487. #  define pawn_attacks(s, c)      pawn_attacks_table[(c)][(s)]
  488.  
  489. static void pawn_attacks_init(void) {
  490.   for (unsigned s = 0; s < 64; s++) {
  491.     int r = rank(s);
  492.     int f = file(s);
  493.  
  494.     uint64_t b = 0;
  495.     if (r != 7) {
  496.       if (f != 0)
  497.         b |= board(square(r + 1, f - 1));
  498.       if (f != 7)
  499.         b |= board(square(r + 1, f + 1));
  500.     }
  501.     pawn_attacks_table[1][s] = b;
  502.  
  503.     b = 0;
  504.     if (r != 0) {
  505.       if (f != 0)
  506.         b |= board(square(r - 1, f - 1));
  507.       if (f != 7)
  508.         b |= board(square(r - 1, f + 1));
  509.     }
  510.     pawn_attacks_table[0][s] = b;
  511.   }
  512. }
  513.  
  514. #endif                          /* TB_PAWN_ATTACKS */
  515.  
  516. static void prt_str(const struct pos *pos, char *str, bool mirror) {
  517.   uint64_t white = pos->white, black = pos->black;
  518.   int i;
  519.   if (mirror) {
  520.     uint64_t tmp = white;
  521.     white = black;
  522.     black = tmp;
  523.   }
  524.   *str++ = 'K';
  525.   for (i = popcount(white & pos->queens); i > 0; i--)
  526.     *str++ = 'Q';
  527.   for (i = popcount(white & pos->rooks); i > 0; i--)
  528.     *str++ = 'R';
  529.   for (i = popcount(white & pos->bishops); i > 0; i--)
  530.     *str++ = 'B';
  531.   for (i = popcount(white & pos->knights); i > 0; i--)
  532.     *str++ = 'N';
  533.   for (i = popcount(white & pos->pawns); i > 0; i--)
  534.     *str++ = 'P';
  535.   *str++ = 'v';
  536.   *str++ = 'K';
  537.   for (i = popcount(black & pos->queens); i > 0; i--)
  538.     *str++ = 'Q';
  539.   for (i = popcount(black & pos->rooks); i > 0; i--)
  540.     *str++ = 'R';
  541.   for (i = popcount(black & pos->bishops); i > 0; i--)
  542.     *str++ = 'B';
  543.   for (i = popcount(black & pos->knights); i > 0; i--)
  544.     *str++ = 'N';
  545.   for (i = popcount(black & pos->pawns); i > 0; i--)
  546.     *str++ = 'P';
  547.   *str++ = '\0';
  548. }
  549.  
  550. /*
  551.  * Given a position, produce a 64-bit material signature key.
  552.  */
  553. static uint64_t calc_key(const struct pos *pos, bool mirror) {
  554.   uint64_t white = pos->white, black = pos->black;
  555.   if (mirror) {
  556.     uint64_t tmp = white;
  557.     white = black;
  558.     black = tmp;
  559.   }
  560.   return popcount(white & pos->queens) * PRIME_WHITE_QUEEN +
  561.       popcount(white & pos->rooks) * PRIME_WHITE_ROOK +
  562.       popcount(white & pos->bishops) * PRIME_WHITE_BISHOP +
  563.       popcount(white & pos->knights) * PRIME_WHITE_KNIGHT +
  564.       popcount(white & pos->pawns) * PRIME_WHITE_PAWN +
  565.       popcount(black & pos->queens) * PRIME_BLACK_QUEEN +
  566.       popcount(black & pos->rooks) * PRIME_BLACK_ROOK +
  567.       popcount(black & pos->bishops) * PRIME_BLACK_BISHOP +
  568.       popcount(black & pos->knights) * PRIME_BLACK_KNIGHT +
  569.       popcount(black & pos->pawns) * PRIME_BLACK_PAWN;
  570. }
  571.  
  572. static uint64_t calc_key_from_pcs(int *pcs, int mirror) {
  573.   mirror = (mirror ? 8 : 0);
  574.   return pcs[WHITE_QUEEN ^ mirror] * PRIME_WHITE_QUEEN +
  575.       pcs[WHITE_ROOK ^ mirror] * PRIME_WHITE_ROOK +
  576.       pcs[WHITE_BISHOP ^ mirror] * PRIME_WHITE_BISHOP +
  577.       pcs[WHITE_KNIGHT ^ mirror] * PRIME_WHITE_KNIGHT +
  578.       pcs[WHITE_PAWN ^ mirror] * PRIME_WHITE_PAWN +
  579.       pcs[BLACK_QUEEN ^ mirror] * PRIME_BLACK_QUEEN +
  580.       pcs[BLACK_ROOK ^ mirror] * PRIME_BLACK_ROOK +
  581.       pcs[BLACK_BISHOP ^ mirror] * PRIME_BLACK_BISHOP +
  582.       pcs[BLACK_KNIGHT ^ mirror] * PRIME_BLACK_KNIGHT +
  583.       pcs[BLACK_PAWN ^ mirror] * PRIME_BLACK_PAWN;
  584. }
  585.  
  586. static uint64_t get_pieces(const struct pos *pos, uint8_t code) {
  587.   switch (code) {
  588.     case WHITE_KING:
  589.       return pos->kings & pos->white;
  590.     case WHITE_QUEEN:
  591.       return pos->queens & pos->white;
  592.     case WHITE_ROOK:
  593.       return pos->rooks & pos->white;
  594.     case WHITE_BISHOP:
  595.       return pos->bishops & pos->white;
  596.     case WHITE_KNIGHT:
  597.       return pos->knights & pos->white;
  598.     case WHITE_PAWN:
  599.       return pos->pawns & pos->white;
  600.     case BLACK_KING:
  601.       return pos->kings & pos->black;
  602.     case BLACK_QUEEN:
  603.       return pos->queens & pos->black;
  604.     case BLACK_ROOK:
  605.       return pos->rooks & pos->black;
  606.     case BLACK_BISHOP:
  607.       return pos->bishops & pos->black;
  608.     case BLACK_KNIGHT:
  609.       return pos->knights & pos->black;
  610.     case BLACK_PAWN:
  611.       return pos->pawns & pos->black;
  612.     default:
  613.       return 0; // Dummy.
  614.   }
  615. }
  616.  
  617. static int probe_wdl_table(const struct pos *pos, int *success) {
  618.   struct TBEntry *ptr;
  619.   struct TBHashEntry *ptr2;
  620.   uint64_t idx;
  621.   uint64_t key;
  622.   int i;
  623.   uint8_t res;
  624.   int p[TBPIECES];
  625.  
  626.  // Obtain the position's material signature key.
  627.   key = calc_key(pos, false);
  628.  
  629.  // Test for KvK.
  630.   if (key == KEY_KvK)
  631.     return 0;
  632.  
  633.   ptr2 = TB_hash[key >> (64 - TBHASHBITS)];
  634.   for (i = 0; i < HSHMAX; i++) {
  635.     if (ptr2[i].key == key)
  636.       break;
  637.   }
  638.   if (i == HSHMAX) {
  639.     *success = 0;
  640.     return 0;
  641.   }
  642.  
  643.   ptr = ptr2[i].ptr;
  644.   if (!ptr->ready) {
  645.     LOCK(TB_MUTEX);
  646.     if (!ptr->ready) {
  647.       char str[16];
  648.       prt_str(pos, str, ptr->key != key);
  649.       if (!init_table_wdl(ptr, str)) {
  650.         ptr2[i].key = 0ULL;
  651.         *success = 0;
  652.         UNLOCK(TB_MUTEX);
  653.         return 0;
  654.       }
  655.      // Memory barrier to ensure ptr->ready = 1 is not reordered.
  656. #ifdef _MSC_VER
  657.       MemoryBarrier (); // Pierre-Marie Baty -- Win32 equivalent
  658. #else
  659.       __asm__ __volatile__("":::"memory");
  660. #endif // _MSC_VER
  661.       ptr->ready = 1;
  662.     }
  663.     UNLOCK(TB_MUTEX);
  664.   }
  665.  
  666.   int bside, mirror, cmirror;
  667.   if (!ptr->symmetric) {
  668.     if (key != ptr->key) {
  669.       cmirror = 8;
  670.       mirror = 0x38;
  671.       bside = pos->turn;
  672.     } else {
  673.       cmirror = mirror = 0;
  674.       bside = !pos->turn;
  675.     }
  676.   } else {
  677.     cmirror = (pos->turn ? 0 : 8);
  678.     mirror = (pos->turn ? 0 : 0x38);
  679.     bside = 0;
  680.   }
  681.  
  682.  // p[i] is to contain the square 0-63 (A1-H8) for a piece of type
  683.  // pc[i] ^ cmirror, where 1 = white pawn, ..., 14 = black king.
  684.  // Pieces of the same type are guaranteed to be consecutive.
  685.   if (!ptr->has_pawns) {
  686.     struct TBEntry_piece *entry = (struct TBEntry_piece *) ptr;
  687.     uint8_t *pc = entry->pieces[bside];
  688.     for (i = 0; i < entry->num;) {
  689.       uint64_t bb = get_pieces(pos, pc[i] ^ cmirror);
  690.       do {
  691.         p[i++] = _lsb(bb);
  692.         bb = poplsb(bb);
  693.       } while (bb);
  694.     }
  695.     idx = encode_piece(entry, entry->norm[bside], p, entry->factor[bside]);
  696.     res = decompress_pairs(entry->precomp[bside], idx);
  697.   } else {
  698.     struct TBEntry_pawn *entry = (struct TBEntry_pawn *) ptr;
  699.     int k = entry->file[0].pieces[0][0] ^ cmirror;
  700.     uint64_t bb = get_pieces(pos, k);
  701.     i = 0;
  702.     do {
  703.       p[i++] = _lsb(bb) ^ mirror;
  704.       bb = poplsb(bb);
  705.     } while (bb);
  706.     int f = pawn_file(entry, p);
  707.     uint8_t *pc = entry->file[f].pieces[bside];
  708.     for (; i < entry->num;) {
  709.       bb = get_pieces(pos, pc[i] ^ cmirror);
  710.       do {
  711.         p[i++] = _lsb(bb) ^ mirror;
  712.         bb = poplsb(bb);
  713.       } while (bb);
  714.     }
  715.     idx =
  716.         encode_pawn(entry, entry->file[f].norm[bside], p,
  717.         entry->file[f].factor[bside]);
  718.     res = decompress_pairs(entry->file[f].precomp[bside], idx);
  719.   }
  720.  
  721.   return ((int) res) - 2;
  722. }
  723.  
  724. static int probe_dtz_table(const struct pos *pos, int wdl, int *success) {
  725.   struct TBEntry *ptr;
  726.   uint64_t idx;
  727.   int i, res;
  728.   int p[TBPIECES];
  729.  
  730.  // Obtain the position's material signature key.
  731.   uint64_t key = calc_key(pos, false);
  732.  
  733.   if (DTZ_table[0].key1 != key && DTZ_table[0].key2 != key) {
  734.     for (i = 1; i < DTZ_ENTRIES; i++) {
  735.       if (DTZ_table[i].key1 == key || DTZ_table[i].key2 == key)
  736.         break; //new
  737.      /*if (DTZ_table[i].key1 == key)
  738.         break; *///mfb old
  739.     }
  740.     if (i < DTZ_ENTRIES) {
  741.       struct DTZTableEntry table_entry = DTZ_table[i];
  742.       for (; i > 0; i--)
  743.         DTZ_table[i] = DTZ_table[i - 1];
  744.       DTZ_table[0] = table_entry;
  745.     } else {
  746.       struct TBHashEntry *ptr2 = TB_hash[key >> (64 - TBHASHBITS)];
  747.       for (i = 0; i < HSHMAX; i++) {
  748.         if (ptr2[i].key == key)
  749.           break;
  750.       }
  751.       if (i == HSHMAX) {
  752.         *success = 0;
  753.         return 0;
  754.       }
  755.       ptr = ptr2[i].ptr;
  756.       char str[16];
  757.       int mirror = (ptr->key != key);
  758.       prt_str(pos, str, mirror);
  759.       if (DTZ_table[DTZ_ENTRIES - 1].entry)
  760.         free_dtz_entry(DTZ_table[DTZ_ENTRIES - 1].entry);
  761.       for (i = DTZ_ENTRIES - 1; i > 0; i--)
  762.         DTZ_table[i] = DTZ_table[i - 1];
  763.       uint64_t key1 = calc_key(pos, mirror);
  764.       uint64_t key2 = calc_key(pos, !mirror);
  765.       load_dtz_table(str, key1, key2);
  766.     }
  767.   }
  768.  
  769.   ptr = DTZ_table[0].entry;
  770.   if (!ptr) {
  771.     *success = 0;
  772.     return 0;
  773.   }
  774.  
  775.   int bside, mirror, cmirror;
  776.   if (!ptr->symmetric) {
  777.     if (key != ptr->key) {
  778.       cmirror = 8;
  779.       mirror = 0x38;
  780.       bside = pos->turn;
  781.     } else {
  782.       cmirror = mirror = 0;
  783.       bside = !pos->turn;
  784.     }
  785.   } else {
  786.     cmirror = (pos->turn ? 0 : 8);
  787.     mirror = (pos->turn ? 0 : 0x38);
  788.     bside = 0;
  789.   }
  790.  
  791.   if (!ptr->has_pawns) {
  792.     struct DTZEntry_piece *entry = (struct DTZEntry_piece *) ptr;
  793.     if ((entry->flags & 1) != bside && !entry->symmetric) {
  794.       *success = -1;
  795.       return 0;
  796.     }
  797.     uint8_t *pc = entry->pieces;
  798.     for (i = 0; i < entry->num;) {
  799.       uint64_t bb = get_pieces(pos, pc[i] ^ cmirror);
  800.       do {
  801.         p[i++] = _lsb(bb);
  802.         bb = poplsb(bb);
  803.       }
  804.       while (bb);
  805.     }
  806.     idx =
  807.         encode_piece((struct TBEntry_piece *) entry, entry->norm, p,
  808.         entry->factor);
  809.     res = decompress_pairs(entry->precomp, idx);
  810.  
  811.     if (entry->flags & 2)
  812.       res = entry->map[entry->map_idx[wdl_to_map[wdl + 2]] + res];
  813.     if (!(entry->flags & pa_flags[wdl + 2]) || (wdl & 1))
  814.       res *= 2;
  815.   } else {
  816.     struct DTZEntry_pawn *entry = (struct DTZEntry_pawn *) ptr;
  817.     int k = entry->file[0].pieces[0] ^ cmirror;
  818.     uint64_t bb = get_pieces(pos, k);
  819.     i = 0;
  820.     do {
  821.       p[i++] = _lsb(bb) ^ mirror;
  822.       bb = poplsb(bb);
  823.     }
  824.     while (bb);
  825.     int f = pawn_file((struct TBEntry_pawn *) entry, p);
  826.     if ((entry->flags[f] & 1) != bside) {
  827.       *success = -1;
  828.       return 0;
  829.     }
  830.     uint8_t *pc = entry->file[f].pieces;
  831.     for (; i < entry->num;) {
  832.       bb = get_pieces(pos, pc[i] ^ cmirror);
  833.       do {
  834.         p[i++] = _lsb(bb) ^ mirror;
  835.         bb = poplsb(bb);
  836.       }
  837.       while (bb);
  838.     }
  839.     idx =
  840.         encode_pawn((struct TBEntry_pawn *) entry, entry->file[f].norm, p,
  841.         entry->file[f].factor);
  842.     res = decompress_pairs(entry->file[f].precomp, idx);
  843.  
  844.     if (entry->flags[f] & 2)
  845.       res = entry->map[entry->map_idx[f][wdl_to_map[wdl + 2]] + res];
  846.     if (!(entry->flags[f] & pa_flags[wdl + 2]) || (wdl & 1))
  847.       res *= 2;
  848.   }
  849.  
  850.   return res;
  851. }
  852.  
  853. static uint16_t *add_move(uint16_t * moves, bool promotes, unsigned from,
  854.     unsigned to) {
  855.   if (!promotes)
  856.     *moves++ = make_move(TB_PROMOTES_NONE, from, to);
  857.   else {
  858.     *moves++ = make_move(TB_PROMOTES_QUEEN, from, to);
  859.     *moves++ = make_move(TB_PROMOTES_KNIGHT, from, to);
  860.     *moves++ = make_move(TB_PROMOTES_ROOK, from, to);
  861.     *moves++ = make_move(TB_PROMOTES_BISHOP, from, to);
  862.   }
  863.   return moves;
  864. }
  865.  
  866. /*
  867.  * Generate all captures or promotions.
  868.  */
  869. static uint16_t *gen_captures_or_promotions(const struct pos *pos,
  870.     uint16_t * moves) {
  871.   uint64_t occ = pos->white | pos->black;
  872.   uint64_t us = (pos->turn ? pos->white : pos->black), them =
  873.       (pos->turn ? pos->black : pos->white);
  874.   uint64_t b, att;
  875.   {
  876.     unsigned from = _lsb(pos->kings & us);
  877.     for (att = king_attacks(from) & them; att; att = poplsb(att)) {
  878.       unsigned to = _lsb(att);
  879.       moves = add_move(moves, false, from, to);
  880.     }
  881.   }
  882.   for (b = us & pos->queens; b; b = poplsb(b)) {
  883.     unsigned from = _lsb(b);
  884.     for (att = queen_attacks(from, occ) & them; att; att = poplsb(att)) {
  885.       unsigned to = _lsb(att);
  886.       moves = add_move(moves, false, from, to);
  887.     }
  888.   }
  889.   for (b = us & pos->rooks; b; b = poplsb(b)) {
  890.     unsigned from = _lsb(b);
  891.     for (att = rook_attacks(from, occ) & them; att; att = poplsb(att)) {
  892.       unsigned to = _lsb(att);
  893.       moves = add_move(moves, false, from, to);
  894.     }
  895.   }
  896.   for (b = us & pos->bishops; b; b = poplsb(b)) {
  897.     unsigned from = _lsb(b);
  898.     for (att = bishop_attacks(from, occ) & them; att; att = poplsb(att)) {
  899.       unsigned to = _lsb(att);
  900.       moves = add_move(moves, false, from, to);
  901.     }
  902.   }
  903.   for (b = us & pos->knights; b; b = poplsb(b)) {
  904.     unsigned from = _lsb(b);
  905.     for (att = knight_attacks(from) & them; att; att = poplsb(att)) {
  906.       unsigned to = _lsb(att);
  907.       moves = add_move(moves, false, from, to);
  908.     }
  909.   }
  910.   for (b = us & pos->pawns; b; b = poplsb(b)) {
  911.     unsigned from = _lsb(b);
  912.     att = pawn_attacks(from, pos->turn);
  913.     if (pos->ep != 0 && ((att & board(pos->ep)) != 0)) {
  914.       unsigned to = pos->ep;
  915.       moves = add_move(moves, false, from, to);
  916.     }
  917.     for (att = att & them; att; att = poplsb(att)) {
  918.       unsigned to = _lsb(att);
  919.       moves = add_move(moves, (rank(to) == 7 || rank(to) == 0), from, to);
  920.     }
  921.     if (pos->turn && rank(from) == 6) {
  922.       unsigned to = from + 8;
  923.       if ((board(to) & occ) == 0)
  924.         moves = add_move(moves, true, from, to);
  925.     } else if (!pos->turn && rank(from) == 1) {
  926.       unsigned to = from - 8;
  927.       if ((board(to) & occ) == 0)
  928.         moves = add_move(moves, true, from, to);
  929.     }
  930.   }
  931.   return moves;
  932. }
  933.  
  934. /*
  935.  * Generate all non-capture pawn moves and promotions.
  936.  */
  937. static uint16_t *gen_pawn_quiets_or_promotions(const struct pos *pos,
  938.     uint16_t * moves) {
  939.   uint64_t occ = pos->white | pos->black;
  940.   uint64_t us = (pos->turn ? pos->white : pos->black);
  941.   uint64_t b, att;
  942.  
  943.   for (b = us & pos->pawns; b; b = poplsb(b)) {
  944.     unsigned from = _lsb(b);
  945.     unsigned next = from + (pos->turn ? 8 : -8);
  946.     att = 0;
  947.     if ((board(next) & occ) == 0) {
  948.       att |= board(next);
  949.       unsigned next2 = from + (pos->turn ? 16 : -16);
  950.       if ((pos->turn ? rank(from) == 1 : rank(from) == 6) &&
  951.           ((board(next2) & occ) == 0))
  952.         att |= board(next2);
  953.     }
  954.     for (; att; att = poplsb(att)) {
  955.       unsigned to = _lsb(att);
  956.       moves = add_move(moves, (rank(to) == 7 || rank(to) == 0), from, to);
  957.     }
  958.   }
  959.   return moves;
  960. }
  961.  
  962. /*
  963.  * Generate all en passant captures.
  964.  */
  965. static uint16_t *gen_pawn_ep_captures(const struct pos *pos, uint16_t * moves) {
  966.   if (pos->ep == 0)
  967.     return moves;
  968.   uint64_t ep = board(pos->ep);
  969.   unsigned to = pos->ep;
  970.   uint64_t us = (pos->turn ? pos->white : pos->black);
  971.   uint64_t b;
  972.   for (b = us & pos->pawns; b; b = poplsb(b)) {
  973.     unsigned from = _lsb(b);
  974.     if ((pawn_attacks(from, pos->turn) & ep) != 0)
  975.       moves = add_move(moves, false, from, to);
  976.   }
  977.   return moves;
  978. }
  979.  
  980. /*
  981.  * Generate all moves.
  982.  */
  983. static uint16_t *gen_moves(const struct pos *pos, uint16_t * moves) {
  984.   uint64_t occ = pos->white | pos->black;
  985.   uint64_t us = (pos->turn ? pos->white : pos->black), them =
  986.       (pos->turn ? pos->black : pos->white);
  987.   uint64_t b, att;
  988.  
  989.   {
  990.     unsigned from = _lsb(pos->kings & us);
  991.     for (att = king_attacks(from) & ~us; att; att = poplsb(att)) {
  992.       unsigned to = _lsb(att);
  993.       moves = add_move(moves, false, from, to);
  994.     }
  995.   }
  996.   for (b = us & pos->queens; b; b = poplsb(b)) {
  997.     unsigned from = _lsb(b);
  998.     for (att = queen_attacks(from, occ) & ~us; att; att = poplsb(att)) {
  999.       unsigned to = _lsb(att);
  1000.       moves = add_move(moves, false, from, to);
  1001.     }
  1002.   }
  1003.   for (b = us & pos->rooks; b; b = poplsb(b)) {
  1004.     unsigned from = _lsb(b);
  1005.     for (att = rook_attacks(from, occ) & ~us; att; att = poplsb(att)) {
  1006.       unsigned to = _lsb(att);
  1007.       moves = add_move(moves, false, from, to);
  1008.     }
  1009.   }
  1010.   for (b = us & pos->bishops; b; b = poplsb(b)) {
  1011.     unsigned from = _lsb(b);
  1012.     for (att = bishop_attacks(from, occ) & ~us; att; att = poplsb(att)) {
  1013.       unsigned to = _lsb(att);
  1014.       moves = add_move(moves, false, from, to);
  1015.     }
  1016.   }
  1017.   for (b = us & pos->knights; b; b = poplsb(b)) {
  1018.     unsigned from = _lsb(b);
  1019.     for (att = knight_attacks(from) & ~us; att; att = poplsb(att)) {
  1020.       unsigned to = _lsb(att);
  1021.       moves = add_move(moves, false, from, to);
  1022.     }
  1023.   }
  1024.   for (b = us & pos->pawns; b; b = poplsb(b)) {
  1025.     unsigned from = _lsb(b);
  1026.     unsigned next = from + (pos->turn ? 8 : -8);
  1027.     att = pawn_attacks(from, pos->turn);
  1028.     if (pos->ep != 0 && ((att & board(pos->ep)) != 0)) {
  1029.       unsigned to = pos->ep;
  1030.       moves = add_move(moves, false, from, to);
  1031.     }
  1032.     att &= them;
  1033.     if ((board(next) & occ) == 0) {
  1034.       att |= board(next);
  1035.       unsigned next2 = from + (pos->turn ? 16 : -16);
  1036.       if ((pos->turn ? rank(from) == 1 : rank(from) == 6) &&
  1037.           ((board(next2) & occ) == 0))
  1038.         att |= board(next2);
  1039.     }
  1040.     for (; att; att = poplsb(att)) {
  1041.       unsigned to = _lsb(att);
  1042.       moves = add_move(moves, (rank(to) == 7 || rank(to) == 0), from, to);
  1043.     }
  1044.   }
  1045.   return moves;
  1046. }
  1047.  
  1048. /*
  1049.  * Test if the given move is an en passant capture.
  1050.  */
  1051. static bool is_en_passant(const struct pos *pos, uint16_t move) {
  1052.   uint16_t from = move_from(move);
  1053.   uint16_t to = move_to(move);
  1054.   uint64_t us = (pos->turn ? pos->white : pos->black);
  1055.   if (pos->ep == 0)
  1056.     return false;
  1057.   if (to != pos->ep)
  1058.     return false;
  1059.   if ((board(from) & us & pos->pawns) != 0)
  1060.     return false;
  1061.   return true;
  1062. }
  1063.  
  1064. /*
  1065.  * Test if the given position is legal (can the king be captured?)
  1066.  */
  1067. static bool is_legal(const struct pos *pos) {
  1068.   uint64_t occ = pos->white | pos->black;
  1069.   uint64_t us = (pos->turn ? pos->black : pos->white), them =
  1070.       (pos->turn ? pos->white : pos->black);
  1071.   uint64_t king = pos->kings & us;
  1072.   unsigned sq = _lsb(king);
  1073.   if (king_attacks(sq) & (pos->kings & them))
  1074.     return false;
  1075.   uint64_t ratt = rook_attacks(sq, occ);
  1076.   uint64_t batt = bishop_attacks(sq, occ);
  1077.   if (ratt & (pos->rooks & them))
  1078.     return false;
  1079.   if (batt & (pos->bishops & them))
  1080.     return false;
  1081.   if ((ratt | batt) & (pos->queens & them))
  1082.     return false;
  1083.   if (knight_attacks(sq) & (pos->knights & them))
  1084.     return false;
  1085.   if (pawn_attacks(sq, !pos->turn) & (pos->pawns & them))
  1086.     return false;
  1087.   return true;
  1088. }
  1089.  
  1090. /*
  1091.  * Test if the king is in check.
  1092.  */
  1093. static bool is_check(const struct pos *pos) {
  1094.   uint64_t occ = pos->white | pos->black;
  1095.   uint64_t us = (pos->turn ? pos->white : pos->black), them =
  1096.       (pos->turn ? pos->black : pos->white);
  1097.   uint64_t king = pos->kings & us;
  1098.   unsigned sq = _lsb(king);
  1099.   uint64_t ratt = rook_attacks(sq, occ);
  1100.   uint64_t batt = bishop_attacks(sq, occ);
  1101.   if (ratt & (pos->rooks & them))
  1102.     return true;
  1103.   if (batt & (pos->bishops & them))
  1104.     return true;
  1105.   if ((ratt | batt) & (pos->queens & them))
  1106.     return true;
  1107.   if (knight_attacks(sq) & (pos->knights & them))
  1108.     return true;
  1109.   if (pawn_attacks(sq, pos->turn) & (pos->pawns & them))
  1110.     return true;
  1111.   return false;
  1112. }
  1113.  
  1114. /*
  1115.  * Test if the king is in checkmate.
  1116.  */
  1117. static bool is_mate(const struct pos *pos) {
  1118.   if (!is_check(pos))
  1119.     return false;
  1120.   uint16_t moves0[MAX_MOVES];
  1121.   uint16_t *moves = moves0;
  1122.   uint16_t *end = gen_moves(pos, moves);
  1123.   for (; moves < end; moves++) {
  1124.     struct pos pos1;
  1125.     if (do_move(&pos1, pos, *moves))
  1126.       return false;
  1127.   }
  1128.   return true;
  1129. }
  1130.  
  1131. /*
  1132.  * Test if the position is valid.
  1133.  */
  1134. static bool is_valid(const struct pos *pos) {
  1135.   if (popcount(pos->kings) != 2)
  1136.     return false;
  1137.   if (popcount(pos->kings & pos->white) != 1)
  1138.     return false;
  1139.   if (popcount(pos->kings & pos->black) != 1)
  1140.     return false;
  1141.   if ((pos->white & pos->black) != 0)
  1142.     return false;
  1143.   if ((pos->kings & pos->queens) != 0)
  1144.     return false;
  1145.   if ((pos->kings & pos->rooks) != 0)
  1146.     return false;
  1147.   if ((pos->kings & pos->bishops) != 0)
  1148.     return false;
  1149.   if ((pos->kings & pos->knights) != 0)
  1150.     return false;
  1151.   if ((pos->kings & pos->pawns) != 0)
  1152.     return false;
  1153.   if ((pos->queens & pos->rooks) != 0)
  1154.     return false;
  1155.   if ((pos->queens & pos->bishops) != 0)
  1156.     return false;
  1157.   if ((pos->queens & pos->knights) != 0)
  1158.     return false;
  1159.   if ((pos->queens & pos->pawns) != 0)
  1160.     return false;
  1161.   if ((pos->rooks & pos->bishops) != 0)
  1162.     return false;
  1163.   if ((pos->rooks & pos->knights) != 0)
  1164.     return false;
  1165.   if ((pos->rooks & pos->pawns) != 0)
  1166.     return false;
  1167.   if ((pos->bishops & pos->knights) != 0)
  1168.     return false;
  1169.   if ((pos->bishops & pos->pawns) != 0)
  1170.     return false;
  1171.   if ((pos->knights & pos->pawns) != 0)
  1172.     return false;
  1173.   if ((pos->white | pos->black) !=
  1174.       (pos->kings | pos->queens | pos->rooks | pos->
  1175.           bishops | pos->knights | pos->pawns))
  1176.     return false;
  1177.   return is_legal(pos);
  1178. }
  1179.  
  1180. #define do_bb_move(b, from, to)                                         \
  1181.     (((b) & (~board(to)) & (~board(from))) |                            \
  1182.         ((((b) >> (from)) & 0x1) << (to)))
  1183.  
  1184. static bool do_move(struct pos *pos, const struct pos *pos0, uint16_t move) {
  1185.   unsigned from = move_from(move);
  1186.   unsigned to = move_to(move);
  1187.   unsigned promotes = move_promotes(move);
  1188.   pos->turn = !pos0->turn;
  1189.   pos->white = do_bb_move(pos0->white, from, to);
  1190.   pos->black = do_bb_move(pos0->black, from, to);
  1191.   pos->kings = do_bb_move(pos0->kings, from, to);
  1192.   pos->queens = do_bb_move(pos0->queens, from, to);
  1193.   pos->rooks = do_bb_move(pos0->rooks, from, to);
  1194.   pos->bishops = do_bb_move(pos0->bishops, from, to);
  1195.   pos->knights = do_bb_move(pos0->knights, from, to);
  1196.   pos->pawns = do_bb_move(pos0->pawns, from, to);
  1197.   pos->ep = 0;
  1198.   if (promotes != TB_PROMOTES_NONE) {
  1199.     pos->pawns &= ~board(to); // Promotion
  1200.     switch (promotes) {
  1201.       case TB_PROMOTES_QUEEN:
  1202.         pos->queens |= board(to);
  1203.         break;
  1204.       case TB_PROMOTES_ROOK:
  1205.         pos->rooks |= board(to);
  1206.         break;
  1207.       case TB_PROMOTES_BISHOP:
  1208.         pos->bishops |= board(to);
  1209.         break;
  1210.       case TB_PROMOTES_KNIGHT:
  1211.         pos->knights |= board(to);
  1212.         break;
  1213.     }
  1214.     pos->rule50 = 0;
  1215.   } else if ((board(from) & pos0->pawns) != 0) {
  1216.     pos->rule50 = 0; // Pawn move
  1217.     if (rank(from) == 1 && rank(to) == 3 &&
  1218.         (pawn_attacks(from + 8, true) & pos0->pawns & pos0->black) != 0)
  1219.       pos->ep = from + 8;
  1220.     else if (rank(from) == 6 && rank(to) == 4 &&
  1221.         (pawn_attacks(from - 8, false) & pos0->pawns & pos0->white) != 0)
  1222.       pos->ep = from - 8;
  1223.     else if (to == pos0->ep) {
  1224.       unsigned ep_to = (pos0->turn ? to + 8 : to - 8);
  1225.       uint64_t ep_mask = ~board(ep_to);
  1226.       pos->white &= ep_mask;
  1227.       pos->black &= ep_mask;
  1228.       pos->pawns &= ep_mask;
  1229.     }
  1230.   } else if ((board(to) & (pos0->white | pos0->black)) != 0)
  1231.     pos->rule50 = 0; // Capture
  1232.   else
  1233.     pos->rule50 = pos0->rule50 + 1; // Normal move
  1234.   if (!is_legal(pos))
  1235.     return false;
  1236.   return true;
  1237. }
  1238.  
  1239. static int probe_ab(const struct pos *pos, int alpha, int beta, int *success) {
  1240.   int v;
  1241.   uint16_t moves0[64];
  1242.   uint16_t *moves = moves0;
  1243.   uint16_t *end = gen_captures_or_promotions(pos, moves);
  1244.   for (; moves < end; moves++) {
  1245.     if (is_en_passant(pos, *moves))
  1246.       continue;
  1247.     struct pos pos1;
  1248.     if (!do_move(&pos1, pos, *moves))
  1249.       continue;
  1250.     v = -probe_ab(&pos1, -beta, -alpha, success);
  1251.     if (*success == 0)
  1252.       return 0;
  1253.     if (v > alpha) {
  1254.       if (v >= beta) {
  1255.         *success = 2;
  1256.         return v;
  1257.       }
  1258.       alpha = v;
  1259.     }
  1260.   }
  1261.  
  1262.   v = probe_wdl_table(pos, success);
  1263.   if (*success == 0)
  1264.     return 0;
  1265.   if (alpha >= v) {
  1266.     *success = 1 + (alpha > 0);
  1267.     return alpha;
  1268.   } else {
  1269.     *success = 1;
  1270.     return v;
  1271.   }
  1272. }
  1273.  
  1274. static int probe_wdl(const struct pos *pos, int *success) {
  1275.   *success = 1;
  1276.   int v = probe_ab(pos, -2, 2, success);
  1277.   if (*success == 0)
  1278.     return 0;
  1279.  
  1280.  // If en passant is not possible, we are done.
  1281.   if (pos->ep == 0)
  1282.     return v;
  1283.  
  1284.  // Now handle en passant.
  1285.   int v1 = -3;
  1286.   uint16_t moves0[2];           // Max=2 possible en-passant captures.
  1287.   uint16_t *moves = moves0;
  1288.   uint16_t *end = gen_pawn_ep_captures(pos, moves);
  1289.   for (; moves < end; moves++) {
  1290.     struct pos pos1;
  1291.     if (!do_move(&pos1, pos, *moves))
  1292.       continue;
  1293.     int v0 = -probe_ab(pos, -2, 2, success);
  1294.     if (*success == 0)
  1295.       return 0;
  1296.     if (v0 > v1)
  1297.       v1 = v0;
  1298.   }
  1299.   if (v1 > -3) {
  1300.     if (v1 >= v)
  1301.       v = v1;
  1302.     else if (v == 0) {
  1303.      // Check whether there is at least one legal non-ep move.
  1304.       uint16_t moves0[MAX_MOVES];
  1305.       uint16_t *moves = moves0;
  1306.       uint16_t *end = gen_moves(pos, moves);
  1307.       bool found = false;
  1308.       for (; moves < end; moves++) {
  1309.         if (is_en_passant(pos, *moves))
  1310.           continue;
  1311.         struct pos pos1;
  1312.         if (do_move(&pos1, pos, *moves)) {
  1313.           found = true;
  1314.           break;
  1315.         }
  1316.       }
  1317.       if (!found)
  1318.         v = v1; // Forced to play the losing ep capture.
  1319.     }
  1320.   }
  1321.  
  1322.   return v;
  1323. }
  1324.  
  1325. static int probe_dtz_no_ep(const struct pos *pos, int *success) {
  1326.   int wdl, dtz;
  1327.   wdl = probe_ab(pos, -2, 2, success);
  1328.   if (wdl == 0)
  1329.     return 0;
  1330.   if (*success == 2)
  1331.     return wdl == 2 ? 1 : 101;
  1332.  
  1333.   uint16_t moves0[MAX_MOVES];
  1334.   uint16_t *moves = moves0, *end = NULL;
  1335.  
  1336.   if (wdl > 0) {
  1337.    // Generate at least all legal non-capturing pawn moves
  1338.    // including non-capturing promotions.
  1339.     end = gen_pawn_quiets_or_promotions(pos, moves);
  1340.     for (; moves < end; moves++) {
  1341.       struct pos pos1;
  1342.       if (!do_move(&pos1, pos, *moves))
  1343.         continue;
  1344.      //int v = pos.ep_square() == SQ_NONE ? -probe_ab(pos, -2, -wdl + 1, success)
  1345.      //                                   : -probe_wdl(pos, success);
  1346.      //int v = -probe_ab(&pos1, -2, -wdl + 1, success);removed mfb
  1347.       int v = (pos1.ep == 0 ? -probe_ab(&pos1, -2, -wdl + 1, success) : -probe_wdl(&pos1, success)); //added mfb
  1348.       if (*success == 0)
  1349.         return 0;
  1350.       if (v == wdl)
  1351.         return (v == 2 ? 1 : 101);
  1352.     }
  1353.   }
  1354.  
  1355.   dtz = 1 + probe_dtz_table(pos, wdl, success);
  1356.   if (*success >= 0) {
  1357.     if (wdl & 1)
  1358.       dtz += 100;
  1359.     return (wdl >= 0 ? dtz : -dtz);
  1360.   }
  1361.  
  1362.   if (wdl > 0) {
  1363.     int best = BEST_NONE;
  1364.     moves = moves0;
  1365.     end = gen_moves(pos, moves);
  1366.     for (; moves < end; moves++) {
  1367.       struct pos pos1;
  1368.       if (!do_move(&pos1, pos, *moves))
  1369.         continue;
  1370.       if (pos1.rule50 == 0)
  1371.         continue;
  1372.       int v = -probe_dtz(&pos1, success);
  1373.       if (*success == 0)
  1374.         return 0;
  1375.       if (v > 0 && v + 1 < best)
  1376.         best = v + 1;
  1377.     }
  1378.     assert(best != BEST_NONE);
  1379.     return best;
  1380.   } else {
  1381.     int best = -1;
  1382.     end = gen_moves(pos, moves);
  1383.     for (; moves < end; moves++) {
  1384.       int v;
  1385.       struct pos pos1;
  1386.       if (!do_move(&pos1, pos, *moves))
  1387.         continue;
  1388.       if (pos1.rule50 == 0) {
  1389.         if (wdl == -2)
  1390.           v = -1;
  1391.         else {
  1392.           v = probe_ab(&pos1, 1, 2, success);
  1393.           v = (v == 2) ? 0 : -101;
  1394.         }
  1395.       } else
  1396.         v = -probe_dtz(&pos1, success) - 1;
  1397.       if (*success == 0)
  1398.         return 0;
  1399.       if (v < best)
  1400.         best = v;
  1401.     }
  1402.     return best;
  1403.   }
  1404. }
  1405.  
  1406. static const int wdl_to_dtz[] = {
  1407.   -1, -101, 0, 101, 1
  1408. };
  1409.  
  1410. /*
  1411.  * Probe the DTZ table for a particular position.
  1412.  * If *success != 0, the probe was successful.
  1413.  * The return value is from the point of view of the side to move:
  1414.  *         n < -100 : loss, but draw under 50-move rule
  1415.  * -100 <= n < -1   : loss in n ply (assuming 50-move counter == 0)
  1416.  *         0            : draw
  1417.  *     1 < n <= 100 : win in n ply (assuming 50-move counter == 0)
  1418.  *   100 < n        : win, but draw under 50-move rule
  1419.  *
  1420.  * The return value n can be off by 1: a return value -n can mean a loss
  1421.  * in n+1 ply and a return value +n can mean a win in n+1 ply. This
  1422.  * cannot happen for tables with positions exactly on the "edge" of
  1423.  * the 50-move rule.
  1424.  *
  1425.  * This implies that if dtz > 0 is returned, the position is certainly
  1426.  * a win if dtz + 50-move-counter <= 99. Care must be taken that the engine
  1427.  * picks moves that preserve dtz + 50-move-counter <= 99.
  1428.  *
  1429.  * If n = 100 immediately after a capture or pawn move, then the position
  1430.  * is also certainly a win, and during the whole phase until the next
  1431.  * capture or pawn move, the inequality to be preserved is
  1432.  * dtz + 50-movecounter <= 100.
  1433.  *
  1434.  * In short, if a move is available resulting in dtz + 50-move-counter <= 99,
  1435.  * then do not accept moves leading to dtz + 50-move-counter == 100.
  1436.  */
  1437. static int probe_dtz(const struct pos *pos, int *success) {
  1438.   *success = 1;
  1439.   int v = probe_dtz_no_ep(pos, success);
  1440.   if (*success == 0)
  1441.     return 0;
  1442.  
  1443.   if (pos->ep == 0)
  1444.     return v;
  1445.  
  1446.   int v1 = -3;
  1447.   uint16_t moves0[2];           // Max=2 possible en-passant captures.
  1448.   uint16_t *moves = moves0;
  1449.   uint16_t *end = gen_pawn_ep_captures(pos, moves);
  1450.   for (; moves < end; moves++) {
  1451.     struct pos pos1;
  1452.     if (!do_move(&pos1, pos, *moves))
  1453.       continue;
  1454.     int v0 = -probe_ab(pos, -2, 2, success);
  1455.     if (*success == 0)
  1456.       return 0;
  1457.     if (v0 > v1)
  1458.       v1 = v0;
  1459.   }
  1460.  
  1461.   if (v1 > -3) {
  1462.     v1 = wdl_to_dtz[v1 + 2];
  1463.     if (v < -100) {
  1464.       if (v1 >= 0)
  1465.         v = v1;
  1466.     } else if (v < 0) {
  1467.       if (v1 >= 0 || v1 < -100)
  1468.         v = v1;
  1469.     } else if (v > 100) {
  1470.       if (v1 > 0)
  1471.         v = v1;
  1472.     } else if (v > 0) {
  1473.       if (v1 == 1)
  1474.         v = v1;
  1475.     } else if (v1 >= 0)
  1476.       v = v1;
  1477.     else {
  1478.       uint16_t moves0[MAX_MOVES];
  1479.       uint16_t *moves = moves0;
  1480.       uint16_t *end = gen_moves(pos, moves);
  1481.       bool found = false;
  1482.       for (; moves < end; moves++) {
  1483.         if (is_en_passant(pos, *moves))
  1484.           continue;
  1485.         struct pos pos1;
  1486.         if (do_move(&pos1, pos, *moves)) {
  1487.           found = true;
  1488.           break;
  1489.         }
  1490.       }
  1491.       if (!found)
  1492.         v = v1; // Forced to play the losing ep capture.
  1493.     }
  1494.   }
  1495.  
  1496.   return v;
  1497. }
  1498.  
  1499. unsigned dtz_to_wdl(int cnt50, int dtz) {
  1500.   int wdl = 0;
  1501.   if (dtz > 0)
  1502.     wdl = (dtz + cnt50 <= 100 ? 2 : 1);
  1503.   else if (dtz < 0)
  1504.     wdl = (-dtz + cnt50 <= 100 ? -2 : -1);
  1505.   return wdl + 2;
  1506. }
  1507.  
  1508. static uint16_t probe_root(const struct pos *pos, int *score,
  1509.     unsigned *results) {
  1510.   int success;
  1511.   int dtz = probe_dtz(pos, &success);
  1512.   if (!success)
  1513.     return 0;
  1514.  
  1515.   int16_t scores[MAX_MOVES];
  1516.   uint16_t moves0[MAX_MOVES];
  1517.   uint16_t *moves = moves0;
  1518.   uint16_t *end = gen_moves(pos, moves);
  1519.   size_t len = end - moves;
  1520.   size_t num_draw = 0;
  1521.   unsigned j = 0;
  1522.   unsigned i = 0;               //mfb
  1523.   for (i = 0; i < len; i++) {
  1524.     struct pos pos1;
  1525.     if (!do_move(&pos1, pos, moves[i])) {
  1526.       scores[i] = SCORE_ILLEGAL;
  1527.       continue;
  1528.     }
  1529.     int v = 0;
  1530.     if (dtz > 0 && is_mate(&pos1))
  1531.       v = 1;
  1532.     else {
  1533.       if (pos1.rule50 != 0) {
  1534.         v = -probe_dtz(&pos1, &success);
  1535.         if (v > 0)
  1536.           v++;
  1537.         else if (v < 0)
  1538.           v--;
  1539.       } else {
  1540.         v = -probe_wdl(&pos1, &success);
  1541.         v = wdl_to_dtz[v + 2];
  1542.       }
  1543.     }
  1544.     num_draw += (v == 0);
  1545.     if (!success)
  1546.       return 0;
  1547.     scores[i] = v;
  1548.     if (results != NULL) {
  1549.       unsigned res = 0;
  1550.       res = TB_SET_WDL(res, dtz_to_wdl(pos->rule50, v));
  1551.       res = TB_SET_FROM(res, move_from(moves[i]));
  1552.       res = TB_SET_TO(res, move_to(moves[i]));
  1553.       res = TB_SET_PROMOTES(res, move_promotes(moves[i]));
  1554.       res = TB_SET_EP(res, is_en_passant(pos, moves[i]));
  1555.       res = TB_SET_DTZ(res, (dtz < 0 ? -dtz : dtz));
  1556.       results[j++] = res;
  1557.     }
  1558.   }
  1559.   if (results != NULL)
  1560.     results[j++] = TB_RESULT_FAILED;
  1561.   if (score != NULL)
  1562.     *score = dtz;
  1563.  
  1564.  // Now be a bit smart about filtering out moves.
  1565.   if (dtz > 0) // winning (or 50-move rule draw)
  1566.   {
  1567.     int best = BEST_NONE;
  1568.     uint16_t best_move = 0;
  1569.     for (i = 0; i < len; i++) {
  1570.       int v = scores[i];
  1571.       if (v == SCORE_ILLEGAL)
  1572.         continue;
  1573.       if (v > 0 && v < best) {
  1574.         best = v;
  1575.         best_move = moves[i];
  1576.       }
  1577.     }
  1578.     return (best == BEST_NONE ? 0 : best_move);
  1579.   } else if (dtz < 0) // losing (or 50-move rule draw)
  1580.   {
  1581.     int best = 0;
  1582.     uint16_t best_move = 0;
  1583.     for (i = 0; i < len; i++) {
  1584.       int v = scores[i];
  1585.       if (v == SCORE_ILLEGAL)
  1586.         continue;
  1587.       if (v < best) {
  1588.         best = v;
  1589.         best_move = moves[i];
  1590.       }
  1591.     }
  1592.     return (best == 0 ? MOVE_CHECKMATE : best_move);
  1593.   } else // drawing
  1594.   {
  1595.    // Check for stalemate:
  1596.     if (num_draw == 0)
  1597.       return MOVE_STALEMATE;
  1598.  
  1599.    // Select a "random" move that preserves the draw.
  1600.    // Uses calc_key as the PRNG.
  1601.     size_t count = calc_key(pos, !pos->turn) % num_draw;
  1602.     for (i = 0; i < len; i++) {
  1603.       int v = scores[i];
  1604.       if (v == SCORE_ILLEGAL)
  1605.         continue;
  1606.       if (v == 0) {
  1607.         if (count == 0)
  1608.           return moves[i];
  1609.         count--;
  1610.       }
  1611.     }
  1612.     return 0;
  1613.   }
  1614. }
  1615.  
  1616. extern bool tb_init_impl(const char *path) {
  1617.   if (sizeof(uint64_t) != 8 && // Paranoid check
  1618.       sizeof(uint32_t) != 4 && sizeof(uint16_t) != 2 && sizeof(uint8_t) != 1)
  1619.     return false;
  1620.   king_attacks_init();
  1621.   knight_attacks_init();
  1622.   bishop_attacks_init();
  1623.   rook_attacks_init();
  1624.   pawn_attacks_init();
  1625.   if (path == NULL)
  1626.     path = "";
  1627.   init_tablebases(path);
  1628.   return true;
  1629. }
  1630.  
  1631. extern unsigned tb_probe_wdl_impl(uint64_t white, uint64_t black,
  1632.     uint64_t kings, uint64_t queens, uint64_t rooks, uint64_t bishops,
  1633.     uint64_t knights, uint64_t pawns, unsigned ep, bool turn, uint64_t hash) {
  1634.   struct pos pos = {
  1635.     white,
  1636.     black,
  1637.     kings,
  1638.     queens,
  1639.     rooks,
  1640.     bishops,
  1641.     knights,
  1642.     pawns,
  1643.     0,
  1644.     ep,
  1645.     turn
  1646.   };
  1647.   static uint64_t cache[4096] = { 0 };
  1648.   uint64_t idx = hash % 1024;
  1649.   if ((cache[idx] & ~0x7) == (hash & ~0x7)) {
  1650.    // Hit
  1651. //        FILE *F = fopen("debug.txt", "a");
  1652. //        fprintf(F, "CACHE_HIT = %.16lX (result=%u)\n", cache[idx],
  1653. //            (unsigned)(cache[idx] & 0x7));
  1654. //        fclose(F);
  1655.     return (cache[idx] & 0x7);
  1656.   }
  1657.  // Miss
  1658.   int success;
  1659.   int v = probe_wdl(&pos, &success);
  1660.   if (success == 0)
  1661.     return TB_RESULT_FAILED;
  1662.   unsigned result = (unsigned) (v + 2);
  1663.   hash &= ~0x7;
  1664.   hash |= (uint64_t) result;
  1665.   cache[idx] = hash;
  1666.   return result;
  1667. }
  1668.  
  1669. extern unsigned tb_probe_root_impl(uint64_t white, uint64_t black,
  1670.     uint64_t kings, uint64_t queens, uint64_t rooks, uint64_t bishops,
  1671.     uint64_t knights, uint64_t pawns, unsigned rule50, unsigned ep, bool turn,
  1672.     unsigned *results) {
  1673.   struct pos pos = {
  1674.     white,
  1675.     black,
  1676.     kings,
  1677.     queens,
  1678.     rooks,
  1679.     bishops,
  1680.     knights,
  1681.     pawns,
  1682.     rule50,
  1683.     ep,
  1684.     turn
  1685.   };
  1686.   int dtz;
  1687.   if (!is_valid(&pos))
  1688.     return TB_RESULT_FAILED;
  1689.   uint16_t move = probe_root(&pos, &dtz, results);
  1690.   if (move == 0)
  1691.     return TB_RESULT_FAILED;
  1692.   if (move == MOVE_CHECKMATE)
  1693.     return TB_RESULT_CHECKMATE;
  1694.   if (move == MOVE_STALEMATE)
  1695.     return TB_RESULT_STALEMATE;
  1696.   unsigned res = 0;
  1697.   res = TB_SET_WDL(res, dtz_to_wdl(rule50, dtz));
  1698.   res = TB_SET_FROM(res, move_from(move));
  1699.   res = TB_SET_TO(res, move_to(move));
  1700.   res = TB_SET_PROMOTES(res, move_promotes(move));
  1701.   res = TB_SET_EP(res, is_en_passant(&pos, move));
  1702.   return res;
  1703. }
  1704.  
  1705. #ifndef TB_NO_HELPER_API
  1706.  
  1707. unsigned tb_pop_count(uint64_t bb) {
  1708.   return popcount(bb);
  1709. }
  1710.  
  1711. unsigned tb_lsb(uint64_t bb) {
  1712.   return _lsb(bb);
  1713. }
  1714.  
  1715. uint64_t tb_pop_lsb(uint64_t bb) {
  1716.   return poplsb(bb);
  1717. }
  1718.  
  1719. uint64_t tb_king_attacks(unsigned sq) {
  1720.   return king_attacks(sq);
  1721. }
  1722.  
  1723. uint64_t tb_queen_attacks(unsigned sq, uint64_t occ) {
  1724.   return queen_attacks(sq, occ);
  1725. }
  1726.  
  1727. uint64_t tb_rook_attacks(unsigned sq, uint64_t occ) {
  1728.   return rook_attacks(sq, occ);
  1729. }
  1730.  
  1731. uint64_t tb_bishop_attacks(unsigned sq, uint64_t occ) {
  1732.   return bishop_attacks(sq, occ);
  1733. }
  1734.  
  1735. uint64_t tb_knight_attacks(unsigned sq) {
  1736.   return knight_attacks(sq);
  1737. }
  1738.  
  1739. uint64_t tb_pawn_attacks(unsigned sq, bool color) {
  1740.   return pawn_attacks(sq, color);
  1741. }
  1742.  
  1743. #endif                          /* TB_NO_HELPER_API */
  1744.