💾 Archived View for runjimmyrunrunyoufuckerrun.com › src › games › chessengines › crafty › history.c captured on 2021-12-17 at 13:26:06.

View Raw

More Information

-=-=-=-=-=-=-

#include "chess.h"
#include "data.h"
/* last modified 08/15/15 */
/*
 *******************************************************************************
 *                                                                             *
 *   History() is used to maintain the two killer moves for each ply.  The     *
 *   most recently used killer is always first in the list.                    *
 *                                                                             *
 *   History() also maintains two counter-moves.  These are moves that are     *
 *   directly used to refute a specific move at the previous ply, rather than  *
 *   just a plain killer that has caused cutoffs previously.                   *
 *                                                                             *
 *   History() finally remembers two moves that were played after a specific   *
 *   move at ply-2 (ie the two moves together create some sort of "plan".)     *
 *                                                                             *
 *   History() also maintains the history counters.  Each time a move fails    *
 *   high, it's history count is increased, while all other moves that were    *
 *   searched will have their counts reduced.  The current counter is a        *
 *   saturating counter in the range 0 <= N <= 2047.                           *
 *                                                                             *
 *******************************************************************************
 */
void History(TREE * RESTRICT tree, int ply, int depth, int side, int move,
    int searched[]) {
  int i, index, mindex;
/*
 ************************************************************
 *                                                          *
 *  Now, add this move to the current killer moves if it is *
 *  not already there.  If the move is already first in the *
 *  list, leave it there, otherwise move the first one down *
 *  to slot two and insert this move into slot one.         *
 *                                                          *
 *  If the best move so far is a capture or a promotion,    *
 *  we skip updating the killers (but still update history  *
 *  information) since we search good captures first, which *
 *  happens before killers are tried, making capture moves  *
 *  useless here.                                           *
 *                                                          *
 *  The update value does not depend on depth.  I used a    *
 *  function of depth for years, but as I examined more and *
 *  more trees, that seemed to be lacking because it gives  *
 *  a really large bias towards moves that work near the    *
 *  root, while most of the nodes searched are near the     *
 *  tips.  One unusual characteristic of this counter is    *
 *  that it is a software-based saturating counter.  That   *
 *  is, it can never exceed 2047, nor can it ever drop      *
 *  below zero.                                             *
 *                                                          *
 ************************************************************
 */
  if (!CaptureOrPromote(move)) {
    if (tree->killers[ply].move1 != move) {
      tree->killers[ply].move2 = tree->killers[ply].move1;
      tree->killers[ply].move1 = move;
    }
/*
 ************************************************************
 *                                                          *
 *  Set the counter-move for the move at the previous ply   *
 *  to be this move that caused the fail-high.              *
 *                                                          *
 ************************************************************
 */
    if (counter_move[tree->curmv[ply - 1] & 4095].move1 != move) {
      counter_move[tree->curmv[ply - 1] & 4095].move2 =
          counter_move[tree->curmv[ply - 1] & 4095].move1;
      counter_move[tree->curmv[ply - 1] & 4095].move1 = move;
    }
/*
 ************************************************************
 *                                                          *
 *  Set the move-pair for the move two plies back so that   *
 *  if we play that move again, we will follow up with this *
 *  move to continue the "plan".                            *
 *                                                          *
 ************************************************************
 */
    if (ply > 2) {
      if (move_pair[tree->curmv[ply - 2] & 4095].move1 != move) {
        move_pair[tree->curmv[ply - 2] & 4095].move2 =
            move_pair[tree->curmv[ply - 2] & 4095].move1;
        move_pair[tree->curmv[ply - 2] & 4095].move1 = move;
      }
    }
/*
 ************************************************************
 *                                                          *
 *  Adjust the history counter for the move that caused the *
 *  fail-high, limiting the max value to +2^20.             *
 *                                                          *
 ************************************************************
 */
    if (depth > 5) {
      mindex = HistoryIndex(side, move);
      history[mindex] += (2048 - history[mindex]) >> 5;
/*
 ************************************************************
 *                                                          *
 *  Adjust the history counters for the moves that were     *
 *  searched but did not cause a fail-high, limiting the    *
 *  min value to -2^20.                                     *
 *                                                          *
 ************************************************************
 */
      for (i = 1; i <= searched[0]; i++) {
        index = HistoryIndex(side, searched[i]);
        if (index != mindex)
          history[index] -= history[index] >> 5;
      }
    }
  }
}