Subversion Repositories Games.Chess Giants

Rev

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

  1. /*
  2.     Protector -- a UCI chess engine
  3.  
  4.     Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)
  5.  
  6.     This program is free software: you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation, either version 3 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  
  19. */
  20.  
  21. #include "tablebase.h"
  22. #include "protector.h"
  23. #include "io.h"
  24. #include <assert.h>
  25.  
  26. #ifdef INCLUDE_TABLEBASE_ACCESS
  27.  
  28. #ifndef _MSC_VER
  29. #include <pthread.h>
  30. pthread_spinlock_t lock;
  31. #else // _MSC_VER
  32. bool lock = 0; // Pierre-Marie Baty -- Win32 thread locking
  33. __declspec(dllimport) void __stdcall Sleep (unsigned long Timeout); // Pierre-Marie Baty -- for Sleep()
  34. #endif // !_MSC_VER
  35. volatile int tbAccessCount = 0;
  36.  
  37. #define MAX_PIECES_PER_SIDE 3
  38. #define NO_EP 127
  39.  
  40. bool tbAvailable = FALSE;
  41. typedef unsigned long long INDEX;
  42. typedef unsigned int squaret;
  43.  
  44. char *cache = 0;
  45.  
  46. #define TB_FASTCALL             /* __fastcall */
  47.  
  48. typedef INDEX(*PfnCalcIndex) (squaret *, squaret *, squaret, int fInverse);
  49.  
  50. extern int IInitializeTb(char *pszPath);
  51. extern int FTbSetCacheSize(void *pv, unsigned long cbSize);
  52. extern void VTbCloseFiles(void);
  53. extern int IDescFindFromCounters(int *piCount);
  54. extern int FRegisteredFun(int iTb, int side);
  55. extern PfnCalcIndex PfnIndCalcFun(int iTb, int side);
  56. extern int TB_FASTCALL L_TbtProbeTable(int iTb, int side, INDEX indOffset);
  57.  
  58. #define pageL       65536
  59. #define tbbe_ssL    ((pageL-4)/2)
  60. #define bev_broken  (tbbe_ssL+1)        /* illegal or busted */
  61. #define bev_mi1     tbbe_ssL    /* mate in 1 move */
  62. #define bev_mimin   1           /* mate in max moves */
  63. #define bev_draw    0           /* draw */
  64. #define bev_limax   (-1)        /* mated in max moves */
  65. #define bev_li0     (-tbbe_ssL) /* mated in 0 moves */
  66.  
  67. #define PfnIndCalc PfnIndCalcFun
  68.  
  69. int setTablebaseCacheSize(unsigned int size)
  70. {
  71.    unsigned long numBytes = (unsigned long) size * 1024 * 1024;
  72.  
  73.    if (cache != 0)
  74.    {
  75.       free(cache);
  76.    }
  77.  
  78.    cache = malloc(numBytes);
  79.  
  80.    if (cache == 0)
  81.    {
  82.       logDebug("### Could not allocate tablebase cache (%lu bytes). ###\n",
  83.                numBytes);
  84.  
  85.       return -1;
  86.    }
  87.  
  88.    if (FTbSetCacheSize(cache, numBytes) == 0)
  89.    {
  90.       logDebug("### Could not set tablebase cache size (%lu bytes). ###\n",
  91.                numBytes);
  92.  
  93.       free(cache);
  94.       cache = 0;
  95.  
  96.       return -2;
  97.    }
  98.  
  99.    /* logDebug("table base cache size set to %lu\n", numBytes); */
  100.  
  101.    return 0;
  102. }
  103.  
  104. int initializeTablebase(const char *path)
  105. {
  106.    int result = IInitializeTb((char *) path);
  107.  
  108.    if (result > 0)
  109.    {
  110.       if (setTablebaseCacheSize(4) != 0)
  111.       {
  112.          closeTablebaseFiles();
  113.  
  114.          return -1;
  115.       }
  116.  
  117.       /* logDebug("Tablebases found at %s\n", path); */
  118.    }
  119.    else
  120.    {
  121.       logDebug("### Error while looking for tablebases in %s ###\n", path);
  122.    }
  123.  
  124.    tbAvailable = (bool) (result > 0);
  125.  
  126.    return (result > 0 ? 0 : -1);
  127. }
  128.  
  129. void closeTablebaseFiles()
  130. {
  131.    VTbCloseFiles();
  132. }
  133.  
  134. static void initializePieceData(const Bitboard * pieces, int *pieceCount,
  135.                                 unsigned int *pieceLocation)
  136. {
  137.    Bitboard tmp = *pieces;
  138.    Square square;
  139.  
  140.    *pieceCount = 0;
  141.  
  142.    ITERATE_BITBOARD(&tmp, square)
  143.    {
  144.       *(pieceLocation++) = square;
  145.       (*pieceCount)++;
  146.    }
  147. }
  148.  
  149. static int getMateValue(int fullMoves)
  150. {
  151.    if (fullMoves > 0)
  152.    {
  153.       return 1 - VALUE_MATED - 2 * fullMoves;
  154.    }
  155.    else
  156.    {
  157.       return VALUE_MATED - 2 * fullMoves;
  158.    }
  159. }
  160.  
  161. int probeTablebase(const Position * position)
  162. {
  163.    int pieceCount[10];
  164.    unsigned int whitePieces[MAX_PIECES_PER_SIDE * 5 + 1];
  165.    unsigned int blackPieces[MAX_PIECES_PER_SIDE * 5 + 1];
  166.    unsigned int *pwhite, *pblack;
  167.    int tableNr, fInvert, tableValue, fullMoves;
  168.    Color color;
  169.    INDEX index;
  170.    Square enPassantSquare = (Square) NO_EP;
  171.  
  172.    initializePieceData(&position->piecesOfType[WHITE_PAWN], &pieceCount[0],
  173.                        &whitePieces[0 * MAX_PIECES_PER_SIDE]);
  174.    initializePieceData(&position->piecesOfType[WHITE_KNIGHT], &pieceCount[1],
  175.                        &whitePieces[1 * MAX_PIECES_PER_SIDE]);
  176.    initializePieceData(&position->piecesOfType[WHITE_BISHOP], &pieceCount[2],
  177.                        &whitePieces[2 * MAX_PIECES_PER_SIDE]);
  178.    initializePieceData(&position->piecesOfType[WHITE_ROOK], &pieceCount[3],
  179.                        &whitePieces[3 * MAX_PIECES_PER_SIDE]);
  180.    initializePieceData(&position->piecesOfType[WHITE_QUEEN], &pieceCount[4],
  181.                        &whitePieces[4 * MAX_PIECES_PER_SIDE]);
  182.  
  183.    initializePieceData(&position->piecesOfType[BLACK_PAWN], &pieceCount[5],
  184.                        &blackPieces[0 * MAX_PIECES_PER_SIDE]);
  185.    initializePieceData(&position->piecesOfType[BLACK_KNIGHT], &pieceCount[6],
  186.                        &blackPieces[1 * MAX_PIECES_PER_SIDE]);
  187.    initializePieceData(&position->piecesOfType[BLACK_BISHOP], &pieceCount[7],
  188.                        &blackPieces[2 * MAX_PIECES_PER_SIDE]);
  189.    initializePieceData(&position->piecesOfType[BLACK_ROOK], &pieceCount[8],
  190.                        &blackPieces[3 * MAX_PIECES_PER_SIDE]);
  191.    initializePieceData(&position->piecesOfType[BLACK_QUEEN], &pieceCount[9],
  192.                        &blackPieces[4 * MAX_PIECES_PER_SIDE]);
  193.  
  194.    tableNr = IDescFindFromCounters(pieceCount);
  195.  
  196.    if (tableNr == 0)
  197.    {
  198.       return TABLEBASE_ERROR;
  199.    }
  200.  
  201.    whitePieces[5 * MAX_PIECES_PER_SIDE] = position->king[WHITE];
  202.    blackPieces[5 * MAX_PIECES_PER_SIDE] = position->king[BLACK];
  203.  
  204.    if (tableNr > 0)
  205.    {
  206.       color = position->activeColor;
  207.       fInvert = 0;
  208.       pwhite = whitePieces;
  209.       pblack = blackPieces;
  210.    }
  211.    else
  212.    {
  213.       color = opponent(position->activeColor);
  214.       fInvert = 1;
  215.       pwhite = blackPieces;
  216.       pblack = whitePieces;
  217.       tableNr = -tableNr;
  218.    }
  219.  
  220. #if defined __APPLE__
  221.    pthread_mutex_lock((pthread_mutex_t *) & lock);
  222. #elif defined _MSC_VER
  223.    while (lock)
  224.       Sleep (1); // allow context switching
  225.    lock = 1; // Pierre-Marie Baty -- Win32 thread locking
  226. #else
  227.    pthread_spin_lock(&lock);
  228. #endif
  229.  
  230.    if (FRegisteredFun(tableNr, color) == FALSE)
  231.    {
  232. #if defined __APPLE__
  233.       pthread_mutex_unlock((pthread_mutex_t *) & lock);
  234. #elif defined _MSC_VER
  235.       lock = 0; // Pierre-Marie Baty -- Win32 thread locking
  236. #else
  237.       pthread_spin_unlock(&lock);
  238. #endif
  239.  
  240.       return TABLEBASE_ERROR;
  241.    }
  242.  
  243.    if (position->enPassantSquare != NO_SQUARE)
  244.    {
  245.       const Bitboard attackers =
  246.          position->piecesOfType[PAWN | position->activeColor] &
  247.          generalMoves[PAWN | opponent(position->activeColor)]
  248.          [position->enPassantSquare];
  249.  
  250.       if (attackers != EMPTY_BITBOARD)
  251.       {
  252.          /*
  253.             dumpSquare(position->enPassantSquare);
  254.             dumpPosition(position);
  255.           */
  256.  
  257.          enPassantSquare = position->enPassantSquare;
  258.       }
  259.    }
  260.  
  261.    index = PfnIndCalcFun(tableNr, color)
  262.       (pwhite, pblack, enPassantSquare, fInvert);
  263.  
  264.    tableValue = L_TbtProbeTable(tableNr, color, index);
  265.  
  266. #if defined __APPLE__
  267.    pthread_mutex_unlock((pthread_mutex_t *) & lock);
  268. #elif defined _MSC_VER
  269.    lock = 0; // Pierre-Marie Baty -- Win32 thread locking
  270. #else
  271.    pthread_spin_unlock(&lock);
  272. #endif
  273.  
  274.    if (tableValue == bev_broken)
  275.    {
  276.       return TABLEBASE_ERROR;
  277.    }
  278.  
  279.    if (tableValue == 0)
  280.    {
  281.       return 0;
  282.    }
  283.  
  284.    fullMoves = (tableValue > 0 ?
  285.                 1 + tbbe_ssL - tableValue : bev_li0 - tableValue);
  286.  
  287.    return getMateValue(fullMoves);
  288. }
  289.  
  290. int initializeModuleTablebase()
  291. {
  292. #if defined __APPLE__
  293.    pthread_mutex_init((pthread_mutex_t *) & lock, tbAccessCount);
  294. #elif defined _MSC_VER
  295.    lock = 0; // Pierre-Marie Baty -- Win32 thread locking
  296. #else
  297.    pthread_spin_init(&lock, tbAccessCount);
  298. #endif
  299.  
  300.    if (commandlineOptions.tablebasePath != 0)
  301.    {
  302.       return initializeTablebase(commandlineOptions.tablebasePath);
  303.    }
  304.    else
  305.    {
  306.       return 0;
  307.    }
  308. }
  309.  
  310. static int testTableFinder()
  311. {
  312. #ifndef NDEBUG
  313.    Variation variation;
  314.    int tableValue;
  315.  
  316.    initializeVariation(&variation, "B6k/8/8/8/8/8/8/K6N w - - 0 1");
  317.    tableValue = probeTablebase(&variation.singlePosition);
  318.    assert(tableValue == 29941);
  319.  
  320.    initializeVariation(&variation, "B6k/8/8/8/8/8/8/K6N b - - 0 1");
  321.    tableValue = probeTablebase(&variation.singlePosition);
  322.    assert(tableValue == -29940);
  323. #endif
  324.  
  325.    return 0;
  326. }
  327.  
  328. static int testMateValues()
  329. {
  330. #ifndef NDEBUG
  331.    Variation variation;
  332.    int tableValue;
  333.  
  334.    initializeVariation(&variation, "R6k/8/6K1/8/8/8/8/8 b - - 0 1");
  335.    tableValue = probeTablebase(&variation.singlePosition);
  336.    assert(tableValue == VALUE_MATED);
  337.  
  338.    initializeVariation(&variation, "7k/8/6K1/8/8/8/8/R7 w - - 0 1");
  339.    tableValue = probeTablebase(&variation.singlePosition);
  340.    assert(tableValue == -VALUE_MATED - 1);
  341. #endif
  342.  
  343.    return 0;
  344. }
  345.  
  346. int testModuleTablebase()
  347. {
  348.    int result;
  349.  
  350.    if (tbAvailable == FALSE)
  351.    {
  352.       return 0;
  353.    }
  354.  
  355.    if (commandlineOptions.tablebasePath == 0)
  356.    {
  357.       return 0;
  358.    }
  359.  
  360.    if ((result = testTableFinder()) != 0)
  361.    {
  362.       return result;
  363.    }
  364.  
  365.    if ((result = testMateValues()) != 0)
  366.    {
  367.       return result;
  368.    }
  369.  
  370.    return 0;
  371. }
  372. #endif
  373.