Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
112 pmbaty 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