Rev 108 | Details | Compare with Previous | 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 | */ |
||
| 154 | pmbaty | 66 | if (tree->counter_move[tree->curmv[ply - 1] & 4095].move1 != move) { |
| 67 | tree->counter_move[tree->curmv[ply - 1] & 4095].move2 = |
||
| 68 | tree->counter_move[tree->curmv[ply - 1] & 4095].move1; |
||
| 69 | tree->counter_move[tree->curmv[ply - 1] & 4095].move1 = move; |
||
| 108 | pmbaty | 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) { |
||
| 154 | pmbaty | 81 | if (tree->move_pair[tree->curmv[ply - 2] & 4095].move1 != move) { |
| 82 | tree->move_pair[tree->curmv[ply - 2] & 4095].move2 = |
||
| 83 | tree->move_pair[tree->curmv[ply - 2] & 4095].move1; |
||
| 84 | tree->move_pair[tree->curmv[ply - 2] & 4095].move1 = move; |
||
| 108 | pmbaty | 85 | } |
| 86 | } |
||
| 87 | /* |
||
| 88 | ************************************************************ |
||
| 89 | * * |
||
| 90 | * Adjust the history counter for the move that caused the * |
||
| 154 | pmbaty | 91 | * fail-high, limiting the max value to 2048. * |
| 108 | pmbaty | 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 * |
||
| 154 | pmbaty | 103 | * min value to 0. * |
| 108 | pmbaty | 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 | } |