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