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