Rev 33 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 33 | pmbaty | 1 | #include "chess.h" |
| 2 | #include "data.h" |
||
| 108 | pmbaty | 3 | /* last modified 04/29/15 */ |
| 33 | pmbaty | 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) { |
||
| 108 | pmbaty | 35 | int where, count; |
| 33 | pmbaty | 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 | */ |
||
| 108 | pmbaty | 48 | tree->rep_list[rep_index + ply] = HashKey; |
| 33 | pmbaty | 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 | */ |
||
| 108 | pmbaty | 68 | count = Reversible(ply) / 2 - 1; |
| 69 | for (where = rep_index + ply - 4; count; where -= 2, count--) { |
||
| 33 | pmbaty | 70 | if (HashKey == tree->rep_list[where]) |
| 71 | return 1; |
||
| 108 | pmbaty | 72 | } |
| 33 | pmbaty | 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 | */ |
||
| 108 | pmbaty | 88 | int Repeat3x(TREE * RESTRICT tree) { |
| 89 | int reps = 0, where; |
||
| 33 | pmbaty | 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 | */ |
||
| 108 | pmbaty | 112 | for (where = rep_index % 2; where < rep_index; where += 2) |
| 33 | pmbaty | 113 | if (HashKey == tree->rep_list[where]) |
| 114 | reps++; |
||
| 115 | return reps == 2; |
||
| 116 | } |