1 /* DreamChess
2 **
3 ** DreamChess is the legal property of its developers, whose names are too
4 ** numerous to list here. Please refer to the AUTHORS.txt file distributed
5 ** with this source distribution.
6 **
7 ** This program is free software: you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation, either version 3 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdlib.h>
22
23 #include "board.h"
24 #include "move.h"
25 #include "repetition.h"
26
27 typedef struct rep_list {
28 /* FIXME */
29 long long position[101 + 100];
30 int head;
31 } rep_list_t;
32
33 static rep_list_t *hist;
34 static int hist_idx;
35 static rep_list_t *cur_list;
36
repetition_init(board_t * board)37 void repetition_init(board_t *board) {
38 hist = malloc(sizeof(rep_list_t));
39 hist_idx = 0;
40 cur_list = &hist[0];
41 cur_list->position[0] = board->hash_key;
42 cur_list->head = 1;
43 }
44
repetition_exit(void)45 void repetition_exit(void) {
46 free(hist);
47 }
48
repetition_add(board_t * board,move_t move)49 void repetition_add(board_t *board, move_t move) {
50 if ((MOVE_GET(move, TYPE) != NORMAL_MOVE) || ((MOVE_GET(move, PIECE) & PIECE_MASK) == PAWN)) {
51 hist_idx++;
52 hist = realloc(hist, sizeof(rep_list_t) * (hist_idx + 1));
53 cur_list = &hist[hist_idx];
54 cur_list->position[0] = board->hash_key;
55 cur_list->head = 1;
56 } else
57 cur_list->position[cur_list->head++] = board->hash_key;
58 }
59
repetition_remove(void)60 void repetition_remove(void) {
61 if (cur_list->head > 1)
62 cur_list->head--;
63 else if (hist_idx > 0) {
64 hist_idx--;
65 cur_list = &hist[hist_idx];
66 }
67 }
68
is_repetition(board_t * board,int ply)69 int is_repetition(board_t *board, int ply) {
70 int i;
71 int cur_head = cur_list->head + ply;
72
73 /* We won't go out of bounds here because of the 50-move rule. */
74 cur_list->position[cur_head] = board->hash_key;
75
76 if (cur_head < 4)
77 return 0;
78
79 /* We only check for two occurrences to prevent transposition table
80 ** hits that lead to a third repetition without us knowing about it.
81 */
82 for (i = cur_head - 2; i >= 0; i -= 2)
83 if (board->hash_key == cur_list->position[i])
84 return 1;
85
86 return 0;
87 }
88
is_draw(board_t * board)89 int is_draw(board_t *board) {
90 int i;
91 int count = 0;
92
93 /* 50 move rule. */
94 if (board->fifty_moves == 100)
95 return 2;
96
97 if (cur_list->head < 9)
98 return 0;
99
100 for (i = cur_list->head - 3; i >= 0; i -= 2) {
101 if (cur_list->position[cur_list->head - 1] == cur_list->position[i])
102 count++;
103 if (count == 2)
104 return 1;
105 }
106
107 return 0;
108 }
109