version 1.4w10UCIb17
[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=StartFen;\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             fen=strdup(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     board_from_fen(board,fen);\r
158     search_perft(board,depth);\r
159 }\r
160 \r
161 // search_perft()\r
162 \r
163 void search_perft(const board_t * board, int depth_max) {\r
164 \r
165    int depth;\r
166    my_timer_t timer[1];\r
167    double time, speed;\r
168    char node_string[StringSize];\r
169    char leafnode_string[StringSize];\r
170 \r
171    ASSERT(board_is_ok(board));\r
172    ASSERT(depth_max>=1&&depth_max<DepthMax);\r
173 \r
174    // init\r
175 \r
176    board_disp(board);\r
177 \r
178    // iterative deepening\r
179 \r
180    for (depth = 1; depth <= depth_max; depth++) {\r
181 \r
182       // init\r
183 \r
184       NodeNb = 0;\r
185       LeafNb = 0;\r
186 \r
187       my_timer_reset(timer);\r
188 \r
189       my_timer_start(timer);\r
190       perft(board,depth);\r
191       my_timer_stop(timer);\r
192 \r
193       time = my_timer_elapsed_real(timer);//my_timer_elapsed_cpu(timer);\r
194       speed = (time < 0.01) ? 0.0 : double(NodeNb) / time;\r
195 \r
196       snprintf(node_string,StringSize,S64_FORMAT,NodeNb);\r
197       snprintf(leafnode_string,StringSize,S64_FORMAT,LeafNb);\r
198 \r
199       printf("depth=%2d nodes=%12s leafnodes=%12s time=%7.2fs nps=%8.0f\n",depth,node_string,leafnode_string,time,speed);\r
200    }\r
201 \r
202 }\r
203 \r
204 // perft()\r
205 \r
206 static void perft(const board_t * board, int depth) {\r
207 \r
208    int me;\r
209    list_t list[1];\r
210    int i, move;\r
211    board_t new_board[1];\r
212 \r
213    ASSERT(board_is_ok(board));\r
214    ASSERT(depth_is_ok(depth));\r
215 \r
216    ASSERT(!is_in_check(board,colour_opp(board->turn)));\r
217 \r
218    // init\r
219 \r
220    NodeNb++;\r
221 \r
222    // leaf\r
223 \r
224    if (depth == 0) {\r
225       LeafNb++;\r
226       return;\r
227    }\r
228 \r
229    // more init\r
230 \r
231    me = board->turn;\r
232 \r
233    // move loop\r
234 \r
235    gen_moves(list,board);\r
236 \r
237    for (i = 0; i < list_size(list); i++) {\r
238 \r
239       move = list_move(list,i);\r
240 \r
241       board_copy(new_board,board);\r
242       move_do(new_board,move);\r
243 \r
244       if (!is_in_check(new_board,me)) perft(new_board,depth-1);\r
245    }\r
246 }\r
247 \r
248 // end of search.cpp\r
249 \r