Add forgotten files 1.4.70b
[polyglot.git] / search.c
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
52 static bool depth_is_ok(int depth) {
53
54    return depth >= 0 && depth < DepthMax;
55 }
56
57 // search()
58
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
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
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
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