Subversion Repositories Games.Chess Giants

Rev

Rev 33 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 33 Rev 108
Line 1... Line 1...
1
#include "chess.h"
1
#include "chess.h"
2
#include "data.h"
2
#include "data.h"
3
/* last modified 02/22/14 */
3
/* last modified 09/16/14 */
4
/*
4
/*
5
 *******************************************************************************
5
 *******************************************************************************
6
 *                                                                             *
6
 *                                                                             *
7
 *   HashProbe() is used to retrieve entries from the transposition table so   *
7
 *   HashProbe() is used to retrieve entries from the transposition table so   *
8
 *   this sub-tree won't have to be searched again if we reach a position that *
8
 *   this sub-tree won't have to be searched again if we reach a position that *
9
 *   has been searched previously.  A transposition table position contains    *
9
 *   has been searched previously.  A transposition table position contains    *
10
 *   the following data packed into 128 bits with each item taking the number  *
10
 *   the following data packed into 128 bits with each item taking the number  *
11
 *   of bits given in the table below:                                         *
11
 *   of bits given in the table below:                                         *
12
 *                                                                             *
12
 *                                                                             *
13
 *     shr  bits     name description                                          *
13
 *     shr  bits   name   description                                          *
14
 *      55   9       age  search id to identify old trans/ref entries.         *
14
 *      55    9    age    search id to identify old trans/ref entries.         *
15
 *      53   2      type  0->value is worthless; 1-> value represents a        *
15
 *      53    2    type   0->value is worthless; 1-> value represents a        *
16
 *                        fail-low bound; 2-> value represents a fail-high     *
16
 *                        fail-low bound; 2-> value represents a fail-high     *
17
 *                        bound; 3-> value is an exact score.                  *
17
 *                        bound; 3-> value is an exact score.                  *
18
 *      32  21      move  best move from the current position, according to    *
18
 *      32   21    move   best move from the current position, according to    *
19
 *                        the search at the time this position was stored.     *
19
 *                        the search at the time this position was stored.     *
20
 *      17  15     draft  the depth of the search below this position, which   *
20
 *      17   15    draft  the depth of the search below this position, which   *
21
 *                        is used to see if we can use this entry at the       *
21
 *                        is used to see if we can use this entry at the       *
22
 *                        current position.                                    *
22
 *                        current position.                                    *
23
 *       0  17     value  unsigned integer value of this position + 65536.     *
23
 *       0   17    value  unsigned integer value of this position + 65536.     *
24
 *                        this might be a good score or search bound.          *
24
 *                        this might be a good score or search bound.          *
25
 *       0  64       key  64 bit hash signature, used to verify that this      *
25
 *       0   64    key    64 bit hash signature, used to verify that this      *
26
 *                        entry goes with the current board position.          *
26
 *                        entry goes with the current board position.          *
27
 *                                                                             *
27
 *                                                                             *
28
 *   The underlying scheme here is that we use a "bucket" of N entries.  In    *
28
 *   The underlying scheme here is that we use a "bucket" of N entries.  In    *
29
 *   HashProbe() we simply compare against each of the four entries for a      *
29
 *   HashProbe() we simply compare against each of the four entries for a      *
30
 *   match.  Each "bucket" is carefully aligned to a 64-byte boundary so that  *
30
 *   match.  Each "bucket" is carefully aligned to a 64-byte boundary so that  *
Line 60... Line 60...
60
int HashProbe(TREE * RESTRICT tree, int ply, int depth, int side, int alpha,
60
int HashProbe(TREE * RESTRICT tree, int ply, int depth, int side, int alpha,
61
    int beta, int *value) {
61
    int beta, int *value) {
62
  HASH_ENTRY *htable;
62
  HASH_ENTRY *htable;
63
  HPATH_ENTRY *ptable;
63
  HPATH_ENTRY *ptable;
64
  uint64_t word1, word2, temp_hashkey;
64
  uint64_t word1, word2, temp_hashkey;
65
  int type, draft, avoid_null = 0, val, entry, i, j;
65
  int type, draft, avoid_null = 0, val, entry, i;
66
 
66
 
67
/*
67
/*
68
 ************************************************************
68
 ************************************************************
69
 *                                                          *
69
 *                                                          *
70
 *  All we have to do is loop through four entries to see   *
70
 *  All we have to do is loop through four entries to see   *
Line 74... Line 74...
74
 *                                                          *
74
 *                                                          *
75
 ************************************************************
75
 ************************************************************
76
 */
