static void send_pv() { char pv_string[StringSize]; board_t board[1]; int move; char move_string[StringSize]; ASSERT(State->state!=WAIT); if (Uci->best_depth == 0) return; // xboard search information if (XB->post) { if (State->state == THINK || State->state == ANALYSE) { line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize); xboard_send(XBoard,"%d %+d %.0f %lld %s",Uci->best_depth,Uci->best_score,Uci->time*100.0,Uci->node_nb,pv_string); } else if (State->state == PONDER && option_get_bool("ShowPonder")) { game_get_board(Game,board); move = State->exp_move; if (move != MoveNone && move_is_legal(move,board)) { move_to_san(move,board,move_string,256); line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize); xboard_send(XBoard,"%d %+d %.0f %lld (%s) %s",Uci->best_depth,Uci->best_score,Uci->time*100.0,Uci->node_nb,move_string,pv_string); } } } // kibitz if ((Uci->searching && option_get_bool("KibitzPV") && Uci->time >= option_get_double("KibitzDelay")) || (!Uci->searching && option_get_bool("KibitzMove"))) { if (State->state == THINK || State->state == ANALYSE) { line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize); xboard_send(XBoard,"%s depth=%d time=%.2f node=%lld speed=%.0f score=%+.2f pv=\"%s\"",option_get_string("KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,double(Uci->best_score)/100.0,pv_string); } else if (State->state == PONDER) { game_get_board(Game,board); move = State->exp_move; if (move != MoveNone && move_is_legal(move,board)) { move_to_san(move,board,move_string,256); line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize); xboard_send(XBoard,"%s depth=%d time=%.2f node=%lld speed=%.0f score=%+.2f pv=\"(%s) %s\"",option_get_string("KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,double(Uci->best_score)/100.0,move_string,pv_string); } } } }
static void send_pv() { char pv_string[StringSize]; board_t board[1]; int move; char move_string[256]; char tb_string[256]; ASSERT(State->state!=WAIT); if (Uci->best_depth == 0) return; // move_string[0]='\0'; // xboard search information if (XB->post && Uci->time >= option_get_double("PostDelay")) { if (State->state == THINK || State->state == ANALYSE) { line_to_san(Uci->best_pv,Uci->board,pv_string,sizeof(pv_string)); tb_to_string(tb_string,sizeof(tb_string)); if(Uci->depth==-1) //hack to clear the engine output window xboard_send(XBoard,"%d %+d %.0f " S64_FORMAT " ",0,Uci->best_score,Uci->time*100.0,Uci->node_nb); xboard_send(XBoard,"%d %+d %.0f " S64_FORMAT " %s %s",Uci->best_depth,Uci->best_score,Uci->time*100.0,Uci->node_nb,pv_string,tb_string); } else if (State->state == PONDER && option_get_bool("ShowPonder")) { game_get_board(Game,board); move = State->exp_move; if (move != MoveNone && move_is_legal(move,board)) { move_to_san(move,board,move_string,sizeof(move_string)); line_to_san(Uci->best_pv,Uci->board,pv_string,sizeof(pv_string)); tb_to_string(tb_string,sizeof(tb_string)); xboard_send(XBoard,"%d %+d %.0f " S64_FORMAT " (%s) %s %s",Uci->best_depth,Uci->best_score,Uci->time*100.0,Uci->node_nb,move_string,pv_string,tb_string); } } } // kibitz if ((Uci->searching && option_get_bool("KibitzPV") && Uci->time >= option_get_double("KibitzDelay")) || (!Uci->searching && option_get_bool("KibitzMove"))) { if (State->state == THINK || State->state == ANALYSE) { line_to_san(Uci->best_pv,Uci->board,pv_string,sizeof(pv_string)); xboard_send(XBoard,"%s depth=%d time=%.2f node=" S64_FORMAT " speed=%.0f score=%+.2f pv=\"%s\"",option_get_string("KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,double(Uci->best_score)/100.0,pv_string); } else if (State->state == PONDER) { game_get_board(Game,board); move = State->exp_move; if (move != MoveNone && move_is_legal(move,board)) { move_to_san(move,board,move_string,sizeof(move_string)); line_to_san(Uci->best_pv,Uci->board,pv_string,sizeof(pv_string)); xboard_send(XBoard,"%s depth=%d time=%.2f node=" S64_FORMAT " speed=%.0f score=%+.2f pv=\"(%s) %s\"",option_get_string("KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,double(Uci->best_score)/100.0,move_string,pv_string); } } } }
static void comp_move(int move) { board_t board[1]; char string[256]; ASSERT(move_is_ok(move)); ASSERT(State->state==THINK); ASSERT(!XB->analyse); if(option_get_bool(Option,"RepeatPV")) send_pv(); // to update time and nodes // send the move game_get_board(Game,board); if (move_is_castle(move,board) && option_get_bool(Option,"Chess960")) { if (!move_to_san(move,board,string,256)) my_fatal("comp_move(): move_to_san() failed\n"); // O-O/O-O-O } else { if (!move_to_can(move,board,string,256)) my_fatal("comp_move(): move_to_can() failed\n"); } gui_send(GUI,"move %s",string); // resign? if (option_get_bool(Option,"Resign") && Uci->root_move_nb > 1) { if (Uci->best_score <= -abs(option_get_int(Option,"ResignScore"))) { State->resign_nb++; my_log("POLYGLOT %d move%s with resign score\n",State->resign_nb,(State->resign_nb>1)?"s":""); if (State->resign_nb >= option_get_int(Option,"ResignMoves")) { my_log("POLYGLOT *** RESIGN ***\n"); gui_send(GUI,"resign"); } } else { if (State->resign_nb > 0) my_log("POLYGLOT resign reset (State->resign_nb=%d)\n",State->resign_nb); State->resign_nb = 0; } } // play the move move_step(move); no_mess(move); }
void time_allocation(double time, double inc, int movestogo) { ASSERT(time>0); ASSERT(inc>=-1.0); ASSERT(movestogo>=-1); double time_max, alloc; // dynamic allocation time_max = time * 0.95 - 1.0; if (time_max < 0.0) time_max = 0.0; alloc = (time_max + inc * double(movestogo-1)) / double(movestogo); alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio); if (alloc > time_max) alloc = time_max; SearchInput->time_limit_1 = alloc; alloc = (time_max + inc * double(movestogo-1)) * 0.5; if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1; if (alloc > time_max) alloc = time_max; SearchInput->time_limit_2 = alloc; alloc = (time_max + inc * double(movestogo-1)) * 0.25; if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1; if (alloc > time_max) alloc = time_max; SearchInput->time_limit_3 = alloc; }
static void get_local(char string[], int size, const char * local) { int len; char * ptr; FILE * file; ASSERT(string!=NULL); ASSERT(size>=65536); ASSERT(local!=NULL); len = strlen(local); if (len >= size) len = size - 1; strncpy(string,local,len); // suppress '\n' ptr = strchr(string,'\n'); if (ptr != NULL) *ptr = '\0'; // log if (option_get_bool("Log")) { file = fopen("fruit.log","a"); if (file != NULL) { fprintf(file,"< %s\n",string); fclose(file); } } }
void engine_open(engine_t * engine){ int affinity; char *my_dir; if( (my_dir = _getcwd( NULL, 0 )) == NULL ) my_fatal("Can't build path: %s\n",strerror(errno)); if(SetCurrentDirectory(option_get_string("EngineDir"))==0){ printf("tellusererror Polyglot:EngineDir error: %s\n",option_get_string("EngineDir")); fflush(stdout); Sleep(50000); my_fatal("EngineDir path error: %s\n",option_get_string("EngineDir")); } pipeEngine.Open(option_get_string("EngineCommand")); //play with affinity #ifndef NO_AFFINITY affinity=option_get_int("Affinity"); if(affinity!=-1){ my_log("POLYGLOT SetProcess Affinity\n"); SetProcessAffinityMask(child,affinity); // } #endif //lets go back SetCurrentDirectory(my_dir); // set priority if (option_get_bool("UseNice")){ my_log("POLYGLOT Adjust Engine Piority\n"); SetPriorityClass(child, GetWin32Priority(option_get_int("NiceValue"))); } }
static bool ponder_move_is_ok(int move) { int status; board_t board[1]; ASSERT(move==MoveNone||move_is_ok(move)); // legal ponder move? if (move == MoveNone) return false; game_get_board(Game,board); if (!move_is_legal(move,board)) return false; // UCI-legal resulting position? game_add_move(Game,move); game_get_board(Game,board); status = game_status(Game); game_rem_move(Game); if (status != PLAYING) return false; // game ended if (option_get_bool("Book") && is_in_book(board)) { return false; } return true; }
static void init() { if (!Init) { // late initialisation Init = true; if (option_get_bool("OwnBook")) { book_open(option_get_string("BookFile")); } //SearchInput->multipv = option_get_int("MultiPV"); trans_alloc(Trans); pawn_init(); pawn_alloc(); material_init(); material_alloc(); pst_init(); eval_init(); } }
static int report_best_score(){ if(!option_get_bool(Option,"ScoreWhite") || colour_is_white(Uci->board->turn)){ return Uci->best_score; }else{ return -Uci->best_score; } }
static void parse_option() { const char * file_name; FILE * file; char line[256]; char * name, * value; file_name = option_get_string("OptionFile"); file = fopen(file_name,"r"); if (file == NULL) my_fatal("Can't open file \"%s\": %s\n",file_name,strerror(errno)); // PolyGlot options (assumed first) while (true) { if (!my_file_read_line(file,line,256)) { my_fatal("parse_option(): missing [Engine] section\n"); } if (my_string_case_equal(line,"[engine]")) break; if (parse_line(line,&name,&value)) option_set(name,value); } if (option_get_bool("Log")) { my_log_open(option_get_string("LogFile")); } my_log("POLYGLOT %s *** START ***\n",Version); my_log("POLYGLOT INI file \"%s\"\n",file_name); engine_open(Engine); Init = true; uci_open(Uci,Engine); while (my_file_read_line(file,line,256)) { if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line); if (parse_line(line,&name,&value)) { uci_send_option(Uci,name,"%s",value); //to get a decent display in winboard_x we need to now if an engine really is doing multipv analysis // "multipv 1" in the pv is meaningless,f.i. toga sends that all the time //therefore check if MultiPV is set to a decent value in the polyglot ini file if(my_string_case_equal(name,"MultiPV") && atoi(value)>1) Uci->multipv_mode=true; } } uci_send_isready(Uci); fclose(file); if (my_string_equal(option_get_string("EngineName"),"<empty>")) { option_set("EngineName",Uci->name); } }
void format_xboard_option_line(char * option_line, option_t *opt){ int j; char option_string[StringSize]; char *tmp; strcpy(option_line,""); // buffer overflow alert strcat(option_line,"feature option=\""); if(opt->mode&PG){ strcat(option_line,"Polyglot "); } sprintf(option_string,"%s",opt->name); strcat(option_line,option_string); sprintf(option_string," -%s",opt->type); strcat(option_line,option_string); if(!IS_BUTTON(opt->type) && strcmp(opt->type,"combo")){ if(strcmp(opt->type,"check")){ sprintf(option_string," %s",opt->value); }else{ sprintf(option_string," %d", my_string_case_equal(opt->value,"true")|| my_string_equal(opt->value,"1") ?1:0); } strcat(option_line,option_string); } if(IS_SPIN(opt->type)){ sprintf(option_string," %s",opt->min); strcat(option_line,option_string); } if(IS_SPIN(opt->type)){ sprintf(option_string," %s",opt->max); strcat(option_line,option_string); } for(j=0;j<opt->var_nb;j++){ if(!strcmp(opt->var[j],opt->value)){ sprintf(option_string," *%s",opt->var[j]); }else{ sprintf(option_string," %s",opt->var[j]); } strcat(option_line,option_string); if(j!=opt->var_nb-1){ strcat(option_line," ///"); } } strcat(option_line,"\""); if(option_get_bool(Option,"WbWorkArounds") && (tmp=strstr(option_line,"Draw"))){ *tmp='d'; my_log("POLYGLOT Decapitalizing \"Draw\" in option \"%s\"\n", opt->name); } }
static void send_info() { int min_depth; if(option_get_bool(Option,"WbWorkArounds2")){ // Silly bug in some versions of WinBoard. // depth <=1 clears the engine output window. // Why shouldn't an engine be allowed to send info at depth 1? min_depth=2; }else{ min_depth=1; } gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth>min_depth?Uci->best_depth:min_depth, 0,0.0,U64(0),Uci->info); }
static void get_stdin(char string[], int size) { FILE * file; ASSERT(string!=NULL); ASSERT(size>=65536); if (!my_file_read_line(stdin,string,size)) { // EOF exit(EXIT_SUCCESS); } // log if (option_get_bool("Log")) { file = fopen("fruit.log","a"); if (file != NULL) { fprintf(file,"< %s\n",string); fclose(file); } } }
static void stop_search() { if (Uci->searching) { ASSERT(Uci->searching); ASSERT(Uci->pending_nb>=1); my_log("POLYGLOT STOP SEARCH\n"); /* engine_send(Engine,"stop"); Uci->searching = false; */ if (option_get_bool("SyncStop")) { uci_send_stop_sync(Uci); } else { uci_send_stop(Uci); } } }
static void init() { if (!Init) { // late initialisation Init = true; if (option_get_bool("OwnBook")) { book_open(option_get_string("BookFile")); } trans_alloc(); pawn_init(); material_init(); pst_init(); eval_init(); tb_cache(option_get_int("NalimovCache")); } }
void send(const char format[], ...) { FILE * file; va_list arg_list; char string[4096]; ASSERT(format!=NULL); va_start(arg_list,format); vsprintf(string,format,arg_list); va_end(arg_list); fprintf(stdout,"%s\n",string); if (option_get_bool("Log")) { file = fopen("fruit.log","a"); if (file != NULL) { fprintf(file,"> %s\n",string); fclose(file); } } }
int main(int argc, char * argv[]) { // board_t board[1]; // init Init = false; #ifdef _WIN32 signal(SIGINT,SIG_IGN); signal(SIGTERM,SIG_IGN); #ifdef SIGPIPE signal(SIGPIPE,SIG_IGN); #endif #endif util_init(); printf("PolyGlot %s by Fabien Letouzey\n",Version); option_init(); uci_options_init(); square_init(); piece_init(); attack_init(); hash_init(); my_random_init(); // build book if (argc >= 2 && my_string_equal(argv[1],"make-book")) { book_make(argc,argv); return EXIT_SUCCESS; } if (argc >= 2 && my_string_equal(argv[1],"merge-book")) { book_merge(argc,argv); return EXIT_SUCCESS; } // read options if (argc == 2) option_set("OptionFile",argv[1]); // HACK for compatibility parse_option(); // HACK: also launches the engine // EPD test if (argc >= 2 && my_string_equal(argv[1],"epd-test")) { epd_test(argc,argv); return EXIT_SUCCESS; } // opening book book_clear(); if (option_get_bool("Book")){ if (book_open(option_get_string("BookFile"))) option_set("Book","false");//some error,set to false } //adapter_loop(); #ifdef _WIN32 Engine_ready_ok=CreateEvent(NULL,FALSE,FALSE,NULL); Engine_sync_stop = CreateEvent(NULL,FALSE,FALSE,NULL); // all set and done.lets open a thread for fun DWORD dwThreadID; HANDLE hThread; hThread= CreateThread( NULL, //default security attributes 0, //default stacksize ThreadFunc, //The thread function! &sCommand, //the commands for the thread function 0, //default creation flags &dwThreadID); //the thread identifier Idle500msecs();// if(hThread==NULL){ my_log("CreateThread failed\n"); } #endif adapter_loop(); engine_send(Engine,"quit"); engine_close(Engine); #ifdef _WIN32 CloseHandle(hThread); //close the thread; #endif return EXIT_SUCCESS; }
static void parse_go(char string[]) { const char * ptr; bool infinite, ponder; int depth, mate, movestogo; sint64 nodes; double binc, btime, movetime, winc, wtime; double time, inc; double time_max, alloc; // init infinite = false; ponder = false; depth = -1; mate = -1; movestogo = -1; nodes = -1; binc = -1.0; btime = -1.0; movetime = -1.0; winc = -1.0; wtime = -1.0; // parse ptr = strtok(string," "); // skip "go" for (ptr = strtok(NULL," "); ptr != NULL; ptr = strtok(NULL," ")) { if (false) { } else if (string_equal(ptr,"binc")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); binc = double(atoi(ptr)) / 1000.0; ASSERT(binc>=0.0); } else if (string_equal(ptr,"btime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); btime = double(atoi(ptr)) / 1000.0; ASSERT(btime>=0.0); } else if (string_equal(ptr,"depth")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); depth = atoi(ptr); ASSERT(depth>=0); } else if (string_equal(ptr,"infinite")) { infinite = true; } else if (string_equal(ptr,"mate")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); mate = atoi(ptr); ASSERT(mate>=0); } else if (string_equal(ptr,"movestogo")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); movestogo = atoi(ptr); ASSERT(movestogo>=0); } else if (string_equal(ptr,"movetime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); movetime = double(atoi(ptr)) / 1000.0; ASSERT(movetime>=0.0); } else if (string_equal(ptr,"nodes")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); nodes = my_atoll(ptr); ASSERT(nodes>=0); } else if (string_equal(ptr,"ponder")) { ponder = true; } else if (string_equal(ptr,"searchmoves")) { // dummy } else if (string_equal(ptr,"winc")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); winc = double(atoi(ptr)) / 1000.0; ASSERT(winc>=0.0); } else if (string_equal(ptr,"wtime")) { ptr = strtok(NULL," "); if (ptr == NULL) my_fatal("parse_go(): missing argument\n"); wtime = double(atoi(ptr)) / 1000.0; ASSERT(wtime>=0.0); } } // init search_clear(); // depth limit // JAS int option_depth = 0; option_depth = option_get_int("Search Depth"); if (option_depth > 0) { depth = option_depth; } // JAS end if (depth >= 0) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = depth; } else if (mate >= 0) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = mate * 2 - 1; // HACK: move -> ply } // time limit if (COLOUR_IS_WHITE(SearchInput->board->turn)) { time = wtime; inc = winc; } else { time = btime; inc = binc; } if (movestogo <= 0 || movestogo > 30) movestogo = 20; // HACK was 30 if (inc < 0.0) inc = 0.0; // JAS int option_movetime = 0; option_movetime = option_get_int("Search Time"); if (option_movetime > 0) { movetime = option_movetime; } // JAS end if (movetime >= 0.0) { // fixed time SearchInput->time_is_limited = true; SearchInput->time_limit_1 = movetime * 5.0; // HACK to avoid early exit SearchInput->time_limit_2 = movetime; } else if (time >= 0.0) { // dynamic allocation time_max = time * 0.95 - 1.0; if (time_max < 0.0) time_max = 0.0; SearchInput->time_is_limited = true; alloc = (time_max + inc * double(movestogo-1)) / double(movestogo); alloc *= (option_get_bool("Ponder") ? PonderRatio : NormalRatio); if (alloc > time_max) alloc = time_max; SearchInput->time_limit_1 = alloc; alloc = (time_max + inc * double(movestogo-1)) * 0.5; if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1; if (alloc > time_max) alloc = time_max; SearchInput->time_limit_2 = alloc; } if (infinite || ponder) SearchInput->infinite = true; // search ASSERT(!Searching); ASSERT(!Delay); Searching = true; Infinite = infinite || ponder; Delay = false; search(); search_update_current(); ASSERT(Searching); ASSERT(!Delay); Searching = false; Delay = Infinite; if (!Delay) send_best_move(); }
void search() { int move; int depth; int i; bool search_ready; for (i = 0; i < MultiPVMax; i++){ save_multipv[SearchCurrent->multipv].mate = 0; save_multipv[SearchCurrent->multipv].depth = 0; save_multipv[SearchCurrent->multipv].max_depth = 0; save_multipv[SearchCurrent->multipv].value = 0; save_multipv[SearchCurrent->multipv].time = 0; save_multipv[SearchCurrent->multipv].node_nb = 0; strcpy(save_multipv[SearchCurrent->multipv].pv_string,""); } SearchInput->multipv = option_get_int("MultiPV")-1; SearchCurrent->multipv = 0; ASSERT(board_is_ok(SearchInput->board)); // opening book if (option_get_bool("OwnBook") && !SearchInput->infinite) { move = book_move(SearchInput->board); if (move != MoveNone) { // play book move SearchBest[SearchCurrent->multipv].move = move; SearchBest[SearchCurrent->multipv].value = 1; SearchBest[SearchCurrent->multipv].flags = SearchExact; SearchBest[SearchCurrent->multipv].depth = 1; SearchBest[SearchCurrent->multipv].pv[0] = move; SearchBest[SearchCurrent->multipv].pv[1] = MoveNone; search_update_best(); return; } } // SearchInput gen_legal_moves(SearchInput->list,SearchInput->board); if (LIST_SIZE(SearchInput->list) < SearchInput->multipv+1){ SearchInput->multipv = LIST_SIZE(SearchInput->list)-1; } if (LIST_SIZE(SearchInput->list) <= 1) { SearchInput->depth_is_limited = true; SearchInput->depth_limit = 4; // was 1 } // SearchInfo if (setjmp(SearchInfo->buf) != 0) { ASSERT(SearchInfo->can_stop); ASSERT(SearchBest->move!=MoveNone); search_update_current(); return; } // SearchRoot list_copy(SearchRoot->list,SearchInput->list); // SearchCurrent board_copy(SearchCurrent->board,SearchInput->board); my_timer_reset(SearchCurrent->timer); my_timer_start(SearchCurrent->timer); // init trans_inc_date(Trans); sort_init(); search_full_init(SearchRoot->list,SearchCurrent->board); // analyze game for evaluation if (SearchCurrent->board->piece_size[White] < 3 && SearchCurrent->board->piece_size[Black] < 3){ trans_endgame = true; } else{ trans_endgame = false; } // iterative deepening search_ready = false; for (depth = 1; depth < DepthMax; depth++) { for (SearchCurrent->multipv = 0; SearchCurrent->multipv <= SearchInput->multipv; SearchCurrent->multipv++){ if (DispDepthStart && SearchCurrent->multipv == 0) send("info depth %d",depth); SearchCurrent->max_extensions = depth * 10; SearchRoot->bad_1 = false; SearchRoot->change = false; board_copy(SearchCurrent->board,SearchInput->board); if (UseShortSearch && depth <= ShortSearchDepth) { search_full_root(SearchRoot->list,SearchCurrent->board,depth,SearchShort); } else { search_full_root(SearchRoot->list,SearchCurrent->board,depth,SearchNormal); } search_update_current(); if (DispDepthEnd && SearchCurrent->multipv == SearchInput->multipv) { send("info depth %d seldepth %d time %.0f nodes " S64_FORMAT " nps %.0f",depth,SearchCurrent->max_depth,SearchCurrent->time*1000.0,SearchCurrent->node_nb,SearchCurrent->speed); } // update search info if (depth >= 1) SearchInfo->can_stop = true; if (depth == 1 && LIST_SIZE(SearchRoot->list) >= 2 && LIST_VALUE(SearchRoot->list,0) >= LIST_VALUE(SearchRoot->list,1) + EasyThreshold) { SearchRoot->easy = true; } if (depth > 1) { SearchRoot->bad_2 = SearchRoot->bad_1; SearchRoot->bad_1 = false; ASSERT(SearchRoot->bad_2==(SearchBest->value<=SearchRoot->last_value-BadThreshold)); } SearchRoot->last_value = SearchBest[SearchCurrent->multipv].value; // stop search? if (SearchInput->depth_is_limited && SearchCurrent->multipv >= SearchInput->multipv && depth >= SearchInput->depth_limit) { SearchRoot->flag = true; } if (SearchInput->time_is_limited && SearchCurrent->time * 2 >= SearchInput->time_limit_1 && !SearchRoot->bad_2) { SearchRoot->flag = true; } if (SearchInput->time_is_limited && SearchCurrent->time >= SearchInput->time_limit_1 * EasyRatio && SearchRoot->easy) { ASSERT(!SearchRoot->bad_2); ASSERT(!SearchRoot->change); SearchRoot->flag = true; } if (SearchInput->time_is_limited && SearchCurrent->time >= SearchInput->time_limit_1 * EarlyRatio && !SearchRoot->bad_2 && !SearchRoot->change) { SearchRoot->flag = true; } if (SearchInfo->can_stop && (SearchInfo->stop || (SearchRoot->flag && !SearchInput->infinite))) { search_ready = true; break; } } if (search_ready) break; } }
static void search_update() { int move; int move_nb; board_t board[1]; ASSERT(!Uci->searching); // launch a new search if needed if (State->state == THINK || State->state == PONDER || State->state == ANALYSE) { // opening book if (State->state == THINK && option_get_bool("Book")) { game_get_board(Game,Uci->board); move = book_move(Uci->board,option_get_bool("BookRandom")); if (move != MoveNone && move_is_legal(move,Uci->board)) { my_log("POLYGLOT *BOOK MOVE*\n"); search_clear(); // clears Uci->ponder_move Uci->best_move = move; board_copy(board,Uci->board); move_do(board,move); Uci->ponder_move = book_move(board,false); // expected move = best book move Uci->best_pv[0] = Uci->best_move; Uci->best_pv[1] = Uci->ponder_move; // can be MoveNone Uci->best_pv[2] = MoveNone; comp_move(Uci->best_move); return; } } // engine search my_log("POLYGLOT START SEARCH\n"); // options uci_send_option(Uci,"UCI_Chess960","%s",option_get_bool("Chess960")?"true":"false"); if (option_get_int("UCIVersion") >= 2) { uci_send_option(Uci,"UCI_Opponent","none none %s %s",(XB->computer)?"computer":"human",XB->name); uci_send_option(Uci,"UCI_AnalyseMode","%s",(XB->analyse)?"true":"false"); } uci_send_option(Uci,"Ponder","%s",ponder()?"true":"false"); // position move = (State->state == PONDER) ? State->exp_move : MoveNone; send_board(move); // updates Uci->board global variable // search if (State->state == THINK || State->state == PONDER) { engine_send_queue(Engine,"go"); if (XB->time_limit) { // fixed time per move engine_send_queue(Engine," movetime %.0f",XB->time_max*1000.0); } else { // time controls if (colour_is_white(Uci->board->turn)) { engine_send_queue(Engine," wtime %.0f btime %.0f",XB->my_time*1000.0,XB->opp_time*1000.0); } else { engine_send_queue(Engine," wtime %.0f btime %.0f",XB->opp_time*1000.0,XB->my_time*1000.0); } if (XB->inc != 0.0) engine_send_queue(Engine," winc %.0f binc %.0f",XB->inc*1000.0,XB->inc*1000.0); if (XB->mps != 0) { move_nb = XB->mps - (Uci->board->move_nb % XB->mps); ASSERT(move_nb>=1&&move_nb<=XB->mps); engine_send_queue(Engine," movestogo %d",move_nb); } } if (XB->depth_limit) engine_send_queue(Engine," depth %d",XB->depth_max); if (State->state == PONDER) engine_send_queue(Engine," ponder"); engine_send(Engine,""); // newline } else if (State->state == ANALYSE) { engine_send(Engine,"go infinite"); } else { ASSERT(false); } // init search info ASSERT(!Uci->searching); search_clear(); Uci->searching = true; Uci->pending_nb++; } }
static void xboard_step() { char string[StringSize]; int move; char move_string[256]; board_t board[1]; xboard_get(XBoard,string,StringSize); if (false) { } else if (match(string,"accepted *")) { // ignore } else if (match(string,"analyze")) { State->computer[White] = false; State->computer[Black] = false; XB->analyse = true; XB->new_hack = false; ASSERT(!XB->result); XB->result = false; mess(); } else if (match(string,"bk")) { if (option_get_bool("Book")) { game_get_board(Game,board); book_disp(board); } } else if (match(string,"black")) { if (colour_is_black(game_turn(Game))) { State->computer[White] = true; State->computer[Black] = false; XB->new_hack = true; XB->result = false; mess(); } } else if (match(string,"computer")) { XB->computer = true; } else if (match(string,"draw")) { // ignore } else if (match(string,"easy")) { XB->ponder = false; mess(); } else if (match(string,"edit")) { // refuse xboard_send(XBoard,"Error (unknown command): %s",string); } else if (match(string,"exit")) { State->computer[White] = false; State->computer[Black] = false; XB->analyse = false; mess(); } else if (match(string,"force")) { State->computer[White] = false; State->computer[Black] = false; mess(); } else if (match(string,"go")) { State->computer[game_turn(Game)] = true; State->computer[colour_opp(game_turn(Game))] = false; XB->new_hack = false; ASSERT(!XB->result); XB->result = false; mess(); } else if (match(string,"hard")) { XB->ponder = true; mess(); } else if (match(string,"hint")) { if (option_get_bool("Book")) { game_get_board(Game,board); move = book_move(board,false); if (move != MoveNone && move_is_legal(move,board)) { move_to_san(move,board,move_string,256); xboard_send(XBoard,"Hint: %s",move_string); } } } else if (match(string,"ics *")) { XB->ics = true; } else if (match(string,"level * *:* *")) { XB->mps = atoi(Star[0]); XB->base = double(atoi(Star[1])) * 60.0 + double(atoi(Star[2])); XB->inc = double(atoi(Star[3])); } else if (match(string,"level * * *")) { XB->mps = atoi(Star[0]); XB->base = double(atoi(Star[1])) * 60.0; XB->inc = double(atoi(Star[2])); } else if (match(string,"name *")) { my_string_set(&XB->name,Star[0]); } else if (match(string,"new")) { my_log("POLYGLOT NEW GAME\n"); option_set("Chess960","false"); game_clear(Game); if (XB->analyse) { State->computer[White] = false; State->computer[Black] = false; } else { State->computer[White] = false; State->computer[Black] = true; } XB->new_hack = true; XB->result = false; XB->depth_limit = false; XB->computer = false; my_string_set(&XB->name,"<empty>"); board_update(); mess(); uci_send_ucinewgame(Uci); } else if (match(string,"nopost")) { XB->post = false; } else if (match(string,"otim *")) { XB->opp_time = double(atoi(Star[0])) / 100.0; if (XB->opp_time < 0.0) XB->opp_time = 0.0; } else if (match(string,"pause")) { // refuse xboard_send(XBoard,"Error (unknown command): %s",string); } else if (match(string,"ping *")) { // HACK; TODO: answer only after an engine move if (DelayPong) { if (XB->ping >= 0) xboard_send(XBoard,"pong %d",XB->ping); // HACK: get rid of old ping XB->ping = atoi(Star[0]); uci_send_isready(Uci); } else { ASSERT(XB->ping==-1); xboard_send(XBoard,"pong %s",Star[0]); } } else if (match(string,"playother")) { State->computer[game_turn(Game)] = false; State->computer[colour_opp(game_turn(Game))] = true; XB->new_hack = false; ASSERT(!XB->result); XB->result = false; mess(); } else if (match(string,"post")) { XB->post = true; } else if (match(string,"protover *")) { XB->proto_ver = atoi(Star[0]); ASSERT(XB->proto_ver>=2); xboard_send(XBoard,"feature done=0"); xboard_send(XBoard,"feature analyze=1"); xboard_send(XBoard,"feature colors=0"); xboard_send(XBoard,"feature draw=1"); xboard_send(XBoard,"feature ics=1"); xboard_send(XBoard,"feature myname=\"%s\"",option_get_string("EngineName")); xboard_send(XBoard,"feature name=1"); xboard_send(XBoard,"feature pause=0"); xboard_send(XBoard,"feature ping=1"); xboard_send(XBoard,"feature playother=1"); xboard_send(XBoard,"feature reuse=1"); xboard_send(XBoard,"feature san=0"); xboard_send(XBoard,"feature setboard=1"); xboard_send(XBoard,"feature sigint=0"); xboard_send(XBoard,"feature sigterm=0"); xboard_send(XBoard,"feature time=1"); xboard_send(XBoard,"feature usermove=1"); if (uci_option_exist(Uci,"UCI_Chess960")) { xboard_send(XBoard,"feature variants=\"normal,fischerandom\""); } else { xboard_send(XBoard,"feature variants=\"normal\""); } if (Uci->ready) xboard_send(XBoard,"feature done=1"); // otherwise "feature done=1" will be sent when the engine is ready } else if (match(string,"quit")) { my_log("POLYGLOT *** \"quit\" from XBoard ***\n"); quit(); } else if (match(string,"random")) { // ignore } else if (match(string,"rating * *")) { // ignore } else if (match(string,"remove")) { if (game_pos(Game) >= 2) { game_goto(Game,game_pos(Game)-2); ASSERT(!XB->new_hack); XB->new_hack = false; // HACK? XB->result = false; board_update(); mess(); } } else if (match(string,"rejected *")) { // ignore } else if (match(string,"reset")) { // protover 3? // refuse xboard_send(XBoard,"Error (unknown command): %s",string); } else if (false || match(string,"result * {*}") || match(string,"result * {* }") || match(string,"result * { *}") || match(string,"result * { * }")) { my_log("POLYGLOT GAME END\n"); XB->result = true; mess(); // book learning if (option_get_bool("Book") && option_get_bool("BookLearn")) { if (false) { } else if (my_string_equal(Star[0],"1-0")) { learn(+1); } else if (my_string_equal(Star[0],"0-1")) { learn(-1); } else if (my_string_equal(Star[0],"1/2-1/2")) { learn(0); } } } else if (match(string,"resume")) { // refuse xboard_send(XBoard,"Error (unknown command): %s",string); } else if (match(string,"sd *")) { XB->depth_limit = true; XB->depth_max = atoi(Star[0]); } else if (match(string,"setboard *")) { my_log("POLYGLOT FEN %s\n",Star[0]); if (!game_init(Game,Star[0])) my_fatal("xboard_step(): bad FEN \"%s\"\n",Star[0]); State->computer[White] = false; State->computer[Black] = false; XB->new_hack = true; // HACK? XB->result = false; board_update(); mess(); } else if (match(string,"st *")) { XB->time_limit = true; XB->time_max = double(atoi(Star[0])); } else if (match(string,"time *")) { XB->my_time = double(atoi(Star[0])) / 100.0; if (XB->my_time < 0.0) XB->my_time = 0.0; } else if (match(string,"undo")) { if (game_pos(Game) >= 1) { game_goto(Game,game_pos(Game)-1); ASSERT(!XB->new_hack); XB->new_hack = false; // HACK? XB->result = false; board_update(); mess(); } } else if (match(string,"usermove *")) { game_get_board(Game,board); move = move_from_san(Star[0],board); if (move != MoveNone && move_is_legal(move,board)) { XB->new_hack = false; ASSERT(!XB->result); XB->result = false; move_step(move); no_mess(move); } else { xboard_send(XBoard,"Illegal move: %s",Star[0]); } } else if (match(string,"variant *")) { if (my_string_equal(Star[0],"fischerandom")) { option_set("Chess960","true"); } else { option_set("Chess960","false"); } } else if (match(string,"white")) { if (colour_is_white(game_turn(Game))) { State->computer[White] = false; State->computer[Black] = true; XB->new_hack = true; XB->result = false; mess(); } } else if (match(string,"xboard")) { // ignore } else if (match(string,".")) { // analyse info if (State->state == ANALYSE) { ASSERT(Uci->searching); ASSERT(Uci->pending_nb>=1); if (Uci->root_move != MoveNone && move_is_legal(Uci->root_move,Uci->board)) { move_to_san(Uci->root_move,Uci->board,move_string,256); xboard_send(XBoard,"stat01: %.0f %lld %d %d %d %s",Uci->time*100.0,Uci->node_nb,Uci->depth,Uci->root_move_nb-(Uci->root_move_pos+1),Uci->root_move_nb,move_string); } else { xboard_send(XBoard,"stat01: %.0f %lld %d %d %d",Uci->time*100.0,Uci->node_nb,Uci->depth,0,0); // HACK } } } else if (match(string,"?")) { // move now if (State->state == THINK) { ASSERT(Uci->searching); ASSERT(Uci->pending_nb>=1); // HACK: just send "stop" to the engine if (Uci->searching) { my_log("POLYGLOT STOP SEARCH\n"); engine_send(Engine,"stop"); } } } else { // unknown command, maybe a move? game_get_board(Game,board); move = move_from_san(string,board); if (move != MoveNone && move_is_legal(move,board)) { XB->new_hack = false; ASSERT(!XB->result); XB->result = false; move_step(move); no_mess(move); } else if (move != MoveNone) { xboard_send(XBoard,"Illegal move: %s",string); } else { xboard_send(XBoard,"Error (unknown command): %s",string); } } }
static void parse_option() { const char * file_name; FILE * file; char line[256]; char * name, * value; file_name = option_get_string("OptionFile"); file = fopen(file_name,"r"); if (file == NULL) my_fatal("Can't open file \"%s\": %s\n",file_name,strerror(errno)); // PolyGlot options (assumed first) //read the ini file,and store the name/value pairs while (true) { if (!my_file_read_line(file,line,sizeof(line))) { my_fatal("parse_option(): missing [Engine] section\n"); } if (my_string_case_equal(line,"[engine]")) break; if (parse_line(line,&name,&value)) option_set(name,value); } if (option_get_bool("Log")) { my_log_open(option_get_string("LogFile"));} while (my_file_read_line(file,line,sizeof(line))) { if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line); if (parse_line(line,&name,&value)) { uci_option_store(name,value); } } fclose(file); //read the optional global.ini file if(!option_get_bool("NoGlobals")){ file=fopen("globals.ini","r"); //override settings,if any if(file!=NULL){ while (true) { if (!my_file_read_line(file,line,sizeof(line))) { my_fatal("parse_option(): missing [Engine] section\n"); } if (my_string_case_equal(line,"[engine]")) break; if (parse_line(line,&name,&value)){ if(!my_string_case_equal(name,"LogFile")) option_set(name,value); } } if (option_get_bool("Log")) { my_log_open(option_get_string("LogFile")); } else my_log_close(); //close it while (my_file_read_line(file,line,sizeof(line))) { if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line); if (parse_line(line,&name,&value)) { uci_option_store(name,value); } } fclose(file); } } my_log("POLYGLOT %s *** START ***\n",Version); my_log("POLYGLOT INI file \"%s\"\n",file_name); //do the dump: engine_open(Engine); Init = true; uci_open(Uci,Engine); uci_option_t *next; init_uci_list(&next); while(next!=NULL){ if(next->var==NULL) break; uci_send_option(Uci,next->var,"%s",next->val); if(my_string_case_equal(next->var,"MultiPV") && atoi(next->val)>1) Uci->multipv_mode=true; next=next->next; } uci_send_isready(Uci); if (my_string_equal(option_get_string("EngineName"),"<empty>")) { option_set("EngineName",Uci->name); } }
void search_full_init(list_t * list, board_t * board) { const char * string; int trans_move, trans_min_depth, trans_max_depth, trans_min_value, trans_max_value; ASSERT(list_is_ok(list)); ASSERT(board_is_ok(board)); // null-move options string = option_get_string("NullMove Pruning"); if (false) { } else if (my_string_equal(string,"Always")) { UseNull = true; UseNullEval = false; } else if (my_string_equal(string,"Fail High")) { UseNull = true; UseNullEval = true; } else if (my_string_equal(string,"Never")) { UseNull = false; UseNullEval = false; } else { ASSERT(false); UseNull = true; UseNullEval = true; } NullReduction = option_get_int("NullMove Reduction"); string = option_get_string("Verification Search"); if (false) { } else if (my_string_equal(string,"Always")) { UseVer = true; UseVerEndgame = false; } else if (my_string_equal(string,"Endgame")) { UseVer = true; UseVerEndgame = true; } else if (my_string_equal(string,"Never")) { UseVer = false; UseVerEndgame = false; } else { ASSERT(false); UseVer = true; UseVerEndgame = true; } VerReduction = option_get_int("Verification Reduction"); // history-pruning options UseHistory = option_get_bool("History Pruning"); HistoryValue = (option_get_int("History Threshold") * 16384 + 50) / 100; UseExtendedHistory = option_get_bool("Toga Extended History Pruning"); HistoryBound = (option_get_int("Toga History Threshold") * 16384 + 50) / 100; // futility-pruning options UseFutility = option_get_bool("Futility Pruning"); FutilityMargin1 = option_get_int("Futility Margin"); FutilityMargin2 = option_get_int("Extended Futility Margin"); // delta-pruning options UseDelta = option_get_bool("Delta Pruning"); DeltaMargin = option_get_int("Delta Margin"); // quiescence-search options CheckNb = option_get_int("Quiescence Check Plies"); CheckDepth = 1 - CheckNb; // standard sort list_note(list); list_sort(list); // basic sort trans_move = MoveNone; if (UseTrans) trans_retrieve(Trans,board->key,&trans_move,&trans_min_depth,&trans_max_depth,&trans_min_value,&trans_max_value); note_moves(list,board,0,trans_move); list_sort(list); }
bool board_to_fen(const board_t * board, char string[], int size) { int pos; int file, rank; int sq, piece; int c; int len; int old_pos; ASSERT(board_is_ok(board)); ASSERT(string!=NULL); ASSERT(size>=92); // init if (size < 92) return false; pos = 0; // piece placement for (rank = 7; rank >= 0; rank--) { for (file = 0; file < 8;) { sq = square_make(file,rank); piece = board->square[sq]; ASSERT(piece==Empty||piece_is_ok(piece)); if (piece == Empty) { len = 0; for (; file < 8 && board->square[square_make(file,rank)] == Empty; file++) { len++; } ASSERT(len>=1&&len<=8); c = '0' + len; } else { c = piece_to_char(piece); file++; } string[pos++] = c; } string[pos++] = '/'; } string[pos-1] = ' '; // HACK: remove the last '/' // active colour string[pos++] = (colour_is_white(board->turn)) ? 'w' : 'b'; string[pos++] = ' '; // castling old_pos = pos; if (option_get_bool("Chess960")) { // FEN-960 if (board->castle[White][SideH] != SquareNone) { string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideH]))); } if (board->castle[White][SideA] != SquareNone) { string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideA]))); } if (board->castle[Black][SideH] != SquareNone) { string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideH]))); } if (board->castle[Black][SideA] != SquareNone) { string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideA]))); } } else { // FEN if (board->castle[White][SideH] != SquareNone) string[pos++] = 'K'; if (board->castle[White][SideA] != SquareNone) string[pos++] = 'Q'; if (board->castle[Black][SideH] != SquareNone) string[pos++] = 'k'; if (board->castle[Black][SideA] != SquareNone) string[pos++] = 'q'; } if (pos == old_pos) string[pos++] = '-'; string[pos++] = ' '; // en-passant if (board->ep_square == SquareNone) { string[pos++] = '-'; } else { if (!square_to_string(board->ep_square,&string[pos],3)) return false; pos += 2; } string[pos++] = ' '; // halfmove clock and fullmove number sprintf(&string[pos],"%d %d",board->ply_nb,board->move_nb+1); return true; }
static bool ponder() { return XB->ponder && (option_get_bool("CanPonder") || uci_option_exist(Uci,"Ponder")); }
void engine_open(engine_t * engine) { const char * dir, * command; char string[StringSize]; int argc; char * ptr; char * argv[256]; int from_engine[2], to_engine[2]; pid_t pid; ASSERT(engine!=NULL); // init dir = option_get_string("EngineDir"); my_log("POLYGLOT Dir \"%s\"\n",dir); command = option_get_string("EngineCommand"); my_log("POLYGLOT Command \"%s\"\n",command); // parse the command line and create the argument list if (strlen(command) >= StringSize) my_fatal("engine_open(): buffer overflow\n"); strcpy(string,command); argc = 0; for (ptr = strtok(string," "); ptr != NULL; ptr = strtok(NULL," ")) { argv[argc++] = ptr; } argv[argc] = NULL; // create the pipes if (pipe(from_engine) == -1) { my_fatal("engine_open(): pipe(): %s\n",strerror(errno)); } if (pipe(to_engine) == -1) { my_fatal("engine_open(): pipe(): %s\n",strerror(errno)); } // create the child process pid = fork(); if (pid == -1) { my_fatal("engine_open(): fork(): %s\n",strerror(errno)); } else if (pid == 0) { // child = engine // close unused pipe descriptors to avoid deadlocks my_close(from_engine[0]); my_close(to_engine[1]); // attach the pipe to standard input my_dup2(to_engine[0],STDIN_FILENO); my_close(to_engine[0]); // attach the pipe to standard output my_dup2(from_engine[1],STDOUT_FILENO); my_close(from_engine[1]); // attach standard error to standard output my_dup2(STDOUT_FILENO,STDERR_FILENO); // set a low priority if (option_get_bool("UseNice")) { my_log("POLYGLOT Adjust Engine Piority"); nice(+option_get_int("NiceValue")); } // change the current directory if (dir[0] != '\0' && chdir(dir) == -1) { my_fatal("engine_open(): chdir(): %s\n",strerror(errno)); } // launch the new executable file execvp(argv[0],&argv[0]); // execvp() only returns when an error has occured my_fatal("engine_open(): execvp(): %s\n",strerror(errno)); } else { // pid > 0 ASSERT(pid>0); // parent = PolyGlot // close unused pipe descriptors to avoid deadlocks my_close(from_engine[1]); my_close(to_engine[0]); // fill in the engine struct engine->io->in_fd = from_engine[0]; engine->io->out_fd = to_engine[1]; engine->io->name = "Engine"; io_init(engine->io); } }
static void search_update() { int move; int move_nb; board_t board[1]; ASSERT(!Uci->searching); // launch a new search if needed if (State->state == THINK || State->state == PONDER || State->state == ANALYSE) { // [VdB] moved up as we need the move number game_get_board(Game,Uci->board); // opening book if (State->state == THINK && option_get_bool(Option,"Book") && Uci->board->move_nb<option_get_int(Option,"BookDepth") ) { move = book_move(Uci->board,option_get_bool(Option,"BookRandom")); if (move != MoveNone && move_is_legal(move,Uci->board)) { my_log("POLYGLOT *BOOK MOVE*\n"); search_clear(); // clears Uci->ponder_move Uci->best_move = move; board_copy(board,Uci->board); move_do(board,move); Uci->ponder_move = book_move(board,FALSE); // expected move = best book move Uci->best_pv[0] = Uci->best_move; Uci->best_pv[1] = Uci->ponder_move; // can be MoveNone Uci->best_pv[2] = MoveNone; comp_move(Uci->best_move); return; } } // engine search my_log("POLYGLOT START SEARCH\n"); // options uci_send_option(Uci,"UCI_3Check","%s", option_get_bool(Option,"3Check")?"true":"false"); uci_send_option(Uci,"UCI_Chess960","%s", option_get_bool(Option,"Chess960")?"true":"false"); uci_send_option(Uci,"UCI_Atomic","%s", option_get_bool(Option,"Atomic")?"true":"false"); uci_send_option(Uci,"UCI_Horde","%s", option_get_bool(Option,"Horde")?"true":"false"); if (option_get_int(Option,"UCIVersion") >= 2) { uci_send_option(Uci,"UCI_Opponent","none none %s %s",(XB->computer)?"computer":"human",XB->name); uci_send_option(Uci,"UCI_AnalyseMode","%s",(XB->analyse)?"true":"false"); } uci_send_option(Uci,"Ponder","%s",ponder()?"true":"false"); // position move = (State->state == PONDER) ? State->exp_move : MoveNone; send_board(move); // updates Uci->board global variable // search if (State->state == THINK || State->state == PONDER) { engine_send_queue(Engine,"go"); if (XB->time_limit) { // fixed time per move if(XB->node_rate > 0){ engine_send_queue(Engine, " nodes %.0f", XB->time_max*((double)XB->node_rate)); }else{ double computed_time; double st_fudge; st_fudge=(double) option_get_int(Option,"STFudge"); my_log("POLYGLOT Giving engine %.0fmsec extra time.\n",st_fudge); computed_time=XB->time_max*1000.0-st_fudge; if(computed_time< 1.0){ computed_time=1.0; } engine_send_queue(Engine, " movetime %.0f", computed_time); } } else { // time controls if(XB->node_rate > 0) { double time; move_nb = 40; if (XB->mps != 0){ move_nb = XB->mps - (Uci->board->move_nb % XB->mps); } time = XB->my_time / move_nb; if(XB->inc != 0){ time += XB->inc; } if(time > XB->my_time){ time = XB->my_time; } engine_send_queue(Engine, " nodes %.0f", time*XB->node_rate); } else { if (colour_is_white(Uci->board->turn)) { engine_send_queue(Engine, " wtime %.0f btime %.0f", XB->my_time*1000.0,XB->opp_time*1000.0); } else { engine_send_queue(Engine, " wtime %.0f btime %.0f", XB->opp_time*1000.0,XB->my_time*1000.0); } if (XB->inc != 0.0){ engine_send_queue(Engine, " winc %.0f binc %.0f", XB->inc*1000.0,XB->inc*1000.0); } if (XB->mps != 0) { move_nb = XB->mps - (Uci->board->move_nb % XB->mps); ASSERT(move_nb>=1&&move_nb<=XB->mps); engine_send_queue(Engine," movestogo %d",move_nb); } } } if (XB->depth_limit) engine_send_queue(Engine," depth %d",XB->depth_max); if (State->state == PONDER) engine_send_queue(Engine," ponder"); engine_send(Engine,""); // newline } else if (State->state == ANALYSE) { engine_send(Engine,"go infinite"); } else { ASSERT(FALSE); } // init search info ASSERT(!Uci->searching); search_clear(); Uci->searching = TRUE; Uci->pending_nb++; } }
static bool ponder() { return XB->ponder && (option_get_bool(Option,"CanPonder") || option_find(Uci->option,"Ponder")); }
void search_full_init(list_t * list, board_t * board, int ThreadId) { const char * string; int trans_move, trans_depth, trans_flags, trans_value; int i, j; entry_t * found_entry; ASSERT(list_is_ok(list)); ASSERT(board_is_ok(board)); // null-move options string = option_get_string("NullMove Pruning"); if (false) { } else if (my_string_equal(string,"Always")) { UseNull = true; UseNullEval = false; } else if (my_string_equal(string,"Fail High")) { UseNull = true; UseNullEval = true; } else if (my_string_equal(string,"Never")) { UseNull = false; UseNullEval = false; } else { ASSERT(false); UseNull = true; UseNullEval = true; } NullReduction = option_get_int("NullMove Reduction"); string = option_get_string("Verification Search"); if (false) { } else if (my_string_equal(string,"Always")) { UseVer = true; UseVerEndgame = false; } else if (my_string_equal(string,"Endgame")) { UseVer = true; UseVerEndgame = true; } else if (my_string_equal(string,"Never")) { UseVer = false; UseVerEndgame = false; } else { ASSERT(false); UseVer = true; UseVerEndgame = true; } VerReduction = option_get_int("Verification Reduction"); // history-pruning options UseHistory = option_get_bool("History Pruning"); HistoryValue = (option_get_int("History Threshold") * 16384 + 50) / 100; // Stockfish Late Move Reductions // about 20 elo better than previous Toga History Reductions for (i = 0; i < 64; i++){ for (j = 0; j < 64; j++){ if (i == 0 || j == 0){ quietPvMoveReduction[i][j] = quietMoveReduction[i][j] = 0; } else{ double pvReduction = log((double) (i)) * log((double) (j)) / 3.0; double nonPvReduction = (1.0 + log((double) (i))) * log((double) (j)) / 2.5; // JD quietPvMoveReduction[i][j] = (int) (pvReduction >= 1.0 ? floor(pvReduction) : 0); quietMoveReduction[i][j] = (int) (nonPvReduction >= 1.0 ? floor(nonPvReduction) : 0); } } } // futility-pruning options UseFutility = option_get_bool("Futility Pruning"); FutilityMargin1 = option_get_int("Futility Margin"); FutilityMargin2 = option_get_int("Extended Futility Margin"); // delta-pruning options UseDelta = option_get_bool("Delta Pruning"); DeltaMargin = option_get_int("Delta Margin"); // quiescence-search options SearchCurrent[ThreadId]->CheckNb = option_get_int("Quiescence Check Plies"); SearchCurrent[ThreadId]->CheckDepth = 1 - SearchCurrent[ThreadId]->CheckNb; // standard sort list_note(list); list_sort(list); // misc SearchCurrent[ThreadId]->last_move = MoveNone; // basic sort trans_move = MoveNone; if (UseTrans) trans_retrieve(Trans,&found_entry,board->key,&trans_move,&trans_depth,&trans_flags,&trans_value); note_moves(list,board,0,trans_move,ThreadId); list_sort(list); }
void xboard2uci_gui_step(char string[]) { int move; char move_string[256]; board_t board[1]; if (FALSE) { } else if (match(string,"accepted *")) { // ignore } else if (match(string,"analyze")) { State->computer[White] = FALSE; State->computer[Black] = FALSE; XB->analyse = TRUE; XB->new_hack = FALSE; ASSERT(!XB->result); XB->result = FALSE; mess(); } else if (match(string,"bk")) { if (option_get_bool(Option,"Book")) { game_get_board(Game,board); book_disp(board); } } else if (match(string,"black")) { if (colour_is_black(game_turn(Game))) { State->computer[White] = TRUE; State->computer[Black] = FALSE; XB->new_hack = TRUE; XB->result = FALSE; mess(); } } else if (match(string,"computer")) { XB->computer = TRUE; } else if (match(string,"draw")) { if(option_find(Uci->option,"UCI_DrawOffers")){ my_log("POLYGLOT draw from XB received"); uci_send_option(Uci,"DrawOffer","%s","draw");} } else if (match(string,"easy")) { XB->ponder = FALSE; mess(); } else if (match(string,"edit")) { // refuse gui_send(GUI,"Error (unknown command): %s",string); } else if (match(string,"exit")) { State->computer[White] = FALSE; State->computer[Black] = FALSE; XB->analyse = FALSE; mess(); } else if (match(string,"force")) { State->computer[White] = FALSE; State->computer[Black] = FALSE; mess(); } else if (match(string,"go")) { State->computer[game_turn(Game)] = TRUE; State->computer[colour_opp(game_turn(Game))] = FALSE; XB->new_hack = FALSE; ASSERT(!XB->result); XB->result = FALSE; mess(); } else if (match(string,"hard")) { XB->ponder = TRUE; mess(); } else if (match(string,"hint")) { move=MoveNone; game_get_board(Game,board); if (option_get_bool(Option,"Book")) { move = book_move(board,FALSE); } if(move==MoveNone && State->hint_move!=MoveNone){ move=State->hint_move; } if (move != MoveNone && move_is_legal(move,board)) { move_to_san(move,board,move_string,256); gui_send(GUI,"Hint: %s",move_string); } } else if (match(string,"ics *")) { XB->ics = TRUE; } else if (match(string,"level * *:* *")) { XB->mps = atoi(Star[0]); XB->base = ((double)atoi(Star[1])) * 60.0 + ((double)atoi(Star[2])); XB->inc = ((double)atoi(Star[3])); } else if (match(string,"level * * *")) { XB->mps = atoi(Star[0]); XB->base = ((double)atoi(Star[1])) * 60.0; XB->inc = ((double)atoi(Star[2])); } else if (match(string,"name *")) { my_string_set(&XB->name,Star[0]); } else if (match(string,"new")) { uci_send_isready_sync(Uci); my_log("POLYGLOT NEW GAME\n"); option_set(Option,"3Check","false"); option_set(Option,"Chess960","false"); option_set(Option,"Atomic","false"); option_set(Option,"Horde","false"); game_clear(Game); if (XB->analyse) { State->computer[White] = FALSE; State->computer[Black] = FALSE; } else { State->computer[White] = FALSE; State->computer[Black] = TRUE; } XB->new_hack = TRUE; XB->result = FALSE; XB->depth_limit = FALSE; XB->node_rate=-1; XB->computer = FALSE; my_string_set(&XB->name,"<empty>"); board_update(); mess(); uci_send_ucinewgame(Uci); } else if (match(string,"nopost")) { XB->post = FALSE; } else if (match(string,"otim *")) { XB->opp_time = ((double)atoi(Star[0])) / 100.0; if (XB->opp_time < 0.0) XB->opp_time = 0.0; } else if (match(string,"pause")) { // refuse gui_send(GUI,"Error (unknown command): %s",string); } else if (match(string,"ping *")) { // HACK; TODO: answer only after an engine move if (DelayPong) { if (XB->ping >= 0) gui_send(GUI,"pong %d",XB->ping); // HACK: get rid of old ping XB->ping = atoi(Star[0]); uci_send_isready_sync(Uci); } else { ASSERT(XB->ping==-1); gui_send(GUI,"pong %s",Star[0]); } } else if (match(string,"nps *")) { // fake WB play-by-nodes mode XB->node_rate = atoi(Star[0]); } else if (match(string,"playother")) { State->computer[game_turn(Game)] = FALSE; State->computer[colour_opp(game_turn(Game))] = TRUE; XB->new_hack = FALSE; ASSERT(!XB->result); XB->result = FALSE; mess(); } else if (match(string,"post")) { XB->post = TRUE; } else if (match(string,"protover *")) { XB->proto_ver = atoi(Star[0]); ASSERT(XB->proto_ver>=2); send_xboard_options(); } else if (match(string,"quit")) { my_log("POLYGLOT *** \"quit\" from GUI ***\n"); quit(); } else if (match(string,"random")) { // ignore } else if (match(string,"rating * *")) { // ignore } else if (match(string,"remove")) { if (game_pos(Game) >= 2) { game_goto(Game,game_pos(Game)-2); ASSERT(!XB->new_hack); XB->new_hack = FALSE; // HACK? XB->result = FALSE; board_update(); mess(); } } else if (match(string,"rejected *")) { // ignore } else if (match(string,"reset")) { // protover 3? // refuse gui_send(GUI,"Error (unknown command): %s",string); } else if (FALSE || match(string,"result * {*}") || match(string,"result * {* }") || match(string,"result * { *}") || match(string,"result * { * }")) { my_log("POLYGLOT GAME END\n"); XB->result = TRUE; mess(); // book learning if (FALSE && option_get_bool(Option,"Book") && option_get_bool(Option,"BookLearn")) { if (FALSE) { } else if (my_string_equal(Star[0],"1-0")) { learn(+1); } else if (my_string_equal(Star[0],"0-1")) { learn(-1); } else if (my_string_equal(Star[0],"1/2-1/2")) { learn(0); } } } else if (match(string,"resume")) { // refuse gui_send(GUI,"Error (unknown command): %s",string); } else if (match(string,"option *=*") || match(string,"option * =*") || match(string,"option *= *") || match(string,"option * = *") ){ char *name=Star[0]; char *value=Star[1]; if(match(name, "Polyglot *")){ char *pg_name=Star[0]; polyglot_set_option(pg_name,value); }else{ option_t *opt=option_find(Uci->option,name); if(opt){ if(my_string_case_equal(opt->type,"check")){ value=my_string_equal(value,"1")?"true":"false"; } start_protected_command(); uci_send_option(Uci, name, "%s", value); end_protected_command(); }else{ gui_send(GUI,"Error (unknown option): %s",name); } } } else if (match(string,"option *")){ char *name=Star[0]; if(match(name, "Polyglot *")){ char *pg_name=Star[0]; polyglot_set_option(pg_name,"<empty>"); }else{ start_protected_command(); // value is ignored if(!uci_send_option(Uci, name, "%s", "<empty>")){ gui_send(GUI,"Error (unknown option): %s",name); }; end_protected_command(); } } else if (XB->has_feature_smp && match(string,"cores *")){ int cores=atoi(Star[0]); if(cores>=1){ // updating the number of cores my_log("POLYGLOT setting the number of cores to %d\n",cores); start_protected_command(); uci_set_threads(Uci,cores); end_protected_command(); } else{ // refuse gui_send(GUI,"Error (unknown command): %s",string); } } else if (match(string,"egtpath * *")){ char *type=Star[0]; char *path=Star[1]; if(my_string_empty(path)){ // refuse gui_send(GUI,"Error (unknown command): %s",string); }else{ if(my_string_case_equal(type,"nalimov") && XB->has_feature_egt_nalimov){ // updating NalimovPath my_log("POLYGLOT setting the Nalimov path to %s\n",path); start_protected_command(); uci_send_option(Uci,"NalimovPath","%s",path); end_protected_command(); }else if(my_string_case_equal(type,"gaviota") && XB->has_feature_egt_gaviota){ // updating GaviotaPath my_log("POLYGLOT setting the Gaviota path to %s\n",path); start_protected_command(); uci_send_option(Uci,"GaviotaTbPath","%s",path); end_protected_command(); }else{ // refuse gui_send(GUI,"Error (unsupported table base format): %s",string); } } } else if (XB->has_feature_memory && match(string,"memory *")){ int memory = atoi(Star[0]); int egt_cache; int real_memory; if(memory>=1){ // updating the available memory option_t *opt; my_log("POLYGLOT setting the amount of memory to %dMb\n",memory); if(XB->has_feature_egt_nalimov && (opt=option_find(Uci->option,"NalimovCache"))){ egt_cache=atoi(opt->value); }else if(XB->has_feature_egt_gaviota && (opt=option_find(Uci->option,"GaviotaTbCache"))){ egt_cache=atoi(opt->value); }else{ egt_cache=0; } my_log("POLYGLOT EGTB Cache is %dMb\n",egt_cache); real_memory=memory-egt_cache; if(real_memory>0){ start_protected_command(); uci_send_option(Uci,"Hash", "%d", real_memory); end_protected_command(); } }else{ // refuse gui_send(GUI,"Error (unknown command): %s",string); } } else if (match(string,"sd *")) { XB->depth_limit = TRUE; XB->depth_max = atoi(Star[0]); } else if (match(string,"setboard *")) { my_log("POLYGLOT FEN %s\n",Star[0]); if (!game_init(Game,Star[0])) my_fatal("xboard_step(): bad FEN \"%s\"\n",Star[0]); State->computer[White] = FALSE; State->computer[Black] = FALSE; XB->new_hack = TRUE; // HACK? XB->result = FALSE; board_update(); mess(); } else if (match(string,"st *")) { XB->time_limit = TRUE; XB->time_max = ((double)atoi(Star[0])); } else if (match(string,"time *")) { XB->my_time = ((double)atoi(Star[0])) / 100.0; if (XB->my_time < 0.0) XB->my_time = 0.0; } else if (match(string,"undo")) { if (game_pos(Game) >= 1) { game_goto(Game,game_pos(Game)-1); ASSERT(!XB->new_hack); XB->new_hack = FALSE; // HACK? XB->result = FALSE; board_update(); mess(); } } else if (match(string,"usermove *")) { game_get_board(Game,board); move = move_from_san(Star[0],board); if (move != MoveNone && move_is_legal(move,board)) { XB->new_hack = FALSE; ASSERT(!XB->result); XB->result = FALSE; move_step(move); no_mess(move); } else { gui_send(GUI,"Illegal move: %s",Star[0]); } } else if (match(string,"variant *")) { if (my_string_equal(Star[0],"3check")) { option_set(Option,"3Check","true"); } else { option_set(Option,"3Check","false"); } if (my_string_equal(Star[0],"fischerandom")) { option_set(Option,"Chess960","true"); } else { option_set(Option,"Chess960","false"); } if (my_string_equal(Star[0],"atomic")) { option_set(Option,"Atomic","true"); } else { option_set(Option,"Atomic","false"); } if (my_string_equal(Star[0],"horde")) { option_set(Option,"Horde","true"); game_init(Game,StartFenHorde); //gui_send(GUI,"setup %s",StartFenHorde); } else { option_set(Option,"Horde","false"); } } else if (match(string,"white")) { if (colour_is_white(game_turn(Game))) { State->computer[White] = FALSE; State->computer[Black] = TRUE; XB->new_hack = TRUE; XB->result = FALSE; mess(); } } else if (match(string,"xboard")) { // ignore } else if (match(string,".")) { // analyse info if (State->state == ANALYSE) { int depth=Uci->best_depth;//HACK: don't clear engine-output window... ASSERT(Uci->searching); ASSERT(Uci->pending_nb>=1); if (Uci->root_move != MoveNone && move_is_legal(Uci->root_move,Uci->board)) { move_to_san(Uci->root_move,Uci->board,move_string,256); gui_send(GUI,"stat01: %.0f "S64_FORMAT" %d %d %d %s",Uci->time*100.0,Uci->node_nb,/*Uci->*/depth,Uci->root_move_nb-(Uci->root_move_pos+1),Uci->root_move_nb,move_string); } else { gui_send(GUI,"stat01: %.0f "S64_FORMAT" %d %d %d",Uci->time*100.0,Uci->node_nb,/*Uci->*/depth,0,0); // HACK } } } else if (match(string,"?")) { // move now if (State->state == THINK) { ASSERT(Uci->searching); ASSERT(Uci->pending_nb>=1); // HACK: just send "stop" to the engine if (Uci->searching) { my_log("POLYGLOT STOP SEARCH\n"); engine_send(Engine,"stop"); } } } else { // unknown command, maybe a move? game_get_board(Game,board); move = move_from_san(string,board); if (move != MoveNone && move_is_legal(move,board)) { XB->new_hack = FALSE; ASSERT(!XB->result); XB->result = FALSE; move_step(move); no_mess(move); } else if (move != MoveNone) { gui_send(GUI,"Illegal move: %s",string); } else { gui_send(GUI,"Error (unknown command): %s",string); } } return; }