Subversion Repositories Games.Chess Giants

Rev

Rev 33 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "chess.h"
  2. #include "data.h"
  3. /* last modified 04/29/15 */
  4. /*
  5.  *******************************************************************************
  6.  *                                                                             *
  7.  *   Repeat() is used to detect a draw by repetition.  The repetition list is  *
  8.  *   a simple 1d array that contains the Zobrist signatures for each position  *
  9.  *   reached in the game since the last irreversable moves at the root.  New   *
  10.  *   positions are only added to this list here in Repeat().                   *
  11.  *                                                                             *
  12.  *   Repeat() scans the list to determine if this position has occurred at     *
  13.  *   once previously (two-fold repetition.)  If so, this will be treated as a  *
  14.  *   draw by Search()/Quiesce().                                               *
  15.  *                                                                             *
  16.  *   Repeat() also handles 50-move draws.  The position[] structure contains   *
  17.  *   the count of moves since the last capture or pawn push.  When this value  *
  18.  *   reaches 100 (plies, which is 50 moves) the score is set to DRAW.          *
  19.  *                                                                             *
  20.  *   Repeat() has one tricky issue.  MakeMoveRoot() has to insert moves into   *
  21.  *   the repetition list so that things will work well.  We end up with the    *
  22.  *   list having entries from 0 through "rep_index" where the last entry is    *
  23.  *   the entry stored after the last actual move in the game.  Search() will   *
  24.  *   call Repeat() at ply=1, which stores the SAME position at position        *
  25.  *   rep_index + 1.  That gets the list out of sync.  To solve this, Iterate() *
  26.  *   decrements rep_index immediately prior to calling Search(), and it then   *
  27.  *   increments it immediately after Search() returns.  This causes Search()   *
  28.  *   to overwrite the entry with the same value for ply=1, but now the list is *
  29.  *   in a sane state for the rest of the search.  Do NOT remove those to lines *
  30.  *   in Iterate() or repetition detection will be broken.                      *
  31.  *                                                                             *
  32.  *******************************************************************************
  33.  */
  34. int Repeat(TREE * RESTRICT tree, int ply) {
  35.   int where, count;
  36.  
  37. /*
  38.  ************************************************************
  39.  *                                                          *
  40.  *  If the 50-move rule has been reached, then adjust the   *
  41.  *  score to reflect the impending draw.  If we have not    *
  42.  *  made 2 moves for each side (or more) since the last     *
  43.  *  irreversible move, there is no way to repeat a prior    *
  44.  *  position.                                               *
  45.  *                                                          *
  46.  ************************************************************
  47.  */
  48.   tree->rep_list[rep_index + ply] = HashKey;
  49.   if (Reversible(ply) < 4)
  50.     return 0;
  51.   if (Reversible(ply) > 99)
  52.     return 2;
  53. /*
  54.  ************************************************************
  55.  *                                                          *
  56.  *  Now we scan the right part of the repetition list,      *
  57.  *  which is to search backward from the entry for 2 plies  *
  58.  *  back (no point in checking current position, we KNOW    *
  59.  *  that is a match but it is not a repetition, it is just  *
  60.  *  the current position's entry which we don't want to     *
  61.  *  check).  We can use the reversible move counter as a    *
  62.  *  limit since there is no point in scanning the list back *
  63.  *  beyond the last capture/pawn move since there can not   *
  64.  *  possibly be a repeat beyond that point.                 *
  65.  *                                                          *
  66.  ************************************************************
  67.  */
  68.   count = Reversible(ply) / 2 - 1;
  69.   for (where = rep_index + ply - 4; count; where -= 2, count--) {
  70.     if (HashKey == tree->rep_list[where])
  71.       return 1;
  72.   }
  73.   return 0;
  74. }
  75.  
  76. /* last modified 05/08/14 */
  77. /*
  78.  *******************************************************************************
  79.  *                                                                             *
  80.  *   Repeat3x() is used to detect a real draw by repetition.  This routine is  *
  81.  *   only called from Main() and simply scans the complete list searching for  *
  82.  *   exactly three repetitions (two additional repetitions of the current      *
  83.  *   position.)  This is used to actually claim a draw by repetition or by the *
  84.  *   50 move rule.                                                             *
  85.  *                                                                             *
  86.  *******************************************************************************
  87.  */
  88. int Repeat3x(TREE * RESTRICT tree) {
  89.   int reps = 0, where;
  90.  
  91. /*
  92.  ************************************************************
  93.  *                                                          *
  94.  *  If the 50-move rule has been reached, then return an    *
  95.  *  indicator that a draw can be claimed if wanted.         *
  96.  *                                                          *
  97.  ************************************************************
  98.  */
  99.   if (Reversible(0) > 99)
  100.     return 2;
  101. /*
  102.  ************************************************************
  103.  *                                                          *
  104.  *  Scan the repetition list to determine if this position  *
  105.  *  has occurred two times previously, making this an       *
  106.  *  actual 3-fold repetition.  Note we only check every     *
  107.  *  other entry since the position has to be repeated 3x    *
  108.  *  with the SAME side on move.                             *
  109.  *                                                          *
  110.  ************************************************************
  111.  */
  112.   for (where = rep_index % 2; where < rep_index; where += 2)
  113.     if (HashKey == tree->rep_list[where])
  114.       reps++;
  115.   return reps == 2;
  116. }
  117.