76
 */
77
  tree->hash_move[ply] = 0;
77
  tree->hash_move[ply] = 0;
78
  temp_hashkey = (side) ? HashKey : ~HashKey;
78
  temp_hashkey = (side) ? HashKey : ~HashKey;
79
  htable = trans_ref + (temp_hashkey & hash_mask);
79
  htable = hash_table + (temp_hashkey & hash_mask);
80
  for (entry = 0; entry < 4; entry++, htable++) {
80
  for (entry = 0; entry < 4; entry++) {
81
    word1 = htable->word1;
81
    word1 = htable[entry].word1;
82
    word2 = htable->word2 ^ word1;
82
    word2 = htable[entry].word2 ^ word1;
83
    if (word2 == temp_hashkey)
83
    if (word2 == temp_hashkey)
84
      break;
84
      break;
85
  }
85
  }
86
/*
86
/*
87
 ************************************************************
87
 ************************************************************
Line 112... Line 112...
112
  if (entry < 4) {
112
  if (entry < 4) {
113
    if (word1 >> 55 != transposition_age) {
113
    if (word1 >> 55 != transposition_age) {
114
      word1 =
114
      word1 =
115
          (word1 & 0x007fffffffffffffull) | ((uint64_t) transposition_age <<
115
          (word1 & 0x007fffffffffffffull) | ((uint64_t) transposition_age <<
116
          55);
116
          55);
117
      htable->word1 = word1;
117
      htable[entry].word1 = word1;
118
      htable->word2 = word1 ^ word2;
118
      htable[entry].word2 = word1 ^ word2;
119
    }
119
    }
120
    val = (word1 & 0x1ffff) - 65536;
120
    val = (word1 & 0x1ffff) - 65536;
121
    draft = (word1 >> 17) & 0x7fff;
121
    draft = (word1 >> 17) & 0x7fff;
122
    tree->hash_move[ply] = (word1 >> 32) & 0x1fffff;
122
    tree->hash_move[ply] = (word1 >> 32) & 0x1fffff;
123
    type = (word1 >> 53) & 3;
123
    type = (word1 >> 53) & 3;
-
 
124
    if ((type & UPPER) &&
124
    if ((type & UPPER) && depth - null_depth - 1 <= draft && val < beta)
125
        depth - null_depth - depth / null_divisor - 1 <= draft && val < beta)
125
      avoid_null = AVOID_NULL_MOVE;
126
      avoid_null = AVOID_NULL_MOVE;
126
    if (depth <= draft) {
127
    if (depth <= draft) {
127
      if (val > 32000)
128
      if (val > 32000)
128
        val -= ply - 1;
129
        val -= ply - 1;
129
      else if (val < -32000)
130
      else if (val < -32000)
Line 148... Line 149...
148
 ************************************************************
149
 ************************************************************
149
 */
150
 */
