Go to most recent revision | Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line | 
|---|---|---|---|
| 108 | pmbaty | 1 | #include "chess.h" | 
| 2 | #include "data.h" | ||
| 3 | /* last modified 08/15/15 */ | ||
| 4 | /* | ||
| 5 |  ******************************************************************************* | ||
| 6 |  *                                                                             * | ||
| 7 |  *   History() is used to maintain the two killer moves for each ply.  The     * | ||
| 8 |  *   most recently used killer is always first in the list.                    * | ||
| 9 |  *                                                                             * | ||
| 10 |  *   History() also maintains two counter-moves.  These are moves that are     * | ||
| 11 |  *   directly used to refute a specific move at the previous ply, rather than  * | ||
| 12 |  *   just a plain killer that has caused cutoffs previously.                   * | ||
| 13 |  *                                                                             * | ||
| 14 |  *   History() finally remembers two moves that were played after a specific   * | ||
| 15 |  *   move at ply-2 (ie the two moves together create some sort of "plan".)     * | ||
| 16 |  *                                                                             * | ||
| 17 |  *   History() also maintains the history counters.  Each time a move fails    * | ||
| 18 |  *   high, it's history count is increased, while all other moves that were    * | ||
| 19 |  *   searched will have their counts reduced.  The current counter is a        * | ||
| 20 |  *   saturating counter in the range 0 <= N <= 2047.                           * | ||
| 21 |  *                                                                             * | ||
| 22 |  ******************************************************************************* | ||
| 23 |  */ | ||
| 24 | void History(TREE * RESTRICT tree, int ply, int depth, int side, int move, | ||
| 25 | int searched[]) { | ||
| 26 | int i, index, mindex; | ||
| 27 | /* | ||
| 28 |  ************************************************************ | ||
| 29 |  *                                                          * | ||
| 30 |  *  Now, add this move to the current killer moves if it is * | ||
| 31 |  *  not already there.  If the move is already first in the * | ||
| 32 |  *  list, leave it there, otherwise move the first one down * | ||
| 33 |  *  to slot two and insert this move into slot one.         * | ||
| 34 |  *                                                          * | ||
| 35 |  *  If the best move so far is a capture or a promotion,    * | ||
| 36 |  *  we skip updating the killers (but still update history  * | ||
| 37 |  *  information) since we search good captures first, which * | ||
| 38 |  *  happens before killers are tried, making capture moves  * | ||
| 39 |  *  useless here.                                           * | ||
| 40 |  *                                                          * | ||
| 41 |  *  The update value does not depend on depth.  I used a    * | ||
| 42 |  *  function of depth for years, but as I examined more and * | ||
| 43 |  *  more trees, that seemed to be lacking because it gives  * | ||
| 44 |  *  a really large bias towards moves that work near the    * | ||
| 45 |  *  root, while most of the nodes searched are near the     * | ||
| 46 |  *  tips.  One unusual characteristic of this counter is    * | ||
| 47 |  *  that it is a software-based saturating counter.  That   * | ||
| 48 |  *  is, it can never exceed 2047, nor can it ever drop      * | ||
| 49 |  *  below zero.                                             * | ||
| 50 |  *                                                          * | ||
| 51 |  ************************************************************ | ||
| 52 |  */ | ||
| 53 | if (!CaptureOrPromote(move)) { | ||
| 54 | if (tree->killers[ply].move1 != move) { | ||
| 55 | tree->killers[ply].move2 = tree->killers[ply].move1; | ||
| 56 | tree->killers[ply].move1 = move; | ||
| 57 |     } | ||
| 58 | /* | ||
| 59 |  ************************************************************ | ||
| 60 |  *                                                          * | ||
| 61 |  *  Set the counter-move for the move at the previous ply   * | ||
| 62 |  *  to be this move that caused the fail-high.              * | ||
| 63 |  *                                                          * | ||
| 64 |  ************************************************************ | ||
| 65 |  */ | ||
| 66 | if (counter_move[tree->curmv[ply - 1] & 4095].move1 != move) { | ||
| 67 | counter_move[tree->curmv[ply - 1] & 4095].move2 = | ||
| 68 | counter_move[tree->curmv[ply - 1] & 4095].move1; | ||
| 69 | counter_move[tree->curmv[ply - 1] & 4095].move1 = move; | ||
| 70 |     } | ||
| 71 | /* | ||
| 72 |  ************************************************************ | ||
| 73 |  *                                                          * | ||
| 74 |  *  Set the move-pair for the move two plies back so that   * | ||
| 75 |  *  if we play that move again, we will follow up with this * | ||
| 76 |  *  move to continue the "plan".                            * | ||
| 77 |  *                                                          * | ||
| 78 |  ************************************************************ | ||
| 79 |  */ | ||
| 80 | if (ply > 2) { | ||
| 81 | if (move_pair[tree->curmv[ply - 2] & 4095].move1 != move) { | ||
| 82 | move_pair[tree->curmv[ply - 2] & 4095].move2 = | ||
| 83 | move_pair[tree->curmv[ply - 2] & 4095].move1; | ||
| 84 | move_pair[tree->curmv[ply - 2] & 4095].move1 = move; | ||
| 85 |       } | ||
| 86 |     } | ||
| 87 | /* | ||
| 88 |  ************************************************************ | ||
| 89 |  *                                                          * | ||
| 90 |  *  Adjust the history counter for the move that caused the * | ||
| 91 |  *  fail-high, limiting the max value to +2^20.             * | ||
| 92 |  *                                                          * | ||
| 93 |  ************************************************************ | ||
| 94 |  */ | ||
| 95 | if (depth > 5) { | ||
| 96 | mindex = HistoryIndex(side, move); | ||
| 97 | history[mindex] += (2048 - history[mindex]) >> 5; | ||
| 98 | /* | ||
| 99 |  ************************************************************ | ||
| 100 |  *                                                          * | ||
| 101 |  *  Adjust the history counters for the moves that were     * | ||
| 102 |  *  searched but did not cause a fail-high, limiting the    * | ||
| 103 |  *  min value to -2^20.                                     * | ||
| 104 |  *                                                          * | ||
| 105 |  ************************************************************ | ||
| 106 |  */ | ||
| 107 | for (i = 1; i <= searched[0]; i++) { | ||
| 108 | index = HistoryIndex(side, searched[i]); | ||
| 109 | if (index != mindex) | ||
| 110 | history[index] -= history[index] >> 5; | ||
| 111 |       } | ||
| 112 |     } | ||
| 113 |   } | ||
| 114 | } |