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