150
      switch (type) {
151
      switch (type) {
151
        case EXACT:
152
        case EXACT:
152
          if (val > alpha && val < beta) {
153
          if (val > alpha && val < beta) {
153
            SavePV(tree, ply, 1 + (draft == MAX_DRAFT));
154
            SavePV(tree, ply, 1);
154
            ptable = hash_path + (temp_hashkey & hash_path_mask);
155
            ptable = hash_path + (temp_hashkey & hash_path_mask);
155
            for (i = 0; i < 16; i++, ptable++)
156
            for (entry = 0; entry < 16; entry++)
156
              if (ptable->path_sig == temp_hashkey) {
157
              if (ptable[entry].path_sig == temp_hashkey) {
-
 
158
                for (i = ply;
157
                for (j = ply; j < Min(MAXPLY - 1, ptable->hash_pathl + ply);
159
                    i < Min(MAXPLY - 1, ptable[entry].hash_pathl + ply); i++)
158
                    j++)
-
 
159
                  tree->pv[ply - 1].path[j] =
160
                  tree->pv[ply - 1].path[i] =
160
                      ptable->hash_path_moves[j - ply];
161
                      ptable[entry].hash_path_moves[i - ply];
161
                if (draft != MAX_DRAFT &&
-
 
162
                    ptable->hash_pathl + ply < MAXPLY - 1)
162
                if (ptable[entry].hash_pathl + ply < MAXPLY - 1)
163
                  tree->pv[ply - 1].pathh = 0;
163
                  tree->pv[ply - 1].pathh = 0;
164
                tree->pv[ply - 1].pathl =
164
                tree->pv[ply - 1].pathl =
165
                    Min(MAXPLY - 1, ply + ptable->hash_pathl);
165
                    Min(MAXPLY - 1, ply + ptable[entry].hash_pathl);
166
                ptable->hash_path_age = transposition_age;
166
                ptable[entry].hash_path_age = transposition_age;
167
                break;
167
                break;
168
              }
168
              }
169
          }
169
          }
170
          return HASH_HIT;
170
          return HASH_HIT;
171
        case UPPER:
171
        case UPPER:
Line 181... Line 181...
181
    return avoid_null;
181
    return avoid_null;
182
  }
182
  }
183
  return HASH_MISS;
183
  return HASH_MISS;
184
}
184
}
185
 
185
 
186
/* last modified 02/22/14 */
186
/* last modified 09/16/14 */
187
/*
187
/*
188
 *******************************************************************************
188
 *******************************************************************************
189
 *                                                                             *
189
 *                                                                             *
190
 *   HashStore() is used to store entries into the transposition table so that *
190
 *   HashStore() is used to store entries into the transposition table so that *
191
 *   this sub-tree won't have to be searched again if the same position is     *
191
 *   this sub-tree won't have to be searched again if the same position is     *
192
 *   reached.  We basically store three types of entries:                      *
192
 *   reached.  We basically store three types of entries:                      *
193
 *                                                                             *
193
 *                                                                             *
194
 *     (1) EXACT.  This entry is stored when we complete a search at some ply  *
194
 *     (1) EXACT.  This entry is stored when we complete a search at some ply  *
195
 *        and end up with a score that is greater than alpha and less than     *
195
 *          and end up with a score that is greater than alpha and less than   *
196
 *        beta, which is an exact score, which also has a best move to try if  *
196
 *          beta, which is an exact score, which also has a best move to try   *
197
 *        we encounter this position again.                                    *
197
 *          if we encounter this position again.                               *
198
 *                                                                             *
198
 *                                                                             *
199
 *     (2) LOWER.  This entry is stored when we complete a search at some ply  *
199
 *     (2) LOWER.  This entry is stored when we complete a search at some ply  *
200
 *        and end up with a score that is greater than or equal to beta.  We   *
200
 *          and end up with a score that is greater than or equal to beta.  We *
201
 *        know know that this score should be at least equal to beta and may   *
201
 *          know know that this score should be at least equal to beta and may *
202
 *        well be even higher.  So this entry represents a lower bound on the  *
202
 *          well be even higher.  So this entry represents a lower bound on    *
203
 *        score for this node, and we also have a good move to try since it    *
203
 *          the score for this node, and we also have a good move to try since *
204
 *        caused the cutoff, although we do not know if it is the best move or *
204
 *          it caused the cutoff, although we do not know if it is the best    *
205
 *        not since not all moves were search.                                 *
205
 *          move or not since not all moves were search.                       *
206
 *                                                                             *
206
 *                                                                             *
207
 *     (3) UPPER.  This entry is stored when we complete a search at some ply  *
207
 *     (3) UPPER.  This entry is stored when we complete a search at some ply  *
208
 *        and end up with a score that is less than or equal to alpha.  We     *
208
 *          and end up with a score that is less than or equal to alpha.  We   *
209
 *        know know that this score should be at least equal to alpha and may  *
209
 *          know know that this score should be at least equal to alpha and    *
210
 *        well be even lower.  So this entry represents an upper bound on the  *
210
 *          may well be even lower.  So this entry represents an upper bound   *
211
 *        score for this node.  We have no idea about which move is best in    *
211
 *          on the score for this node.  We have no idea about which move is   *
212
 *        this position since they all failed low, so we store a best move of  *
212
 *          best in this position since they all failed low, so we store a     *
213
 *        zero.                                                                *
213
 *          best move of zero.                                                 *
214
 *                                                                             *
214
 *                                                                             *
215
 *   For storing, we may require three passes.  We make our first pass looking *
215
 *   For storing, we may require three passes.  We make our first pass looking *
216
 *   for an entry that matches the current hash signature.  If we find a match *
216
 *   for an entry that matches the current hash signature.  If we find a match *
217
 *   then we are constrained to overwrite that entry regardless of any other   *
217
 *   then we are constrained to overwrite that entry regardless of any other   *
218
 *   considerations.  The second pass looks for entries stored in previous     *
218
 *   considerations.  The second pass looks for entries stored in previous     *
Line 274... Line 274...
274
 *    overwrite, we simply choose the entry from the bucket *
274
 *    overwrite, we simply choose the entry from the bucket *
275
 *    with the smallest draft and overwrite that.           *
275
 *    with the smallest draft and overwrite that.           *
276
 *                                                          *
276
 *                                                          *
277
 ************************************************************
277
 ************************************************************
278
 */
