1 // search.c
2
3 // includes
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include "attack.h"
10 #include "board.h"
11 #include "colour.h"
12 #include "engine.h"
13 #include "fen.h"
14 #include "line.h"
15 #include "list.h"
16 #include "move.h"
17 #include "move_do.h"
18 #include "move_gen.h"
19 #include "move_legal.h"
20 #include "option.h"
21 #include "parse.h"
22 #include "san.h"
23 #include "search.h"
24 #include "uci.h"
25 #include "util.h"
26
27 // variables
28
29 static int Depth;
30
31 static int BestMove;
32 static int BestValue;
33 static move_t BestPV[LineSize];
34
35 static sint64 NodeNb;
36 static sint64 LeafNb;
37 static double Time;
38
39 static int Move;
40 static int MovePos;
41 static int MoveNb;
42
43 // prototypes
44
45 static bool depth_is_ok (int depth);
46 static void perft (const board_t * board, int depth);
47
48 // functions
49
50 // depth_is_ok()
51
depth_is_ok(int depth)52 static bool depth_is_ok(int depth) {
53
54 return depth >= 0 && depth < DepthMax;
55 }
56
57 // search()
58
search(const board_t * board,int depth_max,double time_max)59 void search(const board_t * board, int depth_max, double time_max) {
60
61 char string[256];
62
63 ASSERT(board_is_ok(board));
64 ASSERT(depth_max>=1&&depth_max<DepthMax);
65 ASSERT(time_max>=0.0);
66
67 // engine
68
69 Depth = 0;
70
71 BestMove = MoveNone;
72 BestValue = 0;
73 line_clear(BestPV);
74
75 NodeNb = 0;
76 LeafNb = 0;
77 Time = 0.0;
78
79 Move = MoveNone;
80 MovePos = 0;
81 MoveNb = 0;
82
83 // init
84
85 uci_send_ucinewgame(Uci);
86 uci_send_isready_sync(Uci);
87
88 // position
89
90 if (!board_to_fen(board,string,256)) ASSERT(FALSE);
91 engine_send(Engine,"position fen %s",string);
92
93 // search
94
95 engine_send_queue(Engine,"go");
96
97 engine_send_queue(Engine," movetime %.0f",time_max*1000.0);
98 engine_send_queue(Engine," depth %d",depth_max);
99
100 engine_send(Engine,""); // newline
101
102 // wait for feed-back
103
104 while (!engine_eof(Engine)) {
105
106 engine_get(Engine,string);
107
108 if (FALSE) {
109
110 } else if (match(string,"bestmove * ponder *")) {
111
112 BestMove = move_from_can(Star[0],board);
113 ASSERT(BestMove!=MoveNone&&move_is_legal(BestMove,board));
114
115 break;
116
117 } else if (match(string,"bestmove *")) {
118
119 BestMove = move_from_can(Star[0],board);
120 ASSERT(BestMove!=MoveNone&&move_is_legal(BestMove,board));
121
122 break;
123 }
124 }
125
126 printf("\n");
127 }
128
129 // do_perft()
130
do_perft(int argc,char * argv[])131 void do_perft(int argc,char * argv[]){
132 const char * fen=NULL;
133 int depth=1;
134 board_t board[1];
135 int i;
136 for (i = 1; i < argc; i++) {
137 if (FALSE) {
138 } else if (my_string_equal(argv[i],"perft")) {
139 // skip
140 } else if (my_string_equal(argv[i],"-fen")) {
141 i++;
142 if (argv[i] == NULL) my_fatal("do_perft(): missing argument\n");
143 my_string_set(&fen,argv[i]);
144 } else if (my_string_equal(argv[i],"-max-depth")){
145 i++;
146 if (argv[i] == NULL) my_fatal("do_perft(): missing argument\n");
147 depth=atoi(argv[i]);
148 if(depth<1) my_fatal("do_perft(): illegal depth %d\n",depth);
149 } else {
150 my_fatal("do_perft(): unknown option \"%s\"\n",argv[i]);
151 }
152 }
153 if(fen==NULL){
154 my_string_set(&fen,StartFen);
155 }
156 board_from_fen(board,fen);
157 search_perft(board,depth);
158 }
159
160 // search_perft()
161
search_perft(const board_t * board,int depth_max)162 void search_perft(const board_t * board, int depth_max) {
163
164 int depth;
165 my_timer_t timer[1];
166 double time, speed;
167 char node_string[StringSize];
168 char leafnode_string[StringSize];
169
170 ASSERT(board_is_ok(board));
171 ASSERT(depth_max>=1&&depth_max<DepthMax);
172
173 // init
174
175 board_disp(board);
176
177 // iterative deepening
178
179 for (depth = 1; depth <= depth_max; depth++) {
180
181 // init
182
183 NodeNb = 0;
184 LeafNb = 0;
185
186 my_timer_reset(timer);
187
188 my_timer_start(timer);
189 perft(board,depth);
190 my_timer_stop(timer);
191
192 time = my_timer_elapsed_real(timer);//my_timer_elapsed_cpu(timer);
193 speed = (time < 0.01) ? 0.0 : ((double)NodeNb) / time;
194
195 snprintf(node_string,StringSize,S64_FORMAT,NodeNb);
196 snprintf(leafnode_string,StringSize,S64_FORMAT,LeafNb);
197
198 printf("depth=%2d nodes=%12s leafnodes=%12s time=%7.2fs nps=%8.0f\n",depth,node_string,leafnode_string,time,speed);
199 }
200
201 }
202
203 // perft()
204
perft(const board_t * board,int depth)205 static void perft(const board_t * board, int depth) {
206
207 int me;
208 list_t list[1];
209 int i, move;
210 board_t new_board[1];
211
212 ASSERT(board_is_ok(board));
213 ASSERT(depth_is_ok(depth));
214
215 ASSERT(!is_in_check(board,colour_opp(board->turn)));
216
217 // init
218
219 NodeNb++;
220
221 // leaf
222
223 if (depth == 0) {
224 LeafNb++;
225 return;
226 }
227
228 // more init
229
230 me = board->turn;
231
232 // move loop
233
234 gen_moves(list,board);
235
236 for (i = 0; i < list_size(list); i++) {
237
238 move = list_move(list,i);
239
240 board_copy(new_board,board);
241 move_do(new_board,move);
242
243 if (!is_in_check(new_board,me)) perft(new_board,depth-1);
244 }
245 }
246
247 // end of search.cpp
248
249