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; } }
void move_do(board_t * board, int move) { int me, opp; int from, to; int piece, pos, capture; int old_flags, new_flags; int sq, ep_square; int pawn; ASSERT(board_is_ok(board)); ASSERT(move_is_ok(move)); ASSERT(move_is_pseudo(move,board)); // init me = board->turn; opp = colour_opp(me); from = move_from(move); to = move_to(move); piece = board->square[from]; ASSERT(colour_equal(piece,me)); pos = board->pos[from]; ASSERT(pos>=0); // update turn board->turn = opp; board->key ^= random_64(RandomTurn); // update castling rights old_flags = board_flags(board); if (piece_is_king(piece)) { board->castle[me][SideH] = SquareNone; board->castle[me][SideA] = SquareNone; } if (board->castle[me][SideH] == from) board->castle[me][SideH] = SquareNone; if (board->castle[me][SideA] == from) board->castle[me][SideA] = SquareNone; if (board->castle[opp][SideH] == to) board->castle[opp][SideH] = SquareNone; if (board->castle[opp][SideA] == to) board->castle[opp][SideA] = SquareNone; new_flags = board_flags(board); board->key ^= hash_castle_key(new_flags^old_flags); // HACK // update en-passant square ep_square = sq = board->ep_square; if (sq != SquareNone) { board->key ^= random_64(RandomEnPassant+square_file(sq)); board->ep_square = SquareNone; } if (piece_is_pawn(piece) && abs(to-from) == 32) { pawn = piece_make_pawn(opp); if (board->square[to-1] == pawn || board->square[to+1] == pawn) { board->ep_square = sq = (from + to) / 2; board->key ^= random_64(RandomEnPassant+square_file(sq)); } } // update ply number (captures are handled later) board->ply_nb++; if (piece_is_pawn(piece)) board->ply_nb = 0; // conversion // update move number if (me == Black) board->move_nb++; // castle if (colour_equal(board->square[to],me)) { int rank; int king_from, king_to; int rook_from, rook_to; int rook; rank = colour_is_white(me) ? Rank1 : Rank8; king_from = from; rook_from = to; if (to > from) { // h side king_to = square_make(FileG,rank); rook_to = square_make(FileF,rank); } else { // a side king_to = square_make(FileC,rank); rook_to = square_make(FileD,rank); } // remove the rook pos = board->pos[rook_from]; ASSERT(pos>=0); rook = Rook64 | me; // HACK square_clear(board,rook_from,rook); // move the king square_move(board,king_from,king_to,piece); // put the rook back square_set(board,rook_to,rook,pos); ASSERT(board->key==hash_key(board)); return; } // remove the captured piece if (piece_is_pawn(piece) && to == ep_square) { // en-passant capture sq = square_ep_dual(to); capture = board->square[sq]; ASSERT(capture==piece_make_pawn(opp)); square_clear(board,sq,capture); board->ply_nb = 0; // conversion } else { capture = board->square[to]; if (capture != Empty) { // normal capture ASSERT(colour_equal(capture,opp)); ASSERT(!piece_is_king(capture)); square_clear(board,to,capture); board->ply_nb = 0; // conversion } } // move the piece if (move_is_promote(move)) { // promote square_clear(board,from,piece); piece = move_promote_hack(move) | me; // HACK square_set(board,to,piece,pos); } else { // normal move square_move(board,from,to,piece); } ASSERT(board->key==hash_key(board)); }
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); } } }
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; }
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++; } }
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 int move_from_lan(const char string[], const board_t * board) { int len; int move; int promote; char s[256]; int from, to; int colour; int inc; int piece_char; int n; const uint8 * ptr; int piece; int side; ASSERT(string!=NULL); ASSERT(board_is_ok(board)); // init len = strlen(string); if (len != 7) return MoveNone; move = MoveNone; colour = board->turn; // promote promote = 0; switch (string[6]) { case '?': // not a promotion break; case 'N': promote = MovePromoteKnight; break; case 'B': promote = MovePromoteBishop; break; case 'R': promote = MovePromoteRook; break; case 'Q': promote = MovePromoteQueen; break; default: return MoveNone; break; } // to square s[0] = string[4]; s[1] = string[5]; s[2] = '\0'; to = square_from_string(s); if (to == SquareNone) return MoveNone; // known from square? if (string[1] != '?' && string[2] != '?') { // from square s[0] = string[1]; s[1] = string[2]; s[2] = '\0'; from = square_from_string(s); if (from == SquareNone) return MoveNone; // convert "king slide" castling to KxR if (piece_is_king(board->square[from]) && square_rank(to) == square_rank(from) && abs(to-from) > 1) { side = (to > from) ? SideH : SideA; to = board->castle[colour][side]; if (to == SquareNone) return MoveNone; } // move move = move_make(from,to) | promote; return move; } // pawn non-capture? if (string[0] == '?' && string[1] == '?') { if (board->square[to] != Empty) return MoveNone; // useful? inc = (colour_is_white(colour)) ? +16 : -16; from = to - inc; if (board->square[from] == Empty && square_side_rank(to,colour) == Rank4) { from -= inc; } if (board->square[from] != piece_make_pawn(colour)) { // useful? return MoveNone; } // move move = move_make(from,to) | promote; return move; } // pawn capture? piece_char = string[0]; if (piece_char == '?' && string[1] != '?') { piece_char = 'P'; } // attack loop n = 0; for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) { piece = board->square[from]; if (toupper(piece_to_char(piece)) == piece_char) { if (piece_attack(board,piece,from,to)) { if (true && (string[1] == '?' || file_to_char(square_file(from)) == string[1]) && (string[2] == '?' || rank_to_char(square_rank(from)) == string[2])) { if (!is_pinned(board,from,to,colour)) { move = move_make(from,to) | promote; n++; } } } } } if (n != 1) move = MoveNone; return move; }