278
 */
279
  htable = trans_ref + (temp_hashkey & hash_mask);
279
  htable = hash_table + (temp_hashkey & hash_mask);
280
  for (entry = 0; entry < 4; entry++, htable++) {
280
  for (entry = 0; entry < 4; entry++) {
281
    if (temp_hashkey == (htable->word1 ^ htable->word2)) {
281
    if (temp_hashkey == (htable[entry].word1 ^ htable[entry].word2)) {
282
      replace = htable;
282
      replace = htable + entry;
283
      break;
283
      break;
284
    }
284
    }
285
  }
285
  }
286
  if (!replace) {
286
  if (!replace) {
287
    replace_draft = 99999;
287
    replace_draft = 99999;
288
    htable = trans_ref + (temp_hashkey & hash_mask);
-
 
289
    for (entry = 0; entry < 4; entry++, htable++) {
288
    for (entry = 0; entry < 4; entry++) {
290
      age = htable->word1 >> 55;
289
      age = htable[entry].word1 >> 55;
291
      draft = (htable->word1 >> 17) & 0x7fff;
290
      draft = (htable[entry].word1 >> 17) & 0x7fff;
292
      if (age != transposition_age && replace_draft > draft) {
291
      if (age != transposition_age && replace_draft > draft) {
293
        replace = htable;
292
        replace = htable + entry;
294
        replace_draft = draft;
293
        replace_draft = draft;
295
      }
294
      }
296
    }
295
    }
297
    if (!replace) {
296
    if (!replace) {
298
      htable = trans_ref + (temp_hashkey & hash_mask);
-
 
299
      for (entry = 0; entry < 4; entry++, htable++) {
297
      for (entry = 0; entry < 4; entry++) {
300
        draft = (htable->word1 >> 17) & 0x7fff;
298
        draft = (htable[entry].word1 >> 17) & 0x7fff;
301
        if (replace_draft > draft) {
299
        if (replace_draft > draft) {
302
          replace = htable;
300
          replace = htable + entry;
303
          replace_draft = draft;
301
          replace_draft = draft;
304
        }
302
        }
305
      }
303
      }
306
    }
304
    }
307
  }
305
  }
