18
#include "move_legal.h"
32
static const double NormalRatio = 1.0;
33
static const double PonderRatio = 1.25;
39
static bool Searching; // search in progress?
40
static bool Infinite; // infinite or ponder mode?
41
static bool Delay; // postpone "bestmove" in infinite/ponder mode?
46
static void loop_step ();
48
static void parse_go (char string[]);
49
static void parse_position (char string[]);
50
static void parse_setoption (char string[]);
52
static void send_best_move ();
54
static bool string_equal (const char s1[], const char s2[]);
55
static bool string_start_with (const char s1[], const char s2[]);
63
// init (to help debugging)
73
board_from_fen(SearchInput->board,StartFen);
77
while (true) loop_step();
86
// late initialisation
90
if (option_get_bool("OwnBook")) {
91
book_open(option_get_string("BookFile"));
111
while (!SearchInfo->stop && input_available()) loop_step();
116
static void loop_step() {
128
} else if (string_start_with(string,"debug ")) {
132
} else if (string_start_with(string,"go ")) {
134
if (!Searching && !Delay) {
141
} else if (string_equal(string,"isready")) {
143
if (!Searching && !Delay) {
147
send("readyok"); // no need to wait when searching (dixit SMK)
149
} else if (string_equal(string,"ponderhit")) {
155
SearchInput->infinite = false;
168
} else if (string_start_with(string,"position ")) {
170
if (!Searching && !Delay) {
172
parse_position(string);
177
} else if (string_equal(string,"quit")) {
184
} else if (string_start_with(string,"setoption ")) {
186
if (!Searching && !Delay) {
187
parse_setoption(string);
192
} else if (string_equal(string,"stop")) {
196
SearchInfo->stop = true;
205
} else if (string_equal(string,"uci")) {
210
send("id name Fruit " VERSION);
211
send("id author Fabien Letouzey");
217
} else if (string_equal(string,"ucinewgame")) {
219
if (!Searching && !Delay && Init) {
229
static void parse_go(char string[]) {
232
bool infinite, ponder;
233
int depth, mate, movestogo;
235
double binc, btime, movetime, winc, wtime;
237
double time_max, alloc;
258
ptr = strtok(string," "); // skip "go"
260
for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) {
264
} else if (string_equal(ptr,"binc")) {
266
ptr = strtok(NULL," ");
267
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
269
binc = double(atoi(ptr)) / 1000.0;
272
} else if (string_equal(ptr,"btime")) {
274
ptr = strtok(NULL," ");
275
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
277
btime = double(atoi(ptr)) / 1000.0;
280
} else if (string_equal(ptr,"depth")) {
282
ptr = strtok(NULL," ");
283
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
288
} else if (string_equal(ptr,"infinite")) {
292
} else if (string_equal(ptr,"mate")) {
294
ptr = strtok(NULL," ");
295
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
300
} else if (string_equal(ptr,"movestogo")) {
302
ptr = strtok(NULL," ");
303
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
305
movestogo = atoi(ptr);
306
ASSERT(movestogo>=0);
308
} else if (string_equal(ptr,"movetime")) {
310
ptr = strtok(NULL," ");
311
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
313
movetime = double(atoi(ptr)) / 1000.0;
314
ASSERT(movetime>=0.0);
316
} else if (string_equal(ptr,"nodes")) {
318
ptr = strtok(NULL," ");
319
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
321
nodes = my_atoll(ptr);
324
} else if (string_equal(ptr,"ponder")) {
328
} else if (string_equal(ptr,"searchmoves")) {
332
} else if (string_equal(ptr,"winc")) {
334
ptr = strtok(NULL," ");
335
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
337
winc = double(atoi(ptr)) / 1000.0;
340
} else if (string_equal(ptr,"wtime")) {
342
ptr = strtok(NULL," ");
343
if (ptr == NULL) my_fatal("parse_go(): missing argument\n");
345
wtime = double(atoi(ptr)) / 1000.0;
357
SearchInput->depth_is_limited = true;
358
SearchInput->depth_limit = depth;
359
} else if (mate >= 0) {
360
SearchInput->depth_is_limited = true;
361
SearchInput->depth_limit = mate * 2 - 1; // HACK: move -> ply
366
if (COLOUR_IS_WHITE(SearchInput->board->turn)) {
374
if (movestogo <= 0 || movestogo > 30) movestogo = 30; // HACK
375
if (inc < 0.0) inc = 0.0;
377
if (movetime >= 0.0) {
381
SearchInput->time_is_limited = true;
382
SearchInput->time_limit_1 = movetime * 5.0; // HACK to avoid early exit
383
SearchInput->time_limit_2 = movetime;
385
} else if (time >= 0.0) {
387
// dynamic allocation
389
time_max = time * 0.95 - 1.0;
390
if (time_max < 0.0) time_max = 0.0;
392
SearchInput->time_is_limited = true;
394
alloc = (time_max + inc * double(movestogo-1)) / double(movestogo);
395
alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio);
396
if (alloc > time_max) alloc = time_max;
397
SearchInput->time_limit_1 = alloc;
399
alloc = (time_max + inc * double(movestogo-1)) * 0.5;
400
if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1;
401
if (alloc > time_max) alloc = time_max;
402
SearchInput->time_limit_2 = alloc;
405
if (infinite || ponder) SearchInput->infinite = true;
413
Infinite = infinite || ponder;
417
search_update_current();
425
if (!Delay) send_best_move();
430
static void parse_position(char string[]) {
435
char move_string[256];
441
fen = strstr(string,"fen ");
442
moves = strstr(string,"moves ");
446
if (fen != NULL) { // "fen" present
448
if (moves != NULL) { // "moves" present
450
moves[-1] = '\0'; // dirty, but so is UCI
453
board_from_fen(SearchInput->board,fen+4); // CHANGE ME
457
// HACK: assumes startpos
459
board_from_fen(SearchInput->board,StartFen);
464
if (moves != NULL) { // "moves" present
468
while (*ptr != '\0') {
470
move_string[0] = *ptr++;
471
move_string[1] = *ptr++;
472
move_string[2] = *ptr++;
473
move_string[3] = *ptr++;
475
if (*ptr == '\0' || *ptr == ' ') {
476
move_string[4] = '\0';
478
move_string[4] = *ptr++;
479
move_string[5] = '\0';
482
move = move_from_string(move_string,SearchInput->board);
484
move_do(SearchInput->board,move,undo);
486
while (*ptr == ' ') ptr++;
493
static void parse_setoption(char string[]) {
500
name = strstr(string,"name ");
501
value = strstr(string,"value ");
503
if (name == NULL || value == NULL || name >= value) return; // ignore buttons
505
value[-1] = '\0'; // HACK
511
option_set(name,value);
513
// update transposition-table size if needed
515
if (Init && my_string_equal(name,"Hash")) { // Init => already allocated
519
if (option_get_int("Hash") >= 4) {
528
static void send_best_move() {
530
double time, speed, cpu;
532
char move_string[256];
533
char ponder_string[256];
539
// HACK: should be in search.cpp
541
time = SearchCurrent->time;
542
speed = SearchCurrent->speed;
543
cpu = SearchCurrent->cpu;
544
node_nb = SearchCurrent->node_nb;
546
send("info time %.0f nodes " S64_FORMAT " nps %.0f cpuload %.0f",time*1000.0,node_nb,speed,cpu*1000.0);
554
move = SearchBest->move;
557
move_to_string(move,move_string,256);
559
if (pv[0] == move && move_is_ok(pv[1])) {
560
move_to_string(pv[1],ponder_string,256);
561
send("bestmove %s ponder %s",move_string,ponder_string);
563
send("bestmove %s",move_string);
569
void get(char string[], int size) {
571
ASSERT(string!=NULL);
574
if (!my_file_read_line(stdin,string,size)) { // EOF
581
void send(const char format[], ...) {
586
ASSERT(format!=NULL);
588
va_start(arg_list,format);
589
vsprintf(string,format,arg_list);
592
fprintf(stdout,"%s\n",string);
597
static bool string_equal(const char s1[], const char s2[]) {
602
return strcmp(s1,s2) == 0;
605
// string_start_with()
607
static bool string_start_with(const char s1[], const char s2[]) {
612
return strstr(s1,s2) == s1;
615
// end of protocol.cpp