Line 341... Line 339...
341
      }
339
      }
342
    }
340
    }
343
  }
341
  }
344
}
342
}
345
 
343
 
346
/* last modified 02/22/14 */
344
/* last modified 09/16/14 */
347
/*
345
/*
348
 *******************************************************************************
346
 *******************************************************************************
349
 *                                                                             *
347
 *                                                                             *
350
 *   HashStorePV() is called by Iterate() to insert the PV moves so they will  *
348
 *   HashStorePV() is called by Iterate() to insert the PV moves so they will  *
351
 *   be searched before any other moves.  Normally the PV moves would be in    *
349
 *   be searched before any other moves.  Normally the PV moves would be in    *
Line 401... Line 399...
401
 *    overwrite, we simply choose the entry from the bucket *
399
 *    overwrite, we simply choose the entry from the bucket *
402
 *    with the smallest draft and overwrite that.           *
400
 *    with the smallest draft and overwrite that.           *
403
 *                                                          *
401
 *                                                          *
404
 ************************************************************
402
 ************************************************************
405
 */
403
 */
406
  htable = trans_ref + (temp_hashkey & hash_mask);
404
  htable = hash_table + (temp_hashkey & hash_mask);
407
  for (entry = 0; entry < 4; entry++, htable++) {
405
  for (entry = 0; entry < 4; entry++) {
408
    if ((htable->word2 ^ htable->word1) == temp_hashkey) {
406
    if ((htable[entry].word2 ^ htable[entry].word1) == temp_hashkey) {
409
      htable->word1 &= ~((uint64_t) 0x1fffff << 32);
407
      htable[entry].word1 &= ~((uint64_t) 0x1fffff << 32);
410
      htable->word1 |= (uint64_t) tree->pv[0].path[ply] << 32;
408
      htable[entry].word1 |= (uint64_t) tree->pv[0].path[ply] << 32;
411
      htable->word2 = temp_hashkey ^ htable->word1;
409
      htable[entry].word2 = temp_hashkey ^ htable[entry].word1;
412
      break;
410
      break;
413
    }
411
    }
414
  }
412
  }
415
  if (entry == 4) {
413
  if (entry == 4) {
416
    htable = trans_ref + (temp_hashkey & hash_mask);
-
 
417
    replace = 0;
414
    replace = 0;
418
    replace_draft = 99999;
415
    replace_draft = 99999;
419
    for (entry = 0; entry < 4; entry++, htable++) {
416
    for (entry = 0; entry < 4; entry++) {
420
      age = htable->word1 >> 55;
417
      age = htable[entry].word1 >> 55;
421
      draft = (htable->word1 >> 17) & 0x7fff;
418
      draft = (htable[entry].word1 >> 17) & 0x7fff;
422
      if (age != transposition_age && replace_draft > draft) {
419
      if (age != transposition_age && replace_draft > draft) {
423
        replace = htable;
420
        replace = htable + entry;
424
        replace_draft = draft;
421
        replace_draft = draft;
425
      }
422
      }
426
    }
423
    }
427
    if (!replace) {
424
    if (!replace) {
428
      htable = trans_ref + (temp_hashkey & hash_mask);
-
 
429
      for (entry = 0; entry < 4; entry++, htable++) {
425
      for (entry = 0; entry < 4; entry++) {
430
        draft = (htable->word1 >> 17) & 0x7fff;
426
        draft = (htable[entry].word1 >> 17) & 0x7fff;
431
        if (replace_draft > draft) {
427
        if (replace_draft > draft) {
432
          replace = htable;
428
          replace = htable + entry;
433
          replace_draft = draft;
429
          replace_draft = draft;
434
        }
430
        }
435
      }
431
      }
436
    }
432
    }
437
    replace->word1 = word1;
433
    replace->word1 = word1;