+++ /dev/null
-\r
-// adapter.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#ifndef _WIN32\r
-#include <sys/select.h>\r
-#include <sys/types.h> // Mac OS X needs this one\r
-#include <unistd.h>\r
-#endif\r
-\r
-#include "adapter.h"\r
-#include "board.h"\r
-#include "book.h"\r
-#include "colour.h"\r
-#include "engine.h"\r
-#include "fen.h"\r
-#include "game.h"\r
-#include "gui.h"\r
-#include "line.h"\r
-#include "main.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_legal.h"\r
-#include "option.h"\r
-#include "parse.h"\r
-#include "san.h"\r
-#include "uci.h"\r
-#include "util.h"\r
-#include "posix.h"\r
-\r
-\r
-// constants\r
-\r
-static const bool UseDebug = false;\r
-static const bool DelayPong = false;\r
-\r
-static const int StringSize = 4096;\r
-\r
-// types\r
-\r
-struct state_t {\r
- int state;\r
- bool computer[ColourNb];\r
- int exp_move;\r
- int resign_nb;\r
- my_timer_t timer[1];\r
-};\r
-\r
-struct xb_t {\r
- bool has_feature_memory;\r
- bool has_feature_smp;\r
- bool has_feature_egt;\r
- bool analyse;\r
- bool computer;\r
- const char * name;\r
- bool ics;\r
- bool new_hack; // "new" is a C++ keyword\r
- bool ponder;\r
- int ping;\r
- bool post;\r
- int proto_ver;\r
- bool result;\r
-\r
- int mps;\r
- double base;\r
- double inc;\r
- \r
- bool time_limit;\r
- double time_max;\r
- \r
- bool depth_limit;\r
- int depth_max;\r
- \r
- double my_time;\r
- double opp_time;\r
-};\r
-\r
-enum dummy_state_t { WAIT, THINK, PONDER, ANALYSE };\r
-\r
-// variables\r
-\r
-static state_t State[1];\r
-static xb_t XB[1];\r
-\r
-// prototypes\r
-\r
-\r
-static void xboard_step (char string[]);\r
-static void engine_step (char string[]);\r
-\r
-static void comp_move (int move);\r
-static void move_step (int move);\r
-static void board_update ();\r
-\r
-static void mess ();\r
-static void no_mess (int move);\r
-\r
-static void search_update ();\r
-static void search_clear ();\r
-static void update_remaining_time();\r
-static void start_protected_command();\r
-static void end_protected_command();\r
-\r
-static bool active ();\r
-static bool ponder ();\r
-static bool ponder_ok (int ponder_move);\r
-\r
-static void stop_search ();\r
-\r
-static void send_board (int extra_move);\r
-static void send_pv ();\r
-\r
-static void send_xboard_options ();\r
-\r
-static void learn (int result);\r
-\r
-static void adapter_step (); \r
-\r
-// functions\r
-\r
-// adapter_loop()\r
-\r
-void adapter_loop() {\r
-\r
- // init\r
-\r
- game_clear(Game);\r
-\r
- // state\r
-\r
- State->state = WAIT;\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = true;\r
-\r
- State->exp_move = MoveNone;\r
- State->resign_nb = 0;\r
- my_timer_reset(State->timer);\r
-\r
- // yes there are engines that do not have the "Hash" option....\r
- XB->has_feature_memory= uci_option_exist(Uci,"Hash");\r
- XB->has_feature_smp = uci_thread_option_exist(Uci);\r
- // TODO: support for other types of table bases\r
- XB->has_feature_egt = uci_option_exist(Uci,"NalimovPath");\r
- XB->analyse = false;\r
- XB->computer = false;\r
- XB->name = NULL;\r
- my_string_set(&XB->name,"<empty>");\r
- XB->ics = false;\r
- XB->new_hack = true;\r
- XB->ping = -1;\r
- XB->ponder = false;\r
- XB->post = false;\r
- XB->proto_ver = 1;\r
- XB->result = false;\r
-\r
- XB->mps = 0;\r
- XB->base = 300.0;\r
- XB->inc = 0.0;\r
-\r
- XB->time_limit = false;\r
- XB->time_max = 5.0;\r
-\r
- XB->depth_limit = false;\r
- XB->depth_max = 127;\r
-\r
- XB->my_time = 300.0;\r
- XB->opp_time = 300.0;\r
- while (true) adapter_step();\r
-}\r
-\r
-// adapter_step()\r
-\r
-#ifdef _WIN32\r
-static void adapter_step(){ // polling!\r
- bool xin,ein;\r
- char string[StringSize];\r
- if(option_get_bool("UCI")){\r
- xin=gui_get_non_blocking(GUI,string,StringSize);\r
- if(xin) uci_gui_step(string);\r
- ein=engine_get_non_blocking(Engine,string,StringSize);\r
- if(ein) uci_engine_step(string);\r
- }else{\r
- xin=gui_get_non_blocking(GUI,string,StringSize);\r
- if(xin) xboard_step(string);\r
- ein=engine_get_non_blocking(Engine,string,StringSize);\r
- if(ein) engine_step(string);\r
- }\r
- if(xin==false && ein==false) Idle();//nobody wants me,lets have a beauty nap\r
-}\r
-#else\r
-static void adapter_step() {\r
-\r
- fd_set set[1];\r
- int fd_max;\r
- int val;\r
- char string[StringSize];\r
-\r
- // process buffered lines\r
-\r
- while (io_line_ready(GUI->io)){\r
- gui_get(GUI,string,StringSize);\r
- if(option_get_bool("UCI")){\r
- uci_gui_step(string);\r
- }else{\r
- xboard_step(string); // process available xboard lines\r
- }\r
- }\r
- while (io_line_ready(Engine->io)){\r
- engine_get(Engine,string,StringSize);\r
- if(option_get_bool("UCI")){\r
- uci_engine_step(string); // process available engine lines\r
- }else{\r
- engine_step(string);\r
- }\r
- }\r
-\r
- // init\r
-\r
- FD_ZERO(set);\r
- fd_max = -1; // HACK\r
-\r
- // add xboard input\r
-\r
- ASSERT(GUI->io->in_fd>=0);\r
-\r
- FD_SET(GUI->io->in_fd,set);\r
- if (GUI->io->in_fd > fd_max) fd_max = GUI->io->in_fd;\r
-\r
- // add engine input\r
-\r
- ASSERT(Engine->io->in_fd>=0);\r
-\r
- FD_SET(Engine->io->in_fd,set);\r
- if (Engine->io->in_fd > fd_max) fd_max = Engine->io->in_fd;\r
-\r
- // wait for something to read (no timeout)\r
-\r
- ASSERT(fd_max>=0);\r
-\r
- val = select(fd_max+1,set,NULL,NULL,NULL);\r
- if (val == -1 && errno != EINTR) my_fatal("adapter_step(): select(): %s\n",strerror(errno));\r
-\r
- if (val > 0) {\r
- if (FD_ISSET(GUI->io->in_fd,set)) io_get_update(GUI->io); // read some xboard input\r
- if (FD_ISSET(Engine->io->in_fd,set)) io_get_update(Engine->io); // read some engine input\r
- }\r
-}\r
-#endif\r
-\r
-static void xboard_step(char string[]) {\r
-\r
- int move;\r
- char move_string[256];\r
- board_t board[1];\r
- static bool firsttime=true;\r
-\r
- if(firsttime){\r
- if((match(string,"uci"))){\r
- my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
- send_uci_options();\r
- option_set("UCI","true");\r
- return;\r
- }else{\r
- //uci_send_isready(Uci); // In UCI mode this done by the GUI\r
- //Grrr...Toga can fixes the number of threads after "isready"\r
- //So we delay "isready" \r
- }\r
- firsttime=false;\r
- }\r
- if (false) {\r
- \r
- } else if (match(string,"accepted *")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,"analyze")) {\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
-\r
- XB->analyse = true;\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"bk")) {\r
-\r
- if (option_get_bool("Book")) {\r
- game_get_board(Game,board);\r
- book_disp(board);\r
- }\r
-\r
- } else if (match(string,"black")) {\r
-\r
- if (colour_is_black(game_turn(Game))) {\r
-\r
- State->computer[White] = true;\r
- State->computer[Black] = false;\r
-\r
- XB->new_hack = true;\r
- XB->result = false;\r
-\r
- mess();\r
- }\r
-\r
- } else if (match(string,"computer")) {\r
-\r
- XB->computer = true;\r
-\r
- } else if (match(string,"draw")) {\r
- if(uci_option_exist(Uci,"UCI_DrawOffers")){\r
- my_log("POLYGLOT draw from XB received");\r
- uci_send_option(Uci,"DrawOffer","%s","draw");}\r
- } else if (match(string,"easy")) {\r
-\r
- XB->ponder = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"edit")) {\r
-\r
- // refuse\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
-\r
- } else if (match(string,"exit")) {\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
-\r
- XB->analyse = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"force")) {\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"go")) {\r
-\r
- State->computer[game_turn(Game)] = true;\r
- State->computer[colour_opp(game_turn(Game))] = false;\r
-\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"hard")) {\r
-\r
- XB->ponder = true;\r
-\r
- mess();\r
-\r
- } else if (match(string,"hint")) {\r
-\r
- if (option_get_bool("Book")) {\r
-\r
- game_get_board(Game,board);\r
- move = book_move(board,false);\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
- move_to_san(move,board,move_string,256);\r
- gui_send(GUI,"Hint: %s",move_string);\r
- }\r
- }\r
-\r
- } else if (match(string,"ics *")) {\r
-\r
- XB->ics = true;\r
-\r
- } else if (match(string,"level * *:* *")) {\r
-\r
- XB->mps = atoi(Star[0]);\r
- XB->base = double(atoi(Star[1])) * 60.0 + double(atoi(Star[2]));\r
- XB->inc = double(atoi(Star[3]));\r
-\r
- } else if (match(string,"level * * *")) {\r
-\r
- XB->mps = atoi(Star[0]);\r
- XB->base = double(atoi(Star[1])) * 60.0;\r
- XB->inc = double(atoi(Star[2]));\r
-\r
- } else if (match(string,"name *")) {\r
-\r
- my_string_set(&XB->name,Star[0]);\r
-\r
- } else if (match(string,"new")) {\r
-\r
- uci_send_isready(Uci);\r
- my_log("POLYGLOT NEW GAME\n");\r
-\r
- option_set("Chess960","false");\r
-\r
- game_clear(Game);\r
-\r
- if (XB->analyse) {\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
- } else {\r
- State->computer[White] = false;\r
- State->computer[Black] = true;\r
- }\r
-\r
- XB->new_hack = true;\r
- XB->result = false;\r
-\r
- XB->depth_limit = false;\r
-\r
- XB->computer = false;\r
- my_string_set(&XB->name,"<empty>");\r
-\r
- board_update();\r
- mess();\r
-\r
- uci_send_ucinewgame(Uci);\r
-\r
- } else if (match(string,"nopost")) {\r
-\r
- XB->post = false;\r
-\r
- } else if (match(string,"otim *")) {\r
-\r
- XB->opp_time = double(atoi(Star[0])) / 100.0;\r
- if (XB->opp_time < 0.0) XB->opp_time = 0.0;\r
-\r
- } else if (match(string,"pause")) {\r
-\r
- // refuse\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
-\r
- } else if (match(string,"ping *")) {\r
-\r
- // HACK; TODO: answer only after an engine move\r
-\r
- if (DelayPong) {\r
- if (XB->ping >= 0) gui_send(GUI,"pong %d",XB->ping); // HACK: get rid of old ping\r
- XB->ping = atoi(Star[0]);\r
- uci_send_isready(Uci);\r
- } else {\r
- ASSERT(XB->ping==-1);\r
- gui_send(GUI,"pong %s",Star[0]);\r
- }\r
-\r
- } else if (match(string,"playother")) {\r
-\r
- State->computer[game_turn(Game)] = false;\r
- State->computer[colour_opp(game_turn(Game))] = true;\r
-\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"post")) {\r
-\r
- XB->post = true;\r
-\r
- } else if (match(string,"protover *")) {\r
-\r
- send_xboard_options();\r
-\r
- } else if (match(string,"quit")) {\r
- my_log("POLYGLOT *** \"quit\" from GUI ***\n");\r
- quit();\r
- } else if (match(string,"random")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,"rating * *")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,"remove")) {\r
-\r
- if (game_pos(Game) >= 2) {\r
-\r
- game_goto(Game,game_pos(Game)-2);\r
-\r
- ASSERT(!XB->new_hack);\r
- XB->new_hack = false; // HACK?\r
- XB->result = false;\r
-\r
- board_update();\r
- mess();\r
- }\r
-\r
- } else if (match(string,"rejected *")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,"reset")) { // protover 3?\r
-\r
- // refuse\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
-\r
- } else if (false\r
- || match(string,"result * {*}")\r
- || match(string,"result * {* }")\r
- || match(string,"result * { *}")\r
- || match(string,"result * { * }")) {\r
-\r
- my_log("POLYGLOT GAME END\n");\r
-\r
- XB->result = true;\r
-\r
- mess();\r
-\r
- // book learning\r
-\r
- if (option_get_bool("Book") && option_get_bool("BookLearn")) {\r
-\r
- if (false) {\r
- } else if (my_string_equal(Star[0],"1-0")) {\r
- learn(+1);\r
- } else if (my_string_equal(Star[0],"0-1")) {\r
- learn(-1);\r
- } else if (my_string_equal(Star[0],"1/2-1/2")) {\r
- learn(0);\r
- }\r
- }\r
- } else if (match(string,"resume")) {\r
-\r
- // refuse\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
-\r
- } else if (match(string,"option *=*")){\r
- char *name=Star[0];\r
- char *value=Star[1];\r
- if(match(name, "Polyglot *")){\r
- char *pg_name=Star[0];\r
- polyglot_set_option(pg_name,value);\r
- }else{\r
- start_protected_command();\r
- engine_send(Engine,"setoption name %s value %s",name,value);\r
- end_protected_command();\r
- }\r
- } else if (match(string,"option *")){\r
- char *name=Star[0];\r
- start_protected_command();\r
- engine_send(Engine,"setoption name %s",name);\r
- end_protected_command();\r
- } else if (XB->has_feature_smp && match(string,"cores *")){\r
- int cores=atoi(Star[0]);\r
- if(cores>=1){\r
- // updating the number of cores\r
- my_log("POLYGLOT setting the number of cores to %d\n",cores);\r
- start_protected_command();\r
- uci_set_threads(Uci,cores); \r
- end_protected_command();\r
- } else{\r
- // refuse\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
- }\r
- } else if (XB->has_feature_egt && match(string,"egtpath * *")){\r
- char *type=Star[0];\r
- char *path=Star[1];\r
- if(!my_string_case_equal(Star[0],"nalimov")){\r
- // refuse\r
- gui_send(GUI,"Error (unsupported table base format): %s",string);\r
- }else if(my_string_empty(path)){\r
- // refuse\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
- }else{\r
- // updating NalimovPath\r
- my_log("POLYGLOT setting the Nalimov path to %s\n",path);\r
- start_protected_command();\r
- uci_send_option(Uci,"NalimovPath","%s",path);\r
- end_protected_command();\r
- }\r
- } else if (XB->has_feature_memory && match(string,"memory *")){\r
- int memory = atoi(Star[0]);\r
- int nalimov_cache;\r
- int real_memory;\r
- if(memory>=1){\r
- // updating the available memory\r
- my_log("POLYGLOT setting the amount of memory to %dMb\n",memory);\r
- if(uci_get_option(Uci,"NalimovCache")>=0){\r
- nalimov_cache=atoi(Uci->option[uci_get_option(Uci,"NalimovCache")].value);\r
- }else{\r
- nalimov_cache=0;\r
- }\r
- my_log("POLYGLOT Nalimov Cache is %dMb\n",nalimov_cache);\r
- real_memory=memory-nalimov_cache;\r
- if(real_memory>0){\r
- start_protected_command();\r
- uci_send_option(Uci,"Hash", "%d", real_memory);\r
- end_protected_command();\r
- }\r
- }else{\r
- // refuse\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
- }\r
-\r
- } else if (match(string,"sd *")) {\r
-\r
- XB->depth_limit = true;\r
- XB->depth_max = atoi(Star[0]);\r
-\r
- } else if (match(string,"setboard *")) {\r
-\r
- my_log("POLYGLOT FEN %s\n",Star[0]);\r
-\r
- if (!game_init(Game,Star[0])) my_fatal("xboard_step(): bad FEN \"%s\"\n",Star[0]);\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
-\r
- XB->new_hack = true; // HACK?\r
- XB->result = false;\r
-\r
- board_update();\r
- mess();\r
-\r
- } else if (match(string,"st *")) {\r
-\r
- XB->time_limit = true;\r
- XB->time_max = double(atoi(Star[0]));\r
-\r
- } else if (match(string,"time *")) {\r
-\r
- XB->my_time = double(atoi(Star[0])) / 100.0;\r
- if (XB->my_time < 0.0) XB->my_time = 0.0;\r
-\r
- } else if (match(string,"undo")) {\r
-\r
- if (game_pos(Game) >= 1) {\r
-\r
- game_goto(Game,game_pos(Game)-1);\r
-\r
- ASSERT(!XB->new_hack);\r
- XB->new_hack = false; // HACK?\r
- XB->result = false;\r
-\r
- board_update();\r
- mess();\r
- }\r
-\r
- } else if (match(string,"usermove *")) {\r
-\r
- game_get_board(Game,board);\r
- move = move_from_san(Star[0],board);\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
-\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- move_step(move);\r
- no_mess(move);\r
-\r
- } else {\r
-\r
- gui_send(GUI,"Illegal move: %s",Star[0]);\r
- }\r
-\r
- } else if (match(string,"variant *")) {\r
-\r
- if (my_string_equal(Star[0],"fischerandom")) {\r
- option_set("Chess960","true");\r
- } else {\r
- option_set("Chess960","false");\r
- }\r
-\r
- } else if (match(string,"white")) {\r
-\r
- if (colour_is_white(game_turn(Game))) {\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = true;\r
-\r
- XB->new_hack = true;\r
- XB->result = false;\r
-\r
- mess();\r
- }\r
-\r
- } else if (match(string,"xboard")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,".")) { // analyse info\r
-\r
- if (State->state == ANALYSE) {\r
- int depth=Uci->best_depth;//HACK: don't clear engine-output window...\r
-\r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
-\r
- if (Uci->root_move != MoveNone && move_is_legal(Uci->root_move,Uci->board)) {\r
- move_to_san(Uci->root_move,Uci->board,move_string,256);\r
- 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);\r
- } else {\r
- gui_send(GUI,"stat01: %.0f "S64_FORMAT" %d %d %d",Uci->time*100.0,Uci->node_nb,/*Uci->*/depth,0,0); // HACK\r
- }\r
- }\r
-\r
- } else if (match(string,"?")) { // move now\r
-\r
- if (State->state == THINK) {\r
-\r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
-\r
- // HACK: just send "stop" to the engine\r
-\r
- if (Uci->searching) {\r
- my_log("POLYGLOT STOP SEARCH\n");\r
- engine_send(Engine,"stop");\r
- }\r
- }\r
-\r
- } else { // unknown command, maybe a move?\r
-\r
- game_get_board(Game,board);\r
- move = move_from_san(string,board);\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
-\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- move_step(move);\r
- no_mess(move);\r
-\r
- } else if (move != MoveNone) {\r
-\r
- gui_send(GUI,"Illegal move: %s",string);\r
-\r
- } else {\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
- }\r
- }\r
- return;\r
-}\r
-\r
-// engine_step()\r
-\r
-static void engine_step(char string[]) {\r
-\r
- int event;\r
- event = uci_parse(Uci,string);\r
-\r
- // react to events\r
-\r
- if ((event & EVENT_READY) != 0) {\r
-\r
- // the engine is now ready\r
-\r
- if (!Uci->ready) {\r
- Uci->ready = true;\r
- // if (XB->proto_ver >= 2) xboard_send(XBoard,"feature done=1");\r
- }\r
-\r
- if (!DelayPong && XB->ping >= 0) {\r
- gui_send(GUI,"pong %d",XB->ping);\r
- XB->ping = -1;\r
- }\r
- }\r
-\r
- if ((event & EVENT_MOVE) != 0 && State->state == THINK) {\r
-\r
- // the engine is playing a move\r
-\r
- // MEGA HACK: estimate remaining time because XBoard won't send it!\r
-\r
- my_timer_stop(State->timer);\r
-\r
- XB->my_time -= my_timer_elapsed_real(State->timer);\r
- XB->my_time += XB->inc;\r
- if (XB->mps != 0 && (game_move_nb(Game) + 1) % XB->mps == 0) XB->my_time += XB->base;\r
-\r
- if (XB->my_time < 0.0) XB->my_time = 0.0;\r
-\r
- // play the engine move\r
-\r
- comp_move(Uci->best_move);\r
- }\r
-\r
- if ((event & EVENT_PV) != 0) {\r
-\r
- // the engine has sent a new PV\r
-\r
- send_pv();\r
- }\r
- if((event & (EVENT_DRAW|EVENT_RESIGN))!=0){\r
- my_log("POYGLOT draw offer/resign from engine\n");\r
- if(uci_option_exist(Uci,"UCI_DrawOffers")){\r
- if(event & EVENT_DRAW)\r
- gui_send(GUI,"offer draw");\r
- else\r
- gui_send(GUI,"resign");\r
- }\r
- }\r
-}\r
-\r
-// format_xboard_option_line\r
-\r
-void format_xboard_option_line(char * option_line, option_t *opt){\r
- int j;\r
- char option_string[StringSize];\r
- strcpy(option_line,"");\r
- strcat(option_line,"feature option=\"");\r
- if(opt->mode&PG){\r
- strcat(option_line,"Polyglot ");\r
- }\r
- sprintf(option_string,"%s",opt->name);\r
- strcat(option_line,option_string);\r
- sprintf(option_string," -%s",opt->type);\r
- strcat(option_line,option_string);\r
- if(strcmp(opt->type,"button") && strcmp(opt->type,"combo")){\r
- if(strcmp(opt->type,"check")){\r
- sprintf(option_string," %s",opt->default_);\r
- }else{\r
- sprintf(option_string," %d",\r
- strcmp(opt->default_,"true")?0:1);\r
- }\r
- strcat(option_line,option_string);\r
- }\r
- if(!strcmp(opt->type,"spin")){\r
- sprintf(option_string," %s",opt->min);\r
- strcat(option_line,option_string);\r
- }\r
- if(!strcmp(opt->type,"spin")){\r
- sprintf(option_string," %s",opt->max);\r
- strcat(option_line,option_string);\r
- }\r
- for(j=0;j<opt->var_nb;j++){\r
- if(!strcmp(opt->var[j],opt->default_)){\r
- sprintf(option_string," *%s",opt->var[j]);\r
- }else{\r
- sprintf(option_string," %s",opt->var[j]);\r
- }\r
- strcat(option_line,option_string);\r
- if(j!=opt->var_nb-1){\r
- strcat(option_line," ///");\r
- }\r
- }\r
- strcat(option_line,"\"");\r
-}\r
-\r
-// send_xboard_options\r
-\r
-static void send_xboard_options(){\r
- int i;\r
- char option_line[StringSize]="";\r
- option_t *p=Option;\r
- const char * name;\r
- XB->proto_ver = atoi(Star[0]);\r
- ASSERT(XB->proto_ver>=2);\r
- \r
- gui_send(GUI,"feature done=0");\r
- \r
- gui_send(GUI,"feature analyze=1");\r
- gui_send(GUI,"feature colors=0");\r
- gui_send(GUI,"feature draw=1");\r
- gui_send(GUI,"feature ics=1");\r
- gui_send(GUI,"feature myname=\"%s\"",option_get_string("EngineName"));\r
- gui_send(GUI,"feature name=1");\r
- gui_send(GUI,"feature pause=0");\r
- gui_send(GUI,"feature ping=1");\r
- gui_send(GUI,"feature playother=1");\r
- gui_send(GUI,"feature reuse=1");\r
- gui_send(GUI,"feature san=0");\r
- gui_send(GUI,"feature setboard=1");\r
- gui_send(GUI,"feature sigint=0");\r
- gui_send(GUI,"feature sigterm=0");\r
- gui_send(GUI,"feature time=1");\r
- gui_send(GUI,"feature usermove=1");\r
- if (XB->has_feature_memory){\r
- gui_send(GUI,"feature memory=1");\r
- }else{\r
- gui_send(GUI,"feature memory=0");\r
- }\r
- if (XB->has_feature_smp){\r
- gui_send(GUI,"feature smp=1");\r
- }else{\r
- gui_send(GUI,"feature smp=0");\r
- }\r
- if (XB->has_feature_egt){\r
- // TODO: support for other types of table bases\r
- gui_send(GUI,"feature egt=\"nalimov\"");\r
- }else{\r
- gui_send(GUI,"feature egt=\"\"");\r
- }\r
- \r
- if (uci_option_exist(Uci,"UCI_Chess960")) {\r
- gui_send(GUI,"feature variants=\"normal,fischerandom\"");\r
- } else {\r
- gui_send(GUI,"feature variants=\"normal\"");\r
- }\r
- \r
- for(i=0;i<Uci->option_nb;i++){\r
- if(!strcmp(Uci->option[i].name,PolyglotBookFile)) continue;\r
- if(my_string_case_equal(Uci->option[i].name,"UCI_AnalyseMode")) continue;\r
- if(my_string_case_equal(Uci->option[i].name,"Ponder")) continue;\r
- if(my_string_case_equal(Uci->option[i].name,"Hash")) continue;\r
- if(my_string_case_equal(Uci->option[i].name,"NalimovPath")) continue;\r
- if((name=uci_thread_option(Uci))!=NULL && my_string_case_equal(Uci->option[i].name,name)) continue;\r
- format_xboard_option_line(option_line,Uci->option+i);\r
-\r
- gui_send(GUI,"%s",option_line);\r
-\r
- }\r
- while(p->name){\r
- if(p->mode &XBOARD){\r
- format_xboard_option_line(option_line,p);\r
- gui_send(GUI,"%s",option_line);\r
- }\r
- p++;\r
- } \r
- gui_send(GUI,"feature done=1"); \r
- \r
-}\r
-\r
-// comp_move()\r
-\r
-static void comp_move(int move) {\r
-\r
- board_t board[1];\r
- char string[256];\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- ASSERT(State->state==THINK);\r
- ASSERT(!XB->analyse);\r
-\r
- if(option_get_bool("RepeatPV")==true)\r
- send_pv(); // to update time and nodes\r
-\r
- // send the move\r
-\r
- game_get_board(Game,board);\r
-\r
- if (move_is_castle(move,board) && option_get_bool("Chess960")) {\r
- if (!move_to_san(move,board,string,256)) my_fatal("comp_move(): move_to_san() failed\n"); // O-O/O-O-O\r
- } else {\r
- if (!move_to_can(move,board,string,256)) my_fatal("comp_move(): move_to_can() failed\n");\r
- }\r
-\r
- gui_send(GUI,"move %s",string);\r
-\r
- // resign?\r
-\r
- if (option_get_bool("Resign") && Uci->root_move_nb > 1) {\r
-\r
- if (Uci->best_score <= -abs(option_get_int("ResignScore"))) {\r
-\r
- State->resign_nb++;\r
- my_log("POLYGLOT %d move%s with resign score\n",State->resign_nb,(State->resign_nb>1)?"s":"");\r
-\r
- if (State->resign_nb >= option_get_int("ResignMoves")) {\r
- my_log("POLYGLOT *** RESIGN ***\n");\r
- gui_send(GUI,"resign");\r
- }\r
-\r
- } else {\r
-\r
- if (State->resign_nb > 0) my_log("POLYGLOT resign reset (State->resign_nb=%d)\n",State->resign_nb);\r
- State->resign_nb = 0;\r
- }\r
- }\r
-\r
- // play the move\r
-\r
- move_step(move);\r
- no_mess(move);\r
-}\r
-\r
-// move_step()\r
-\r
-static void move_step(int move) {\r
-\r
- board_t board[1];\r
- char move_string[256];\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- // log\r
-\r
- game_get_board(Game,board);\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
-\r
- move_to_san(move,board,move_string,256);\r
- my_log("POLYGLOT MOVE %s\n",move_string);\r
-\r
- } else {\r
-\r
- move_to_can(move,board,move_string,256);\r
- my_log("POLYGLOT ILLEGAL MOVE \"%s\"\n",move_string);\r
- board_disp(board);\r
-\r
- my_fatal("move_step(): illegal move \"%s\"\n",move_string);\r
- }\r
-\r
- // play the move\r
-\r
- game_add_move(Game,move);\r
- board_update();\r
-}\r
-\r
-// board_update()\r
-\r
-static void board_update() {\r
-\r
- // handle game end\r
-\r
- ASSERT(!XB->result);\r
-\r
- switch (game_status(Game)) {\r
- case PLAYING:\r
- break;\r
- case WHITE_MATES:\r
- gui_send(GUI,"1-0 {White mates}");\r
- break;\r
- case BLACK_MATES:\r
- gui_send(GUI,"0-1 {Black mates}");\r
- break;\r
- case STALEMATE:\r
- gui_send(GUI,"1/2-1/2 {Stalemate}");\r
- break;\r
- case DRAW_MATERIAL:\r
- gui_send(GUI,"1/2-1/2 {Draw by insufficient material}");\r
- break;\r
- case DRAW_FIFTY:\r
- gui_send(GUI,"1/2-1/2 {Draw by fifty-move rule}");\r
- break;\r
- case DRAW_REPETITION:\r
- gui_send(GUI,"1/2-1/2 {Draw by repetition}");\r
- break;\r
- default:\r
- ASSERT(false);\r
- break;\r
- }\r
-}\r
-\r
-// mess()\r
-\r
-static void mess() {\r
-\r
- // clear state variables\r
-\r
- State->resign_nb = 0;\r
- State->exp_move = MoveNone;\r
- my_timer_reset(State->timer);\r
-\r
- // abort a possible search\r
-\r
- stop_search();\r
-\r
- // calculate the new state\r
-\r
- if (false) {\r
- } else if (!active()) {\r
- State->state = WAIT;\r
- my_log("POLYGLOT WAIT\n");\r
- } else if (XB->analyse) {\r
- State->state = ANALYSE;\r
- my_log("POLYGLOT ANALYSE\n");\r
- } else if (State->computer[game_turn(Game)]) {\r
- State->state = THINK;\r
- my_log("POLYGLOT THINK\n");\r
- } else {\r
- State->state = WAIT;\r
- my_log("POLYGLOT WAIT\n");\r
- }\r
-\r
- search_update();\r
-}\r
-\r
-// no_mess()\r
-\r
-static void no_mess(int move) {\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- // just received a move, calculate the new state\r
-\r
- if (false) {\r
-\r
- } else if (!active()) {\r
-\r
- stop_search(); // abort a possible search\r
-\r
- State->state = WAIT;\r
- State->exp_move = MoveNone;\r
-\r
- my_log("POLYGLOT WAIT\n");\r
-\r
- } else if (State->state == WAIT) {\r
-\r
- ASSERT(State->computer[game_turn(Game)]);\r
- ASSERT(!State->computer[colour_opp(game_turn(Game))]);\r
- ASSERT(!XB->analyse);\r
-\r
- my_log("POLYGLOT WAIT -> THINK\n");\r
-\r
- State->state = THINK;\r
- State->exp_move = MoveNone;\r
-\r
- } else if (State->state == THINK) {\r
-\r
- ASSERT(!State->computer[game_turn(Game)]);\r
- ASSERT(State->computer[colour_opp(game_turn(Game))]);\r
- ASSERT(!XB->analyse);\r
-\r
- if (ponder() && ponder_ok(Uci->ponder_move)) {\r
-\r
- my_log("POLYGLOT THINK -> PONDER\n");\r
-\r
- State->state = PONDER;\r
- State->exp_move = Uci->ponder_move;\r
-\r
- } else {\r
-\r
- my_log("POLYGLOT THINK -> WAIT\n");\r
-\r
- State->state = WAIT;\r
- State->exp_move = MoveNone;\r
- }\r
-\r
- } else if (State->state == PONDER) {\r
-\r
- ASSERT(State->computer[game_turn(Game)]);\r
- ASSERT(!State->computer[colour_opp(game_turn(Game))]);\r
- ASSERT(!XB->analyse);\r
-\r
- if (move == State->exp_move && Uci->searching) {\r
-\r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
-\r
- my_timer_start(State->timer);//also resets\r
-\r
- my_log("POLYGLOT PONDER -> THINK (*** HIT ***)\n");\r
- engine_send(Engine,"ponderhit");\r
-\r
- State->state = THINK;\r
- State->exp_move = MoveNone;\r
-\r
- send_pv(); // update display\r
-\r
- return; // do not launch a new search\r
-\r
- } else {\r
-\r
- my_log("POLYGLOT PONDER -> THINK (miss)\n");\r
-\r
- stop_search();\r
-\r
- State->state = THINK;\r
- State->exp_move = MoveNone;\r
- }\r
-\r
- } else if (State->state == ANALYSE) {\r
-\r
- ASSERT(XB->analyse);\r
-\r
- my_log("POLYGLOT ANALYSE -> ANALYSE\n");\r
-\r
- stop_search();\r
-\r
- } else {\r
-\r
- ASSERT(false);\r
- }\r
-\r
- search_update();\r
-}\r
-\r
-// start_protected_command()\r
-\r
-static void start_protected_command(){\r
- stop_search();\r
-}\r
-\r
-static void end_protected_command(){\r
- if(Uci->ready){ // not init faze\r
- uci_send_isready_sync(Uci); // gobble up spurious "bestmove"\r
- }\r
- update_remaining_time();\r
- search_update(); // relaunch search if necessary\r
-}\r
-\r
-// update_remaining_time()\r
-\r
-static void update_remaining_time(){\r
- double reduce;\r
- if(State->timer->running){\r
- my_timer_stop(State->timer);\r
- reduce = my_timer_elapsed_real(State->timer);\r
- my_log("POLYGLOT reducing remaing time by %f seconds\n",reduce);\r
- XB->my_time -= reduce;\r
- if(XB->my_time<0.0){\r
- XB->my_time=0.0;\r
- }\r
- }\r
-}\r
-\r
-\r
-// search_update()\r
-\r
-static void search_update() {\r
-\r
- int move;\r
- int move_nb;\r
- board_t board[1];\r
- int nalimov_cache;\r
- int real_memory;\r
-\r
- ASSERT(!Uci->searching);\r
-\r
-\r
-\r
- \r
- // launch a new search if needed\r
-\r
- \r
-\r
- if (State->state == THINK || State->state == PONDER || State->state == ANALYSE) {\r
-\r
- // opening book\r
-\r
- if (State->state == THINK && option_get_bool("Book")) {\r
-\r
- game_get_board(Game,Uci->board);\r
-\r
- move = book_move(Uci->board,option_get_bool("BookRandom"));\r
-\r
- if (move != MoveNone && move_is_legal(move,Uci->board)) {\r
-\r
- my_log("POLYGLOT *BOOK MOVE*\n");\r
-\r
- search_clear(); // clears Uci->ponder_move\r
- Uci->best_move = move;\r
-\r
- board_copy(board,Uci->board);\r
- move_do(board,move);\r
- Uci->ponder_move = book_move(board,false); // expected move = best book move\r
-\r
- Uci->best_pv[0] = Uci->best_move;\r
- Uci->best_pv[1] = Uci->ponder_move; // can be MoveNone\r
- Uci->best_pv[2] = MoveNone;\r
-\r
- comp_move(Uci->best_move);\r
-\r
- return;\r
- }\r
- }\r
-\r
- // engine search\r
-\r
- my_log("POLYGLOT START SEARCH\n");\r
-\r
- // options\r
-\r
- uci_send_option(Uci,"UCI_Chess960","%s",option_get_bool("Chess960")?"true":"false");\r
-\r
- if (option_get_int("UCIVersion") >= 2) {\r
- uci_send_option(Uci,"UCI_Opponent","none none %s %s",(XB->computer)?"computer":"human",XB->name);\r
- uci_send_option(Uci,"UCI_AnalyseMode","%s",(XB->analyse)?"true":"false");\r
- }\r
-\r
- uci_send_option(Uci,"Ponder","%s",ponder()?"true":"false");\r
-\r
- // position\r
-\r
- move = (State->state == PONDER) ? State->exp_move : MoveNone;\r
- send_board(move); // updates Uci->board global variable\r
-\r
- // search\r
-\r
- if (State->state == THINK || State->state == PONDER) {\r
-\r
- engine_send_queue(Engine,"go");\r
-\r
- if (XB->time_limit) {\r
-\r
- // fixed time per move\r
-\r
- engine_send_queue(Engine," movetime %.0f",XB->time_max*1000.0);\r
-\r
- } else {\r
-\r
- // time controls\r
-\r
- if (colour_is_white(Uci->board->turn)) {\r
- engine_send_queue(Engine," wtime %.0f btime %.0f",XB->my_time*1000.0,XB->opp_time*1000.0);\r
- } else {\r
- engine_send_queue(Engine," wtime %.0f btime %.0f",XB->opp_time*1000.0,XB->my_time*1000.0);\r
- }\r
-\r
- if (XB->inc != 0.0) engine_send_queue(Engine," winc %.0f binc %.0f",XB->inc*1000.0,XB->inc*1000.0);\r
-\r
- if (XB->mps != 0) {\r
-\r
- move_nb = XB->mps - (Uci->board->move_nb % XB->mps);\r
- ASSERT(move_nb>=1&&move_nb<=XB->mps);\r
-\r
- engine_send_queue(Engine," movestogo %d",move_nb);\r
- }\r
- }\r
-\r
- if (XB->depth_limit) engine_send_queue(Engine," depth %d",XB->depth_max);\r
-\r
- if (State->state == PONDER) engine_send_queue(Engine," ponder");\r
-\r
- engine_send(Engine,""); // newline\r
-\r
- } else if (State->state == ANALYSE) {\r
-\r
- engine_send(Engine,"go infinite");\r
-\r
- } else {\r
-\r
- ASSERT(false);\r
- }\r
-\r
- // init search info\r
-\r
- ASSERT(!Uci->searching);\r
-\r
- search_clear();\r
-\r
- Uci->searching = true;\r
- Uci->pending_nb++;\r
- }\r
-}\r
-\r
-// search_clear()\r
-\r
-static void search_clear() {\r
-\r
- uci_clear(Uci);\r
-\r
- // TODO: MOVE ME\r
-\r
- my_timer_start(State->timer);//also resets\r
-}\r
-\r
-// active()\r
-\r
-static bool active() {\r
-\r
- // position state\r
-\r
- if (game_status(Game) != PLAYING) return false; // game ended\r
-\r
- // xboard state\r
-\r
- if (XB->analyse) return true; // analysing\r
- if (!State->computer[White] && !State->computer[Black]) return false; // force mode\r
- if (XB->new_hack || XB->result) return false; // unstarted or ended game\r
-\r
- return true; // playing\r
-}\r
-\r
-// ponder()\r
-\r
-static bool ponder() {\r
-\r
- return XB->ponder && (option_get_bool("CanPonder") || uci_option_exist(Uci,"Ponder"));\r
-}\r
-// ponder_ok()\r
-\r
-static bool ponder_ok(int move) {\r
- int status;\r
- board_t board[1];\r
-\r
- ASSERT(move==MoveNone||move_is_ok(move));\r
-\r
- // legal ponder move?\r
-\r
- if (move == MoveNone) return false;\r
-\r
- game_get_board(Game,board);\r
- if (!move_is_legal(move,board)) return false;\r
-\r
- // UCI-legal resulting position?\r
-\r
- game_add_move(Game,move);\r
-\r
- game_get_board(Game,board);\r
- status = game_status(Game);\r
-\r
- game_rem_move(Game);\r
-\r
- if (status != PLAYING) return false; // game ended\r
-\r
- if (option_get_bool("Book") && is_in_book(board)) {\r
- return false;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-// stop_search()\r
-\r
-static void stop_search() {\r
-\r
- if (Uci->searching) {\r
-\r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
-\r
- my_log("POLYGLOT STOP SEARCH\n");\r
-\r
-/*\r
- engine_send(Engine,"stop");\r
- Uci->searching = false;\r
-*/\r
-\r
- if (option_get_bool("SyncStop")) {\r
- uci_send_stop_sync(Uci);\r
- } else {\r
- uci_send_stop(Uci);\r
- }\r
- }\r
-}\r
-\r
-// send_board()\r
-\r
-static void send_board(int extra_move) {\r
-\r
- char fen[256];\r
- int start, end;\r
- board_t board[1];\r
- int pos;\r
- int move;\r
- char string[256];\r
-\r
- ASSERT(extra_move==MoveNone||move_is_ok(extra_move));\r
-\r
- ASSERT(!Uci->searching);\r
-\r
- // init\r
-\r
- game_get_board(Game,Uci->board);\r
- if (extra_move != MoveNone) move_do(Uci->board,extra_move);\r
-\r
- board_to_fen(Uci->board,fen,256);\r
- my_log("POLYGLOT FEN %s\n",fen);\r
-\r
- ASSERT(board_can_play(Uci->board));\r
-\r
- // more init\r
-\r
- start = 0;\r
- end = game_pos(Game);\r
- ASSERT(end>=start);\r
-\r
- // position\r
-\r
- game_get_board(Game,board,start);\r
- board_to_fen(board,string,256);\r
-\r
- engine_send_queue(Engine,"position");\r
-\r
- if (my_string_equal(string,StartFen)) {\r
- engine_send_queue(Engine," startpos");\r
- } else {\r
- engine_send_queue(Engine," fen %s",string);\r
- }\r
-\r
- // move list\r
-\r
- if (end > start || extra_move != MoveNone) engine_send_queue(Engine," moves");\r
-\r
- for (pos = start; pos < end; pos++) { // game moves\r
-\r
- move = game_move(Game,pos);\r
-\r
- move_to_can(move,board,string,256);\r
- engine_send_queue(Engine," %s",string);\r
-\r
- move_do(board,move);\r
- }\r
-\r
- if (extra_move != MoveNone) { // move to ponder on\r
- move_to_can(extra_move,board,string,256);\r
- engine_send_queue(Engine," %s",string);\r
- }\r
-\r
- // end\r
-\r
- engine_send(Engine,""); // newline\r
-}\r
-\r
-// send_pv()\r
-\r
-static void send_pv() {\r
-\r
- char pv_string[StringSize];\r
- board_t board[1];\r
- int move;\r
- char move_string[StringSize];\r
-\r
- ASSERT(State->state!=WAIT);\r
-\r
- if (Uci->best_depth == 0) return;\r
-\r
- // xboard search information\r
-\r
- if (XB->post) {\r
-\r
- if (State->state == THINK || State->state == ANALYSE) {\r
-\r
- line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
-\r
- if(Uci->depth==-1) //hack to clear the engine output window\r
- gui_send(GUI,"%d %+d %.0f "S64_FORMAT" ",0,Uci->best_score,Uci->time*100.0,Uci->node_nb);\r
-\r
- gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth,Uci->best_score,Uci->time*100.0,Uci->node_nb,pv_string);\r
-\r
- } else if (State->state == PONDER && option_get_bool("ShowPonder")) {\r
-\r
- game_get_board(Game,board);\r
- move = State->exp_move;\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
- move_to_san(move,board,move_string,256);\r
- line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
- gui_send(GUI,"%d %+d %.0f "S64_FORMAT" (%s) %s",Uci->best_depth,Uci->best_score,Uci->time*100.0,Uci->node_nb,move_string,pv_string);\r
- }\r
- }\r
- }\r
-\r
- // kibitz\r
-\r
- if ((Uci->searching && option_get_bool("KibitzPV") && Uci->time >= option_get_double("KibitzDelay"))\r
- || (!Uci->searching && option_get_bool("KibitzMove"))) {\r
-\r
- if (State->state == THINK || State->state == ANALYSE) {\r
-\r
- line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
- gui_send(GUI,"%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);\r
-\r
- } else if (State->state == PONDER) {\r
-\r
- game_get_board(Game,board);\r
- move = State->exp_move;\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
- move_to_san(move,board,move_string,256);\r
- line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
- gui_send(GUI,"%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);\r
- }\r
- }\r
- }\r
-}\r
-\r
-// learn()\r
-\r
-static void learn(int result) {\r
-\r
- int pos;\r
- board_t board[1];\r
- int move;\r
-\r
- ASSERT(result>=-1&&result<=+1);\r
-\r
- ASSERT(XB->result);\r
- ASSERT(State->computer[White]||State->computer[Black]);\r
-\r
- // init\r
-\r
- pos = 0;\r
-\r
- if (false) {\r
- } else if (State->computer[White]) {\r
- pos = 0;\r
- } else if (State->computer[Black]) {\r
- pos = 1;\r
- result = -result;\r
- } else {\r
- my_fatal("learn(): unknown side\n");\r
- }\r
-\r
- if (false) {\r
- } else if (result > 0) {\r
- my_log("POLYGLOT *LEARN WIN*\n");\r
- } else if (result < 0) {\r
- my_log("POLYGLOT *LEARN LOSS*\n");\r
- } else {\r
- my_log("POLYGLOT *LEARN DRAW*\n");\r
- }\r
-\r
- // loop\r
-\r
- for (; pos < Game->size; pos += 2) {\r
-\r
- game_get_board(Game,board,pos);\r
- move = game_move(Game,pos);\r
-\r
- book_learn_move(board,move,result);\r
- }\r
-\r
- book_flush();\r
-}\r
-\r
-// end of adapter.cpp\r
+++ /dev/null
-\r
-// adapter.h\r
-\r
-#ifndef ADAPTER_H\r
-#define ADAPTER_H\r
-\r
-// includes\r
-\r
-#include "util.h"\r
-#include "uci2uci.h"\r
-\r
-// types\r
-\r
-\r
-\r
-\r
-\r
-// functions\r
-\r
-extern void adapter_loop ();\r
-\r
-\r
-#endif // !defined ADAPTER_H\r
-\r
-// end of adapter.h\r
-\r
+++ /dev/null
-\r
-// attack.cpp\r
-\r
-// includes\r
-\r
-#include "board.h"\r
-#include "colour.h"\r
-#include "move.h"\r
-#include "attack.h"\r
-#include "piece.h"\r
-#include "util.h"\r
-\r
-// macros\r
-\r
-#define DELTA_INC(delta) (DeltaInc[128+(delta)])\r
-#define DELTA_MASK(delta) (DeltaMask[128+(delta)])\r
-\r
-// "constants"\r
-\r
-const sint8 KnightInc[8+1] = {\r
- -33, -31, -18, -14, +14, +18, +31, +33, 0\r
-};\r
-\r
-const sint8 BishopInc[4+1] = {\r
- -17, -15, +15, +17, 0\r
-};\r
-\r
-const sint8 RookInc[4+1] = {\r
- -16, -1, +1, +16, 0\r
-};\r
-\r
-const sint8 QueenInc[8+1] = {\r
- -17, -16, -15, -1, +1, +15, +16, +17, 0\r
-};\r
-\r
-const sint8 KingInc[8+1] = {\r
- -17, -16, -15, -1, +1, +15, +16, +17, 0\r
-};\r
-\r
-// variables\r
-\r
-static sint8 DeltaInc[256];\r
-static uint8 DeltaMask[256];\r
-\r
-// prototypes\r
-\r
-static bool delta_is_ok (int delta);\r
-static bool inc_is_ok (int inc);\r
-\r
-// functions\r
-\r
-// attack_init()\r
-\r
-void attack_init() {\r
-\r
- int delta;\r
- int dir, inc, dist;\r
-\r
- for (delta = -128; delta < +128; delta++) {\r
- DeltaInc[128+delta] = IncNone;\r
- DeltaMask[128+delta] = 0;\r
- }\r
-\r
- DeltaMask[128-17] |= BlackPawnFlag;\r
- DeltaMask[128-15] |= BlackPawnFlag;\r
-\r
- DeltaMask[128+15] |= WhitePawnFlag;\r
- DeltaMask[128+17] |= WhitePawnFlag;\r
-\r
- for (dir = 0; dir < 8; dir++) {\r
- delta = KnightInc[dir];\r
- ASSERT(delta_is_ok(delta));\r
- DeltaMask[128+delta] |= KnightFlag;\r
- }\r
-\r
- for (dir = 0; dir < 4; dir++) {\r
- inc = BishopInc[dir];\r
- ASSERT(inc!=IncNone);\r
- for (dist = 1; dist < 8; dist++) {\r
- delta = inc*dist;\r
- ASSERT(delta_is_ok(delta));\r
- ASSERT(DeltaInc[128+delta]==IncNone);\r
- DeltaInc[128+delta] = inc;\r
- DeltaMask[128+delta] |= BishopFlag;\r
- }\r
- }\r
-\r
- for (dir = 0; dir < 4; dir++) {\r
- inc = RookInc[dir];\r
- ASSERT(inc!=IncNone);\r
- for (dist = 1; dist < 8; dist++) {\r
- delta = inc*dist;\r
- ASSERT(delta_is_ok(delta));\r
- ASSERT(DeltaInc[128+delta]==IncNone);\r
- DeltaInc[128+delta] = inc;\r
- DeltaMask[128+delta] |= RookFlag;\r
- }\r
- }\r
-\r
- for (dir = 0; dir < 8; dir++) {\r
- delta = KingInc[dir];\r
- ASSERT(delta_is_ok(delta));\r
- DeltaMask[128+delta] |= KingFlag;\r
- }\r
-}\r
-\r
-// delta_is_ok()\r
-\r
-static bool delta_is_ok(int delta) {\r
-\r
- if (delta < -119 || delta > +119) return false;\r
-\r
- return true;\r
-}\r
-\r
-// inc_is_ok()\r
-\r
-static bool inc_is_ok(int inc) {\r
-\r
- int dir;\r
-\r
- for (dir = 0; dir < 8; dir++) {\r
- if (KingInc[dir] == inc) return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-// is_in_check()\r
-\r
-bool is_in_check(const board_t * board, int colour) {\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(colour_is_ok(colour));\r
-\r
- return is_attacked(board,king_pos(board,colour),colour_opp(colour));\r
-}\r
-\r
-// is_attacked()\r
-\r
-bool is_attacked(const board_t * board, int to, int colour) {\r
-\r
- const uint8 * ptr;\r
- int from, piece;\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(square_is_ok(to));\r
- ASSERT(colour_is_ok(colour));\r
-\r
- for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) {\r
-\r
- piece = board->square[from];\r
- ASSERT(colour_equal(piece,colour));\r
-\r
- if (piece_attack(board,piece,from,to)) return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-// piece_attack()\r
-\r
-bool piece_attack(const board_t * board, int piece, int from, int to) {\r
-\r
- int delta;\r
- int inc, sq;\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(piece_is_ok(piece));\r
- ASSERT(square_is_ok(from));\r
- ASSERT(square_is_ok(to));\r
-\r
- delta = to - from;\r
- ASSERT(delta_is_ok(delta));\r
-\r
- if ((piece & DELTA_MASK(delta)) == 0) return false; // no pseudo-attack\r
-\r
- if (!piece_is_slider(piece)) return true;\r
-\r
- inc = DELTA_INC(delta);\r
- ASSERT(inc_is_ok(inc));\r
-\r
- for (sq = from+inc; sq != to; sq += inc) {\r
- ASSERT(square_is_ok(sq));\r
- if (board->square[sq] != Empty) return false; // blocker\r
- }\r
-\r
- return true;\r
-}\r
-\r
-// is_pinned()\r
-\r
-bool is_pinned(const board_t * board, int from, int to, int colour) {\r
-\r
- int king;\r
- int inc;\r
- int sq, piece;\r
-\r
- ASSERT(board!=NULL);\r
- ASSERT(square_is_ok(from));\r
- ASSERT(square_is_ok(to));\r
- ASSERT(colour_is_ok(colour));\r
-\r
- king = king_pos(board,colour);\r
-\r
- inc = DELTA_INC(king-from);\r
- if (inc == IncNone) return false; // not a line\r
-\r
- sq = from;\r
- do sq += inc; while (board->square[sq] == Empty);\r
-\r
- if (sq != king) return false; // blocker\r
-\r
- sq = from;\r
- do sq -= inc; while ((piece=board->square[sq]) == Empty);\r
-\r
- return square_is_ok(sq)\r
- && (piece & DELTA_MASK(king-sq)) != 0\r
- && piece_colour(piece) == colour_opp(colour)\r
- && DELTA_INC(king-to) != inc;\r
-}\r
-\r
-// end of attack.cpp\r
-\r
+++ /dev/null
-\r
-// board.cpp\r
-\r
-// includes\r
-\r
-#include <cstdio>\r
-\r
-#include "attack.h"\r
-#include "board.h"\r
-#include "colour.h"\r
-#include "fen.h"\r
-#include "hash.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_gen.h"\r
-#include "move_legal.h"\r
-#include "piece.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool UseSlowDebug = false;\r
-\r
-// functions\r
-\r
-// board_is_ok()\r
-\r
-bool board_is_ok(const board_t * board) {\r
-\r
- int sq, piece;\r
- int colour, pos;\r
- int king, rook;\r
-\r
- if (board == NULL) return false;\r
-\r
- // optional heavy DEBUG mode\r
-\r
- if (!UseSlowDebug) return true;\r
-\r
- // squares\r
-\r
- for (sq = 0; sq < SquareNb; sq++) {\r
- piece = board->square[sq];\r
- if (square_is_ok(sq)) {\r
- pos = board->pos[sq];\r
- if (piece == Empty) {\r
- if (pos != -1) return false;\r
- } else {\r
- if (pos < 0) return false;\r
- if (board->list[piece_colour(piece)][pos] != sq) return false;\r
- }\r
- } else {\r
- if (piece != Knight64) return false;\r
- }\r
- }\r
-\r
- // white piece list\r
-\r
- colour = White;\r
- pos = 0;\r
-\r
- if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false;\r
-\r
- sq = board->list[colour][pos];\r
- if (sq == SquareNone) return false;\r
- if (board->pos[sq] != pos) return false;\r
- piece = board->square[sq];\r
- if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false;\r
-\r
- for (pos++; pos < board->list_size[colour]; pos++) {\r
- sq = board->list[colour][pos];\r
- if (sq == SquareNone) return false;\r
- if (board->pos[sq] != pos) return false;\r
- if (!colour_equal(board->square[sq],colour)) return false;\r
- }\r
-\r
- sq = board->list[colour][pos];\r
- if (sq != SquareNone) return false;\r
-\r
- // black piece list\r
-\r
- colour = Black;\r
- pos = 0;\r
-\r
- if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false;\r
-\r
- sq = board->list[colour][pos];\r
- if (sq == SquareNone) return false;\r
- if (board->pos[sq] != pos) return false;\r
- piece = board->square[sq];\r
- if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false;\r
-\r
- for (pos++; pos < board->list_size[colour]; pos++) {\r
- sq = board->list[colour][pos];\r
- if (sq == SquareNone) return false;\r
- if (board->pos[sq] != pos) return false;\r
- if (!colour_equal(board->square[sq],colour)) return false;\r
- }\r
-\r
- sq = board->list[colour][pos];\r
- if (sq != SquareNone) return false;\r
-\r
- // TODO: material\r
-\r
- if (board->number[WhiteKing12] != 1) return false;\r
- if (board->number[BlackKing12] != 1) return false;\r
-\r
- if (!colour_is_ok(board->turn)) return false;\r
-\r
- // castling status\r
-\r
- if (board->castle[White][SideH] != SquareNone) {\r
-\r
- king = board->list[White][0];\r
- if (king < A1 || king > H1) return false;\r
- if (board->square[king] != WhiteKing256) return false;\r
-\r
- rook = board->castle[White][SideH];\r
- if (rook < A1 || rook > H1) return false;\r
- if (board->square[rook] != WhiteRook256) return false;\r
-\r
- if (rook <= king) return false;\r
- }\r
-\r
- if (board->castle[White][SideA] != SquareNone) {\r
-\r
- king = board->list[White][0];\r
- if (king < A1 || king > H1) return false;\r
- if (board->square[king] != WhiteKing256) return false;\r
-\r
- rook = board->castle[White][SideA];\r
- if (rook < A1 || rook > H1) return false;\r
- if (board->square[rook] != WhiteRook256) return false;\r
-\r
- if (rook >= king) return false;\r
- }\r
-\r
- if (board->castle[Black][SideH] != SquareNone) {\r
-\r
- king = board->list[Black][0];\r
- if (king < A8 || king > H8) return false;\r
- if (board->square[king] != BlackKing256) return false;\r
-\r
- rook = board->castle[Black][SideH];\r
- if (rook < A8 || rook > H8) return false;\r
- if (board->square[rook] != BlackRook256) return false;\r
-\r
- if (rook <= king) return false;\r
- }\r
-\r
- if (board->castle[Black][SideA] != SquareNone) {\r
-\r
- king = board->list[Black][0];\r
- if (king < A8 || king > H8) return false;\r
- if (board->square[king] != BlackKing256) return false;\r
-\r
- rook = board->castle[Black][SideA];\r
- if (rook < A8 || rook > H8) return false;\r
- if (board->square[rook] != BlackRook256) return false;\r
-\r
- if (rook >= king) return false;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-// board_clear()\r
-\r
-void board_clear(board_t * board) {\r
-\r
- int file, rank, sq;\r
- int colour, pos;\r
- int piece;\r
-\r
- ASSERT(board!=NULL);\r
-\r
- // edge squares\r
-\r
- for (sq = 0; sq < SquareNb; sq++) {\r
- board->square[sq] = Knight64; // HACK: uncoloured knight\r
- board->pos[sq] = -1;\r
- }\r
-\r
- // empty squares\r
-\r
- for (rank = 0; rank < 8; rank++) {\r
- for (file = 0; file < 8; file++) {\r
- sq = square_make(file,rank);\r
- board->square[sq] = Empty;\r
- }\r
- }\r
-\r
- // piece lists\r
-\r
- for (colour = 0; colour < 3; colour++) {\r
- for (pos = 0; pos < 32; pos++) { // HACK\r
- board->list[colour][pos] = SquareNone;\r
- }\r
- board->list_size[colour] = 0;\r
- }\r
-\r
- // material\r
-\r
- for (piece = 0; piece < 12; piece++) {\r
- board->number[piece] = 0;\r
- }\r
-\r
- // rest\r
-\r
- board->turn = ColourNone;\r
- board->castle[White][SideH] = SquareNone;\r
- board->castle[White][SideA] = SquareNone;\r
- board->castle[Black][SideH] = SquareNone;\r
- board->castle[Black][SideA] = SquareNone;\r
- board->ep_square = SquareNone;\r
-\r
- board->ply_nb = 0;\r
- board->move_nb = 0;\r
-\r
- board->key = 0;\r
-}\r
-\r
-// board_start()\r
-\r
-void board_start(board_t * board) {\r
-\r
- ASSERT(board!=NULL);\r
-\r
- if (!board_from_fen(board,StartFen)) ASSERT(false);\r
-}\r
-\r
-// board_copy()\r
-\r
-void board_copy(board_t * dst, const board_t * src) {\r
-\r
- ASSERT(dst!=NULL);\r
- ASSERT(board_is_ok(src));\r
-\r
- *dst = *src;\r
-}\r
-\r
-// board_equal()\r
-\r
-bool board_equal(const board_t * board_1, const board_t * board_2) {\r
-\r
- int sq_64, sq;\r
-\r
- ASSERT(board_is_ok(board_1));\r
- ASSERT(board_is_ok(board_2));\r
-\r
- // fast comparison\r
-\r
- if (board_1->key != board_2->key) return false;\r
-\r
- // slow comparison\r
-\r
- for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
- sq = square_from_64(sq_64);\r
- if (board_1->square[sq] != board_2->square[sq]) return false;\r
- }\r
-\r
- if (board_1->turn != board_2->turn) return false;\r
- if (board_1->castle[White][SideH] != board_2->castle[White][SideH]) return false;\r
- if (board_1->castle[White][SideA] != board_2->castle[White][SideA]) return false;\r
- if (board_1->castle[Black][SideH] != board_2->castle[Black][SideH]) return false;\r
- if (board_1->castle[Black][SideA] != board_2->castle[Black][SideA]) return false;\r
- if (board_1->ep_square != board_2->ep_square) return false;\r
-\r
- return true;\r
-}\r
-\r
-// board_init_list()\r
-\r
-void board_init_list(board_t * board) {\r
-\r
- int sq_64, sq, piece;\r
- int colour, pos;\r
-\r
- ASSERT(board!=NULL);\r
-\r
- // init\r
-\r
- for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
- sq = square_from_64(sq_64);\r
- board->pos[sq] = -1;\r
- }\r
-\r
- for (piece = 0; piece < 12; piece++) board->number[piece] = 0;\r
-\r
- // white piece list\r
-\r
- colour = White;\r
- pos = 0;\r
-\r
- for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
- sq = square_from_64(sq_64);\r
- piece = board->square[sq];\r
- ASSERT(pos>=0&&pos<=16);\r
- if (colour_equal(piece,colour) && piece_is_king(piece)) {\r
- board->pos[sq] = pos;\r
- board->list[colour][pos] = sq;\r
- pos++;\r
- board->number[piece_to_12(piece)]++;\r
- }\r
- }\r
- ASSERT(pos==1);\r
-\r
- for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
- sq = square_from_64(sq_64);\r
- piece = board->square[sq];\r
- ASSERT(pos>=0&&pos<=16);\r
- if (colour_equal(piece,colour) && !piece_is_king(piece)) {\r
- board->pos[sq] = pos;\r
- board->list[colour][pos] = sq;\r
- pos++;\r
- board->number[piece_to_12(piece)]++;\r
- }\r
- }\r
-\r
- ASSERT(pos>=1&&pos<=16);\r
- board->list[colour][pos] = SquareNone;\r
- board->list_size[colour] = pos;\r
-\r
- // black piece list\r
-\r
- colour = Black;\r
- pos = 0;\r
-\r
- for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
- sq = square_from_64(sq_64);\r
- piece = board->square[sq];\r
- ASSERT(pos>=0&&pos<=16);\r
- if (colour_equal(piece,colour) && piece_is_king(piece)) {\r
- board->pos[sq] = pos;\r
- board->list[colour][pos] = sq;\r
- pos++;\r
- board->number[piece_to_12(piece)]++;\r
- }\r
- }\r
- ASSERT(pos==1);\r
-\r
- for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
- sq = square_from_64(sq_64);\r
- piece = board->square[sq];\r
- ASSERT(pos>=1&&pos<=16);\r
- if (colour_equal(piece,colour) && !piece_is_king(piece)) {\r
- board->pos[sq] = pos;\r
- board->list[colour][pos] = sq;\r
- pos++;\r
- board->number[piece_to_12(piece)]++;\r
- }\r
- }\r
-\r
- ASSERT(pos>=1&&pos<=16);\r
- board->list[colour][pos] = SquareNone;\r
- board->list_size[colour] = pos;\r
-\r
- // hash key\r
-\r
- board->key = hash_key(board);\r
-}\r
-\r
-// board_flags()\r
-\r
-int board_flags(const board_t * board) {\r
-\r
- int flags;\r
-\r
- flags = 0;\r
-\r
- if (board->castle[White][SideH] != SquareNone) flags |= 1 << 0;\r
- if (board->castle[White][SideA] != SquareNone) flags |= 1 << 1;\r
- if (board->castle[Black][SideH] != SquareNone) flags |= 1 << 2;\r
- if (board->castle[Black][SideA] != SquareNone) flags |= 1 << 3;\r
-\r
- return flags;\r
-}\r
-\r
-// board_can_play()\r
-\r
-bool board_can_play(const board_t * board) {\r
-\r
- list_t list[1];\r
- int i, move;\r
-\r
- ASSERT(board_is_ok(board));\r
-\r
- gen_moves(list,board);\r
-\r
- for (i = 0; i < list_size(list); i++) {\r
- move = list_move(list,i);\r
- if (pseudo_is_legal(move,board)) return true;\r
- }\r
-\r
- return false; // no legal move\r
-}\r
-\r
-// board_mobility()\r
-\r
-int board_mobility(const board_t * board) {\r
-\r
- list_t list[1];\r
-\r
- ASSERT(board_is_ok(board));\r
-\r
- gen_legal_moves(list,board);\r
-\r
- return list_size(list);\r
-}\r
-\r
-// board_is_check()\r
-\r
-bool board_is_check(const board_t * board) {\r
-\r
- ASSERT(board_is_ok(board));\r
-\r
- return is_in_check(board,board->turn);\r
-}\r
-\r
-// board_is_mate()\r
-\r
-bool board_is_mate(const board_t * board) {\r
-\r
- ASSERT(board_is_ok(board));\r
-\r
- if (!board_is_check(board)) return false;\r
- if (board_can_play(board)) return false;\r
-\r
- return true;\r
-}\r
-\r
-// board_is_stalemate()\r
-\r
-bool board_is_stalemate(const board_t * board) {\r
-\r
- ASSERT(board_is_ok(board));\r
-\r
- if (board_is_check(board)) return false;\r
- if (board_can_play(board)) return false;\r
-\r
- return true;\r
-}\r
-\r
-// king_pos()\r
-\r
-int king_pos(const board_t * board, int colour) {\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(colour_is_ok(colour));\r
-\r
- return board->list[colour][0];\r
-}\r
-\r
-// board_disp()\r
-\r
-void board_disp(const board_t * board) {\r
-\r
- int file, rank, sq;\r
- int piece, c;\r
- char fen[256];\r
-\r
- ASSERT(board!=NULL);\r
-\r
- if (!board_to_fen(board,fen,256)) ASSERT(false);\r
- my_log("POLYGLOT %s\n",fen);\r
- my_log("POLYGLOT\n");\r
-\r
- for (rank = 7; rank >= 0; rank--) {\r
-\r
- my_log("POLYGLOT ");\r
-\r
- for (file = 0; file < 8; file++) {\r
-\r
- sq = square_make(file,rank);\r
- piece = board->square[sq];\r
-\r
- c = (piece != Empty) ? piece_to_char(piece) : '-';\r
- my_log("%c ",c);\r
- }\r
-\r
- my_log("\n");\r
- }\r
-\r
- my_log("POLYGLOT\n");\r
-\r
- my_log("POLYGLOT %s to play\n",(colour_is_black(board->turn))?"black":"white");\r
- my_log("POLYGLOT\n");\r
-}\r
-\r
-// end of board.cpp\r
-\r
+++ /dev/null
-\r
-// book.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "board.h"\r
-#include "book.h"\r
-#include "move.h"\r
-#include "move_legal.h"\r
-#include "san.h"\r
-#include "util.h"\r
-#include "option.h"\r
-\r
-// types\r
-\r
-struct entry_t {\r
- uint64 key;\r
- uint16 move;\r
- uint16 count;\r
- uint16 n;\r
- uint16 sum;\r
-};\r
-\r
-// variables\r
-\r
-static FILE * BookFile;\r
-static int BookSize;\r
-\r
-// prototypes\r
-\r
-static int find_pos (uint64 key);\r
-\r
-static void read_entry (entry_t * entry, int n);\r
-static void write_entry (const entry_t * entry, int n);\r
-\r
-static uint64 read_integer (FILE * file, int size);\r
-static void write_integer (FILE * file, int size, uint64 n);\r
-\r
-// functions\r
-\r
-// book_clear()\r
-\r
-void book_clear() {\r
-\r
- BookFile = NULL;\r
- BookSize = 0;\r
-}\r
-\r
-bool book_is_open(){\r
- return BookFile!=NULL;\r
-}\r
-\r
-// book_open()\r
-\r
-void book_open(const char file_name[]) {\r
-\r
- ASSERT(file_name!=NULL);\r
- if(option_get_bool("BookLearn")){\r
- BookFile = fopen(file_name,"rb+");\r
- }else{\r
- BookFile = fopen(file_name,"rb");\r
- }\r
- \r
-// if (BookFile == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
- if (BookFile == NULL) return; \r
-\r
- if (fseek(BookFile,0,SEEK_END) == -1) {\r
- my_fatal("book_open(): fseek(): %s\n",strerror(errno));\r
- }\r
-\r
- BookSize = ftell(BookFile) / 16;\r
-// if (BookSize == 0) my_fatal("book_open(): empty file\n");\r
- if (BookSize == 0) {\r
- book_close();\r
- book_clear(); \r
- };\r
-}\r
-\r
-// book_close()\r
-\r
-void book_close() {\r
-\r
- if(BookFile==NULL) return;\r
-\r
- if (fclose(BookFile) == EOF) {\r
- my_fatal("book_close(): fclose(): %s\n",strerror(errno));\r
- }\r
-}\r
-\r
-// is_in_book()\r
-\r
-bool is_in_book(const board_t * board) {\r
-\r
- int pos;\r
- entry_t entry[1];\r
-\r
- if(BookFile==NULL) return false;\r
-\r
- ASSERT(board!=NULL);\r
-\r
- for (pos = find_pos(board->key); pos < BookSize; pos++) {\r
- read_entry(entry,pos);\r
- if (entry->key == board->key) return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-// book_move()\r
-\r
-int book_move(const board_t * board, bool random) {\r
-\r
- int best_move;\r
- int best_score;\r
- int pos;\r
- entry_t entry[1];\r
- int move;\r
- int score;\r
-\r
- if(BookFile==NULL) return MoveNone;\r
-\r
- ASSERT(board!=NULL);\r
- ASSERT(random==true||random==false);\r
-\r
-\r
- best_move = MoveNone;\r
- best_score = 0;\r
- for (pos = find_pos(board->key); pos < BookSize; pos++) {\r
-\r
- read_entry(entry,pos);\r
- if (entry->key != board->key) break;\r
-\r
- move = entry->move;\r
- score = entry->count;\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
-\r
- // pick this move?\r
-\r
- ASSERT(score>0);\r
-\r
- if (random) {\r
- best_score += score;\r
- if (my_random_int(best_score) < score) best_move = move;\r
- } else {\r
- if (score > best_score) {\r
- best_move = move;\r
- best_score = score;\r
- }\r
- }\r
-\r
- } else {\r
-\r
- ASSERT(false);\r
- }\r
- }\r
-\r
- return best_move;\r
-}\r
-\r
-// book_disp()\r
-\r
-void book_disp(const board_t * board) {\r
-\r
- int first_pos;\r
- int sum;\r
- int pos;\r
- entry_t entry[1];\r
- int move;\r
- int score;\r
- char move_string[256];\r
-\r
- ASSERT(board!=NULL);\r
-\r
- if(BookFile==NULL) return; \r
-\r
- first_pos = find_pos(board->key);\r
-\r
- // sum\r
-\r
- sum = 0;\r
-\r
- for (pos = first_pos; pos < BookSize; pos++) {\r
-\r
- read_entry(entry,pos);\r
- if (entry->key != board->key) break;\r
-\r
- sum += entry->count;\r
- }\r
-\r
- // disp\r
-\r
- for (pos = first_pos; pos < BookSize; pos++) {\r
-\r
- read_entry(entry,pos);\r
- if (entry->key != board->key) break;\r
-\r
- move = entry->move;\r
- score = entry->count;\r
-\r
- if (score > 0 && move != MoveNone && move_is_legal(move,board)) {\r
- move_to_san(move,board,move_string,256);\r
- printf(" %s (%.0f%%)\n",move_string,(double(score)/double(sum))*100.0);\r
- }\r
- }\r
-\r
- printf("\n");\r
-}\r
-\r
-// book_learn_move()\r
-\r
-void book_learn_move(const board_t * board, int move, int result) {\r
-\r
- int pos;\r
- entry_t entry[1];\r
-\r
- if(BookFile==NULL) return;\r
-\r
- ASSERT(board!=NULL);\r
- ASSERT(move_is_ok(move));\r
- ASSERT(result>=-1&&result<=+1);\r
-\r
- ASSERT(move_is_legal(move,board));\r
-\r
- for (pos = find_pos(board->key); pos < BookSize; pos++) {\r
-\r
- read_entry(entry,pos);\r
- if (entry->key != board->key) break;\r
-\r
- if (entry->move == move) {\r
-\r
- entry->n++;\r
- entry->sum += result+1;\r
-\r
- write_entry(entry,pos);\r
-\r
- break;\r
- }\r
- }\r
-}\r
-\r
-// book_flush()\r
-\r
-void book_flush() {\r
-\r
- if(BookFile==NULL) return;\r
-\r
- if (fflush(BookFile) == EOF) {\r
- my_fatal("book_flush(): fflush(): %s\n",strerror(errno));\r
- }\r
-}\r
-\r
-// find_pos()\r
-\r
-static int find_pos(uint64 key) {\r
-\r
- int left, right, mid;\r
- entry_t entry[1];\r
-\r
- // binary search (finds the leftmost entry)\r
-\r
- left = 0;\r
- right = BookSize-1;\r
-\r
- ASSERT(left<=right);\r
-\r
- while (left < right) {\r
-\r
- mid = (left + right) / 2;\r
- ASSERT(mid>=left&&mid<right);\r
-\r
- read_entry(entry,mid);\r
-\r
- if (key <= entry->key) {\r
- right = mid;\r
- } else {\r
- left = mid+1;\r
- }\r
- }\r
-\r
- ASSERT(left==right);\r
-\r
- read_entry(entry,left);\r
-\r
- return (entry->key == key) ? left : BookSize;\r
-}\r
-\r
-// read_entry()\r
-\r
-static void read_entry(entry_t * entry, int n) {\r
-\r
- ASSERT(entry!=NULL);\r
- ASSERT(n>=0&&n<BookSize);\r
-\r
- if (fseek(BookFile,n*16,SEEK_SET) == -1) {\r
- my_fatal("read_entry(): fseek(): %s\n",strerror(errno));\r
- }\r
-\r
- entry->key = read_integer(BookFile,8);\r
- entry->move = read_integer(BookFile,2);\r
- entry->count = read_integer(BookFile,2);\r
- entry->n = read_integer(BookFile,2);\r
- entry->sum = read_integer(BookFile,2);\r
-}\r
-\r
-// write_entry()\r
-\r
-static void write_entry(const entry_t * entry, int n) {\r
-\r
- ASSERT(entry!=NULL);\r
- ASSERT(n>=0&&n<BookSize);\r
-\r
- if (fseek(BookFile,n*16,SEEK_SET) == -1) {\r
- my_fatal("write_entry(): fseek(): %s\n",strerror(errno));\r
- }\r
-\r
- write_integer(BookFile,8,entry->key);\r
- write_integer(BookFile,2,entry->move);\r
- write_integer(BookFile,2,entry->count);\r
- write_integer(BookFile,2,entry->n);\r
- write_integer(BookFile,2,entry->sum);\r
-}\r
-\r
-// read_integer()\r
-\r
-static uint64 read_integer(FILE * file, int size) {\r
-\r
- uint64 n;\r
- int i;\r
- int b;\r
-\r
- ASSERT(file!=NULL);\r
- ASSERT(size>0&&size<=8);\r
-\r
- n = 0;\r
-\r
- for (i = 0; i < size; i++) {\r
-\r
- b = fgetc(file);\r
-\r
- if (b == EOF) {\r
- if (feof(file)) {\r
- my_fatal("read_integer(): fgetc(): EOF reached\n");\r
- } else { // error\r
- my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));\r
- }\r
- }\r
-\r
- ASSERT(b>=0&&b<256);\r
- n = (n << 8) | b;\r
- }\r
-\r
- return n;\r
-}\r
-\r
-// write_integer()\r
-\r
-static void write_integer(FILE * file, int size, uint64 n) {\r
-\r
- int i;\r
- int b;\r
-\r
- ASSERT(file!=NULL);\r
- ASSERT(size>0&&size<=8);\r
- ASSERT(size==8||n>>(size*8)==0);\r
-\r
- for (i = size-1; i >= 0; i--) {\r
-\r
- b = (n >> (i*8)) & 0xFF;\r
- ASSERT(b>=0&&b<256);\r
-\r
- if (fputc(b,file) == EOF) {\r
- my_fatal("write_integer(): fputc(): %s\n",strerror(errno));\r
- }\r
- }\r
-}\r
-\r
-// end of book.cpp\r
-\r
+++ /dev/null
-// book_make.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cmath>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "board.h"\r
-#include "book_make.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_gen.h"\r
-#include "move_legal.h"\r
-#include "pgn.h"\r
-#include "san.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const int COUNT_MAX = 16384;\r
-static const int StringSize = 4096;\r
-\r
-static const int NIL = -1;\r
-\r
-// defines\r
-\r
-#define opp_search(s) ((s)==BOOK?ALL:BOOK)\r
-\r
-// types\r
-\r
-struct entry_t {\r
- uint64 key;\r
- uint16 move;\r
- uint16 count;\r
-// Unfortunately the minggw32 cross compiler [4.2.1-sjlj (mingw32-2)] \r
-// seems to have a bug with anon structs contained in unions when using -O2.\r
-// See the ASSERT below in "read_entry_file"...\r
-// To be fair this seems to be illegal in C++\r
-// although it is hard to understand why, and the compiler does not complain\r
-// even with -Wall.\r
-// union { \r
-// struct { \r
- uint16 n;\r
- uint16 sum;\r
-// };\r
-// struct {\r
- uint8 height;\r
- int line;\r
-// };\r
- // };\r
- uint8 colour;\r
-};\r
-\r
-struct book_t {\r
- int size;\r
- int alloc;\r
- uint32 mask;\r
- entry_t * entry;\r
- sint32 * hash;\r
-};\r
-\r
-enum search_t {\r
- BOOK,\r
- ALL\r
-};\r
-\r
-struct info_t {\r
- int height;\r
- int line;\r
- int initial_color;\r
- bool book_trans_only;\r
- bool extended_search;\r
- uint16 moves[1024];\r
- double probs[1024];\r
- uint64 keys[1024];\r
- FILE *output;\r
-};\r
-\r
-\r
-// variables\r
-\r
-static int MaxPly;\r
-static int MinGame;\r
-static double MinScore;\r
-static bool RemoveWhite, RemoveBlack;\r
-static bool Uniform;\r
-static bool Quiet=false;\r
-\r
-static book_t Book[1];\r
-\r
-// prototypes\r
-\r
-static void book_clear ();\r
-static void book_insert (const char file_name[]);\r
-static void book_filter ();\r
-static void book_sort ();\r
-static void book_save (const char file_name[]);\r
-\r
-static int find_entry (const board_t * board, int move);\r
-static void resize ();\r
-static void halve_stats (uint64 key);\r
-\r
-static bool keep_entry (int pos);\r
-\r
-static int entry_score (const entry_t * entry);\r
-\r
-static int key_compare (const void * p1, const void * p2);\r
-\r
-static void write_integer (FILE * file, int size, uint64 n);\r
-static uint64 read_integer(FILE * file, int size);\r
-\r
-static void read_entry_file(FILE *f, entry_t *entry);\r
-static void write_entry_file(FILE * f, const entry_t * entry);\r
-\r
-// functions\r
-\r
-// book_make()\r
-\r
-void book_make(int argc, char * argv[]) {\r
-\r
- int i;\r
- const char * pgn_file;\r
- const char * bin_file;\r
-\r
- pgn_file = NULL;\r
- my_string_set(&pgn_file,"book.pgn");\r
-\r
- bin_file = NULL;\r
- my_string_set(&bin_file,"book.bin");\r
-\r
- MaxPly = 1024;\r
- MinGame = 3;\r
- MinScore = 0.0;\r
- RemoveWhite = false;\r
- RemoveBlack = false;\r
- Uniform = false;\r
-\r
- for (i = 1; i < argc; i++) {\r
-\r
- if (false) {\r
-\r
- } else if (my_string_equal(argv[i],"make-book")) {\r
-\r
- // skip\r
-\r
- } else if (my_string_equal(argv[i],"-pgn")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("book_make(): missing argument\n");\r
-\r
- my_string_set(&pgn_file,argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-bin")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("book_make(): missing argument\n");\r
-\r
- my_string_set(&bin_file,argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-max-ply")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("book_make(): missing argument\n");\r
-\r
- MaxPly = atoi(argv[i]);\r
- ASSERT(MaxPly>=0);\r
-\r
- } else if (my_string_equal(argv[i],"-min-game")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("book_make(): missing argument\n");\r
-\r
- MinGame = atoi(argv[i]);\r
- ASSERT(MinGame>0);\r
-\r
- } else if (my_string_equal(argv[i],"-min-score")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("book_make(): missing argument\n");\r
-\r
- MinScore = atof(argv[i]) / 100.0;\r
- ASSERT(MinScore>=0.0&&MinScore<=1.0);\r
-\r
- } else if (my_string_equal(argv[i],"-only-white")) {\r
-\r
- RemoveWhite = false;\r
- RemoveBlack = true;\r
-\r
- } else if (my_string_equal(argv[i],"-only-black")) {\r
-\r
- RemoveWhite = true;\r
- RemoveBlack = false;\r
-\r
- } else if (my_string_equal(argv[i],"-uniform")) {\r
-\r
- Uniform = true;\r
-\r
- } else {\r
-\r
- my_fatal("book_make(): unknown option \"%s\"\n",argv[i]);\r
- }\r
- }\r
-\r
- book_clear();\r
-\r
- printf("inserting games ...\n");\r
- book_insert(pgn_file);\r
-\r
- printf("filtering entries ...\n");\r
- book_filter();\r
-\r
- printf("sorting entries ...\n");\r
- book_sort();\r
-\r
- printf("saving entries ...\n");\r
- book_save(bin_file);\r
-\r
- printf("all done!\n");\r
-}\r
-\r
-// book_clear()\r
-\r
-static void book_clear() {\r
-\r
- int index;\r
-\r
- Book->alloc = 1;\r
- Book->mask = (Book->alloc * 2) - 1;\r
-\r
- Book->entry = (entry_t *) my_malloc(Book->alloc*sizeof(entry_t));\r
- Book->size = 0;\r
-\r
- Book->hash = (sint32 *) my_malloc((Book->alloc*2)*sizeof(sint32));\r
- for (index = 0; index < Book->alloc*2; index++) {\r
- Book->hash[index] = NIL;\r
- }\r
-}\r
-\r
-// book_insert()\r
-\r
-static void book_insert(const char file_name[]) {\r
-\r
- pgn_t pgn[1];\r
- board_t board[1];\r
- int ply;\r
- int result;\r
- char string[256];\r
- int move;\r
- int pos;\r
-\r
- ASSERT(file_name!=NULL);\r
-\r
- // init\r
-\r
- pgn->game_nb=1;\r
- // scan loop\r
-\r
- pgn_open(pgn,file_name);\r
-\r
- while (pgn_next_game(pgn)) {\r
-\r
- board_start(board);\r
- ply = 0;\r
- result = 0;\r
-\r
- if (false) {\r
- } else if (my_string_equal(pgn->result,"1-0")) {\r
- result = +1;\r
- } else if (my_string_equal(pgn->result,"0-1")) {\r
- result = -1;\r
- }\r
-\r
- while (pgn_next_move(pgn,string,256)) {\r
-\r
- if (ply < MaxPly) {\r
-\r
- move = move_from_san(string,board);\r
-\r
- if (move == MoveNone || !move_is_legal(move,board)) {\r
- my_fatal("book_insert(): illegal move \"%s\" at line %d, column %d,game %d\n",string,pgn->move_line,pgn->move_column,pgn->game_nb);\r
- }\r
-\r
- pos = find_entry(board,move);\r
-\r
- Book->entry[pos].n++;\r
- Book->entry[pos].sum += result+1;\r
-\r
- if (Book->entry[pos].n >= COUNT_MAX) {\r
- halve_stats(board->key);\r
- }\r
-\r
- move_do(board,move);\r
- ply++;\r
- result = -result;\r
- }\r
- }\r
- pgn->game_nb++;\r
- if (pgn->game_nb % 10000 == 0) printf("%d games ...\n",pgn->game_nb);\r
- }\r
-\r
- pgn_close(pgn);\r
-\r
- printf("%d game%s.\n",pgn->game_nb,(pgn->game_nb>2)?"s":"");\r
- printf("%d entries.\n",Book->size);\r
-\r
- return;\r
-}\r
-\r
-// book_filter()\r
-\r
-static void book_filter() {\r
-\r
- int src, dst;\r
-\r
- // entry loop\r
-\r
- dst = 0;\r
-\r
- for (src = 0; src < Book->size; src++) {\r
- if (keep_entry(src)) Book->entry[dst++] = Book->entry[src];\r
- }\r
-\r
- ASSERT(dst>=0&&dst<=Book->size);\r
- Book->size = dst;\r
-\r
- printf("%d entries.\n",Book->size);\r
-}\r
-\r
-// book_sort()\r
-\r
-static void book_sort() {\r
-\r
- // sort keys for binary search\r
-\r
- qsort(Book->entry,Book->size,sizeof(entry_t),&key_compare);\r
-}\r
-\r
-// book_save()\r
-\r
-static void book_save(const char file_name[]) {\r
-\r
- FILE * file;\r
- int pos;\r
-\r
- ASSERT(file_name!=NULL);\r
-\r
- file = fopen(file_name,"wb");\r
- if (file == NULL) my_fatal("book_save(): can't open file \"%s\" for writing: %s\n",file_name,strerror(errno));\r
-\r
- // entry loop\r
-\r
- for (pos = 0; pos < Book->size; pos++) {\r
-\r
- ASSERT(keep_entry(pos));\r
-\r
- write_integer(file,8,Book->entry[pos].key);\r
- write_integer(file,2,Book->entry[pos].move);\r
- write_integer(file,2,entry_score(&Book->entry[pos]));\r
- write_integer(file,2,0);\r
- write_integer(file,2,0);\r
- }\r
-\r
- fclose(file);\r
-}\r
-\r
-// find_entry()\r
-\r
-static int find_entry(const board_t * board, int move) {\r
-\r
- uint64 key;\r
- int index;\r
- int pos;\r
-\r
- ASSERT(board!=NULL);\r
- ASSERT(move==MoveNone || move_is_ok(move));\r
-\r
- ASSERT(move==MoveNone || move_is_legal(move,board));\r
-\r
- // init\r
-\r
- key = board->key;\r
-\r
- // search\r
-\r
- for (index = key & (uint64) Book->mask; (pos=Book->hash[index]) != NIL; index = (index+1) & Book->mask) {\r
-\r
- ASSERT(pos>=0&&pos<Book->size);\r
-\r
- if (Book->entry[pos].key == key && Book->entry[pos].move == move) {\r
- return pos; // found\r
- }\r
- }\r
-\r
- // not found\r
-\r
- ASSERT(Book->size<=Book->alloc);\r
-\r
- if (Book->size == Book->alloc) {\r
-\r
- // allocate more memory\r
-\r
- resize();\r
-\r
- for (index = key & (uint64) Book->mask; Book->hash[index] != NIL; index = (index+1) & Book->mask)\r
- ;\r
- }\r
-\r
- // create a new entry\r
-\r
- ASSERT(Book->size<Book->alloc);\r
- pos = Book->size++;\r
-\r
- Book->entry[pos].key = key;\r
- Book->entry[pos].move = move;\r
- Book->entry[pos].n = 0;\r
- Book->entry[pos].sum = 0;\r
- Book->entry[pos].colour = board->turn;\r
-\r
- // insert into the hash table\r
-\r
- ASSERT(index>=0&&index<Book->alloc*2);\r
- ASSERT(Book->hash[index]==NIL);\r
- Book->hash[index] = pos;\r
-\r
- ASSERT(pos>=0&&pos<Book->size);\r
-\r
- return pos;\r
-}\r
-\r
-// rebuild_hash_table\r
-\r
-static void rebuild_hash_table(){\r
- int index,pos;\r
- for (index = 0; index < Book->alloc*2; index++) {\r
- Book->hash[index] = NIL;\r
- }\r
- for (pos = 0; pos < Book->size; pos++) {\r
- for (index = Book->entry[pos].key & (uint64) Book->mask; Book->hash[index] != NIL; index = (index+1) & Book->mask)\r
- ;\r
- ASSERT(index>=0&&index<Book->alloc*2);\r
- Book->hash[index] = pos;\r
- }\r
-}\r
-\r
-static void resize() {\r
-\r
- int size;\r
-\r
- ASSERT(Book->size==Book->alloc);\r
-\r
- Book->alloc *= 2;\r
- Book->mask = (Book->alloc * 2) - 1;\r
-\r
- size = 0;\r
- size += Book->alloc * sizeof(entry_t);\r
- size += (Book->alloc*2) * sizeof(sint32);\r
-\r
- if (size >= 1048576) if(!Quiet){printf("allocating %gMB ...\n",double(size)/1048576.0);}\r
-\r
- // resize arrays\r
-\r
- Book->entry = (entry_t *) my_realloc(Book->entry,Book->alloc*sizeof(entry_t));\r
- Book->hash = (sint32 *) my_realloc(Book->hash,(Book->alloc*2)*sizeof(sint32));\r
-\r
- // rebuild hash table\r
-\r
- rebuild_hash_table();\r
-}\r
-\r
-\r
-// halve_stats()\r
-\r
-static void halve_stats(uint64 key) {\r
-\r
- int index;\r
- int pos;\r
-\r
- // search\r
-\r
- for (index = key & (uint64) Book->mask; (pos=Book->hash[index]) != NIL; index = (index+1) & Book->mask) {\r
-\r
- ASSERT(pos>=0&&pos<Book->size);\r
-\r
- if (Book->entry[pos].key == key) {\r
- Book->entry[pos].n = (Book->entry[pos].n + 1) / 2;\r
- Book->entry[pos].sum = (Book->entry[pos].sum + 1) / 2;\r
- }\r
- }\r
-}\r
-\r
-// keep_entry()\r
-\r
-static bool keep_entry(int pos) {\r
-\r
- const entry_t * entry;\r
- int colour;\r
- double score;\r
-\r
- ASSERT(pos>=0&&pos<Book->size);\r
-\r
- entry = &Book->entry[pos];\r
-\r
- // if (entry->n == 0) return false;\r
- if (entry->n < MinGame) return false;\r
-\r
- if (entry->sum == 0) return false;\r
-\r
- score = (double(entry->sum) / double(entry->n)) / 2.0;\r
- ASSERT(score>=0.0&&score<=1.0);\r
-\r
- if (score < MinScore) return false;\r
-\r
- colour = entry->colour;\r
-\r
- if ((RemoveWhite && colour_is_white(colour))\r
- || (RemoveBlack && colour_is_black(colour))) {\r
- return false;\r
- }\r
-\r
- if (entry_score(entry) == 0) return false; // REMOVE ME?\r
-\r
- return true;\r
-}\r
-\r
-// entry_score()\r
-\r
-static int entry_score(const entry_t * entry) {\r
-\r
- int score;\r
-\r
- ASSERT(entry!=NULL);\r
-\r
- // score = entry->n; // popularity\r
- score = entry->sum; // "expectancy"\r
-\r
- if (Uniform) score = 1;\r
-\r
- ASSERT(score>=0);\r
-\r
- return score;\r
-}\r
-\r
-// key_compare()\r
-\r
-static int key_compare(const void * p1, const void * p2) {\r
-\r
- const entry_t * entry_1, * entry_2;\r
-\r
- ASSERT(p1!=NULL);\r
- ASSERT(p2!=NULL);\r
-\r
- entry_1 = (const entry_t *) p1;\r
- entry_2 = (const entry_t *) p2;\r
-\r
- if (entry_1->key > entry_2->key) {\r
- return +1;\r
- } else if (entry_1->key < entry_2->key) {\r
- return -1;\r
- } else {\r
- return entry_score(entry_2) - entry_score(entry_1); // highest score first\r
- }\r
-}\r
-\r
-// write_integer()\r
-\r
-static void write_integer(FILE * file, int size, uint64 n) {\r
-\r
- int i;\r
- int b;\r
-\r
- ASSERT(file!=NULL);\r
- ASSERT(size>0&&size<=8);\r
- ASSERT(size==8||n>>(size*8)==0);\r
-\r
- for (i = size-1; i >= 0; i--) {\r
- b = (n >> (i*8)) & 0xFF;\r
- ASSERT(b>=0&&b<256);\r
- fputc(b,file);\r
- }\r
-}\r
-\r
-// read_integer()\r
-\r
-static uint64 read_integer(FILE * file, int size) {\r
- uint64 n;\r
- int i;\r
- int b;\r
- ASSERT(file!=NULL);\r
- ASSERT(size>0&&size<=8);\r
- n = 0;\r
- for (i = 0; i < size; i++) {\r
- b = fgetc(file);\r
- if (b == EOF) {\r
- if (feof(file)) {\r
- my_fatal("read_integer(): fgetc(): EOF reached\n");\r
- } else { // error\r
- my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));\r
- }\r
- }\r
- ASSERT(b>=0&&b<256);\r
- n = (n << 8) | b;\r
- }\r
- return n;\r
-}\r
-\r
-// read_entry_file\r
-\r
-static void read_entry_file(FILE *f, entry_t *entry){\r
- uint64 n;\r
- ASSERT(entry!=NULL);\r
- n = entry->key = read_integer(f,8);\r
- entry->move = read_integer(f,2);\r
- entry->count = read_integer(f,2);\r
- entry->n = read_integer(f,2);\r
- entry->sum = read_integer(f,2);\r
- ASSERT(n==entry->key); // test for mingw compiler bug with anon structs\r
-}\r
-\r
-// write_entry_file\r
-\r
-static void write_entry_file(FILE * f, const entry_t * entry) {\r
- ASSERT(entry!=NULL);\r
- write_integer(f,8,entry->key);\r
- write_integer(f,2,entry->move);\r
- write_integer(f,2,entry->count);\r
- write_integer(f,2,entry->n);\r
- write_integer(f,2,entry->sum);\r
-}\r
-\r
-static void print_list(const board_t *board, list_t *list){\r
- int i;\r
- uint16 move;\r
- char move_string[256];\r
- for (i = 0; i < list_size(list); i++) {\r
- move = list_move(list,i);\r
- move_to_san(move,board,move_string,256);\r
- printf("%s",move_string);\r
- }\r
- printf("\n");\r
-}\r
-\r
-// book_load()\r
-// loads a polyglot book\r
-\r
-static void book_load(const char filename[]){\r
- FILE* f;\r
- entry_t entry[1];\r
- int size;\r
- int i;\r
- int pos;\r
- int index;\r
- ASSERT(filename!=NULL);\r
- if(!(f=fopen(filename,"rb"))){\r
- my_fatal("book_load() : can't open file \"%s\" for reading: %s\n",filename,strerror(errno));\r
- }\r
- fseek(f,0L,SEEK_END); // superportable way to get size of book!\r
- size=ftell(f)/16;\r
- fseek(f,0,SEEK_SET);\r
- for(i=0L;i<size;i++){\r
- read_entry_file(f,entry);\r
- ASSERT(Book->size<=Book->alloc);\r
- if (Book->size == Book->alloc) {\r
- // allocate more memoryx\r
- resize();\r
- }\r
- // insert into the book\r
- pos = Book->size++;\r
- Book->entry[pos].key = entry->key;\r
- ASSERT(entry->move!=MoveNone);\r
- Book->entry[pos].move = entry->move;\r
- Book->entry[pos].count = entry->count;\r
- Book->entry[pos].n = entry->n;\r
- Book->entry[pos].sum = entry->sum;\r
- Book->entry[pos].colour = ColourNone;\r
- // find free hash table spot\r
- for (index = entry->key & (uint64) Book->mask;\r
- Book->hash[index] != NIL;\r
- index = (index+1) & Book->mask);\r
- // insert into the hash table\r
- ASSERT(index>=0&&index<Book->alloc*2);\r
- ASSERT(Book->hash[index]==NIL);\r
- Book->hash[index] = pos;\r
- ASSERT(pos>=0&&pos<Book->size);\r
- }\r
- fclose(f);\r
-}\r
-\r
-// gen_book_moves()\r
-// similar signature as gen_legal_moves\r
-static int gen_book_moves(list_t * list, const board_t * board){\r
- int first_pos, pos, index;\r
- entry_t entry[1];\r
- list_clear(list);\r
- bool found;\r
- found=FALSE;\r
- for (index = board->key & (uint64) Book->mask; (first_pos=Book->hash[index]) != NIL; index = (index+1) & Book->mask) {\r
- ASSERT(first_pos>=0&&first_pos<Book->size);\r
- if (Book->entry[first_pos].key == board->key) {\r
- found=TRUE;\r
- break; // found\r
- }\r
- }\r
- if(!found) return -1;\r
- if(Book->entry[first_pos].move==MoveNone) return -1;\r
- for (pos = first_pos; pos < Book->size; pos++) {\r
- *entry=Book->entry[pos];\r
- if (entry->key != board->key) break;\r
- if (entry->count > 0 &&\r
- entry->move != MoveNone &&\r
- move_is_legal(entry->move,board)) {\r
- list_add(list,entry->move,entry->count);\r
- }\r
- }\r
- return first_pos;\r
-}\r
-\r
-// gen_opp_book_moves()\r
-// moves to which opponent has a reply in book\r
-// similar signature as gen_legal_moves\r
-static void gen_opp_book_moves(list_t * list, const board_t * board){\r
- int move;\r
- list_t new_list[1], legal_moves[1];\r
- board_t new_board[1];\r
- int i;\r
- list_clear(list);\r
- gen_legal_moves(legal_moves,board);\r
- for (i = 0; i < list_size(legal_moves); i++) {\r
- move = list_move(legal_moves,i);\r
- // scratch_board\r
- memcpy(new_board, board, sizeof(board_t));\r
- move_do(new_board,move);\r
- gen_book_moves(new_list,new_board); // wasteful in time but tested!\r
- if(list_size(new_list)!=0){\r
- list_add(list,move);\r
- }\r
- }\r
-}\r
-\r
-static void print_moves(info_t *info){\r
- board_t board[1];\r
- char move_string[256];\r
- int i;\r
- int color=White;\r
- if(!info->output){\r
- return;\r
- }\r
- board_start(board);\r
- for(i=0;i<info->height;i++){\r
- if(color==White){\r
- fprintf(info->output,"%d. ",i/2+1);\r
- color=Black;\r
- }else{\r
- color=White;\r
- }\r
- move_to_san(info->moves[i],board,move_string,256);\r
- fprintf(info->output,"%s", move_string);\r
- if(color==colour_opp(info->initial_color)){\r
- fprintf(info->output,"{%.0f%%} ",100*info->probs[i]);\r
- }else{\r
- fprintf(info->output," ");\r
- }\r
- move_do(board,info->moves[i]);\r
- }\r
-}\r
-\r
-static int search_book(board_t *board, info_t *info, search_t search){\r
- list_t list[1];\r
- board_t new_board[1];\r
- uint16 move;\r
- int count;\r
- int ret;\r
- int i;\r
- int offset;\r
- int pos;\r
- int size;\r
- int prob_sum;\r
- double probs[256];\r
- for(i=0;i<256;i++){\r
- probs[i]=0.0; // kill compiler warnings\r
- }\r
- for(i=0;i<info->height;i++){\r
- if(board->key==info->keys[i]){\r
- if(info->output){\r
- fprintf(info->output,"%d: ",info->line);\r
- print_moves(info);\r
- fprintf(info->output,"{cycle: ply=%d}\n",i);\r
- }\r
- info->line++;\r
- return 1; // end of line because of cycle\r
- }\r
- }\r
- if(!info->book_trans_only || (info->book_trans_only && search==BOOK)){\r
- info->keys[info->height]=board->key;\r
- size=Book->size; // hack\r
- pos=find_entry(board,MoveNone);\r
- if(size==Book->size){\r
- if(info->output){\r
- fprintf(info->output,"%d: ",info->line);\r
- print_moves(info);\r
- fprintf(info->output,"{trans: line=%d, ply=%d}\n",\r
- Book->entry[pos].line,\r
- Book->entry[pos].height);\r
- }\r
- info->line++;\r
- return 1; // end of line because of transposition\r
- }else{\r
- Book->entry[pos].height=info->height;\r
- Book->entry[pos].line=info->line;\r
- }\r
- }\r
- count=0;\r
- if(search==BOOK){\r
- offset=gen_book_moves(list,board);\r
- if(info->extended_search){\r
- gen_legal_moves(list,board);\r
- }\r
-// ASSERT(offset!=-1);\r
- if(offset!=-1){ // only false in starting position for black book\r
- Book->entry[offset].colour=board->turn;\r
- prob_sum=0;\r
- if(!info->extended_search){\r
- for(i=0;i<list_size(list);i++){\r
- prob_sum+=uint16(list_value(list,i));\r
- }\r
- for(i=0;i<list_size(list);i++){\r
- probs[i]=double(uint16(list_value(list,i)))/double(prob_sum);\r
- }\r
- }\r
- }\r
- }else{\r
- gen_opp_book_moves(list,board);\r
- }\r
- for (i = 0; i < list_size(list); i++) {\r
- move = list_move(list,i);\r
- memcpy(new_board, board, sizeof(board_t));\r
- ASSERT(move_is_legal(move,new_board));\r
- move_do(new_board,move);\r
- ASSERT(search!=opp_search(search));\r
- info->moves[info->height++]=move;\r
- if(search==BOOK){\r
- info->probs[info->height-1]=probs[i];\r
- }\r
- ret=search_book(new_board, info, opp_search(search));\r
- if(ret==0 && search==BOOK){\r
- if(info->output){\r
- fprintf(info->output,"%d: ",info->line);\r
- print_moves(info);\r
- fprintf(info->output,"\n");\r
- }\r
- info->line++;\r
- ret=1; // end of line book move counts for 1\r
- }\r
- info->height--;\r
- ASSERT(info->height>=0);\r
- count+=ret;\r
- }\r
- return count;\r
-}\r
-\r
-void init_info(info_t *info){\r
- info->line=1;\r
- info->height=0;\r
- info->output=NULL;\r
- info->initial_color=White;\r
- info->book_trans_only=FALSE;\r
-}\r
-\r
-// book_clean()\r
-// remove MoveNone entries from book and rebuild hash table\r
-void book_clean(){\r
- int read_ptr,write_ptr;\r
- write_ptr=0;\r
- for(read_ptr=0;read_ptr<Book->size;read_ptr++){\r
- if(Book->entry[read_ptr].move!=MoveNone){\r
- Book->entry[write_ptr++]=Book->entry[read_ptr];\r
- }\r
- }\r
- Book->size=write_ptr;\r
- rebuild_hash_table();\r
-}\r
-\r
-// book_dump()\r
-\r
-void book_dump(int argc, char * argv[]) {\r
- const char * bin_file=NULL;\r
- const char * txt_file=NULL;\r
- char string[StringSize];\r
- int color=ColourNone;\r
- board_t board[1];\r
- info_t info[1];\r
- int i;\r
- FILE *f;\r
- my_string_set(&bin_file,"book.bin");\r
- for (i = 1; i < argc; i++) {\r
- if (false) {\r
- } else if (my_string_equal(argv[i],"dump-book")) {\r
- // skip\r
- } else if (my_string_equal(argv[i],"-bin")) {\r
- i++;\r
- if (i==argc) my_fatal("book_dump(): missing argument\n");\r
- my_string_set(&bin_file,argv[i]);\r
- } else if (my_string_equal(argv[i],"-out")) {\r
- i++;\r
- if (i==argc) my_fatal("book_dump(): missing argument\n");\r
- my_string_set(&txt_file,argv[i]);\r
- } else if (my_string_equal(argv[i],"-color") || my_string_equal(argv[i],"-colour")) {\r
- i++;\r
- if (i == argc) my_fatal("book_dump(): missing argument\n");\r
- if(my_string_equal(argv[i],"white")){\r
- color=White;\r
- }else if (my_string_equal(argv[i],"black")){\r
- color=Black;\r
- }else{\r
- my_fatal("book_dump(): unknown color \"%s\"\n",argv[i]);\r
- }\r
- } else {\r
- my_fatal("book_dump(): unknown option \"%s\"\n",argv[i]);\r
- }\r
- }\r
- if(color==ColourNone){\r
- my_fatal("book_dump(): you must specify a color\n");\r
- }\r
- if(txt_file==NULL){\r
- snprintf(string,StringSize,"book_%s.txt",color?"white":"black");\r
- my_string_set(&txt_file,string);\r
- }\r
-\r
- book_clear();\r
- if(!Quiet){printf("loading book ...\n");}\r
- book_load(bin_file);\r
- board_start(board);\r
- init_info(info);\r
- info->initial_color=color;\r
- if(!(f=fopen(txt_file,"w"))){\r
- my_fatal("book_dump(): can't open file \"%s\" for writing: %s",\r
- txt_file,strerror(errno));\r
- }\r
- info->output=f;\r
- fprintf(info->output,"Dump of \"%s\" for %s.\n",\r
- bin_file,color==White?"white":"black");\r
- if(color==White){\r
- if(!Quiet){printf("generating lines for white...\n");}\r
- search_book(board,info, BOOK);\r
- }else{\r
- if(!Quiet){printf("generating lines for black...\n");}\r
- search_book(board,info, ALL);\r
- }\r
-}\r
-\r
-// book_info()\r
-\r
-void book_info(int argc,char* argv[]){\r
- const char *bin_file=NULL;\r
- board_t board[1];\r
- info_t info[1];\r
- uint64 last_key;\r
- int pos;\r
- int white_pos,black_pos,total_pos,white_pos_extended,\r
- black_pos_extended,white_pos_extended_diff,black_pos_extended_diff;\r
- int s;\r
- bool extended_search=FALSE;\r
- int i;\r
- Quiet=TRUE;\r
- my_string_set(&bin_file,"book.bin");\r
-\r
- for (i = 1; i < argc; i++) {\r
- if (false) {\r
- } else if (my_string_equal(argv[i],"info-book")) {\r
- // skip\r
- } else if (my_string_equal(argv[i],"-bin")) {\r
- i++;\r
- if (i==argc) my_fatal("book_info(): missing argument\n");\r
- my_string_set(&bin_file,argv[i]);\r
- } else if (my_string_equal(argv[i],"-exact")) {\r
- extended_search=TRUE;\r
- } else {\r
- my_fatal("book_info(): unknown option \"%s\"\n",argv[i]);\r
- }\r
- }\r
- book_clear();\r
- if(!Quiet){printf("loading book ...\n");}\r
- book_load(bin_file);\r
- s=Book->size;\r
-\r
- board_start(board);\r
- init_info(info);\r
- info->book_trans_only=FALSE;\r
- info->initial_color=White;\r
- info->extended_search=FALSE;\r
- search_book(board,info, BOOK);\r
- printf("Lines for white : %8d\n",info->line-1);\r
-\r
-\r
- info->line=1;\r
- info->height=0;\r
- info->initial_color=Black;\r
- book_clean();\r
- ASSERT(Book->size==s);\r
- board_start(board);\r
- search_book(board,info, ALL);\r
- printf("Lines for black : %8d\n",info->line-1);\r
-\r
- book_clean();\r
- ASSERT(Book->size==s);\r
- white_pos=0;\r
- black_pos=0;\r
- total_pos=0;\r
- last_key=0;\r
- for(pos=0;pos<Book->size;pos++){\r
- if(Book->entry[pos].key==last_key){\r
- ASSERT(Book->entry[pos].colour==ColourNone);\r
- continue;\r
- }\r
- last_key=Book->entry[pos].key;\r
- total_pos++;\r
- if(Book->entry[pos].colour==White){\r
- white_pos++;\r
- }else if(Book->entry[pos].colour==Black){\r
- black_pos++;\r
- }\r
- }\r
- printf("Positions on lines for white : %8d\n",white_pos);\r
- printf("Positions on lines for black : %8d\n",black_pos);\r
-\r
- \r
- if(extended_search){\r
- init_info(info);\r
- info->book_trans_only=TRUE;\r
- info->initial_color=White;\r
- info->extended_search=TRUE;\r
- book_clean();\r
- board_start(board);\r
- search_book(board,info, BOOK);\r
-\r
- init_info(info);\r
- info->book_trans_only=TRUE;\r
- info->initial_color=Black;\r
- info->extended_search=TRUE;\r
- book_clean();\r
- board_start(board);\r
- search_book(board,info, ALL);\r
- book_clean();\r
- ASSERT(Book->size==s);\r
- white_pos_extended=0;\r
- black_pos_extended=0;\r
- last_key=0;\r
- for(pos=0;pos<Book->size;pos++){\r
- if(Book->entry[pos].key==last_key){\r
- ASSERT(Book->entry[pos].colour==ColourNone);\r
- continue;\r
- }\r
- last_key=Book->entry[pos].key;\r
- if(Book->entry[pos].colour==White){\r
- white_pos_extended++;\r
- }else if(Book->entry[pos].colour==Black){\r
- black_pos_extended++;\r
- }\r
- }\r
- white_pos_extended_diff=white_pos_extended-white_pos;\r
- black_pos_extended_diff=black_pos_extended-black_pos;\r
- printf("Unreachable white positions(?) : %8d\n",\r
- white_pos_extended_diff);\r
- printf("Unreachable black positions(?) : %8d\n",\r
- black_pos_extended_diff);\r
-\r
- }\r
- if(extended_search){\r
- printf("Isolated positions : %8d\n",\r
- total_pos-white_pos_extended-black_pos_extended);\r
- }else{\r
- printf("Isolated positions : %8d\n",\r
- total_pos-white_pos-black_pos);\r
- }\r
-}\r
-\r
-\r
-\r
-// end of book_make.cpp\r
-\r
+++ /dev/null
-\r
-// book_merge.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "book_merge.h"\r
-#include "util.h"\r
-\r
-// types\r
-\r
-struct book_t {\r
- FILE * file;\r
- int size;\r
-};\r
-\r
-struct entry_t {\r
- uint64 key;\r
- uint16 move;\r
- uint16 count;\r
- uint16 n;\r
- uint16 sum;\r
-};\r
-\r
-// variables\r
-\r
-static book_t In1[1];\r
-static book_t In2[1];\r
-static book_t Out[1];\r
-\r
-// prototypes\r
-\r
-static void book_clear (book_t * book);\r
-\r
-static void book_open (book_t * book, const char file_name[], const char mode[]);\r
-static void book_close (book_t * book);\r
-\r
-static bool read_entry (book_t * book, entry_t * entry, int n);\r
-static void write_entry (book_t * book, const entry_t * entry);\r
-\r
-static uint64 read_integer (FILE * file, int size);\r
-static void write_integer (FILE * file, int size, uint64 n);\r
-\r
-// functions\r
-\r
-// book_merge()\r
-\r
-void book_merge(int argc, char * argv[]) {\r
-\r
- int i;\r
- const char * in_file_1;\r
- const char * in_file_2;\r
- const char * out_file;\r
- int i1, i2;\r
- bool b1, b2;\r
- entry_t e1[1], e2[1];\r
- int skip;\r
-\r
- in_file_1 = NULL;\r
- my_string_clear(&in_file_1);\r
-\r
- in_file_2 = NULL;\r
- my_string_clear(&in_file_2);\r
-\r
- out_file = NULL;\r
- my_string_set(&out_file,"out.bin");\r
-\r
- for (i = 1; i < argc; i++) {\r
-\r
- if (false) {\r
-\r
- } else if (my_string_equal(argv[i],"merge-book")) {\r
-\r
- // skip\r
-\r
- } else if (my_string_equal(argv[i],"-in1")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
-\r
- my_string_set(&in_file_1,argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-in2")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
-\r
- my_string_set(&in_file_2,argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-out")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
-\r
- my_string_set(&out_file,argv[i]);\r
-\r
- } else {\r
-\r
- my_fatal("book_merge(): unknown option \"%s\"\n",argv[i]);\r
- }\r
- }\r
-\r
- book_clear(In1);\r
- book_clear(In2);\r
- book_clear(Out);\r
-\r
- book_open(In1,in_file_1,"rb");\r
- book_open(In2,in_file_2,"rb");\r
- book_open(Out,out_file,"wb");\r
-\r
- skip = 0;\r
-\r
- i1 = 0;\r
- i2 = 0;\r
-\r
- while (true) {\r
-\r
- b1 = read_entry(In1,e1,i1);\r
- b2 = read_entry(In2,e2,i2);\r
-\r
- if (false) {\r
-\r
- } else if (!b1 && !b2) {\r
-\r
- break;\r
-\r
- } else if (b1 && !b2) {\r
-\r
- write_entry(Out,e1);\r
- i1++;\r
-\r
- } else if (b2 && !b1) {\r
-\r
- write_entry(Out,e2);\r
- i2++;\r
-\r
- } else {\r
-\r
- ASSERT(b1);\r
- ASSERT(b2);\r
-\r
- if (false) {\r
- } else if (e1->key < e2->key) {\r
- write_entry(Out,e1);\r
- i1++;\r
- } else if (e1->key > e2->key) {\r
- write_entry(Out,e2);\r
- i2++;\r
- } else {\r
- ASSERT(e1->key==e2->key);\r
- skip++;\r
- i2++;\r
- }\r
- }\r
- }\r
-\r
- book_close(In1);\r
- book_close(In2);\r
- book_close(Out);\r
-\r
- if (skip != 0) {\r
- printf("skipped %d entr%s.\n",skip,(skip>1)?"ies":"y");\r
- }\r
-\r
- printf("done!\n");\r
-}\r
-\r
-// book_clear()\r
-\r
-static void book_clear(book_t * book) {\r
-\r
- ASSERT(book!=NULL);\r
-\r
- book->file = NULL;\r
- book->size = 0;\r
-}\r
-\r
-// book_open()\r
-\r
-static void book_open(book_t * book, const char file_name[], const char mode[]) {\r
-\r
- ASSERT(book!=NULL);\r
- ASSERT(file_name!=NULL);\r
- ASSERT(mode!=NULL);\r
-\r
- book->file = fopen(file_name,mode);\r
- if (book->file == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
-\r
- if (fseek(book->file,0,SEEK_END) == -1) {\r
- my_fatal("book_open(): fseek(): %s\n",strerror(errno));\r
- }\r
-\r
- book->size = ftell(book->file) / 16;\r
-}\r
-\r
-// book_close()\r
-\r
-static void book_close(book_t * book) {\r
-\r
- ASSERT(book!=NULL);\r
-\r
- if (fclose(book->file) == EOF) {\r
- my_fatal("book_close(): fclose(): %s\n",strerror(errno));\r
- }\r
-}\r
-\r
-// read_entry()\r
-\r
-static bool read_entry(book_t * book, entry_t * entry, int n) {\r
-\r
- ASSERT(book!=NULL);\r
- ASSERT(entry!=NULL);\r
-\r
- if (n < 0 || n >= book->size) return false;\r
-\r
- ASSERT(n>=0&&n<book->size);\r
-\r
- if (fseek(book->file,n*16,SEEK_SET) == -1) {\r
- my_fatal("read_entry(): fseek(): %s\n",strerror(errno));\r
- }\r
-\r
- entry->key = read_integer(book->file,8);\r
- entry->move = read_integer(book->file,2);\r
- entry->count = read_integer(book->file,2);\r
- entry->n = read_integer(book->file,2);\r
- entry->sum = read_integer(book->file,2);\r
-\r
- return true;\r
-}\r
-\r
-// write_entry()\r
-\r
-static void write_entry(book_t * book, const entry_t * entry) {\r
-\r
- ASSERT(book!=NULL);\r
- ASSERT(entry!=NULL);\r
-\r
- write_integer(book->file,8,entry->key);\r
- write_integer(book->file,2,entry->move);\r
- write_integer(book->file,2,entry->count);\r
- write_integer(book->file,2,entry->n);\r
- write_integer(book->file,2,entry->sum);\r
-}\r
-\r
-// read_integer()\r
-\r
-static uint64 read_integer(FILE * file, int size) {\r
-\r
- uint64 n;\r
- int i;\r
- int b;\r
-\r
- ASSERT(file!=NULL);\r
- ASSERT(size>0&&size<=8);\r
-\r
- n = 0;\r
-\r
- for (i = 0; i < size; i++) {\r
-\r
- b = fgetc(file);\r
-\r
- if (b == EOF) {\r
- if (feof(file)) {\r
- my_fatal("read_integer(): fgetc(): EOF reached\n");\r
- } else { // error\r
- my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));\r
- }\r
- }\r
-\r
- ASSERT(b>=0&&b<256);\r
- n = (n << 8) | b;\r
- }\r
-\r
- return n;\r
-}\r
-\r
-// write_integer()\r
-\r
-static void write_integer(FILE * file, int size, uint64 n) {\r
-\r
- int i;\r
- int b;\r
-\r
- ASSERT(file!=NULL);\r
- ASSERT(size>0&&size<=8);\r
- ASSERT(size==8||n>>(size*8)==0);\r
-\r
- for (i = size-1; i >= 0; i--) {\r
-\r
- b = (n >> (i*8)) & 0xFF;\r
- ASSERT(b>=0&&b<256);\r
-\r
- if (fputc(b,file) == EOF) {\r
- my_fatal("write_integer(): fputc(): %s\n",strerror(errno));\r
- }\r
- }\r
-}\r
-\r
-// end of book_merge.cpp\r
-\r
+++ /dev/null
-\r
-// colour.cpp\r
-\r
-// includes\r
-\r
-#include "colour.h"\r
-#include "util.h"\r
-\r
-// functions\r
-\r
-// colour_is_ok()\r
-\r
-bool colour_is_ok(int colour) {\r
-\r
- return colour == Black || colour == White;\r
-}\r
-\r
-// colour_is_white()\r
-\r
-bool colour_is_white(int colour) {\r
-\r
- ASSERT(colour_is_ok(colour));\r
-\r
- return colour == White;\r
-}\r
-\r
-// colour_is_black()\r
-\r
-bool colour_is_black(int colour) {\r
-\r
- ASSERT(colour_is_ok(colour));\r
-\r
- return colour == Black;\r
-}\r
-\r
-// colour_equal()\r
-\r
-bool colour_equal(int colour_1, int colour_2) {\r
-\r
- ASSERT(colour_is_ok(colour_2));\r
-\r
- return (colour_1 & colour_2) != 0;\r
-}\r
-\r
-// colour_opp()\r
-\r
-int colour_opp(int colour) {\r
-\r
- ASSERT(colour_is_ok(colour));\r
-\r
- return colour ^ (BlackFlag^WhiteFlag);\r
-}\r
-\r
-// end of colour.cpp\r
-\r
+++ /dev/null
-#ifndef _WIN32\r
-\r
-// engine.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdarg>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include <sys/types.h>\r
-#include <sys/resource.h>\r
-#include <unistd.h>\r
-\r
-#include "engine.h"\r
-#include "io.h"\r
-#include "option.h"\r
-#include "util.h"\r
-\r
-\r
-// constants\r
-\r
-static const unsigned int StringSize = 4096;\r
-\r
-// variables\r
-\r
-engine_t Engine[1];\r
-\r
-// prototypes\r
-\r
-static void my_close (int fd);\r
-static void my_dup2 (int old_fd, int new_fd);\r
-\r
-// functions\r
-\r
-// engine_is_ok()\r
-\r
-bool engine_is_ok(const engine_t * engine) {\r
-\r
- if (engine == NULL) return false;\r
-\r
- if (!io_is_ok(engine->io)) return false;\r
-\r
- return true;\r
-}\r
-\r
-// engine_open()\r
-\r
-void engine_open(engine_t * engine) {\r
-\r
- const char * dir, * command;\r
- char string[StringSize];\r
- int argc;\r
- char * ptr;\r
- char * argv[256];\r
- int from_engine[2], to_engine[2];\r
- pid_t pid;\r
-\r
- ASSERT(engine!=NULL);\r
-\r
- // init\r
-\r
- dir = option_get_string("EngineDir");\r
- my_log("POLYGLOT Dir \"%s\"\n",dir);\r
-\r
- command = option_get_string("EngineCommand");\r
- my_log("POLYGLOT Command \"%s\"\n",command);\r
-\r
- // parse the command line and create the argument list\r
-\r
- if (strlen(command) >= StringSize) my_fatal("engine_open(): buffer overflow\n");\r
- strcpy(string,command);\r
-\r
- argc = 0;\r
-\r
- for (ptr = strtok(string," "); ptr != NULL; ptr = strtok(NULL," ")) {\r
- argv[argc++] = ptr;\r
- }\r
-\r
- argv[argc] = NULL;\r
-\r
- // create the pipes\r
-\r
- if (pipe(from_engine) == -1) {\r
- my_fatal("engine_open(): pipe(): %s\n",strerror(errno));\r
- }\r
-\r
- if (pipe(to_engine) == -1) {\r
- my_fatal("engine_open(): pipe(): %s\n",strerror(errno));\r
- }\r
-\r
- // create the child process\r
-\r
- pid = fork();\r
-\r
- if (pid == -1) {\r
-\r
- my_fatal("engine_open(): fork(): %s\n",strerror(errno));\r
-\r
- } else if (pid == 0) {\r
-\r
- // child = engine\r
-\r
- // close unused pipe descriptors to avoid deadlocks\r
-\r
- my_close(from_engine[0]);\r
- my_close(to_engine[1]);\r
-\r
- // attach the pipe to standard input\r
-\r
- my_dup2(to_engine[0],STDIN_FILENO);\r
- my_close(to_engine[0]);\r
-\r
- // attach the pipe to standard output\r
-\r
- my_dup2(from_engine[1],STDOUT_FILENO);\r
- my_close(from_engine[1]);\r
-\r
- // attach standard error to standard output\r
-\r
- my_dup2(STDOUT_FILENO,STDERR_FILENO);\r
-\r
- // set a low priority\r
-\r
- if (option_get_bool("UseNice")) {\r
- my_log("POLYGLOT Adjust Engine Piority");\r
- nice(option_get_int("NiceValue"));\r
- }\r
-\r
- // change the current directory\r
-\r
- if (dir[0] != '\0' && chdir(dir) == -1) {\r
- my_fatal("engine_open(): chdir(): %s\n",strerror(errno));\r
- }\r
-\r
- // launch the new executable file\r
-\r
- execvp(argv[0],&argv[0]);\r
-\r
- // execvp() only returns when an error has occured\r
-\r
- my_fatal("engine_open(): execvp(): %s\n",strerror(errno));\r
-\r
- } else { // pid > 0\r
-\r
- ASSERT(pid>0);\r
-\r
- // parent = PolyGlot\r
-\r
- // close unused pipe descriptors to avoid deadlocks\r
-\r
- my_close(from_engine[1]);\r
- my_close(to_engine[0]);\r
-\r
- // fill in the engine struct\r
-\r
- engine->io->in_fd = from_engine[0];\r
- engine->io->out_fd = to_engine[1];\r
- engine->io->name = "Engine";\r
- engine->pid=pid;\r
- engine->state|=ENGINE_ACTIVE; // can we test if this really true?\r
-\r
- io_init(engine->io);\r
- }\r
-}\r
-\r
-// engine_active\r
-\r
-bool engine_active(engine_t *engine){\r
- return (engine->state & ENGINE_ACTIVE)!=0;\r
-}\r
-\r
-// engine_eof\r
-\r
-bool engine_eof(engine_t *engine){\r
- return (engine->state & ENGINE_EOF)!=0;\r
-}\r
-\r
-// engine_set_nice_value()\r
-\r
-void engine_set_nice_value(engine_t * engine, int value){\r
- setpriority(PRIO_PROCESS,engine->pid,value);\r
-}\r
-\r
-\r
-// engine_close()\r
-\r
-void engine_close(engine_t * engine) {\r
-\r
- ASSERT(engine_is_ok(engine));\r
-\r
- char string[StringSize];\r
- io_close(engine->io);\r
- // TODO: timeout\r
- while (!engine_eof(engine)) {\r
- engine_get(engine,string,StringSize); \r
- }\r
-\r
-}\r
-\r
-// engine_get_non_blocking()\r
-\r
-bool engine_get_non_blocking(engine_t * engine, char string[], int size){\r
- if(io_line_ready(engine->io)){\r
- engine_get(engine,string,StringSize);\r
- return true;\r
- }else{\r
- string[0]='\0';\r
- return false;\r
- }\r
-}\r
-\r
-// engine_get()\r
-\r
-void engine_get(engine_t * engine, char string[], int size) {\r
-\r
- ASSERT(engine_is_ok(engine));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=256);\r
-\r
- while (!io_line_ready(engine->io)) {\r
- io_get_update(engine->io);\r
- }\r
-\r
- if (!io_get_line(engine->io,string,size)) { // EOF\r
- engine->state|=ENGINE_EOF;\r
- }\r
-}\r
-\r
-// engine_send()\r
-\r
-void engine_send(engine_t * engine, const char format[], ...) {\r
-\r
- va_list arg_list;\r
- char string[StringSize];\r
-\r
- ASSERT(engine_is_ok(engine));\r
- ASSERT(format!=NULL);\r
-\r
- // format\r
-\r
- va_start(arg_list,format);\r
- vsprintf(string,format,arg_list);\r
- va_end(arg_list);\r
-\r
- // send\r
-\r
- io_send(engine->io,"%s",string);\r
-}\r
-\r
-// engine_send_queue()\r
-\r
-void engine_send_queue(engine_t * engine, const char format[], ...) {\r
-\r
- va_list arg_list;\r
- char string[StringSize];\r
-\r
- ASSERT(engine_is_ok(engine));\r
- ASSERT(format!=NULL);\r
-\r
- // format\r
-\r
- va_start(arg_list,format);\r
- vsprintf(string,format,arg_list);\r
- va_end(arg_list);\r
-\r
- // send\r
-\r
- io_send_queue(engine->io,"%s",string);\r
-}\r
-\r
-// my_close()\r
-\r
-static void my_close(int fd) {\r
-\r
- ASSERT(fd>=0);\r
-\r
- if (close(fd) == -1) my_fatal("my_close(): close(): %s\n",strerror(errno));\r
-}\r
-\r
-// my_dup2()\r
-\r
-static void my_dup2(int old_fd, int new_fd) {\r
-\r
- ASSERT(old_fd>=0);\r
- ASSERT(new_fd>=0);\r
-\r
- if (dup2(old_fd,new_fd) == -1) my_fatal("my_dup2(): dup2(): %s\n",strerror(errno));\r
-}\r
-\r
-// end of posix part\r
-#else\r
-\r
-// WIN32 part\r
-\r
-// includes\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <windows.h>\r
-#include <direct.h>\r
-\r
-\r
-\r
-#include "engine.h"\r
-#include "option.h"\r
-#include "pipe.h"\r
-#include "posix.h"\r
-\r
-// constants\r
-\r
-static const int StringSize = 4096;\r
-\r
-// variables\r
-\r
-static int nQueuePtr = 0;\r
-static char szQueueString[StringSize];\r
-engine_t Engine[1];\r
-\r
-// functions\r
-\r
-void set_affinity(engine_t *engine, int affin){\r
- if(affin==-1) return;\r
-\r
- typedef void (WINAPI *SPAM)(HANDLE, int);\r
- SPAM pSPAM;\r
- pSPAM = (SPAM) GetProcAddress(\r
- GetModuleHandle(TEXT("kernel32.dll")), \r
- "SetProcessAffinityMask");\r
- if(NULL != pSPAM){\r
- // [HGM] avoid crash on Win95 by first checking if API call exists\r
- my_log("POLYGLOT Setting process affinity to %d\n",affin);\r
- pSPAM((engine->io).hProcess,affin);\r
- }else{\r
- my_log("POLYGLOT API call \"SetProcessAffinityMask\" not available\n");\r
- }\r
-}\r
-\r
-DWORD GetWin32Priority(int nice)\r
-{\r
-/*\r
-REALTIME_PRIORITY_CLASS 0x00000100\r
-HIGH_PRIORITY_CLASS 0x00000080\r
-ABOVE_NORMAL_PRIORITY_CLASS 0x00008000\r
-NORMAL_PRIORITY_CLASS 0x00000020\r
-BELOW_NORMAL_PRIORITY_CLASS 0x00004000\r
-IDLE_PRIORITY_CLASS 0x00000040\r
-*/\r
- if (nice < -15) return 0x00000080;\r
- if (nice < 0) return 0x00008000;\r
- if (nice == 0) return 0x00000020;\r
- if (nice < 15) return 0x00004000;\r
- return 0x00000040;\r
-}\r
-\r
-void engine_set_nice_value(engine_t *engine, int value){\r
- SetPriorityClass((engine->io).hProcess,\r
- GetWin32Priority(value));\r
-}\r
-\r
-void engine_send_queue(engine_t * engine,const char *szFormat, ...) {\r
- nQueuePtr += vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));\r
-}\r
-\r
-void engine_send(engine_t * engine, const char *szFormat, ...) {\r
- vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));\r
- (engine->io).LineOutput(szQueueString);\r
- my_log("Adapter->Engine: %s\n",szQueueString);\r
- nQueuePtr = 0;\r
-}\r
-\r
-void engine_close(engine_t * engine){\r
- char string[StringSize];\r
- (engine->io).Close();\r
- // TODO: Timeout\r
- while (!engine_eof(engine)) { \r
- engine_get(Engine,string,StringSize);\r
- }\r
- (engine->io).Kill();\r
-}\r
-\r
-void engine_open(engine_t * engine){\r
- int affinity;\r
- char *my_dir;\r
- engine->state=0;\r
- if( (my_dir = _getcwd( NULL, 0 )) == NULL )\r
- my_fatal("Can't build path: %s\n",strerror(errno));\r
- SetCurrentDirectory(option_get_string("EngineDir"));\r
- (engine->io).Open(option_get_string("EngineCommand"));\r
- if((engine->io).Active()){\r
- engine->state|=ENGINE_ACTIVE;\r
- //play with affinity (bad idea)\r
- affinity=option_get_int("Affinity");\r
- if(affinity!=-1) set_affinity(engine,affinity); //AAA\r
- //lets go back\r
- SetCurrentDirectory(my_dir);\r
- // set a low priority\r
- if (option_get_bool("UseNice")){\r
- my_log("POLYGLOT Adjust Engine Piority\n");\r
- engine_set_nice_value(engine, option_get_int("NiceValue"));\r
- }\r
- }\r
- \r
-}\r
-\r
-bool engine_active(engine_t *engine){\r
- return (engine->state & ENGINE_ACTIVE)!=0;\r
-}\r
-\r
-bool engine_eof(engine_t *engine){\r
- return (engine->state & ENGINE_EOF)!=0;\r
-}\r
-\r
-bool engine_get_non_blocking(engine_t * engine, char *szLineStr, int size){\r
- if(engine_eof(engine)){ return false;}\r
- if ((engine->io).GetBuffer(szLineStr)) {\r
- my_log("Engine->Adapter: %s\n",szLineStr);\r
- return true;\r
- } else {\r
- szLineStr[0]='\0';\r
- if(engine->io.EOF_()){\r
- engine->state|=ENGINE_EOF;\r
- my_log("POLYGLOT *** EOF from Engine ***\n");\r
- }\r
- return false;\r
- }\r
-}\r
-\r
-void engine_get(engine_t * engine, char *szLineStr, int size){\r
- (engine->io).LineInput(szLineStr);\r
- if(engine->io.EOF_()){\r
- engine->state|=ENGINE_EOF;\r
- my_log("POLYGLOT *** EOF from Engine ***\n");\r
- }else{\r
- my_log("Engine->Adapter: %s\n",szLineStr);\r
- }\r
-}\r
-\r
-\r
-#endif\r
+++ /dev/null
-\r
-// epd.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "board.h"\r
-#include "engine.h"\r
-#include "epd.h"\r
-#include "fen.h"\r
-#include "line.h"\r
-#include "main.h"\r
-#include "move.h"\r
-#include "move_legal.h"\r
-#include "option.h"\r
-#include "parse.h"\r
-#include "san.h"\r
-#include "uci.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool UseDebug = false;\r
-static const bool UseTrace = false;\r
-\r
-static const int StringSize = 4096;\r
-\r
-// variables\r
-\r
-static int MinDepth;\r
-static int MaxDepth;\r
-\r
-static double MaxTime;\r
-static double MinTime;\r
-\r
-static int DepthDelta;\r
-\r
-static int FirstMove;\r
-static int FirstDepth;\r
-static int FirstSelDepth;\r
-static int FirstScore;\r
-static double FirstTime;\r
-static uint64 FirstNodeNb;\r
-static move_t FirstPV[LineSize];\r
-\r
-static int LastMove;\r
-static int LastDepth;\r
-static int LastSelDepth;\r
-static int LastScore;\r
-static double LastTime;\r
-static uint64 LastNodeNb;\r
-static move_t LastPV[LineSize];\r
-\r
-static my_timer_t Timer[1];\r
-\r
-// prototypes\r
-\r
-static void epd_test_file (const char file_name[]);\r
-\r
-static bool is_solution (int move, const board_t * board, const char bm[], const char am[]);\r
-static bool string_contain (const char string[], const char substring[]);\r
-\r
-static bool engine_step ();\r
-\r
-// functions\r
-\r
-// epd_test()\r
-\r
-void epd_test(int argc, char * argv[]) {\r
-\r
- int i;\r
- const char * epd_file;\r
-\r
- epd_file = NULL;\r
- my_string_set(&epd_file,"wac.epd");\r
-\r
- MinDepth = 8;\r
- MaxDepth = 63;\r
-\r
- MinTime = 1.0;\r
- MaxTime = 5.0;\r
-\r
- DepthDelta = 3;\r
-\r
- for (i = 1; i < argc; i++) {\r
-\r
- if (false) {\r
-\r
- } else if (my_string_equal(argv[i],"epd-test")) {\r
-\r
- // skip\r
-\r
- } else if (my_string_equal(argv[i],"-epd")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
-\r
- my_string_set(&epd_file,argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-min-depth")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
-\r
- MinDepth = atoi(argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-max-depth")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
-\r
- MaxDepth = atoi(argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-min-time")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
-\r
- MinTime = atof(argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-max-time")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
-\r
- MaxTime = atof(argv[i]);\r
-\r
- } else if (my_string_equal(argv[i],"-depth-delta")) {\r
-\r
- i++;\r
- if (argv[i] == NULL) my_fatal("epd_test(): missing argument\n");\r
-\r
- DepthDelta = atoi(argv[i]);\r
-\r
- } else {\r
-\r
- my_fatal("epd_test(): unknown option \"%s\"\n",argv[i]);\r
- }\r
- }\r
-\r
- if(MinTime>MaxTime){\r
- MaxTime=MinTime;\r
- }\r
- \r
- epd_test_file(epd_file);\r
-}\r
-\r
-// epd_test_file()\r
-\r
-static void epd_test_file(const char file_name[]) {\r
-\r
- FILE * file;\r
- int hit, tot;\r
- char epd[StringSize];\r
- char am[StringSize], bm[StringSize], id[StringSize];\r
- board_t board[1];\r
- char string[StringSize];\r
- int move;\r
- char pv_string[StringSize];\r
- bool correct;\r
- double depth_tot, time_tot, node_tot;\r
- int line=0;\r
-\r
- ASSERT(file_name!=NULL);\r
-\r
- // init\r
-\r
- file = fopen(file_name,"r");\r
- if (file == NULL) my_fatal("epd_test_file(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
-\r
- hit = 0;\r
- tot = 0;\r
-\r
- depth_tot = 0.0;\r
- time_tot = 0.0;\r
- node_tot = 0.0;\r
-\r
- printf("\nEngineName=%s\n",option_get_string("EngineName"));\r
-\r
- printf("\n[Search parameters: MaxDepth=%d MaxTime=%.1f DepthDelta=%d MinDepth=%d MinTime=%.1f]\n\n",MaxDepth,MaxTime,DepthDelta,MinDepth,MinTime);\r
-\r
- // loop\r
-\r
- while (my_file_read_line(file,epd,StringSize)) {\r
- line++;\r
- if(my_string_whitespace(epd)) continue;\r
- if (UseTrace) printf("%s\n",epd);\r
-\r
- if (!epd_get_op(epd,"am",am,StringSize)) strcpy(am,"");\r
- if (!epd_get_op(epd,"bm",bm,StringSize)) strcpy(bm,"");\r
- if (!epd_get_op(epd,"id",id,StringSize)) strcpy(id,"");\r
-\r
- if (my_string_empty(am) && my_string_empty(bm)) {\r
- my_fatal("epd_test(): no am or bm field at line %d\n",line);\r
- }\r
-\r
- // init\r
-\r
- uci_send_ucinewgame(Uci);\r
- uci_send_isready_sync(Uci);\r
-\r
- ASSERT(!Uci->searching);\r
-\r
- // position\r
- if (!board_from_fen(board,epd)) ASSERT(false);\r
- if (!board_to_fen(board,string,StringSize)) ASSERT(false);\r
-\r
- engine_send(Engine,"position fen %s",string);\r
-\r
- // search\r
-\r
- my_timer_start(Timer); // also resets\r
- \r
- // which ones of the next two alternatives is best?\r
- engine_send(Engine,"go movetime %.0f depth %d",MaxTime*1000.0,MaxDepth);\r
- //engine_send(Engine,"go infinite");\r
-\r
- // engine data\r
-\r
- board_copy(Uci->board,board);\r
-\r
- uci_clear(Uci);\r
- Uci->searching = true;\r
- Uci->pending_nb++;\r
-\r
- FirstMove = MoveNone;\r
- FirstDepth = 0;\r
- FirstSelDepth = 0;\r
- FirstScore = 0;\r
- FirstTime = 0.0;\r
- FirstNodeNb = 0;\r
- line_clear(FirstPV);\r
-\r
- LastMove = MoveNone;\r
- LastDepth = 0;\r
- LastSelDepth = 0;\r
- LastScore = 0;\r
- LastTime = 0.0;\r
- LastNodeNb = 0;\r
- line_clear(LastPV);\r
-\r
- // parse engine output\r
-\r
- while (!engine_eof(Engine) && engine_step()) {\r
- bool stop=false;\r
-\r
- // stop search?\r
-// printf("Uci->time=%.2f time=%.2f\n",Uci->time,my_timer_elapsed_real(Timer));\r
- if (Uci->depth > MaxDepth){\r
- my_log("POLYGLOT Maximum depth %d reached\n",MaxDepth);\r
- stop=true;\r
- }else if(my_timer_elapsed_real(Timer) >= MaxTime){\r
- my_log("POLYGLOT Maximum search time %.2fs reached\n",MaxTime);\r
- stop=true;\r
- }else if(Uci->depth - FirstDepth >= DepthDelta){\r
- if(Uci->depth > MinDepth){\r
- if(Uci->time >= MinTime){\r
- if(is_solution(FirstMove,board,bm,am)){\r
- my_log("POLYGLOT Solution found\n",MaxTime);\r
- stop=true;\r
- }\r
- }\r
- }\r
- }\r
- if(stop){\r
- my_log("POLYGLOT Stopping engine\n");\r
- engine_send(Engine,"stop");\r
- break;\r
- }\r
- }\r
- \r
- move = FirstMove;\r
- correct = is_solution(move,board,bm,am);\r
-\r
- if (correct) hit++;\r
- tot++;\r
-\r
- if (correct) {\r
- depth_tot += double(FirstDepth);\r
- time_tot += FirstTime;\r
- node_tot += double(sint64(FirstNodeNb));\r
- }\r
-\r
- printf("%2d: %-15s %s %4d",tot,id,correct?"OK":"--",hit);\r
-\r
- if (!line_to_san(LastPV,Uci->board,pv_string,StringSize)) ASSERT(false);\r
- printf(" score=%+6.2f pv [D=%2d, T=%7.2fs, N=%6dk] =%s\n",double(LastScore)/100.0,FirstDepth,FirstTime,(int)FirstNodeNb/1000,pv_string);\r
- }\r
-\r
- printf("\nscore=%d/%d",hit,tot);\r
-\r
- if (hit != 0) {\r
-\r
- depth_tot /= double(hit);\r
- time_tot /= double(hit);\r
- node_tot /= double(hit);\r
-\r
- printf(" [averages on correct positions: depth=%.1f time=%.2f nodes=%.0f]",depth_tot,time_tot,node_tot);\r
- }\r
-\r
- printf("\n");\r
-\r
- fclose(file);\r
- quit();\r
-}\r
-\r
-// is_solution()\r
-\r
-static bool is_solution(int move, const board_t * board, const char bm[], const char am[]) {\r
-\r
- char move_string[256];\r
- bool correct;\r
-\r
- ASSERT(move!=MoveNone);\r
- ASSERT(bm!=NULL);\r
- ASSERT(am!=NULL);\r
-\r
- if (!move_is_legal(move,board)) {\r
- board_disp(board);\r
- move_disp(move,board);\r
- printf("\n\n");\r
- }\r
-\r
- ASSERT(move_is_legal(move,board));\r
-\r
- if (!move_to_san(move,board,move_string,256)) ASSERT(false);\r
-\r
- correct = false;\r
- if (!my_string_empty(bm)) {\r
- correct = string_contain(bm,move_string);\r
- } else if (!my_string_empty(am)) {\r
- correct = !string_contain(am,move_string);\r
- } else {\r
- ASSERT(false);\r
- }\r
-\r
- return correct;\r
-}\r
-\r
-// epd_get_op()\r
-\r
-bool epd_get_op(const char record[], const char opcode[], char string[], int size) {\r
-\r
- char op[256];\r
- int len;\r
- const char *p_start, *p_end;\r
-\r
- ASSERT(record!=NULL);\r
- ASSERT(opcode!=NULL);\r
- ASSERT(string!=NULL);\r
- ASSERT(size>0);\r
-\r
- // find the opcode\r
-\r
- sprintf(op," %s ",opcode); \r
-\r
- p_start = strstr(record,op);\r
- if (p_start == NULL){\r
- sprintf(op,";%s ",opcode); \r
- p_start = strstr(record,op);\r
- if (p_start == NULL){\r
- return false;\r
- }\r
- }\r
-\r
- // skip the opcode\r
-\r
- p_start += strlen(op);\r
-\r
- // find the end\r
- p_end = strchr(p_start,';');\r
- if (p_end == NULL) return false;\r
-\r
- // calculate the length\r
-\r
- len = p_end - p_start;\r
- if (size < len+1) my_fatal("epd_get_op(): size < len+1\n");\r
-\r
- strncpy(string,p_start,len);\r
- string[len] = '\0';\r
-\r
- return true;\r
-}\r
-\r
-// string_contain()\r
-\r
-static bool string_contain(const char string[], const char substring[]) {\r
-\r
- char new_string[StringSize], *p;\r
-\r
- strcpy(new_string,string); // HACK\r
-\r
- for (p = strtok(new_string," "); p != NULL; p = strtok(NULL," ")) {\r
- if (my_string_equal(p,substring)) return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-// engine_step()\r
-\r
-static bool engine_step() {\r
-\r
- char string[StringSize];\r
- int event;\r
-\r
- engine_get(Engine,string,StringSize);\r
- event = uci_parse(Uci,string);\r
-\r
- if ((event & EVENT_MOVE) != 0) {\r
-\r
- return false;\r
- }\r
-\r
- if ((event & EVENT_PV) != 0) {\r
-\r
- LastMove = Uci->best_pv[0];\r
- LastDepth = Uci->best_depth;\r
- LastSelDepth = Uci->best_sel_depth;\r
- LastScore = Uci->best_score;\r
- LastTime = Uci->time;\r
- LastNodeNb = Uci->node_nb;\r
- line_copy(LastPV,Uci->best_pv);\r
-\r
- if (LastMove != FirstMove) {\r
- FirstMove = LastMove;\r
- FirstDepth = LastDepth;\r
- FirstSelDepth = LastSelDepth;\r
- FirstScore = LastScore;\r
- FirstTime = LastTime;\r
- FirstNodeNb = LastNodeNb;\r
- line_copy(FirstPV,LastPV);\r
- }\r
- }\r
-\r
- return true;\r
-}\r
-\r
-// end of epd.cpp\r
-\r
+++ /dev/null
-\r
-// fen.cpp\r
-\r
-// includes\r
-\r
-#include <cctype>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-\r
-#include "board.h"\r
-#include "colour.h"\r
-#include "fen.h"\r
-#include "option.h"\r
-#include "piece.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// "constants"\r
-\r
-// const char * StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w HAha - 0 1";\r
-const char * StartFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";\r
-\r
-// variables\r
-\r
-static const bool Strict = false;\r
-\r
-// macros\r
-\r
-#define skip_white_space() \\r
- c=string[pos];\\r
- if (c != ' ' && c!='\t') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos); \\r
- while(c==' ' || c=='\t') c=string[++pos];\r
-\r
-\r
-// functions\r
-\r
-// board_from_fen()\r
-\r
-bool board_from_fen(board_t * board, const char string[]) {\r
-\r
- int pos;\r
- int file, rank, sq;\r
- int c;\r
- int i, len;\r
- int piece;\r
- int king_pos[ColourNb];\r
-\r
- ASSERT(board!=NULL);\r
- ASSERT(string!=NULL);\r
-\r
- board_clear(board);\r
-\r
- king_pos[White] = SquareNone;\r
- king_pos[Black] = SquareNone;\r
-\r
- pos = 0;\r
- c = string[pos];\r
-\r
- // piece placement\r
-\r
- for (rank = 7; rank >= 0; rank--) {\r
-\r
- for (file = 0; file < 8;) {\r
-\r
- sq = square_make(file,rank);\r
-\r
- if (c >= '1' && c <= '8') { // empty square(s)\r
-\r
- len = c - '0';\r
- if (file + len > 8) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-\r
- for (i = 0; i < len; i++) {\r
- board->square[sq++] = Empty;\r
- file++;\r
- }\r
-\r
- } else { // piece\r
-\r
- piece = piece_from_char(c);\r
- if (piece == PieceNone256) my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
-\r
- if (piece_is_king(piece)) king_pos[piece_colour(piece)] = sq;\r
-\r
- board->square[sq++] = piece;\r
- file++;\r
- }\r
-\r
- c = string[++pos];\r
- }\r
-\r
- if (rank > 0) {\r
- if (c != '/') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- c = string[++pos];\r
- }\r
- }\r
-\r
- // active colour\r
-\r
- skip_white_space();\r
-\r
- switch (c) {\r
- case 'w':\r
- board->turn = White;\r
- break;\r
- case 'b':\r
- board->turn = Black;\r
- break;\r
- default:\r
- my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- break;\r
- }\r
-\r
- c = string[++pos];\r
-\r
- // castling\r
-\r
- skip_white_space();\r
-\r
- board->castle[White][SideH] = SquareNone;\r
- board->castle[White][SideA] = SquareNone;\r
- board->castle[Black][SideH] = SquareNone;\r
- board->castle[Black][SideA] = SquareNone;\r
-\r
- if (c == '-') { // no castling rights\r
-\r
- c = string[++pos];\r
-\r
- } else {\r
-\r
- // TODO: filter out illegal rights\r
-\r
- do {\r
-\r
- if (false) {\r
-\r
- } else if (c == 'K') {\r
-\r
- for (sq = H1; sq > king_pos[White]; sq--) {\r
- if (board->square[sq] == WhiteRook256) {\r
- board->castle[White][SideH] = sq;\r
- break;\r
- }\r
- }\r
-\r
- } else if (c == 'Q') {\r
-\r
- for (sq = A1; sq < king_pos[White]; sq++) {\r
- if (board->square[sq] == WhiteRook256) {\r
- board->castle[White][SideA] = sq;\r
- break;\r
- }\r
- }\r
-\r
- } else if (c == 'k') {\r
-\r
- for (sq = H8; sq > king_pos[Black]; sq--) {\r
- if (board->square[sq] == BlackRook256) {\r
- board->castle[Black][SideH] = sq;\r
- break;\r
- }\r
- }\r
-\r
- } else if (c == 'q') {\r
-\r
- for (sq = A8; sq < king_pos[Black]; sq++) {\r
- if (board->square[sq] == BlackRook256) {\r
- board->castle[Black][SideA] = sq;\r
- break;\r
- }\r
- }\r
-\r
- } else if (c >= 'A' && c <= 'H') {\r
-\r
- // white castling right\r
-\r
- sq = square_make(file_from_char(tolower(c)),Rank1);\r
-\r
- if (sq > king_pos[White]) { // h side\r
- board->castle[White][SideH] = sq;\r
- } else { // a side\r
- board->castle[White][SideA] = sq;\r
- }\r
-\r
- } else if (c >= 'a' && c <= 'h') {\r
-\r
- // black castling right\r
-\r
- sq = square_make(file_from_char(tolower(c)),Rank8);\r
-\r
- if (sq > king_pos[Black]) { // h side\r
- board->castle[Black][SideH] = sq;\r
- } else { // a side\r
- board->castle[Black][SideA] = sq;\r
- }\r
-\r
- } else {\r
-\r
- my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- }\r
-\r
- c = string[++pos];\r
-\r
- } while (c != ' ');\r
- }\r
-\r
- // en-passant\r
-\r
- skip_white_space();\r
-\r
- if (c == '-') { // no en-passant\r
-\r
- sq = SquareNone;\r
- c = string[++pos];\r
-\r
- } else {\r
-\r
- if (c < 'a' || c > 'h') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- file = file_from_char(c);\r
- c = string[++pos];\r
-\r
- if (c < '1' || c > '8') my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- rank = rank_from_char(c);\r
- c = string[++pos];\r
-\r
- sq = square_make(file,rank);\r
- }\r
-\r
- board->ep_square = sq;\r
-\r
- // halfmove clock\r
-\r
- board->ply_nb = 0;\r
- board->move_nb = 0; // HACK, in case of broken syntax\r
-\r
- if (c != ' ') {\r
- if (!Strict) goto update;\r
- my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- }\r
- c = string[++pos];\r
-\r
- if (!isdigit(c)) {\r
- if (!Strict) goto update;\r
- my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- }\r
-\r
- board->ply_nb = atoi(&string[pos]);\r
- do c = string[++pos]; while (isdigit(c));\r
-\r
- // fullmove number\r
-\r
- board->move_nb = 0;\r
-\r
- if (c != ' ') {\r
- if (!Strict) goto update;\r
- my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- }\r
- c = string[++pos];\r
-\r
- if (!isdigit(c)) {\r
- if (!Strict) goto update;\r
- my_fatal("board_from_fen(): bad FEN (pos=%d)\n",pos);\r
- }\r
-\r
- board->move_nb = atoi(&string[pos]) - 1;\r
- do c = string[++pos]; while (isdigit(c));\r
-\r
- // board update\r
-\r
-update:\r
- board_init_list(board);\r
-\r
- return true;\r
-}\r
-\r
-// board_to_fen()\r
-\r
-bool board_to_fen(const board_t * board, char string[], int size) {\r
-\r
- int pos;\r
- int file, rank;\r
- int sq, piece;\r
- int c;\r
- int len;\r
- int old_pos;\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=92);\r
-\r
- // init\r
-\r
- if (size < 92) return false;\r
-\r
- pos = 0;\r
-\r
- // piece placement\r
-\r
- for (rank = 7; rank >= 0; rank--) {\r
-\r
- for (file = 0; file < 8;) {\r
-\r
- sq = square_make(file,rank);\r
- piece = board->square[sq];\r
- ASSERT(piece==Empty||piece_is_ok(piece));\r
-\r
- if (piece == Empty) {\r
-\r
- len = 0;\r
- for (; file < 8 && board->square[square_make(file,rank)] == Empty; file++) {\r
- len++;\r
- }\r
-\r
- ASSERT(len>=1&&len<=8);\r
- c = '0' + len;\r
-\r
- } else {\r
-\r
- c = piece_to_char(piece);\r
- file++;\r
- }\r
-\r
- string[pos++] = c;\r
- }\r
-\r
- string[pos++] = '/';\r
- }\r
-\r
- string[pos-1] = ' '; // HACK: remove the last '/'\r
-\r
- // active colour\r
-\r
- string[pos++] = (colour_is_white(board->turn)) ? 'w' : 'b';\r
- string[pos++] = ' ';\r
-\r
- // castling\r
-\r
- old_pos = pos;\r
-\r
- if (option_get_bool("Chess960")) {\r
-\r
- // FEN-960\r
-\r
- if (board->castle[White][SideH] != SquareNone) {\r
- string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideH])));\r
- }\r
-\r
- if (board->castle[White][SideA] != SquareNone) {\r
- string[pos++] = toupper(file_to_char(square_file(board->castle[White][SideA])));\r
- }\r
-\r
- if (board->castle[Black][SideH] != SquareNone) {\r
- string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideH])));\r
- }\r
-\r
- if (board->castle[Black][SideA] != SquareNone) {\r
- string[pos++] = tolower(file_to_char(square_file(board->castle[Black][SideA])));\r
- }\r
-\r
- } else {\r
-\r
- // FEN\r
-\r
- if (board->castle[White][SideH] != SquareNone) string[pos++] = 'K';\r
- if (board->castle[White][SideA] != SquareNone) string[pos++] = 'Q';\r
- if (board->castle[Black][SideH] != SquareNone) string[pos++] = 'k';\r
- if (board->castle[Black][SideA] != SquareNone) string[pos++] = 'q';\r
- }\r
-\r
- if (pos == old_pos) string[pos++] = '-';\r
-\r
- string[pos++] = ' ';\r
-\r
- // en-passant\r
-\r
- if (board->ep_square == SquareNone) {\r
- string[pos++] = '-';\r
- } else {\r
- if (!square_to_string(board->ep_square,&string[pos],3)) return false;\r
- pos += 2;\r
- }\r
-\r
- string[pos++] = ' ';\r
-\r
- // halfmove clock and fullmove number\r
-\r
- sprintf(&string[pos],"%d %d",board->ply_nb,board->move_nb+1);\r
-\r
- return true;\r
-}\r
-\r
-// end of fen.cpp\r
-\r
+++ /dev/null
-\r
-// game.cpp\r
-\r
-// includes\r
-\r
-#include "attack.h"\r
-#include "board.h"\r
-#include "fen.h"\r
-#include "game.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_legal.h"\r
-#include "piece.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool UseSlowDebug = false;\r
-\r
-// variables\r
-\r
-game_t Game[1];\r
-\r
-// prototypes\r
-\r
-static void game_update (game_t * game);\r
-static int game_comp_status (const game_t * game);\r
-\r
-// functions\r
-\r
-// game_is_ok()\r
-\r
-bool game_is_ok(const game_t * game) {\r
-\r
- board_t board[1];\r
- int pos, move;\r
-\r
- if (game == NULL) return false;\r
-\r
- if (game->size < 0 || game->size > GameSize) return false;\r
- if (game->pos < 0 || game->pos > game->size) return false;\r
-\r
- // optional heavy DEBUG mode\r
-\r
- if (!UseSlowDebug) return true;\r
-\r
- if (!board_is_ok(game->start_board)) return false;\r
-\r
- board_copy(board,game->start_board);\r
-\r
- for (pos = 0; pos <= game->size; pos++) {\r
-\r
- if (pos == game->pos) {\r
- if (!board_equal(game->board,board)) return false;\r
- }\r
-\r
- if (pos >= game->size) break;\r
-\r
- if (game->key[pos] != board->key) return false;\r
-\r
- move = game->move[pos];\r
- //if (!move_is_legal(move,board)); //huh??\r
- if (!move_is_legal(move,board)) return false; \r
-\r
- move_do(board,move);\r
- }\r
-\r
- if (game->status != game_comp_status(game)) return false;\r
-\r
- return true;\r
-}\r
-\r
-// game_clear()\r
-\r
-void game_clear(game_t * game) {\r
-\r
- ASSERT(game!=NULL);\r
-\r
- game_init(game,StartFen);\r
-}\r
-\r
-// game_init()\r
-\r
-bool game_init(game_t * game, const char fen[]) {\r
-\r
- ASSERT(game!=NULL);\r
- ASSERT(fen!=NULL);\r
-\r
- if (!board_from_fen(game->start_board,fen)) return false;\r
-\r
- game->size = 0;\r
-\r
- board_copy(game->board,game->start_board);\r
- game->pos = 0;\r
-\r
- game_update(game);\r
-\r
- return true;\r
-}\r
-\r
-// game_status()\r
-\r
-int game_status(const game_t * game) {\r
-\r
- ASSERT(game!=NULL);\r
-\r
- return game->status;\r
-}\r
-\r
-// game_size()\r
-\r
-int game_size(const game_t * game) {\r
-\r
- ASSERT(game!=NULL);\r
-\r
- return game->size;\r
-}\r
-\r
-// game_pos()\r
-\r
-int game_pos(const game_t * game) {\r
-\r
- ASSERT(game!=NULL);\r
-\r
- return game->pos;\r
-}\r
-\r
-// game_move()\r
-\r
-int game_move(const game_t * game, int pos) {\r
-\r
- ASSERT(game!=NULL);\r
- ASSERT(pos>=0&&pos<game->pos);\r
-\r
- return game->move[pos];\r
-}\r
-\r
-// game_get_board()\r
-\r
-void game_get_board(const game_t * game, board_t * board, int pos) {\r
-\r
- int start;\r
- int i;\r
-\r
- ASSERT(game!=NULL);\r
- ASSERT(board!=NULL);\r
- ASSERT(pos==-1||(pos>=0&&pos<=game->size)); // HACK\r
-\r
- if (pos < 0) pos = game->pos;\r
-\r
- if (pos >= game->pos) { // forward from current position\r
- start = game->pos;\r
- board_copy(board,game->board);\r
- } else { // backward => replay the whole game\r
- start = 0;\r
- board_copy(board,game->start_board);\r
- }\r
-\r
- for (i = start; i < pos; i++) move_do(board,game->move[i]);\r
-}\r
-\r
-// game_turn()\r
-\r
-int game_turn(const game_t * game) {\r
-\r
- ASSERT(game!=NULL);\r
-\r
- return game->board->turn;\r
-}\r
-\r
-// game_move_nb()\r
-\r
-int game_move_nb(const game_t * game) {\r
-\r
- ASSERT(game!=NULL);\r
-\r
- return game->board->move_nb;\r
-}\r
-\r
-// game_add_move()\r
-\r
-void game_add_move(game_t * game, int move) {\r
-\r
- ASSERT(game!=NULL);\r
- ASSERT(move_is_ok(move));\r
-\r
- ASSERT(move_is_legal(move,game->board));\r
-\r
- if (game->pos >= GameSize) my_fatal("game_add_move(): game overflow\n");\r
-\r
- game->move[game->pos] = move;\r
- game->key[game->pos] = game->board->key;\r
-\r
- move_do(game->board,move);\r
- game->pos++;\r
-\r
- game->size = game->pos; // truncate game, HACK: before calling game_is_ok() in game_update()\r
-\r
- game_update(game);\r
-}\r
-\r
-// game_rem_move()\r
-\r
-void game_rem_move(game_t * game) {\r
-\r
- ASSERT(game!=NULL);\r
-\r
- game_goto(game,game->pos-1);\r
-\r
- game->size = game->pos; // truncate game\r
-}\r
-\r
-// game_goto()\r
-\r
-void game_goto(game_t * game, int pos) {\r
-\r
- int i;\r
-\r
- ASSERT(game!=NULL);\r
- ASSERT(pos>=0&&pos<=game->size);\r
-\r
- if (pos < game->pos) { // going backward => replay the whole game\r
- board_copy(game->board,game->start_board);\r
- game->pos = 0;\r
- }\r
-\r
- for (i = game->pos; i < pos; i++) move_do(game->board,game->move[i]);\r
- ASSERT(i==pos);\r
-\r
- game->pos = pos;\r
-\r
- game_update(game);\r
-}\r
-\r
-// game_disp()\r
-\r
-void game_disp(const game_t * game) {\r
-\r
- board_t board[1];\r
- int i, move;\r
-\r
- ASSERT(game_is_ok(game));\r
-\r
- board_copy(board,game->start_board);\r
-\r
- board_disp(board);\r
-\r
- for (i = 0; i < game->pos; i++) {\r
-\r
- move = game->move[i];\r
- move_disp(move,board);\r
-\r
- move_do(board,move);\r
- }\r
-\r
- my_log("POLYGLOT\n");\r
-\r
- board_disp(board);\r
-}\r
-\r
-// game_update()\r
-\r
-static void game_update(game_t * game) {\r
-\r
- ASSERT(game!=NULL);\r
-\r
- game->status = game_comp_status(game);\r
-\r
- ASSERT(game_is_ok(game));\r
-}\r
-\r
-// game_comp_status()\r
-\r
-static int game_comp_status(const game_t * game) {\r
-\r
- int i, n;\r
- int wb, bb;\r
- const board_t * board;\r
- uint64 key;\r
- int start;\r
-\r
- ASSERT(game!=NULL);\r
-\r
- // init\r
-\r
- board = game->board;\r
-\r
- // mate and stalemate\r
-\r
- if (!board_can_play(board)) {\r
- if (false) {\r
- } else if (is_in_check(board,Black)) { // HACK\r
- return WHITE_MATES;\r
- } else if (is_in_check(board,White)) { // HACK\r
- return BLACK_MATES;\r
- } else {\r
- return STALEMATE;\r
- }\r
- }\r
-\r
- // insufficient material\r
-\r
- if (board->number[WhitePawn12] == 0\r
- && board->number[BlackPawn12] == 0\r
- && board->number[WhiteQueen12] == 0\r
- && board->number[BlackQueen12] == 0\r
- && board->number[WhiteRook12] == 0\r
- && board->number[BlackRook12] == 0) {\r
-\r
- if (board->number[WhiteBishop12]\r
- + board->number[BlackBishop12]\r
- + board->number[WhiteKnight12]\r
- + board->number[BlackKnight12] <= 1) { // KK, KBK and KNK\r
-\r
- return DRAW_MATERIAL;\r
-\r
- } else if (board->number[WhiteBishop12] == 1\r
- && board->number[BlackBishop12] == 1\r
- && board->number[WhiteKnight12] == 0\r
- && board->number[BlackKnight12] == 0) {\r
-\r
- wb = board->list[White][1]; // HACK\r
- bb = board->list[Black][1]; // HACK\r
-\r
- if (square_colour(wb) == square_colour(bb)) { // KBKB\r
- return DRAW_MATERIAL;\r
- }\r
- }\r
- }\r
-\r
- // 50-move rule\r
-\r
- if (board->ply_nb >= 100) return DRAW_FIFTY;\r
-\r
- // position repetition\r
-\r
- key = board->key;\r
- n = 0;\r
-\r
- start = game->pos - board->ply_nb;\r
- if (start < 0) start = 0;\r
-\r
- for (i = game->pos-4; i >= start; i -= 2) {\r
- if (game->key[i] == key) {\r
- if (++n == 2) return DRAW_REPETITION;\r
- }\r
- }\r
-\r
- return PLAYING;\r
-}\r
-\r
-// end of game.cpp\r
-\r
+++ /dev/null
-// gui.cpp
-
-// includes
-
-#include <cstdarg>
-#include <csignal>
-
-#include "gui.h"
-#include "main.h"
-
-// constants
-
-static const int StringSize = 4096;
-
-// variables
-
-gui_t GUI[1];
-
-// functions
-
-// sig_quit()
-
-static void sig_quit(int dummy){
- my_log("POLYGLOT *** SIGINT Received ***\n");
- quit();
-}
-
-
-// gui_init()
-
-void gui_init(gui_t *gui){
-
-// the following is nice if the "GUI" is a console!
- signal(SIGINT,sig_quit);
-#ifdef _WIN32
- signal(SIGTERM,SIG_IGN);
-#ifdef SIGPIPE
- signal(SIGPIPE,SIG_IGN);
-#endif
-#endif
-
-#ifdef _WIN32
- (gui->io).Open();
-#else
-
- gui->io->in_fd = STDIN_FILENO;
- gui->io->out_fd = STDOUT_FILENO;
- gui->io->name = "GUI";
-
- io_init(gui->io);
-#endif
-}
-
-
-// gui_get_non_blocking()
-
-bool gui_get_non_blocking(gui_t * gui, char string[], int size) {
-
- ASSERT(gui!=NULL);
- ASSERT(string!=NULL);
- ASSERT(size>=256);
-#ifndef _WIN32
- if(io_line_ready(gui->io)){
- gui_get(GUI,string,StringSize);
- return true;
- }else{
- string[0]='\0';
- return false;
- }
-#else
- if((gui->io).EOF_()){
- my_log("POLYGLOT *** EOF from GUI ***\n");
- quit();
- return true; // we never get here
- }else if ((gui->io).GetBuffer(string)) {
- my_log("GUI->Adapter: %s\n", string);
- return true;
- } else {
- string[0]='\0';
- return false;
- }
-#endif
-}
-
-// gui_get()
-
-void gui_get(gui_t * gui, char string[], int size) {
- bool data_available;
-#ifdef _WIN32
- if((gui->io).EOF_()){
- my_log("POLYGLOT *** EOF from GUI ***\n");
- quit();
- }
- (gui->io).LineInput(string);
- my_log("GUI->Adapter: %s\n", string);
-#else
- if (!io_get_line(gui->io,string,size)) { // EOF
- my_log("POLYGLOT *** EOF from GUI ***\n");
- quit();
- }
-#endif
-}
-
-
-// gui_send()
-
-void gui_send(gui_t * gui, const char format[], ...) {
-
- va_list arg_list;
- char string[StringSize];
-
- ASSERT(gui!=NULL);
- ASSERT(format!=NULL);
-
- // format
-
- va_start(arg_list,format);
- vsprintf(string,format,arg_list);
- va_end(arg_list);
-
- // send
-
-#ifndef _WIN32
- io_send(gui->io,"%s",string);
-#else
- gui->io.LineOutput(string);
- my_log("Adapter->GUI: %s\n",string);
-#endif
-}
-
+++ /dev/null
-\r
-// hash.cpp\r
-\r
-// includes\r
-\r
-#include "board.h"\r
-#include "hash.h"\r
-#include "piece.h"\r
-#include "random.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// variables\r
-\r
-static uint64 Castle64[16];\r
-\r
-// prototypes\r
-\r
-static uint64 hash_castle_key_debug (int flags);\r
-\r
-// functions\r
-\r
-// hash_init()\r
-\r
-void hash_init() {\r
-\r
- int i;\r
-\r
- for (i = 0; i < 16; i++) Castle64[i] = hash_castle_key_debug(i);\r
-}\r
-\r
-// hash_key()\r
-\r
-uint64 hash_key(const board_t * board) {\r
-\r
- uint64 key;\r
- int colour;\r
- const uint8 * ptr;\r
- int sq, piece;\r
-\r
- ASSERT(board_is_ok(board));\r
-\r
- // init\r
-\r
- key = 0;\r
-\r
- // pieces\r
-\r
- for (colour = 1; colour <= 2; colour++) { // HACK\r
- for (ptr = board->list[colour]; (sq=*ptr) != SquareNone; ptr++) {\r
- piece = board->square[sq];\r
- key ^= hash_piece_key(piece,sq);\r
- }\r
- }\r
-\r
- // castle flags\r
-\r
- key ^= hash_castle_key(board_flags(board));\r
-\r
- // en-passant square\r
-\r
- sq = board->ep_square;\r
- if (sq != SquareNone) key ^= hash_ep_key(sq);\r
-\r
- // turn\r
-\r
- key ^= hash_turn_key(board->turn);\r
-\r
- return key;\r
-}\r
-\r
-// hash_piece_key()\r
-\r
-uint64 hash_piece_key(int piece, int square) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
- ASSERT(square_is_ok(square));\r
-\r
- return random_64(RandomPiece+piece_to_12(piece)*64+square_to_64(square));\r
-}\r
-\r
-// hash_castle_key()\r
-\r
-uint64 hash_castle_key(int flags) {\r
-\r
- ASSERT((flags&~0xF)==0);\r
-\r
- return Castle64[flags];\r
-}\r
-\r
-// hash_castle_key_debug()\r
-\r
-static uint64 hash_castle_key_debug(int flags) {\r
-\r
- uint64 key;\r
- int i;\r
-\r
- ASSERT((flags&~0xF)==0);\r
-\r
- key = 0;\r
-\r
- for (i = 0; i < 4; i++) {\r
- if ((flags & (1<<i)) != 0) key ^= random_64(RandomCastle+i);\r
- }\r
-\r
- return key;\r
-}\r
-\r
-// hash_ep_key()\r
-\r
-uint64 hash_ep_key(int square) {\r
-\r
- ASSERT(square_is_ok(square));\r
-\r
- return random_64(RandomEnPassant+square_file(square));\r
-}\r
-\r
-// hash_turn_key()\r
-\r
-uint64 hash_turn_key(int colour) {\r
-\r
- ASSERT(colour_is_ok(colour));\r
-\r
- return (colour_is_white(colour)) ? random_64(RandomTurn) : 0;\r
-}\r
-\r
-// end of hash.cpp\r
-\r
+++ /dev/null
-#ifndef _WIN32
-
-// io.cpp
-
-// includes
-
-#include <cerrno>
-#include <cstdarg>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "io.h"
-#include "util.h"
-
-// constants
-
-static const bool UseDebug = false;
-static const bool UseCR = false;
-
-static const int StringSize = 4096;
-
-static const char LF = '\n';
-static const char CR = '\r';
-
-// prototypes
-
-static int my_read (int fd, char string[], int size);
-static void my_write (int fd, const char string[], int size);
-
-// functions
-
-// io_is_ok()
-
-bool io_is_ok(const io_t * io) {
-
- if (io == NULL) return false;
-
- if (io->name == NULL) return false;
-
- if (io->in_eof != true && io->in_eof != false) return false;
-
- if (io->in_size < 0 || io->in_size > BufferSize) return false;
- if (io->out_size < 0 || io->out_size > BufferSize) return false;
-
- return true;
-}
-
-// io_init()
-
-void io_init(io_t * io) {
-
- ASSERT(io!=NULL);
-
- io->in_eof = false;
-
- io->in_size = 0;
- io->out_size = 0;
-
- ASSERT(io_is_ok(io));
-}
-
-// io_close()
-
-void io_close(io_t * io) {
-
- ASSERT(io_is_ok(io));
-
- ASSERT(io->out_fd>=0);
-
- my_log("Adapter>Engine: EOF\n",io->name);
-
- if (close(io->out_fd) == -1) {
- my_fatal("io_close(): close(): %s\n",strerror(errno));
- }
-
- io->out_fd = -1;
-}
-
-// io_get_update()
-
-void io_get_update(io_t * io) {
-
- int pos, size;
- int n;
-
- ASSERT(io_is_ok(io));
-
- ASSERT(io->in_fd>=0);
- ASSERT(!io->in_eof);
-
- // init
-
- pos = io->in_size;
-
- size = BufferSize - pos;
- if (size <= 0) my_fatal("io_get_update(): buffer overflow\n");
-
- // read as many data as possible
- n = my_read(io->in_fd,&io->in_buffer[pos],size);
- if (UseDebug) my_log("POLYGLOT read %d byte%s from %s\n",n,(n>1)?"s":"",io->name);
-
- if (n > 0) { // at least one character was read
-
- // update buffer size
-
- ASSERT(n>=1&&n<=size);
-
- io->in_size += n;
- ASSERT(io->in_size>=0&&io->in_size<=BufferSize);
-
- } else { // EOF
-
- ASSERT(n==0);
-
- io->in_eof = true;
- }
-}
-
-// io_line_ready()
-
-bool io_line_ready(const io_t * io) {
-
- ASSERT(io_is_ok(io));
-
- if (io->in_eof) return true;
-
- if (memchr(io->in_buffer,LF,io->in_size) != NULL) return true; // buffer contains LF
-
- return false;
-}
-
-// io_get_line()
-
-bool io_get_line(io_t * io, char string[], int size) {
-
- int src, dst;
- int c;
-
- ASSERT(io_is_ok(io));
- ASSERT(string!=NULL);
- ASSERT(size>=256);
-
- src = 0;
- dst = 0;
-
- while (true) {
-
- // test for end of buffer
-
- if (src >= io->in_size) {
- if (io->in_eof) {
- my_log("%s->Adapter: EOF\n",io->name);
- return false;
- } else {
- my_fatal("io_get_line(): no EOL in buffer\n");
- }
- }
-
- // test for end of string
-
- if (dst >= size) my_fatal("io_get_line(): buffer overflow\n");
-
- // copy the next character
-
- c = io->in_buffer[src++];
-
- if (c == LF) { // LF => line complete
- string[dst] = '\0';
- break;
- } else if (c != CR) { // skip CRs
- string[dst++] = c;
- }
- }
-
- // shift the buffer
-
- ASSERT(src>0);
-
- io->in_size -= src;
- ASSERT(io->in_size>=0);
-
- if (io->in_size > 0) memmove(&io->in_buffer[0],&io->in_buffer[src],io->in_size);
-
- // return
-
- my_log("%s->Adapter: %s\n",io->name,string);
-
- return true;
-}
-
-// io_send()
-
-void io_send(io_t * io, const char format[], ...) {
-
- va_list arg_list;
- char string[StringSize];
- int len;
-
- ASSERT(io_is_ok(io));
- ASSERT(format!=NULL);
-
- ASSERT(io->out_fd>=0);
-
- // format
-
- va_start(arg_list,format);
- vsprintf(string,format,arg_list);
- va_end(arg_list);
-
- // append string to buffer
-
- len = strlen(string);
- if (io->out_size + len > BufferSize-2) my_fatal("io_send(): buffer overflow\n");
-
- memcpy(&io->out_buffer[io->out_size],string,len);
- io->out_size += len;
-
- ASSERT(io->out_size>=0&&io->out_size<=BufferSize-2);
-
- // log
-
- io->out_buffer[io->out_size] = '\0';
- my_log("Adapter->%s: %s\n",io->name,io->out_buffer);
-// my_log("> %f %s %s\n",now_real(),io->name,io->out_buffer);
- // append EOL to buffer
-
- if (UseCR) io->out_buffer[io->out_size++] = CR;
- io->out_buffer[io->out_size++] = LF;
-
- ASSERT(io->out_size>=0&&io->out_size<=BufferSize);
-
- // flush buffer
-
- if (UseDebug) my_log("POLYGLOT writing %d byte%s to %s\n",io->out_size,(io->out_size>1)?"s":"",io->name);
- my_write(io->out_fd,io->out_buffer,io->out_size);
-
- io->out_size = 0;
-}
-
-// io_send_queue()
-
-void io_send_queue(io_t * io, const char format[], ...) {
-
- va_list arg_list;
- char string[StringSize];
- int len;
-
- ASSERT(io_is_ok(io));
- ASSERT(format!=NULL);
-
- ASSERT(io->out_fd>=0);
-
- // format
-
- va_start(arg_list,format);
- vsprintf(string,format,arg_list);
- va_end(arg_list);
-
- // append string to buffer
-
- len = strlen(string);
- if (io->out_size + len > BufferSize-2) my_fatal("io_send_queue(): buffer overflow\n");
-
- memcpy(&io->out_buffer[io->out_size],string,len);
- io->out_size += len;
-
- ASSERT(io->out_size>=0&&io->out_size<=BufferSize-2);
-}
-
-// my_read()
-
-static int my_read(int fd, char string[], int size) {
-
- int n;
-
- ASSERT(fd>=0);
- ASSERT(string!=NULL);
- ASSERT(size>0);
-
- do {
- n = read(fd,string,size);
- } while (n == -1 && errno == EINTR);
-
- if (n == -1) my_fatal("my_read(): read(): %s\n",strerror(errno));
-
- ASSERT(n>=0);
-
- return n;
-}
-
-// my_write()
-
-static void my_write(int fd, const char string[], int size) {
-
- int n;
-
- ASSERT(fd>=0);
- ASSERT(string!=NULL);
- ASSERT(size>0);
-
- do {
-
- n = write(fd,string,size);
-
- // if (n == -1 && errno != EINTR && errno != EPIPE) my_fatal("my_write(): write(): %s\n",strerror(errno));
-
- if (n == -1) {
- if (false) {
- } else if (errno == EINTR) {
- n = 0; // nothing has been written
- } else if (errno == EPIPE) {
- n = size; // pretend everything has been written
- } else {
- my_fatal("my_write(): write(): %s\n",strerror(errno));
- }
- }
-
- ASSERT(n>=0);
-
- string += n;
- size -= n;
-
- } while (size > 0);
-
- ASSERT(size==0);
-}
-
-// end of io.cpp
-
-#endif
+++ /dev/null
-\r
-// line.cpp\r
-\r
-// includes\r
-\r
-#include <cstring>\r
-\r
-#include "board.h"\r
-#include "line.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_legal.h"\r
-#include "san.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool Strict = false; // false\r
-static const bool UseDebug = false; // false\r
-\r
-static const int StringSize = 1024;\r
-\r
-// functions\r
-\r
-// line_is_ok()\r
-\r
-bool line_is_ok(const move_t line[]) {\r
-\r
- int move;\r
-\r
- if (line == NULL) return false;\r
-\r
- while ((move = *line++) != MoveNone) {\r
- if (!move_is_ok(move)) return false;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-// line_clear()\r
-\r
-void line_clear(move_t line[]) {\r
-\r
- ASSERT(line!=NULL);\r
-\r
- *line = MoveNone;\r
-}\r
-\r
-// line_copy()\r
-\r
-void line_copy(move_t dst[], const move_t src[]) {\r
-\r
- ASSERT(dst!=NULL);\r
- ASSERT(src!=NULL);\r
-\r
- ASSERT(dst!=src);\r
-\r
- while ((*dst++ = *src++) != MoveNone)\r
- ;\r
-}\r
-\r
-// line_from_can()\r
-\r
-bool line_from_can (move_t line[], const board_t * board, const char string[], int size) {\r
-\r
- int pos;\r
- char new_string[StringSize], *p;\r
- int move;\r
- board_t new_board[1];\r
-\r
- ASSERT(line!=NULL);\r
- ASSERT(board_is_ok(board));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=LineSize);\r
-\r
- // init\r
-\r
- pos = 0;\r
- board_copy(new_board,board);\r
-\r
- // loop\r
-\r
- strcpy(new_string,string); // HACK\r
-\r
- for (p = strtok(new_string," "); p != NULL; p = strtok(NULL," ")) {\r
-\r
- move = move_from_can(p,new_board);\r
-\r
- ASSERT(move!=MoveNone);\r
- ASSERT(move_is_legal(move,new_board));\r
-\r
- if (move == MoveNone || !move_is_legal(move,new_board)) break; // HACK: ignore illegal moves\r
-\r
- if (pos >= size) return false;\r
- line[pos++] = move;\r
-\r
- move_do(new_board,move);\r
- }\r
-\r
- if (pos >= size) return false;\r
- line[pos] = MoveNone;\r
-\r
- return true;\r
-}\r
-\r
-// line_to_can()\r
-\r
-bool line_to_can(const move_t line[], const board_t * board, char string[], int size) {\r
-\r
- board_t new_board[1];\r
- int pos;\r
- int move;\r
-\r
- ASSERT(line_is_ok(line));\r
- ASSERT(board_is_ok(board));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=StringSize);\r
-\r
- // init\r
-\r
- if (size < StringSize) return false;\r
-\r
- board_copy(new_board,board);\r
- pos = 0;\r
-\r
- // loop\r
-\r
- while ((move = *line++) != MoveNone) {\r
-\r
- if (pos != 0) {\r
- if (pos >= size) return false;\r
- string[pos++] = ' ';\r
- }\r
-\r
- if (!move_to_can(move,new_board,&string[pos],size-pos)) return false;\r
- pos += strlen(&string[pos]);\r
-\r
- move_do(new_board,move);\r
- }\r
-\r
- if (pos >= size) return false;\r
- string[pos] = '\0';\r
-\r
- return true;\r
-}\r
-\r
-// line_to_san()\r
-\r
-bool line_to_san(const move_t line[], const board_t * board, char string[], int size) {\r
-\r
- board_t new_board[1];\r
- int pos;\r
- int move;\r
- char move_string[256];\r
-\r
- ASSERT(line_is_ok(line));\r
- ASSERT(board_is_ok(board));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=StringSize);\r
-\r
- // init\r
-\r
- if (size < StringSize) return false;\r
-\r
- board_copy(new_board,board);\r
- pos = 0;\r
-\r
- // loop\r
-\r
- while ((move = *line++) != MoveNone) {\r
-\r
- if (pos != 0) {\r
- if (pos >= size) return false;\r
- string[pos++] = ' ';\r
- }\r
-\r
- if (!move_is_legal(move,new_board)\r
- || !move_to_san(move,new_board,&string[pos],size-pos)) {\r
-\r
- if (Strict || UseDebug) {\r
-\r
- move_to_can(move,new_board,move_string,256);\r
- my_log("POLYGLOT ILLEGAL MOVE IN LINE %s\n",move_string);\r
-\r
- board_disp(new_board);\r
- }\r
-\r
- if (Strict) my_fatal("line_to_san(): illegal move\n");\r
-\r
- break;\r
- }\r
-\r
- pos += strlen(&string[pos]);\r
-\r
- move_do(new_board,move);\r
- }\r
-\r
- if (pos >= size) return false;\r
- string[pos] = '\0';\r
-\r
- return true;\r
-}\r
-\r
-// end of line.cpp\r
-\r
+++ /dev/null
-\r
-// list.cpp\r
-\r
-// includes\r
-\r
-#include "board.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "util.h"\r
-\r
-// functions\r
-\r
-// list_is_ok()\r
-\r
-bool list_is_ok(const list_t * list) {\r
-\r
- if (list == NULL) return false;\r
-\r
- if (list->size >= ListSize) return false;\r
-\r
- return true;\r
-}\r
-\r
-// list_clear()\r
-\r
-void list_clear(list_t * list) {\r
-\r
- ASSERT(list!=NULL);\r
-\r
- list->size = 0;\r
-}\r
-\r
-// list_add()\r
-\r
-void list_add(list_t * list, int move, int value) {\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(move_is_ok(move));\r
- ASSERT(value>=-32767&&value<=+32767);\r
-\r
- ASSERT(list->size<ListSize-1);\r
-\r
- list->move[list->size] = move;\r
- list->value[list->size] = value;\r
- list->size++;\r
-}\r
-\r
-// list_remove()\r
-\r
-void list_remove(list_t * list, int index) {\r
-\r
- int i;\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(index>=0&&index<list->size);\r
-\r
- for (i = index; i < list->size-1; i++) {\r
- list->move[i] = list->move[i+1];\r
- list->value[i] = list->value[i+1];\r
- }\r
-\r
- list->size--;\r
-}\r
-\r
-// list_is_empty()\r
-\r
-bool list_is_empty(const list_t * list) {\r
-\r
- ASSERT(list_is_ok(list));\r
-\r
- return list->size == 0;\r
-}\r
-\r
-// list_size()\r
-\r
-int list_size(const list_t * list) {\r
-\r
- ASSERT(list_is_ok(list));\r
-\r
- return list->size;\r
-}\r
-\r
-// list_move()\r
-\r
-int list_move(const list_t * list, int index) {\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(index>=0&&index<list->size);\r
-\r
- return list->move[index];\r
-}\r
-\r
-// list_value()\r
-\r
-int list_value(const list_t * list, int index) {\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(index>=0&&index<list->size);\r
-\r
- return list->value[index];\r
-}\r
-\r
-// list_copy()\r
-\r
-void list_copy(list_t * dst, const list_t * src) {\r
-\r
- int i;\r
-\r
- ASSERT(dst!=NULL);\r
- ASSERT(list_is_ok(src));\r
-\r
- dst->size = src->size;\r
-\r
- for (i = 0; i < src->size; i++) {\r
- dst->move[i] = src->move[i];\r
- dst->value[i] = src->value[i];\r
- }\r
-}\r
-\r
-// list_move_to_front()\r
-\r
-void list_move_to_front(list_t * list, int index) {\r
-\r
- int i;\r
- int move, value;\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(index>=0&&index<list->size);\r
-\r
- if (index != 0) {\r
-\r
- move = list->move[index];\r
- value = list->value[index];\r
-\r
- for (i = index; i > 0; i--) {\r
- list->move[i] = list->move[i-1];\r
- list->value[i] = list->value[i-1];\r
- }\r
-\r
- list->move[0] = move;\r
- list->value[0] = value;\r
- }\r
-}\r
-\r
-// list_note()\r
-\r
-void list_note(list_t * list) {\r
-\r
- int i, move;\r
-\r
- ASSERT(list_is_ok(list));\r
-\r
- for (i = 0; i < list->size; i++) {\r
- move = list->move[i];\r
- ASSERT(move_is_ok(move));\r
- list->value[i] = -move_order(move);\r
- }\r
-}\r
-\r
-// list_sort()\r
-\r
-void list_sort(list_t * list) {\r
-\r
- int i, j;\r
- int best_index, best_move, best_value;\r
-\r
- ASSERT(list_is_ok(list));\r
-\r
- for (i = 0; i < list->size-1; i++) {\r
-\r
- best_index = i;\r
- best_value = list->value[i];\r
-\r
- for (j = i+1; j < list->size; j++) {\r
- if (list->value[j] > best_value) {\r
- best_index = j;\r
- best_value = list->value[j];\r
- }\r
- }\r
-\r
- if (best_index != i) {\r
-\r
- best_move = list->move[best_index];\r
- ASSERT(best_value==list->value[best_index]);\r
-\r
- for (j = best_index; j > i; j--) {\r
- list->move[j] = list->move[j-1];\r
- list->value[j] = list->value[j-1];\r
- }\r
-\r
- list->move[i] = best_move;\r
- list->value[i] = best_value;\r
- }\r
- }\r
-\r
- if (DEBUG) {\r
- for (i = 0; i < list->size-1; i++) {\r
- ASSERT(list->value[i]>=list->value[i+1]);\r
- }\r
- }\r
-}\r
-\r
-// list_contain()\r
-\r
-bool list_contain(const list_t * list, int move) {\r
-\r
- int i;\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(move_is_ok(move));\r
-\r
- for (i = 0; i < list->size; i++) {\r
- if (list->move[i] == move) return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-// list_equal()\r
-\r
-bool list_equal(list_t * list_1, list_t * list_2) {\r
-\r
- list_t copy_1[1], copy_2[1];\r
- int i;\r
-\r
- ASSERT(list_is_ok(list_1));\r
- ASSERT(list_is_ok(list_2));\r
-\r
- if (list_1->size != list_2->size) return false;\r
-\r
- list_copy(copy_1,list_1);\r
- list_note(copy_1);\r
- list_sort(copy_1);\r
-\r
- list_copy(copy_2,list_2);\r
- list_note(copy_2);\r
- list_sort(copy_2);\r
-\r
- for (i = 0; i < copy_1->size; i++) {\r
- if (copy_1->move[i] != copy_2->move[i]) return false;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-// list_disp()\r
-\r
-void list_disp(const list_t * list, const board_t * board) {\r
-\r
- int i, move, value;\r
- char string[256];\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(board_is_ok(board));\r
-\r
- for (i = 0; i < list->size; i++) {\r
-\r
- move = list->move[i];\r
- value = list->value[i];\r
-\r
- if (!move_to_can(move,board,string,256)) ASSERT(false);\r
- my_log("POLYGLOT %-5s %04X %+4d\n",string,move,value);\r
- }\r
-\r
- my_log("POLYGLOT\n");\r
-}\r
-\r
-// end of list.cpp\r
-\r
+++ /dev/null
-\r
-// main.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "attack.h"\r
-#include "board.h"\r
-#include "book.h"\r
-#include "book_make.h"\r
-#include "book_merge.h"\r
-#include "engine.h"\r
-#include "epd.h"\r
-#include "fen.h"\r
-#include "gui.h"\r
-#include "hash.h"\r
-#include "list.h"\r
-#include "main.h"\r
-#include "mainloop.h"\r
-#include "move.h"\r
-#include "move_gen.h"\r
-#include "option.h"\r
-#include "piece.h"\r
-#include "search.h"\r
-#include "square.h"\r
-#include "uci.h"\r
-#include "util.h"\r
-#include "xboard2uci.h"\r
-#include "uci2uci.h"\r
-\r
-// constants\r
-\r
-\r
-static const char * const Version = "1.4b27";\r
-static const char * const HelpMessage = "\\r
-SYNTAX\n\\r
-* polyglot [configfile]\n\\r
-* polyglot -ec enginecommand\n\\r
-* polyglot make-book [-pgn inputfile] [-bin outputfile] [-max-ply ply] [-min-game games] [-min-score score] [-only-white] [-only-black] [-uniform]\n\\r
-* polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\\r
-* polyglot info-book [-bin inputfile] [-exact]\n\\r
-* polyglot dumb-book [-bin inputfile] -color color [-out outputfile]\n\\r
-* polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-min-time time] [-max-time time] [-depth-delta delta]\n\\r
-* polyglot perft [-fen fen] [-max-depth depth]\\r
-";\r
-\r
-static const int SearchDepth = 63;\r
-static const double SearchTime = 3600.0;\r
-static const int StringSize = 4096;\r
-\r
-// variables\r
-\r
-static bool Init;\r
-\r
-// prototypes\r
-\r
-static void parse_option ();\r
-static void init_book ();\r
-static bool parse_line (char line[], char * * name_ptr, char * * value_ptr);\r
-static void stop_search ();\r
-\r
-// functions\r
-\r
-// main()\r
-\r
-int main(int argc, char * argv[]) {\r
-\r
-// board_t board[1];\r
-\r
- if(argc>=2 && ((my_string_case_equal(argv[1],"help")) || (my_string_case_equal(argv[1],"-help")) || (my_string_case_equal(argv[1],"--help")) || (my_string_case_equal(argv[1],"-h")) || my_string_case_equal(argv[1],"/?"))){\r
- printf("%s\n",HelpMessage);\r
- return EXIT_SUCCESS;\r
- }\r
- // init\r
-\r
- Init = false;\r
-\r
- util_init();\r
- printf("PolyGlot %s by Fabien Letouzey\n",Version);\r
- \r
- option_init();\r
- \r
- square_init();\r
- piece_init();\r
- attack_init();\r
- \r
- hash_init();\r
- \r
- my_random_init();\r
-\r
- // build book\r
- \r
- if (argc >= 2 && my_string_equal(argv[1],"make-book")) {\r
- book_make(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
- \r
- if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
- book_merge(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
-\r
- if (argc >= 2 && my_string_equal(argv[1],"merge-book")) {\r
- book_merge(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
-\r
- if (argc >= 2 && my_string_equal(argv[1],"dump-book")) {\r
- book_dump(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
-\r
- if (argc >= 2 && my_string_equal(argv[1],"info-book")) {\r
- book_info(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
- \r
- if (argc >= 2 && my_string_equal(argv[1],"perft")) {\r
- do_perft(argc,argv);\r
- return EXIT_SUCCESS;\r
- }\r
- \r
- if (argc >= 3 && my_string_equal(argv[1],"-ec")) {\r
- option_set("EngineCommand",argv[2]);\r
- engine_open(Engine);\r
- if(!engine_active(Engine)){\r
- my_fatal("Could not start \"%s\"\n",option_get("EngineCommand"));\r
- }\r
- Init=true;\r
- gui_init(GUI);\r
- uci_open(Uci,Engine);\r
- if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
- option_set("EngineName",Uci->name);\r
- }\r
- mainloop();\r
- return EXIT_SUCCESS; \r
- }\r
- \r
- // read options\r
- \r
- if (argc == 2) option_set("OptionFile",argv[1]); // HACK for compatibility\r
-\r
- parse_option(); // HACK: also launches the engine\r
- \r
- // EPD test\r
- \r
- if (argc >= 2 && my_string_equal(argv[1],"epd-test")){\r
- epd_test(argc,argv);\r
- return EXIT_SUCCESS;\r
- }else if(argc >= 3 && my_string_equal(argv[2],"epd-test")){\r
- epd_test(argc-1,argv+1);\r
- return EXIT_SUCCESS;\r
- }\r
- \r
- if (argc >= 3) my_fatal("Too many arguments\n");\r
-\r
-\r
- init_book();\r
- gui_init(GUI);\r
- mainloop();\r
- return EXIT_SUCCESS; \r
-}\r
-\r
-// polyglot_set_option\r
-\r
-void polyglot_set_option(char *name, char *value){ // this must be cleaned up!\r
- option_set(name,value);\r
- if(option_get_bool("Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){\r
- my_log("POLYGLOT *** SETTING BOOK ***\n");\r
- my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile"));\r
- book_close();\r
- book_clear();\r
- book_open(option_get_string("BookFile"));\r
- if(!book_is_open()){\r
- my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string("BookFile"));\r
- }\r
- }else if(option_get_bool("Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){\r
- my_log("POLYGLOT *** SETTING LOGFILE ***\n");\r
- my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string("LogFile"));\r
- my_log_close();\r
- my_log_open(option_get_string("LogFile"));\r
- }else if(option_get_bool("UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){\r
- my_log("POLYGLOT Adjust Engine Piority\n");\r
- engine_set_nice_value(Engine,atoi(option_get_string("NiceValue")));\r
- }else if(my_string_case_equal(name,"Book") && !option_get_bool("Book")){\r
- book_close();\r
- book_clear();\r
- }else if(my_string_case_equal(name,"UseNice") && !option_get_bool("UseNice")){\r
- my_log("POLYGLOT Adjust Engine Piority\n");\r
- engine_set_nice_value(Engine,0);\r
- }else if(my_string_case_equal(name,"Log") && !option_get_bool("Log")){\r
- my_log("POLYGLOT QUIT LOGGING\n");\r
- my_log_close();\r
- }\r
-}\r
-\r
-\r
-// init_book()\r
-\r
-static void init_book(){\r
- book_clear();\r
- if (option_get_bool("Book")){\r
- my_log("POLYGLOT *** SETTING BOOK ***\n");\r
- my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile"));\r
- book_open(option_get_string("BookFile"));\r
- if(!book_is_open()){\r
- my_log("POLYGLOT Unable to open book \"%s\"\n",\r
- option_get_string("BookFile"));\r
- }\r
- }\r
-}\r
-\r
-// parse_option()\r
-\r
-static void parse_option() {\r
-\r
- const char * file_name;\r
- FILE * file;\r
- char line[256];\r
- char * name, * value;\r
- file_name = option_get_string("OptionFile");\r
- \r
- file = fopen(file_name,"r");\r
- if (file == NULL) {\r
- my_fatal("Can't open file \"%s\": %s\n",file_name,strerror(errno));\r
- }\r
- \r
- // PolyGlot options (assumed first)\r
- \r
- while (true) {\r
- \r
- if (!my_file_read_line(file,line,256)) {\r
- my_fatal("parse_option(): missing [Engine] section\n");\r
- }\r
- \r
- if (my_string_case_equal(line,"[engine]")) break;\r
- \r
- if (parse_line(line,&name,&value)) {\r
- option_set(name,value);\r
- option_set_default(name,value);\r
- }\r
- }\r
- \r
- if (option_get_bool("Log")) {\r
- my_log_open(option_get_string("LogFile"));\r
- }\r
- \r
- my_log("POLYGLOT *** START ***\n");\r
- my_log("POLYGLOT INI file \"%s\"\n",file_name);\r
- engine_open(Engine);\r
- if(!engine_active(Engine)){\r
- my_fatal("Could not start \"%s\"\n",option_get("EngineCommand"));\r
- }\r
-\r
- if (option_get_bool("UCI")) {\r
- my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
- }\r
- uci_open(Uci,Engine);\r
- Init = true;\r
- while (my_file_read_line(file,line,256)) {\r
- if (line[0] == '[') my_fatal("parse_option(): unknown section %s\n",line);\r
- if (parse_line(line,&name,&value)) {\r
- uci_send_option(Uci,name,"%s",value);\r
- //to get a decent display in winboard_x we need to now if an engine really is doing multipv analysis\r
- // "multipv 1" in the pv is meaningless,f.i. toga sends that all the time\r
- //therefore check if MultiPV is set to a decent value in the polyglot ini file\r
- if(my_string_case_equal(name,"MultiPV") && atoi(value)>1) Uci->multipv_mode=true;\r
- }\r
- }\r
- if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
- option_set("EngineName",Uci->name);\r
- }\r
- \r
- fclose(file);\r
-}\r
-\r
-// parse_line()\r
-\r
-static bool parse_line(char line[], char * * name_ptr, char * * value_ptr) {\r
- \r
- char * ptr;\r
- char * name, * value;\r
- \r
- ASSERT(line!=NULL);\r
- ASSERT(name_ptr!=NULL);\r
- ASSERT(value_ptr!=NULL);\r
- \r
- // remove comments\r
- \r
- ptr = strchr(line,';');\r
- if (ptr != NULL) *ptr = '\0';\r
- \r
- ptr = strchr(line,'#');\r
- if (ptr != NULL) *ptr = '\0';\r
- \r
- // split at '='\r
- \r
- ptr = strchr(line,'=');\r
- if (ptr == NULL) return false;\r
- \r
- name = line;\r
- value = ptr+1;\r
- \r
- // cleanup name\r
- \r
- while (*name == ' ') name++; // remove leading spaces\r
- \r
- while (ptr > name && ptr[-1] == ' ') ptr--; // remove trailing spaces\r
- *ptr = '\0';\r
- \r
- if (*name == '\0') return false;\r
- \r
- // cleanup value\r
- \r
- ptr = &value[strlen(value)]; // pointer to string terminator\r
- \r
- while (*value == ' ') value++; // remove leading spaces\r
- \r
- while (ptr > value && ptr[-1] == ' ') ptr--; // remove trailing spaces\r
- *ptr = '\0';\r
- \r
- if (*value == '\0') return false;\r
- \r
- // end\r
- \r
- *name_ptr = name;\r
- *value_ptr = value;\r
- \r
- return true;\r
-}\r
-\r
-// quit()\r
-\r
-void quit() {\r
-\r
- my_log("POLYGLOT *** QUIT ***\n");\r
- \r
- if (Init) {\r
- \r
- stop_search();\r
- engine_send(Engine,"quit");\r
- my_log("POLYGLOT Closing engine\n");\r
- engine_close(Engine);\r
- \r
- }\r
- my_log("POLYGLOT Calling exit\n");\r
- exit(EXIT_SUCCESS);\r
-}\r
-\r
-// stop_search()\r
-\r
-static void stop_search() {\r
- \r
- if (Init && Uci->searching) {\r
- \r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
- \r
- my_log("POLYGLOT STOP SEARCH\n");\r
- \r
- if (option_get_bool("SyncStop")) {\r
- uci_send_stop_sync(Uci);\r
- } else {\r
- uci_send_stop(Uci);\r
- }\r
- }\r
-}\r
-\r
-\r
-// end of main.cpp\r
-\r
+++ /dev/null
-// mainloop.cpp\r
-\r
-// constants\r
-\r
-static const int StringSize = 4096;\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#ifndef _WIN32\r
-#include <sys/select.h>\r
-#include <sys/types.h> // Mac OS X needs this one\r
-#include <unistd.h>\r
-#endif\r
-\r
-#include "main.h"\r
-#include "engine.h"\r
-#include "gui.h"\r
-#include "option.h"\r
-#include "xboard2uci.h"\r
-#include "uci2uci.h"\r
-\r
-// prototypes\r
-\r
-static void mainloop_init ();\r
-static void mainloop_wait_for_event ();\r
-static void mainloop_engine_step(char * string);\r
-static void mainloop_gui_step(char * string);\r
-\r
-// functions\r
-\r
-// mainloop_init()\r
- \r
-static void mainloop_init(){\r
- if(!option_get_bool("UCI")){\r
- xboard2uci_init(); // the default\r
- }\r
-}\r
-\r
-// mainloop_engine_step()\r
-\r
-static void mainloop_engine_step(char * string){\r
- if(option_get_bool("UCI")){\r
- uci2uci_engine_step(string); \r
- }else{\r
- xboard2uci_engine_step(string);\r
- }\r
-}\r
-\r
-// mainloop_gui_step()\r
-\r
-static void mainloop_gui_step(char * string){\r
- if(option_get_bool("UCI")){\r
- uci2uci_gui_step(string); \r
- }else if(my_string_equal(string,"uci")){ // mode auto detection\r
- my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
- option_set("UCI","true");\r
- uci2uci_gui_step(string);\r
- }else{\r
- xboard2uci_gui_step(string);\r
- }\r
-}\r
-\r
-// mainloop()\r
-\r
-void mainloop() {\r
- char string[StringSize];\r
- mainloop_init();\r
- while (!engine_eof(Engine)) {\r
- // process buffered lines\r
- while(TRUE){\r
- if(gui_get_non_blocking(GUI,string,StringSize)){\r
- mainloop_gui_step(string);\r
- }else if(!engine_eof(Engine) &&\r
- engine_get_non_blocking(Engine,string,StringSize) ){\r
- mainloop_engine_step(string);\r
- }else{\r
- break;\r
- }\r
- }\r
- mainloop_wait_for_event();\r
- }\r
- my_log("POLYGLOT *** Mainloop has ended ***\n");\r
- // This should be handled better.\r
- engine_close(Engine);\r
- my_log("POLYGLOT Calling exit\n");\r
- exit(EXIT_SUCCESS);\r
-\r
-}\r
-\r
-\r
-\r
-\r
-// mainloop_wait_for_event()\r
-\r
-static void mainloop_wait_for_event(){\r
-#ifdef _WIN32\r
- HANDLE hHandles[2];\r
- char string[StringSize];\r
- hHandles[0]=(GUI->io).hEvent;\r
- hHandles[1]=(Engine->io).hEvent;\r
- WaitForMultipleObjects(2, // count\r
- hHandles, //\r
- FALSE, // return if one object is signaled\r
- INFINITE // no timeout\r
- );\r
-#else\r
- fd_set set[1];\r
- int fd_max;\r
- int val;\r
- char string[StringSize];\r
- // init\r
-\r
- FD_ZERO(set);\r
- fd_max = -1; // HACK\r
-\r
- // add gui input\r
-\r
- ASSERT(GUI->io->in_fd>=0);\r
-\r
- FD_SET(GUI->io->in_fd,set);\r
- if (GUI->io->in_fd > fd_max) fd_max = GUI->io->in_fd;\r
-\r
- // add engine input\r
-\r
- ASSERT(Engine->io->in_fd>=0);\r
-\r
- FD_SET(Engine->io->in_fd,set);\r
- if (Engine->io->in_fd > fd_max) fd_max = Engine->io->in_fd;\r
-\r
- // wait for something to read (no timeout)\r
-\r
- ASSERT(fd_max>=0);\r
- val = select(fd_max+1,set,NULL,NULL,NULL);\r
- if (val == -1 && errno != EINTR) my_fatal("adapter_step(): select(): %s\n",strerror(errno));\r
-\r
- if (val > 0) {\r
- if (FD_ISSET(GUI->io->in_fd,set)) io_get_update(GUI->io); // read some xboard input\r
- if (FD_ISSET(Engine->io->in_fd,set)) io_get_update(Engine->io); // read some engine input\r
- } \r
-#endif\r
-}\r
-\r
-\r
-\r
+++ /dev/null
-\r
-// move.cpp\r
-\r
-// includes\r
-\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "attack.h"\r
-#include "colour.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_gen.h"\r
-#include "move_legal.h"\r
-#include "option.h"\r
-#include "piece.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// "constants"\r
-\r
-static const uint8 PromotePiece[5] = { PieceNone64, Knight64, Bishop64, Rook64, Queen64 };\r
-\r
-// functions\r
-\r
-// move_is_ok()\r
-\r
-bool move_is_ok(int move) {\r
-\r
- if (move < 0 || move >= 65536) return false;\r
-\r
- if (move == MoveNone) return false;\r
-\r
- return true;\r
-}\r
-\r
-// move_make()\r
-\r
-int move_make(int from, int to) {\r
-\r
- ASSERT(square_is_ok(from));\r
- ASSERT(square_is_ok(to));\r
-\r
- return (square_to_64(from) << 6) | square_to_64(to);\r
-}\r
-\r
-// move_make_flags()\r
-\r
-int move_make_flags(int from, int to, int flags) {\r
-\r
- ASSERT(square_is_ok(from));\r
- ASSERT(square_is_ok(to));\r
- ASSERT((flags&~0xF000)==0);\r
-\r
- ASSERT(to!=from);\r
-\r
- return (square_to_64(from) << 6) | square_to_64(to) | flags;\r
-}\r
-\r
-// move_from()\r
-\r
-int move_from(int move) {\r
-\r
- int from_64;\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- from_64 = (move >> 6) & 077;\r
-\r
- return square_from_64(from_64);\r
-}\r
-\r
-// move_to()\r
-\r
-int move_to(int move) {\r
-\r
- int to_64;\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- to_64 = move & 077;\r
-\r
- return square_from_64(to_64);\r
-}\r
-\r
-// move_promote_hack()\r
-\r
-int move_promote_hack(int move) {\r
-\r
- int code;\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- ASSERT(move_is_promote(move));\r
-\r
- code = move >> 12;\r
- ASSERT(code>=1&&code<=4);\r
-\r
- return PromotePiece[code];\r
-}\r
-\r
-// move_is_capture()\r
-\r
-bool move_is_capture(int move, const board_t * board) {\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- if (move_is_en_passant(move,board)) return true;\r
- if (board->square[move_to(move)] != Empty) return true;\r
-\r
- return false;\r
-}\r
-\r
-// move_is_promote()\r
-\r
-bool move_is_promote(int move) {\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- return (move & MoveFlags) != 0;\r
-}\r
-\r
-// move_is_en_passant()\r
-\r
-bool move_is_en_passant(int move, const board_t * board) {\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- return piece_is_pawn(move_piece(move,board))\r
- && move_to(move) == board->ep_square;\r
-}\r
-\r
-// move_is_castle()\r
-\r
-bool move_is_castle(int move, const board_t * board) {\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- return colour_equal(board->square[move_to(move)],board->turn);\r
-}\r
-\r
-// move_piece()\r
-\r
-int move_piece(int move, const board_t * board) {\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- return board->square[move_from(move)];\r
-}\r
-\r
-// move_capture()\r
-\r
-int move_capture(int move, const board_t * board) {\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- if (move_is_en_passant(move,board)) {\r
- return piece_pawn_opp(move_piece(move,board));\r
- }\r
-\r
- return board->square[move_to(move)];\r
-}\r
-\r
-// move_promote()\r
-\r
-int move_promote(int move, const board_t * board) {\r
-\r
- int code;\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- if (move_is_promote(move)) {\r
- code = move >> 12;\r
- ASSERT(code>=1&&code<=4);\r
- return PromotePiece[code] | board->turn;\r
- }\r
-\r
- return Empty;\r
-}\r
-\r
-// move_is_check()\r
-\r
-bool move_is_check(int move, const board_t * board) {\r
-\r
- board_t new_board[1];\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- board_copy(new_board,board);\r
- move_do(new_board,move);\r
- ASSERT(!is_in_check(new_board,colour_opp(new_board->turn)));\r
-\r
- return board_is_check(new_board);\r
-}\r
-\r
-// move_is_mate()\r
-\r
-bool move_is_mate(int move, const board_t * board) {\r
-\r
- board_t new_board[1];\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- board_copy(new_board,board);\r
- move_do(new_board,move);\r
- ASSERT(!is_in_check(new_board,colour_opp(new_board->turn)));\r
-\r
- return board_is_mate(new_board);\r
-}\r
-\r
-// move_to_can()\r
-\r
-bool move_to_can(int move, const board_t * board, char string[], int size) {\r
-\r
- int from, to;\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=6);\r
-\r
- ASSERT(move_is_legal(move,board));\r
-\r
- if (size < 6) return false;\r
-\r
- // init\r
-\r
- from = move_from(move);\r
- to = move_to(move);\r
-\r
- // king-slide castling\r
-\r
- if (move_is_castle(move,board) && !option_get_bool("Chess960")) {\r
- if (false) {\r
- } else if (from == E1 && to == H1) {\r
- to = G1;\r
- } else if (from == E1 && to == A1) {\r
- to = C1;\r
- } else if (from == E8 && to == H8) {\r
- to = G8;\r
- } else if (from == E8 && to == A8) {\r
- to = C8;\r
- }\r
- }\r
-\r
- // normal moves\r
-\r
- if (!square_to_string(from,&string[0],3)) ASSERT(false);\r
- if (!square_to_string(to,&string[2],3)) ASSERT(false);\r
- ASSERT(strlen(string)==4);\r
-\r
- // promotes\r
-\r
- if (move_is_promote(move)) {\r
- string[4] = piece_to_char(move_promote_hack(move)|Black); // HACK: black => lower-case\r
- string[5] = '\0';\r
- }\r
-\r
- // debug\r
-\r
- ASSERT(move_from_can(string,board)==move);\r
-\r
- return true;\r
-}\r
-\r
-// move_from_can()\r
-\r
-int move_from_can(const char string[], const board_t * board) {\r
-\r
- char tmp_string[256];\r
- int from, to;\r
- int side;\r
- int move;\r
-\r
- ASSERT(string!=NULL);\r
- ASSERT(board_is_ok(board));\r
-\r
- // from\r
-\r
- tmp_string[0] = string[0];\r
- tmp_string[1] = string[1];\r
- tmp_string[2] = '\0';\r
-\r
- from = square_from_string(tmp_string);\r
- if (from == SquareNone) return MoveNone;\r
-\r
- // to\r
-\r
- tmp_string[0] = string[2];\r
- tmp_string[1] = string[3];\r
- tmp_string[2] = '\0';\r
-\r
- to = square_from_string(tmp_string);\r
- if (to == SquareNone) return MoveNone;\r
-\r
- // convert "king slide" castling to KxR\r
-\r
- if (piece_is_king(board->square[from])\r
- && square_rank(to) == square_rank(from)\r
- && abs(to-from) > 1) {\r
- side = (to > from) ? SideH : SideA;\r
- to = board->castle[board->turn][side];\r
- if (to == SquareNone) return MoveNone;\r
- }\r
-\r
- // move\r
-\r
- move = move_make(from,to);\r
-\r
- // promote\r
-\r
- switch (string[4]) {\r
- case '\0': // not a promotion\r
- if (piece_is_pawn(board->square[from])\r
- && square_side_rank(to,board->turn) == Rank8\r
- && option_get_bool("PromoteWorkAround")) {\r
- move |= MovePromoteQueen;\r
- }\r
- break;\r
- case 'N':\r
- case 'n':\r
- move |= MovePromoteKnight;\r
- break;\r
- case 'B':\r
- case 'b':\r
- move |= MovePromoteBishop;\r
- break;\r
- case 'R':\r
- case 'r':\r
- move |= MovePromoteRook;\r
- break;\r
- case 'Q':\r
- case 'q':\r
- move |= MovePromoteQueen;\r
- break;\r
- default:\r
- return MoveNone;\r
- break;\r
- }\r
-\r
- // debug\r
-\r
- ASSERT(move_is_legal(move,board));\r
-\r
- return move;\r
-}\r
-\r
-// move_order()\r
-\r
-int move_order(int move) {\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- return ((move & 07777) << 3) | (move >> 12); // from, to, promote\r
-}\r
-\r
-// move_disp()\r
-\r
-void move_disp(int move, const board_t * board) {\r
-\r
- char string[256];\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- if (!move_to_can(move,board,string,256)) ASSERT(false);\r
- my_log("POLYGLOT %s\n",string);\r
-}\r
-\r
-// end of move.cpp\r
-\r
+++ /dev/null
-\r
-// move_do.cpp\r
-\r
-// includes\r
-\r
-#include <cstdlib>\r
-\r
-#include "board.h"\r
-#include "colour.h"\r
-#include "hash.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_legal.h"\r
-#include "piece.h"\r
-#include "random.h"\r
-#include "util.h"\r
-\r
-// prototypes\r
-\r
-static void square_clear (board_t * board, int square, int piece);\r
-static void square_set (board_t * board, int square, int piece, int pos);\r
-static void square_move (board_t * board, int from, int to, int piece);\r
-\r
-// functions\r
-\r
-// move_do()\r
-\r
-void move_do(board_t * board, int move) {\r
-\r
- int me, opp;\r
- int from, to;\r
- int piece, pos, capture;\r
- int old_flags, new_flags;\r
- int sq, ep_square;\r
- int pawn;\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(move_is_ok(move));\r
-\r
- ASSERT(move_is_pseudo(move,board));\r
-\r
- // init\r
-\r
- me = board->turn;\r
- opp = colour_opp(me);\r
-\r
- from = move_from(move);\r
- to = move_to(move);\r
-\r
- piece = board->square[from];\r
- ASSERT(colour_equal(piece,me));\r
-\r
- pos = board->pos[from];\r
- ASSERT(pos>=0);\r
-\r
- // update turn\r
-\r
- board->turn = opp;\r
- board->key ^= random_64(RandomTurn);\r
-\r
- // update castling rights\r
-\r
- old_flags = board_flags(board);\r
-\r
- if (piece_is_king(piece)) {\r
- board->castle[me][SideH] = SquareNone;\r
- board->castle[me][SideA] = SquareNone;\r
- }\r
-\r
- if (board->castle[me][SideH] == from) board->castle[me][SideH] = SquareNone;\r
- if (board->castle[me][SideA] == from) board->castle[me][SideA] = SquareNone;\r
-\r
- if (board->castle[opp][SideH] == to) board->castle[opp][SideH] = SquareNone;\r
- if (board->castle[opp][SideA] == to) board->castle[opp][SideA] = SquareNone;\r
-\r
- new_flags = board_flags(board);\r
-\r
- board->key ^= hash_castle_key(new_flags^old_flags); // HACK\r
-\r
- // update en-passant square\r
-\r
- ep_square = sq = board->ep_square;\r
- if (sq != SquareNone) {\r
- board->key ^= random_64(RandomEnPassant+square_file(sq));\r
- board->ep_square = SquareNone;\r
- }\r
-\r
- if (piece_is_pawn(piece) && abs(to-from) == 32) {\r
- pawn = piece_make_pawn(opp);\r
- if (board->square[to-1] == pawn || board->square[to+1] == pawn) {\r
- board->ep_square = sq = (from + to) / 2;\r
- board->key ^= random_64(RandomEnPassant+square_file(sq));\r
- }\r
- }\r
-\r
- // update ply number (captures are handled later)\r
-\r
- board->ply_nb++;\r
- if (piece_is_pawn(piece)) board->ply_nb = 0; // conversion\r
-\r
- // update move number\r
-\r
- if (me == Black) board->move_nb++;\r
-\r
- // castle\r
-\r
- if (colour_equal(board->square[to],me)) {\r
-\r
- int rank;\r
- int king_from, king_to;\r
- int rook_from, rook_to;\r
- int rook;\r
-\r
- rank = colour_is_white(me) ? Rank1 : Rank8;\r
-\r
- king_from = from;\r
- rook_from = to;\r
-\r
- if (to > from) { // h side\r
- king_to = square_make(FileG,rank);\r
- rook_to = square_make(FileF,rank);\r
- } else { // a side\r
- king_to = square_make(FileC,rank);\r
- rook_to = square_make(FileD,rank);\r
- }\r
-\r
- // remove the rook\r
-\r
- pos = board->pos[rook_from];\r
- ASSERT(pos>=0);\r
-\r
- rook = Rook64 | me; // HACK\r
-\r
- square_clear(board,rook_from,rook);\r
-\r
- // move the king\r
-\r
- square_move(board,king_from,king_to,piece);\r
-\r
- // put the rook back\r
-\r
- square_set(board,rook_to,rook,pos);\r
-\r
- ASSERT(board->key==hash_key(board));\r
-\r
- return;\r
- }\r
-\r
- // remove the captured piece\r
-\r
- if (piece_is_pawn(piece) && to == ep_square) {\r
-\r
- // en-passant capture\r
-\r
- sq = square_ep_dual(to);\r
- capture = board->square[sq];\r
- ASSERT(capture==piece_make_pawn(opp));\r
-\r
- square_clear(board,sq,capture);\r
-\r
- board->ply_nb = 0; // conversion\r
-\r
- } else {\r
-\r
- capture = board->square[to];\r
-\r
- if (capture != Empty) {\r
-\r
- // normal capture\r
-\r
- ASSERT(colour_equal(capture,opp));\r
- ASSERT(!piece_is_king(capture));\r
-\r
- square_clear(board,to,capture);\r
-\r
- board->ply_nb = 0; // conversion\r
- }\r
- }\r
-\r
- // move the piece\r
-\r
- if (move_is_promote(move)) {\r
-\r
- // promote\r
-\r
- square_clear(board,from,piece);\r
- piece = move_promote_hack(move) | me; // HACK\r
- square_set(board,to,piece,pos);\r
-\r
- } else {\r
-\r
- // normal move\r
-\r
- square_move(board,from,to,piece);\r
- }\r
-\r
- ASSERT(board->key==hash_key(board));\r
-}\r
-\r
-// square_clear()\r
-\r
-static void square_clear(board_t * board, int square, int piece) {\r
-\r
- int pos, piece_12, colour;\r
- int sq, size;\r
-\r
- ASSERT(board!=NULL);\r
- ASSERT(square_is_ok(square));\r
- ASSERT(piece_is_ok(piece));\r
-\r
- // init\r
-\r
- pos = board->pos[square];\r
- ASSERT(pos>=0);\r
-\r
- colour = piece_colour(piece);\r
- piece_12 = piece_to_12(piece);\r
-\r
- // square\r
-\r
- ASSERT(board->square[square]==piece);\r
- board->square[square] = Empty;\r
-\r
- ASSERT(board->pos[square]==pos);\r
- board->pos[square] = -1; // not needed\r
-\r
- // piece list\r
-\r
- ASSERT(board->list_size[colour]>=2);\r
- size = --board->list_size[colour];\r
- ASSERT(pos<=size);\r
-\r
- if (pos != size) {\r
-\r
- sq = board->list[colour][size];\r
- ASSERT(square_is_ok(sq));\r
- ASSERT(sq!=square);\r
-\r
- ASSERT(board->pos[sq]==size);\r
- board->pos[sq] = pos;\r
-\r
- ASSERT(board->list[colour][pos]==square);\r
- board->list[colour][pos] = sq;\r
- }\r
-\r
- board->list[colour][size] = SquareNone;\r
-\r
- // material\r
-\r
- ASSERT(board->number[piece_12]>=1);\r
- board->number[piece_12]--;\r
-\r
- // hash key\r
-\r
- board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square));\r
-}\r
-\r
-// square_set()\r
-\r
-static void square_set(board_t * board, int square, int piece, int pos) {\r
-\r
- int piece_12, colour;\r
- int sq, size;\r
-\r
- ASSERT(board!=NULL);\r
- ASSERT(square_is_ok(square));\r
- ASSERT(piece_is_ok(piece));\r
- ASSERT(pos>=0);\r
-\r
- // init\r
-\r
- colour = piece_colour(piece);\r
- piece_12 = piece_to_12(piece);\r
-\r
- // square\r
-\r
- ASSERT(board->square[square]==Empty);\r
- board->square[square] = piece;\r
-\r
- ASSERT(board->pos[square]==-1);\r
- board->pos[square] = pos;\r
-\r
- // piece list\r
-\r
- size = board->list_size[colour]++;\r
- ASSERT(board->list[colour][size]==SquareNone);\r
- ASSERT(pos<=size);\r
-\r
- if (pos != size) {\r
-\r
- sq = board->list[colour][pos];\r
- ASSERT(square_is_ok(sq));\r
- ASSERT(sq!=square);\r
-\r
- ASSERT(board->pos[sq]==pos);\r
- board->pos[sq] = size;\r
-\r
- ASSERT(board->list[colour][size]==SquareNone);\r
- board->list[colour][size] = sq;\r
- }\r
-\r
- board->list[colour][pos] = square;\r
-\r
- // material\r
-\r
- ASSERT(board->number[piece_12]<=8);\r
- board->number[piece_12]++;\r
-\r
- // hash key\r
-\r
- board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square));\r
-}\r
-\r
-// square_move()\r
-\r
-static void square_move(board_t * board, int from, int to, int piece) {\r
-\r
- int colour, pos;\r
- int piece_index;\r
-\r
- ASSERT(board!=NULL);\r
- ASSERT(square_is_ok(from));\r
- ASSERT(square_is_ok(to));\r
- ASSERT(piece_is_ok(piece));\r
-\r
- // init\r
-\r
- colour = piece_colour(piece);\r
-\r
- pos = board->pos[from];\r
- ASSERT(pos>=0);\r
-\r
- // from\r
-\r
- ASSERT(board->square[from]==piece);\r
- board->square[from] = Empty;\r
-\r
- ASSERT(board->pos[from]==pos);\r
- board->pos[from] = -1; // not needed\r
-\r
- // to\r
-\r
- ASSERT(board->square[to]==Empty);\r
- board->square[to] = piece;\r
-\r
- ASSERT(board->pos[to]==-1);\r
- board->pos[to] = pos;\r
-\r
- // piece list\r
-\r
- ASSERT(board->list[colour][pos]==from);\r
- board->list[colour][pos] = to;\r
-\r
- // hash key\r
-\r
- piece_index = RandomPiece + piece_to_12(piece) * 64;\r
-\r
- board->key ^= random_64(piece_index+square_to_64(from))\r
- ^ random_64(piece_index+square_to_64(to));\r
-}\r
-\r
-// end of move_do.cpp\r
-\r
+++ /dev/null
-\r
-// move_gen.cpp\r
-\r
-// includes\r
-\r
-#include "attack.h"\r
-#include "board.h"\r
-#include "colour.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "move_gen.h"\r
-#include "move_legal.h"\r
-#include "piece.h"\r
-#include "util.h"\r
-\r
-// prototypes\r
-\r
-static void add_all_moves (list_t * list, const board_t * board);\r
-static void add_castle_moves (list_t * list, const board_t * board);\r
-\r
-static void add_pawn_move (list_t * list, int from, int to);\r
-\r
-// functions\r
-\r
-// gen_legal_moves()\r
-\r
-void gen_legal_moves(list_t * list, const board_t * board) {\r
-\r
- ASSERT(list!=NULL);\r
- ASSERT(board_is_ok(board));\r
-\r
- gen_moves(list,board);\r
- filter_legal(list,board);\r
-}\r
-\r
-// gen_moves()\r
-\r
-void gen_moves(list_t * list, const board_t * board) {\r
-\r
- ASSERT(list!=NULL);\r
- ASSERT(board_is_ok(board));\r
-\r
- list_clear(list);\r
-\r
- add_all_moves(list,board);\r
- if (!is_in_check(board,board->turn)) add_castle_moves(list,board);\r
-}\r
-\r
-// add_all_moves()\r
-\r
-static void add_all_moves(list_t * list, const board_t * board) {\r
-\r
- int me, opp;\r
- const uint8 * ptr;\r
- const sint8 * ptr_inc;\r
- int from, to;\r
- int inc;\r
- int piece, capture;\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(board_is_ok(board));\r
-\r
- me = board->turn;\r
- opp = colour_opp(me);\r
-\r
- for (ptr = board->list[me]; (from=*ptr) != SquareNone; ptr++) {\r
-\r
- piece = board->square[from];\r
- ASSERT(colour_equal(piece,me));\r
-\r
- switch (piece_type(piece)) {\r
-\r
- case WhitePawn64:\r
-\r
- to = from + 15;\r
- if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
- add_pawn_move(list,from,to);\r
- }\r
-\r
- to = from + 17;\r
- if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
- add_pawn_move(list,from,to);\r
- }\r
-\r
- to = from + 16;\r
- if (board->square[to] == Empty) {\r
- add_pawn_move(list,from,to);\r
- if (square_rank(from) == Rank2) {\r
- to = from + 32;\r
- if (board->square[to] == Empty) {\r
- ASSERT(!square_is_promote(to));\r
- list_add(list,move_make(from,to));\r
- }\r
- }\r
- }\r
-\r
- break;\r
-\r
- case BlackPawn64:\r
-\r
- to = from - 17;\r
- if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
- add_pawn_move(list,from,to);\r
- }\r
-\r
- to = from - 15;\r
- if (to == board->ep_square || colour_equal(board->square[to],opp)) {\r
- add_pawn_move(list,from,to);\r
- }\r
-\r
- to = from - 16;\r
- if (board->square[to] == Empty) {\r
- add_pawn_move(list,from,to);\r
- if (square_rank(from) == Rank7) {\r
- to = from - 32;\r
- if (board->square[to] == Empty) {\r
- ASSERT(!square_is_promote(to));\r
- list_add(list,move_make(from,to));\r
- }\r
- }\r
- }\r
-\r
- break;\r
-\r
- case Knight64:\r
-\r
- for (ptr_inc = KnightInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
- to = from + inc;\r
- capture = board->square[to];\r
- if (capture == Empty || colour_equal(capture,opp)) {\r
- list_add(list,move_make(from,to));\r
- }\r
- }\r
-\r
- break;\r
-\r
- case Bishop64:\r
-\r
- for (ptr_inc = BishopInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
- for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
- list_add(list,move_make(from,to));\r
- }\r
- if (colour_equal(capture,opp)) {\r
- list_add(list,move_make(from,to));\r
- }\r
- }\r
-\r
- break;\r
-\r
- case Rook64:\r
-\r
- for (ptr_inc = RookInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
- for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
- list_add(list,move_make(from,to));\r
- }\r
- if (colour_equal(capture,opp)) {\r
- list_add(list,move_make(from,to));\r
- }\r
- }\r
-\r
- break;\r
-\r
- case Queen64:\r
-\r
- for (ptr_inc = QueenInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
- for (to = from+inc; (capture=board->square[to]) == Empty; to += inc) {\r
- list_add(list,move_make(from,to));\r
- }\r
- if (colour_equal(capture,opp)) {\r
- list_add(list,move_make(from,to));\r
- }\r
- }\r
-\r
- break;\r
-\r
- case King64:\r
-\r
- for (ptr_inc = KingInc; (inc=*ptr_inc) != IncNone; ptr_inc++) {\r
- to = from + inc;\r
- capture = board->square[to];\r
- if (capture == Empty || colour_equal(capture,opp)) {\r
- list_add(list,move_make(from,to));\r
- }\r
- }\r
-\r
- break;\r
-\r
- default:\r
-\r
- ASSERT(false);\r
- break;\r
- }\r
- }\r
-}\r
-\r
-// add_castle_moves()\r
-\r
-static void add_castle_moves(list_t * list, const board_t * board) {\r
-\r
- int me, opp;\r
- int rank;\r
- int king_from, king_to;\r
- int rook_from, rook_to;\r
- bool legal;\r
- int inc;\r
- int sq;\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(board_is_ok(board));\r
-\r
- ASSERT(!is_in_check(board,board->turn));\r
-\r
- me = board->turn;\r
- opp = colour_opp(me);\r
-\r
- rank = colour_is_white(me) ? Rank1 : Rank8;\r
-\r
- // h-side castling\r
-\r
- if (board->castle[me][SideH] != SquareNone) {\r
-\r
- king_from = king_pos(board,me);\r
- king_to = square_make(FileG,rank);\r
- rook_from = board->castle[me][SideH];\r
- rook_to = square_make(FileF,rank);\r
-\r
- ASSERT(square_rank(king_from)==rank);\r
- ASSERT(square_rank(rook_from)==rank);\r
- ASSERT(board->square[king_from]==(King64|me)); // HACK\r
- ASSERT(board->square[rook_from]==(Rook64|me)); // HACK\r
- ASSERT(rook_from>king_from);\r
-\r
- legal = true;\r
-\r
- if (king_to != king_from) {\r
-\r
- inc = (king_to > king_from) ? +1 : -1;\r
-\r
- for (sq = king_from+inc; true; sq += inc) {\r
-\r
- if (sq != rook_from && board->square[sq] != Empty) legal = false;\r
- if (is_attacked(board,sq,opp)) legal = false;\r
-\r
- if (sq == king_to) break;\r
- }\r
- }\r
-\r
- if (rook_to != rook_from) {\r
-\r
- inc = (rook_to > rook_from) ? +1 : -1;\r
-\r
- for (sq = rook_from+inc; true; sq += inc) {\r
- if (sq != king_from && board->square[sq] != Empty) legal = false;\r
- if (sq == rook_to) break;\r
- }\r
- }\r
-\r
- if (legal) list_add(list,move_make(king_from,rook_from));\r
- }\r
-\r
- // a-side castling\r
-\r
- if (board->castle[me][SideA] != SquareNone) {\r
-\r
- king_from = king_pos(board,me);\r
- king_to = square_make(FileC,rank);\r
- rook_from = board->castle[me][SideA];\r
- rook_to = square_make(FileD,rank);\r
-\r
- ASSERT(square_rank(king_from)==rank);\r
- ASSERT(square_rank(rook_from)==rank);\r
- ASSERT(board->square[king_from]==(King64|me)); // HACK\r
- ASSERT(board->square[rook_from]==(Rook64|me)); // HACK\r
- ASSERT(rook_from<king_from);\r
-\r
- legal = true;\r
-\r
- if (king_to != king_from) {\r
-\r
- inc = (king_to > king_from) ? +1 : -1;\r
-\r
- for (sq = king_from+inc; true; sq += inc) {\r
-\r
- if (sq != rook_from && board->square[sq] != Empty) legal = false;\r
- if (is_attacked(board,sq,opp)) legal = false;\r
-\r
- if (sq == king_to) break;\r
- }\r
- }\r
-\r
- if (rook_to != rook_from) {\r
-\r
- inc = (rook_to > rook_from) ? +1 : -1;\r
-\r
- for (sq = rook_from+inc; true; sq += inc) {\r
- if (sq != king_from && board->square[sq] != Empty) legal = false;\r
- if (sq == rook_to) break;\r
- }\r
- }\r
-\r
- if (legal) list_add(list,move_make(king_from,rook_from));\r
- }\r
-}\r
-\r
-// add_pawn_move()\r
-\r
-static void add_pawn_move(list_t * list, int from, int to) {\r
-\r
- int move;\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(square_is_ok(from));\r
- ASSERT(square_is_ok(to));\r
-\r
- move = move_make(from,to);\r
-\r
- if (square_is_promote(to)) {\r
- list_add(list,move|MovePromoteKnight);\r
- list_add(list,move|MovePromoteBishop);\r
- list_add(list,move|MovePromoteRook);\r
- list_add(list,move|MovePromoteQueen);\r
- } else {\r
- list_add(list,move);\r
- }\r
-}\r
-\r
-// end of move_gen.cpp\r
-\r
+++ /dev/null
-\r
-// move_legal.cpp\r
-\r
-// includes\r
-\r
-#include "attack.h"\r
-#include "colour.h"\r
-#include "fen.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_gen.h"\r
-#include "move_legal.h"\r
-#include "piece.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// prototypes\r
-\r
-static bool move_is_legal_debug (int move, const board_t * board);\r
-\r
-// functions\r
-\r
-// move_is_pseudo()\r
-\r
-bool move_is_pseudo(int move, const board_t * board) {\r
-\r
- list_t list[1];\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- gen_moves(list,board);\r
-\r
- return list_contain(list,move);\r
-}\r
-\r
-// pseudo_is_legal()\r
-\r
-bool pseudo_is_legal(int move, const board_t * board) {\r
-\r
- board_t new_board[1];\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- ASSERT(move_is_pseudo(move,board));\r
-\r
- board_copy(new_board,board);\r
- move_do(new_board,move);\r
-\r
- return !is_in_check(new_board,colour_opp(new_board->turn));\r
-}\r
-\r
-// move_is_legal()\r
-\r
-bool move_is_legal(int move, const board_t * board) {\r
-\r
- bool legal;\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- legal = move_is_pseudo(move,board) && pseudo_is_legal(move,board);\r
- ASSERT(legal==move_is_legal_debug(move,board));\r
-\r
- return legal;\r
-}\r
-\r
-// filter_legal()\r
-\r
-void filter_legal(list_t * list, const board_t * board) {\r
-\r
- int pos;\r
- int i, move, value;\r
-\r
- ASSERT(list_is_ok(list));\r
- ASSERT(board_is_ok(board));\r
-\r
- pos = 0;\r
-\r
- for (i = 0; i < list_size(list); i++) {\r
-\r
- ASSERT(pos>=0&&pos<=i);\r
-\r
- move = list_move(list,i);\r
- value = list_value(list,i);\r
-\r
- if (pseudo_is_legal(move,board)) {\r
- list->move[pos] = move;\r
- list->value[pos] = value;\r
- pos++;\r
- }\r
- }\r
-\r
- ASSERT(pos>=0&&pos<=list_size(list));\r
- list->size = pos;\r
-}\r
-\r
-// move_is_legal_debug()\r
-\r
-static bool move_is_legal_debug(int move, const board_t * board) {\r
-\r
- list_t list[1];\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
-\r
- gen_legal_moves(list,board);\r
-\r
- return list_contain(list,move);\r
-}\r
-\r
-// end of move_legal.cpp\r
-\r
+++ /dev/null
-\r
-// option.cpp\r
-\r
-// includes\r
-\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "option.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool UseDebug = false;\r
-\r
-\r
-// variables\r
-\r
-#define NNB { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL }\r
-option_t Option[] = {\r
-\r
- { "OptionFile", "string","0","0", "polyglot.ini", NULL,0,NNB, PG}, \r
-\r
- // options\r
-\r
- { "EngineName", "string","0","0", "<empty>" , NULL,0,NNB, PG}, \r
- { "EngineDir", "string","0","0", "." , NULL,0,NNB, PG}, \r
- { "EngineCommand", "string","0","0", "<empty>" , NULL,0,NNB, PG}, \r
-\r
- { "Log", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD|UCI}, \r
- { "LogFile", "string","0","0", "polyglot.log", NULL,0,NNB, PG|XBOARD|UCI}, \r
-\r
- { "UCI", "string","0","0", "false" , NULL,0,NNB, PG}, \r
-\r
- { "UseNice", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD|UCI}, \r
- { "NiceValue", "spin", "0","20", "5" , NULL,0,NNB, PG|XBOARD|UCI}, \r
-\r
- { "Chess960", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, \r
-\r
- { "Resign", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, \r
- { "ResignMoves", "spin","0","10000", "3" , NULL,0,NNB, PG|XBOARD}, \r
- { "ResignScore", "spin","0","10000", "600" , NULL,0,NNB, PG|XBOARD}, \r
-\r
- { "MateScore", "spin","0","1000000", "10000" , NULL,0,NNB, PG|XBOARD}, \r
-\r
- { "Book", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD|UCI}, \r
- { "BookFile", "string","0","0", "book.bin" , NULL,0,NNB, PG|XBOARD|UCI}, \r
-\r
- { "BookRandom", "check","0","0", "true" , NULL,0,NNB, PG|XBOARD|UCI}, \r
- { "BookLearn", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, \r
-\r
- { "KibitzMove", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, \r
- { "KibitzPV", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, \r
-\r
- { "KibitzCommand", "string","0","0", "tellall" , NULL,0,NNB, PG|XBOARD}, \r
- { "KibitzDelay", "spin","0","10000", "5" , NULL,0,NNB, PG|XBOARD}, \r
- { "KibitzInterval", "spin","0","10000", "0" , NULL,0,NNB, PG|XBOARD}, \r
-\r
- { "ShowPonder", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, \r
- { "ScoreWhite", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, \r
-\r
- // work-arounds\r
-\r
- { "UCIVersion", "spin","1","2", "2" , NULL,0,NNB, PG|XBOARD}, \r
- { "CanPonder", "check","1","2", "false" , NULL,0,NNB, PG|XBOARD}, \r
- { "SyncStop", "check","1","2", "false" , NULL,0,NNB, PG|XBOARD}, \r
- { "Affinity", "spin","-1","32", "-1" , NULL,0,NNB, PG}, \r
- { "RepeatPV", "check","0","0", "true" , NULL,0,NNB, PG|XBOARD},\r
- { "PromoteWorkAround","check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, \r
-\r
- { NULL, NULL,"0","0", NULL , NULL,0,NNB, 0},\r
-};\r
-\r
-// prototypes\r
-\r
-static option_t * option_find (const char var[]);\r
-\r
-// functions\r
-\r
-// option_init()\r
-\r
-void option_init() {\r
-\r
- option_t *p=Option;\r
- const char * name;\r
-\r
- while((name=(p++)->name)){\r
- option_set(name,option_get_default(name));\r
- }\r
-}\r
-\r
-\r
-// option_set()\r
-\r
-bool option_set(const char name[], const char value[]) {\r
-\r
- option_t * opt;\r
- ASSERT(name!=NULL);\r
- ASSERT(value!=NULL);\r
-\r
- opt = option_find(name);\r
- if (opt == NULL) return false;\r
-\r
- my_string_set(&opt->value,value);\r
-\r
- if (UseDebug) my_log("POLYGLOT OPTION SET \"%s\" -> \"%s\"\n",opt->name,opt->value);\r
-\r
- return true;\r
-}\r
-// option_set()\r
-\r
-bool option_set_default(const char name[], const char value[]) {\r
-\r
- option_t * opt;\r
- ASSERT(name!=NULL);\r
- ASSERT(value!=NULL);\r
-\r
- opt = option_find(name);\r
- if (opt == NULL) return false;\r
-\r
- opt->default_=my_strdup(value);\r
-\r
- if (UseDebug) my_log("POLYGLOT OPTION DEFAULT SET \"%s\" -> \"%s\"\n",opt->name,opt->default_);\r
-\r
- return true;\r
-}\r
-\r
-// option_get()\r
-\r
-const char * option_get(const char name[]) {\r
-\r
- option_t * opt;\r
-\r
- ASSERT(name!=NULL);\r
-\r
- opt = option_find(name);\r
- if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",name);\r
-\r
- if (UseDebug) my_log("POLYGLOT OPTION GET \"%s\" -> \"%s\"\n",opt->name,opt->value);\r
-\r
- return opt->value;\r
-}\r
-\r
-// option_get_default()\r
-\r
-const char * option_get_default(const char name[]) {\r
-\r
- option_t * opt;\r
-\r
- ASSERT(name!=NULL);\r
-\r
- opt = option_find(name);\r
- if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",name);\r
-\r
- if (UseDebug) my_log("POLYGLOT OPTION GET \"%s\" -> \"%s\"\n",opt->name,opt->value);\r
-\r
- return opt->default_;\r
-}\r
-\r
-// option_get_bool()\r
-\r
-bool option_get_bool(const char name[]) {\r
-\r
- const char * value;\r
-\r
- value = option_get(name);\r
-\r
- if (false) {\r
- } else if (my_string_case_equal(value,"true") || my_string_case_equal(value,"yes") || my_string_equal(value,"1")) {\r
- return true;\r
- } else if (my_string_case_equal(value,"false") || my_string_case_equal(value,"no") || my_string_equal(value,"0")) {\r
- return false;\r
- }\r
-\r
- ASSERT(false);\r
-\r
- return false;\r
-}\r
-\r
-// option_get_double()\r
-\r
-double option_get_double(const char name[]) {\r
-\r
- const char * value;\r
-\r
- value = option_get(name);\r
-\r
- return atof(value);\r
-}\r
-\r
-// option_get_int()\r
-\r
-int option_get_int(const char name[]) {\r
-\r
- const char * value;\r
-\r
- value = option_get(name);\r
-\r
- return atoi(value);\r
-}\r
-\r
-// option_get_string()\r
-\r
-const char * option_get_string(const char name[]) {\r
-\r
- const char * value;\r
-\r
- value = option_get(name);\r
-\r
- return value;\r
-}\r
-\r
-// option_find()\r
-\r
-static option_t * option_find(const char name[]) {\r
-\r
- option_t * opt;\r
-\r
- ASSERT(name!=NULL);\r
-\r
-\r
- for (opt = &Option[0]; opt->name != NULL; opt++) {\r
- if (my_string_case_equal(opt->name,name)) return opt;\r
- }\r
-\r
- return NULL;\r
-}\r
-\r
-// end of option.cpp\r
-\r
+++ /dev/null
-\r
-// parse.cpp\r
-\r
-// includes\r
-\r
-#include <cstring>\r
-\r
-#include "parse.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const int StringSize = 256;\r
-\r
-// variables\r
-\r
-char * Star[STAR_NUMBER];\r
-\r
-// prototypes\r
-\r
-static bool match_rec (char string[], const char pattern[], char * star[]);\r
-\r
-// functions\r
-\r
-// match()\r
-\r
-bool match(char string[], const char pattern[]) {\r
-\r
- ASSERT(string!=NULL);\r
- ASSERT(pattern!=NULL);\r
-\r
- ASSERT(strstr(pattern,"**")==NULL);\r
-\r
- return match_rec(string,pattern,Star);\r
-}\r
-\r
-// match_rec()\r
-\r
-static bool match_rec(char string[], const char pattern[], char * star[]) {\r
-\r
- int c;\r
-\r
- ASSERT(string!=NULL);\r
- ASSERT(pattern!=NULL);\r
- ASSERT(star!=NULL);\r
-\r
- // iterative matches\r
-\r
- while ((c=*pattern++) != '*') {\r
- if (false) {\r
- } else if (c == '\0') { // end of pattern\r
- while (*string == ' ') string++; // skip trailing spaces\r
- return *string == '\0';\r
- } else if (c == ' ') { // spaces\r
- if (*string++ != ' ') return false; // mismatch\r
- while (*string == ' ') string++; // skip trailing spaces\r
- } else { // normal character\r
- if (*string++ != c) return false; // mismatch\r
- }\r
- }\r
-\r
- // recursive wildcard match\r
-\r
- ASSERT(c=='*');\r
-\r
- while (*string == ' ') string++; // skip leading spaces\r
- *star++ = string; // remember beginning of star\r
-\r
- while ((c=*string++) != '\0') { // reject empty-string match\r
- if (c != ' ' && match_rec(string,pattern,star)) { // shortest match\r
- ASSERT(string>star[-1]);\r
- *string = '\0'; // truncate star\r
- return true;\r
- }\r
- }\r
-\r
- return false;\r
-}\r
-\r
-// parse_is_ok()\r
-\r
-bool parse_is_ok(const parse_t * parse) {\r
-\r
- if (parse == NULL) return false;\r
- if (parse->string == NULL) return false;\r
- if (parse->pos < 0 || parse->pos > (int) strlen(parse->string)) return false;\r
- if (parse->keyword_nb < 0 || parse->keyword_nb >= KEYWORD_NUMBER) return false;\r
-\r
- return true;\r
-}\r
-\r
-// parse_open()\r
-\r
-void parse_open(parse_t * parse, const char string[]) {\r
-\r
- ASSERT(parse!=NULL);\r
- ASSERT(string!=NULL);\r
-\r
- parse->string = string;\r
- parse->pos = 0;\r
- parse->keyword_nb = 0;\r
-}\r
-\r
-// parse_close()\r
-\r
-void parse_close(parse_t * parse) {\r
-\r
- int i;\r
-\r
- ASSERT(parse_is_ok(parse));\r
-\r
- parse->string = NULL;\r
- parse->pos = 0;\r
-\r
- for (i = 0; i < parse->keyword_nb; i++) {\r
- my_string_clear(&parse->keyword[i]);\r
- }\r
-\r
- parse->keyword_nb = 0;\r
-}\r
-\r
-// parse_add_keyword()\r
-\r
-void parse_add_keyword(parse_t * parse, const char keyword[]) {\r
-\r
- const char * * string;\r
-\r
- ASSERT(parse_is_ok(parse));\r
- ASSERT(keyword!=NULL);\r
-\r
- if (parse->keyword_nb < KEYWORD_NUMBER) {\r
-\r
- string = &parse->keyword[parse->keyword_nb];\r
- parse->keyword_nb++;\r
-\r
- *string = NULL;\r
- my_string_set(string,keyword);\r
- }\r
-}\r
-\r
-// parse_get_word()\r
-\r
-bool parse_get_word(parse_t * parse, char string[], int size) {\r
-\r
- int pos;\r
- int c;\r
-\r
- ASSERT(parse!=NULL);\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=256);\r
-\r
- // skip blanks\r
-\r
- for (; parse->string[parse->pos] == ' '; parse->pos++)\r
- ;\r
-\r
- ASSERT(parse->string[parse->pos]!=' ');\r
-\r
- // copy word\r
-\r
- pos = 0;\r
-\r
- while (true) {\r
-\r
- c = parse->string[parse->pos];\r
- if (c == ' ' || pos >= size-1) c = '\0';\r
-\r
- string[pos] = c;\r
- if (c == '\0') break;\r
-\r
- parse->pos++;\r
- pos++;\r
- }\r
-\r
- ASSERT(strchr(string,' ')==NULL);\r
-\r
- return pos > 0; // non-empty word?\r
-}\r
-\r
-// parse_get_string()\r
-\r
-bool parse_get_string(parse_t * parse, char string[], int size) {\r
-\r
- int pos;\r
- parse_t parse_2[1];\r
- char word[StringSize];\r
- int i;\r
- int c;\r
-\r
- ASSERT(parse!=NULL);\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=256);\r
-\r
- // skip blanks\r
-\r
- for (; parse->string[parse->pos] == ' '; parse->pos++)\r
- ;\r
-\r
- ASSERT(parse->string[parse->pos]!=' ');\r
-\r
- // copy string\r
-\r
- pos = 0;\r
-\r
- while (true) {\r
-\r
- parse_open(parse_2,&parse->string[parse->pos]);\r
-\r
- if (!parse_get_word(parse_2,word,StringSize)) {\r
- string[pos] = '\0';\r
- parse_close(parse_2);\r
- goto finished;\r
- }\r
-\r
- for (i = 0; i < parse->keyword_nb; i++) {\r
- if (my_string_equal(parse->keyword[i],word)) {\r
- string[pos] = '\0';\r
- parse_close(parse_2);\r
- goto finished;\r
- }\r
- }\r
-\r
- parse_close(parse_2);\r
-\r
- // copy spaces\r
-\r
- while (true) {\r
-\r
- c = parse->string[parse->pos];\r
- if (c != ' ') break;\r
-\r
- if (pos >= size-1) c = '\0';\r
-\r
- string[pos] = c;\r
- if (c == '\0') break;\r
-\r
- parse->pos++;\r
- pos++;\r
- }\r
-\r
- // copy non spaces\r
-\r
- while (true) {\r
-\r
- c = parse->string[parse->pos];\r
- if (c == ' ' || pos >= size-1) c = '\0';\r
-\r
- string[pos] = c;\r
- if (c == '\0') break;\r
-\r
- parse->pos++;\r
- pos++;\r
- }\r
-\r
- string[pos] = '\0';\r
- }\r
-\r
-finished: ;\r
-\r
- return pos > 0; // non-empty string?\r
-}\r
-\r
-// end of parse.cpp\r
-\r
+++ /dev/null
-\r
-// pgn.cpp\r
-\r
-// includes\r
-\r
-#include <cctype>\r
-#include <cerrno>\r
-#include <cstdio>\r
-#include <cstring>\r
-\r
-#include "pgn.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool DispMove = false;\r
-static const bool DispToken = false;\r
-static const bool DispChar = false;\r
-\r
-static const int TAB_SIZE = 8;\r
-\r
-static const int CHAR_EOF = 256;\r
-\r
-// types\r
-\r
-enum token_t {\r
- TOKEN_ERROR = -1,\r
- TOKEN_EOF = 256,\r
- TOKEN_SYMBOL = 257,\r
- TOKEN_STRING = 258,\r
- TOKEN_INTEGER = 259,\r
- TOKEN_NAG = 260,\r
- TOKEN_RESULT = 261\r
-};\r
-\r
-// prototypes\r
-\r
-static void pgn_token_read (pgn_t * pgn);\r
-static void pgn_token_unread (pgn_t * pgn);\r
-\r
-static void pgn_read_token (pgn_t * pgn);\r
-\r
-static bool is_symbol_start (int c);\r
-static bool is_symbol_next (int c);\r
-\r
-static void pgn_skip_blanks (pgn_t * pgn);\r
-\r
-static void pgn_char_read (pgn_t * pgn);\r
-static void pgn_char_unread (pgn_t * pgn);\r
-\r
-// functions\r
-\r
-// pgn_open()\r
-\r
-void pgn_open(pgn_t * pgn, const char file_name[]) {\r
-\r
- ASSERT(pgn!=NULL);\r
- ASSERT(file_name!=NULL);\r
-\r
- pgn->file = fopen(file_name,"r");\r
- if (pgn->file == NULL) my_fatal("pgn_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
-\r
- pgn->char_hack = CHAR_EOF; // DEBUG\r
- pgn->char_line = 1;\r
- pgn->char_column = 0;\r
- pgn->char_unread = false;\r
- pgn->char_first = true;\r
-\r
- pgn->token_type = TOKEN_ERROR; // DEBUG\r
- strcpy(pgn->token_string,"?"); // DEBUG\r
- pgn->token_length = -1; // DEBUG\r
- pgn->token_line = -1; // DEBUG\r
- pgn->token_column = -1; // DEBUG\r
- pgn->token_unread = false;\r
- pgn->token_first = true;\r
-\r
- strcpy(pgn->result,"?"); // DEBUG\r
- strcpy(pgn->fen,"?"); // DEBUG\r
-\r
- pgn->move_line = -1; // DEBUG\r
- pgn->move_column = -1; // DEBUG\r
-}\r
-\r
-// pgn_close()\r
-\r
-void pgn_close(pgn_t * pgn) {\r
-\r
- ASSERT(pgn!=NULL);\r
-\r
- fclose(pgn->file);\r
-}\r
-\r
-// pgn_next_game()\r
-\r
-bool pgn_next_game(pgn_t * pgn) {\r
-\r
- char name[PGN_STRING_SIZE];\r
- char value[PGN_STRING_SIZE];\r
-\r
- ASSERT(pgn!=NULL);\r
-\r
- // init\r
-\r
- strcpy(pgn->result,"*");\r
- strcpy(pgn->fen,"");\r
-\r
- // loop\r
-\r
- while (true) {\r
-\r
- pgn_token_read(pgn);\r
-\r
- if (pgn->token_type != '[') break;\r
-\r
- // tag\r
-\r
- pgn_token_read(pgn);\r
- if (pgn->token_type != TOKEN_SYMBOL) {\r
- my_fatal("pgn_next_game(): malformed tag at line %d, column %d, game %d\n",pgn->token_line,pgn->token_column,pgn->game_nb);\r
- }\r
- strcpy(name,pgn->token_string);\r
-\r
- pgn_token_read(pgn);\r
- if (pgn->token_type != TOKEN_STRING) {\r
- my_fatal("pgn_next_game(): malformed tag at line %d, column %d, game %d\n",pgn->token_line,pgn->token_column,pgn->game_nb);\r
- }\r
- strcpy(value,pgn->token_string);\r
-\r
- pgn_token_read(pgn);\r
- if (pgn->token_type != ']') {\r
- my_fatal("pgn_next_game(): malformed tag at line %d, column %d, game %d\n",pgn->token_line,pgn->token_column,pgn->game_nb);\r
- }\r
-\r
- // special tag?\r
-\r
- if (false) {\r
- } else if (my_string_equal(name,"Result")) {\r
- strcpy(pgn->result,value);\r
- } else if (my_string_equal(name,"FEN")) {\r
- strcpy(pgn->fen,value);\r
- }\r
- }\r
-\r
- if (pgn->token_type == TOKEN_EOF) return false;\r
-\r
- pgn_token_unread(pgn);\r
-\r
- return true;\r
-}\r
-\r
-// pgn_next_move()\r
-\r
-bool pgn_next_move(pgn_t * pgn, char string[], int size) {\r
-\r
- int depth;\r
-\r
- ASSERT(pgn!=NULL);\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=PGN_STRING_SIZE);\r
-\r
- // init\r
-\r
- pgn->move_line = -1; // DEBUG\r
- pgn->move_column = -1; // DEBUG\r
-\r
- // loop\r
-\r
- depth = 0;\r
-\r
- while (true) {\r
-\r
- pgn_token_read(pgn);\r
-\r
- if (false) {\r
-\r
- } else if (pgn->token_type == '(') {\r
-\r
- // open RAV\r
-\r
- depth++;\r
-\r
- } else if (pgn->token_type == ')') {\r
-\r
- // close RAV\r
-\r
- if (depth == 0) {\r
- my_fatal("pgn_next_move(): malformed variation at line %d, column %d, game %d\n",pgn->token_line,pgn->token_column,pgn->game_nb);\r
- }\r
-\r
- depth--;\r
- ASSERT(depth>=0);\r
-\r
- } else if (pgn->token_type == TOKEN_RESULT) {\r
-\r
- // game finished\r
-\r
- if (depth > 0) {\r
- my_fatal("pgn_next_move(): malformed variation at line %d, column %d, game %d\n",pgn->token_line,pgn->token_column,pgn->game_nb);\r
- }\r
-\r
- return false;\r
-\r
- } else {\r
-\r
- // skip optional move number\r
-\r
- if (pgn->token_type == TOKEN_INTEGER) {\r
- do pgn_token_read(pgn); while (pgn->token_type == '.');\r
- }\r
-\r
- // move must be a symbol\r
-\r
- if (pgn->token_type != TOKEN_SYMBOL) {\r
- my_fatal("pgn_next_move(): malformed move at line %d, column %d, game %d\n",pgn->token_line,pgn->token_column,pgn->game_nb);\r
- }\r
-\r
- // store move for later use\r
-\r
- if (depth == 0) {\r
-\r
- if (pgn->token_length >= size) {\r
- my_fatal("pgn_next_move(): move too long at line %d, column %d, game %d\n",pgn->token_line,pgn->token_column,pgn->game_nb);\r
- }\r
-\r
- strcpy(string,pgn->token_string);\r
- pgn->move_line = pgn->token_line;\r
- pgn->move_column = pgn->token_column;\r
- }\r
-\r
- // skip optional NAGs\r
-\r
- do pgn_token_read(pgn); while (pgn->token_type == TOKEN_NAG);\r
- pgn_token_unread(pgn);\r
-\r
- // return move\r
-\r
- if (depth == 0) {\r
- if (DispMove) printf("move=\"%s\"\n",string);\r
- return true;\r
- }\r
- }\r
- }\r
-\r
- ASSERT(false);\r
-\r
- return false;\r
-}\r
-\r
-// pgn_token_read()\r
-\r
-static void pgn_token_read(pgn_t * pgn) {\r
-\r
- ASSERT(pgn!=NULL);\r
-\r
- // token "stack"\r
-\r
- if (pgn->token_unread) {\r
- pgn->token_unread = false;\r
- return;\r
- }\r
-\r
- // consume the current token\r
-\r
- if (pgn->token_first) {\r
- pgn->token_first = false;\r
- } else {\r
- ASSERT(pgn->token_type!=TOKEN_ERROR);\r
- ASSERT(pgn->token_type!=TOKEN_EOF);\r
- }\r
-\r
- // read a new token\r
-\r
- pgn_read_token(pgn);\r
- if (pgn->token_type == TOKEN_ERROR) my_fatal("pgn_token_read(): lexical error at line %d, column %d, game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
-\r
- if (DispToken) printf("< L%d C%d \"%s\" (%03X)\n",pgn->token_line,pgn->token_column,pgn->token_string,pgn->token_type);\r
-}\r
-\r
-// pgn_token_unread()\r
-\r
-static void pgn_token_unread(pgn_t * pgn) {\r
-\r
- ASSERT(pgn!=NULL);\r
-\r
- ASSERT(!pgn->token_unread);\r
- ASSERT(!pgn->token_first);\r
-\r
- pgn->token_unread = true;\r
-}\r
-\r
-// pgn_read_token()\r
-\r
-static void pgn_read_token(pgn_t * pgn) {\r
-\r
- ASSERT(pgn!=NULL);\r
-\r
- // skip white-space characters\r
-\r
- pgn_skip_blanks(pgn);\r
-\r
- // init\r
-\r
- pgn->token_type = TOKEN_ERROR;\r
- strcpy(pgn->token_string,"");\r
- pgn->token_length = 0;\r
- pgn->token_line = pgn->char_line;\r
- pgn->token_column = pgn->char_column;\r
-\r
- // determine token type\r
-\r
- if (false) {\r
-\r
- } else if (pgn->char_hack == CHAR_EOF) {\r
-\r
- pgn->token_type = TOKEN_EOF;\r
-\r
- } else if (strchr(".[]()<>",pgn->char_hack) != NULL) {\r
-\r
- // single-character token\r
-\r
- pgn->token_type = pgn->char_hack;\r
- sprintf(pgn->token_string,"%c",pgn->char_hack);\r
- pgn->token_length = 1;\r
-\r
- } else if (pgn->char_hack == '*') {\r
-\r
- pgn->token_type = TOKEN_RESULT;\r
- sprintf(pgn->token_string,"%c",pgn->char_hack);\r
- pgn->token_length = 1;\r
-\r
- } else if (pgn->char_hack == '!') {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (false) {\r
-\r
- } else if (pgn->char_hack == '!') { // "!!"\r
-\r
- pgn->token_type = TOKEN_NAG;\r
- strcpy(pgn->token_string,"3");\r
- pgn->token_length = 1;\r
-\r
- } else if (pgn->char_hack == '?') { // "!?"\r
-\r
- pgn->token_type = TOKEN_NAG;\r
- strcpy(pgn->token_string,"5");\r
- pgn->token_length = 1;\r
-\r
- } else { // "!"\r
-\r
- pgn_char_unread(pgn);\r
-\r
- pgn->token_type = TOKEN_NAG;\r
- strcpy(pgn->token_string,"1");\r
- pgn->token_length = 1;\r
- }\r
-\r
- } else if (pgn->char_hack == '?') {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (false) {\r
-\r
- } else if (pgn->char_hack == '?') { // "??"\r
-\r
- pgn->token_type = TOKEN_NAG;\r
- strcpy(pgn->token_string,"4");\r
- pgn->token_length = 1;\r
-\r
- } else if (pgn->char_hack == '!') { // "?!"\r
-\r
- pgn->token_type = TOKEN_NAG;\r
- strcpy(pgn->token_string,"6");\r
- pgn->token_length = 1;\r
-\r
- } else { // "?"\r
-\r
- pgn_char_unread(pgn);\r
-\r
- pgn->token_type = TOKEN_NAG;\r
- strcpy(pgn->token_string,"2");\r
- pgn->token_length = 1;\r
- }\r
-\r
- } else if (is_symbol_start(pgn->char_hack)) {\r
-\r
- // symbol, integer, or result\r
-\r
- pgn->token_type = TOKEN_INTEGER;\r
- pgn->token_length = 0;\r
-\r
- do {\r
-\r
- if (pgn->token_length >= PGN_STRING_SIZE-1) {\r
- my_fatal("pgn_read_token(): symbol too long at line %d, column %d,game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- if (!isdigit(pgn->char_hack)) pgn->token_type = TOKEN_SYMBOL;\r
-\r
- pgn->token_string[pgn->token_length++] = pgn->char_hack;\r
-\r
- pgn_char_read(pgn);\r
-\r
- } while (is_symbol_next(pgn->char_hack));\r
-\r
- pgn_char_unread(pgn);\r
-\r
- ASSERT(pgn->token_length>0&&pgn->token_length<PGN_STRING_SIZE);\r
- pgn->token_string[pgn->token_length] = '\0';\r
-\r
- if (my_string_equal(pgn->token_string,"1-0")\r
- || my_string_equal(pgn->token_string,"0-1")\r
- || my_string_equal(pgn->token_string,"1/2-1/2")) {\r
- pgn->token_type = TOKEN_RESULT;\r
- }\r
-\r
- } else if (pgn->char_hack == '"') {\r
-\r
- // string\r
-\r
- pgn->token_type = TOKEN_STRING;\r
- pgn->token_length = 0;\r
-\r
- while (true) {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (pgn->char_hack == CHAR_EOF) {\r
- my_fatal("pgn_read_token(): EOF in string at line %d, column %d, game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- if (pgn->char_hack == '"') break;\r
-\r
- if (pgn->char_hack == '\\') {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (pgn->char_hack == CHAR_EOF) {\r
- my_fatal("pgn_read_token(): EOF in string at line %d, column %d, game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- if (pgn->char_hack != '"' && pgn->char_hack != '\\') {\r
-\r
- // bad escape, ignore\r
-\r
- if (pgn->token_length >= PGN_STRING_SIZE-1) {\r
- my_fatal("pgn_read_token(): string too long at line %d, column %d,game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- pgn->token_string[pgn->token_length++] = '\\';\r
- }\r
- }\r
-\r
- if (pgn->token_length >= PGN_STRING_SIZE-1) {\r
- my_fatal("pgn_read_token(): string too long at line %d, column %d,game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- pgn->token_string[pgn->token_length++] = pgn->char_hack;\r
- }\r
-\r
- ASSERT(pgn->token_length>=0&&pgn->token_length<PGN_STRING_SIZE);\r
- pgn->token_string[pgn->token_length] = '\0';\r
-\r
- } else if (pgn->char_hack == '$') {\r
-\r
- // NAG\r
-\r
- pgn->token_type = TOKEN_NAG;\r
- pgn->token_length = 0;\r
-\r
- while (true) {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (!isdigit(pgn->char_hack)) break;\r
-\r
- if (pgn->token_length >= 3) {\r
- my_fatal("pgn_read_token(): NAG too long at line %d, column %d, game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- pgn->token_string[pgn->token_length++] = pgn->char_hack;\r
- }\r
-\r
- pgn_char_unread(pgn);\r
-\r
- if (pgn->token_length == 0) {\r
- my_fatal("pgn_read_token(): malformed NAG at line %d, column %d,game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- ASSERT(pgn->token_length>0&&pgn->token_length<=3);\r
- pgn->token_string[pgn->token_length] = '\0';\r
-\r
- } else {\r
-\r
- // unknown token\r
-\r
- my_fatal("lexical error at line %d, column %d, game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-}\r
-\r
-// pgn_skip_blanks()\r
-\r
-static void pgn_skip_blanks(pgn_t * pgn) {\r
-\r
- ASSERT(pgn!=NULL);\r
-\r
- while (true) {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (false) {\r
- }else if(pgn->char_hack==CHAR_EOF){ break;\r
- } else if (isspace(pgn->char_hack)) {\r
-\r
- // skip white space\r
-\r
- } else if (pgn->char_hack == ';') {\r
-\r
- // skip comment to EOL\r
-\r
- do {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (pgn->char_hack == CHAR_EOF) {\r
- my_fatal("pgn_skip_blanks(): EOF in comment at line %d, column %d,game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- } while (pgn->char_hack != '\n');\r
-\r
- } else if (pgn->char_hack == '%' && pgn->char_column == 0) {\r
-\r
- // skip comment to EOL\r
-\r
- do {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (pgn->char_hack == CHAR_EOF) {\r
- my_fatal("pgn_skip_blanks(): EOF in comment at line %d, column %d, game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- } while (pgn->char_hack != '\n');\r
-\r
- } else if (pgn->char_hack == '{') {\r
-\r
- // skip comment to next '}'\r
-\r
- do {\r
-\r
- pgn_char_read(pgn);\r
-\r
- if (pgn->char_hack == CHAR_EOF) {\r
- my_fatal("pgn_skip_blanks(): EOF in comment at line %d, column %d, game %d\n",pgn->char_line,pgn->char_column,pgn->game_nb);\r
- }\r
-\r
- } while (pgn->char_hack != '}');\r
-\r
- } else { // not a white space\r
-\r
- break;\r
- }\r
- }\r
-}\r
-\r
-// is_symbol_start()\r
-\r
-static bool is_symbol_start(int c) {\r
-\r
- return strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",c) != NULL;\r
-}\r
-\r
-// is_symbol_next()\r
-\r
-static bool is_symbol_next(int c) {\r
-\r
- return strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+#=:-/",c) != NULL;\r
-}\r
-\r
-// pgn_char_read()\r
-\r
-static void pgn_char_read(pgn_t * pgn) {\r
-\r
- ASSERT(pgn!=NULL);\r
-\r
- // char "stack"\r
-\r
- if (pgn->char_unread) {\r
- pgn->char_unread = false;\r
- return;\r
- }\r
-\r
- // consume the current character\r
-\r
- if (pgn->char_first) {\r
-\r
- pgn->char_first = false;\r
-\r
- } else {\r
-\r
- // update counters\r
-\r
- ASSERT(pgn->char_hack!=CHAR_EOF);\r
-\r
- if (false) {\r
- } else if (pgn->char_hack == '\n') {\r
- pgn->char_line++;\r
- pgn->char_column = 0;\r
- } else if (pgn->char_hack == '\t') {\r
- pgn->char_column += TAB_SIZE - (pgn->char_column % TAB_SIZE);\r
- } else {\r
- pgn->char_column++;\r
- }\r
- }\r
-\r
- // read a new character\r
-\r
- pgn->char_hack = fgetc(pgn->file);\r
-\r
- if (pgn->char_hack == EOF) {\r
- if (ferror(pgn->file)) my_fatal("pgn_char_read(): fgetc(): %s\n",strerror(errno));\r
- pgn->char_hack = CHAR_EOF;\r
- }\r
-\r
- if (DispChar) printf("< L%d C%d '%c' (%02X)\n",pgn->char_line,pgn->char_column,pgn->char_hack,pgn->char_hack);\r
-}\r
-\r
-// pgn_char_unread()\r
-\r
-static void pgn_char_unread(pgn_t * pgn) {\r
-\r
- ASSERT(pgn!=NULL);\r
-\r
- ASSERT(!pgn->char_unread);\r
- ASSERT(!pgn->char_first);\r
-\r
- pgn->char_unread = true;\r
-}\r
-\r
-// end of pgn.cpp\r
-\r
+++ /dev/null
-\r
-// piece.cpp\r
-\r
-// includes\r
-\r
-#include <cstring>\r
-\r
-#include "colour.h"\r
-#include "piece.h"\r
-#include "util.h"\r
-\r
-// "constants"\r
-\r
-static const uint8 MakePawn[ColourNb] = { PieceNone256, BlackPawn256, WhitePawn256 }; // -BW\r
-\r
-static const uint8 PieceFrom12[12] = {\r
- BlackPawn256, WhitePawn256,\r
- BlackKnight256, WhiteKnight256,\r
- BlackBishop256, WhiteBishop256,\r
- BlackRook256, WhiteRook256,\r
- BlackQueen256, WhiteQueen256,\r
- BlackKing256, WhiteKing256,\r
-};\r
-\r
-static const char PieceString[12+1] = "pPnNbBrRqQkK";\r
-\r
-// variables\r
-\r
-static sint8 PieceTo12[256];\r
-\r
-// functions\r
-\r
-// piece_init()\r
-\r
-void piece_init() {\r
-\r
- int piece;\r
-\r
- for (piece = 0; piece < 256; piece++) PieceTo12[piece] = -1;\r
-\r
- for (piece = 0; piece < 12; piece++) {\r
- PieceTo12[PieceFrom12[piece]] = piece;\r
- }\r
-}\r
-\r
-// piece_is_ok()\r
-\r
-bool piece_is_ok(int piece) {\r
-\r
- if (piece < 0 || piece >= 256) return false;\r
-\r
- if (PieceTo12[piece] < 0) return false;\r
-\r
- return true;\r
-}\r
-\r
-// piece_make_pawn()\r
-\r
-int piece_make_pawn(int colour) {\r
-\r
- ASSERT(colour_is_ok(colour));\r
-\r
- return MakePawn[colour];\r
-}\r
-\r
-// piece_pawn_opp()\r
-\r
-int piece_pawn_opp(int piece) {\r
-\r
- ASSERT(piece==BlackPawn256||piece==WhitePawn256);\r
-\r
- return piece ^ 15;\r
-}\r
-\r
-// piece_colour()\r
-\r
-int piece_colour(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return piece & 3;\r
-}\r
-\r
-// piece_type()\r
-\r
-int piece_type(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return piece & ~3;\r
-}\r
-\r
-// piece_is_pawn()\r
-\r
-bool piece_is_pawn(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return (piece & PawnFlags) != 0;\r
-}\r
-\r
-// piece_is_knight()\r
-\r
-bool piece_is_knight(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return (piece & KnightFlag) != 0;\r
-}\r
-\r
-// piece_is_bishop()\r
-\r
-bool piece_is_bishop(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return (piece & QueenFlags) == BishopFlag;\r
-}\r
-\r
-// piece_is_rook()\r
-\r
-bool piece_is_rook(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return (piece & QueenFlags) == RookFlag;\r
-}\r
-\r
-// piece_is_queen()\r
-\r
-bool piece_is_queen(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return (piece & QueenFlags) == QueenFlags;\r
-}\r
-\r
-// piece_is_king()\r
-\r
-bool piece_is_king(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return (piece & KingFlag) != 0;\r
-}\r
-\r
-// piece_is_slider()\r
-\r
-bool piece_is_slider(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return (piece & QueenFlags) != 0;\r
-}\r
-\r
-// piece_to_12()\r
-\r
-int piece_to_12(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return PieceTo12[piece];\r
-}\r
-\r
-// piece_from_12()\r
-\r
-int piece_from_12(int piece) {\r
-\r
- ASSERT(piece>=0&&piece<12);\r
-\r
- return PieceFrom12[piece];\r
-}\r
-\r
-// piece_to_char()\r
-\r
-int piece_to_char(int piece) {\r
-\r
- ASSERT(piece_is_ok(piece));\r
-\r
- return PieceString[piece_to_12(piece)];\r
-}\r
-\r
-// piece_from_char()\r
-\r
-int piece_from_char(int c) {\r
-\r
- const char * ptr;\r
-\r
- ptr = strchr(PieceString,c);\r
- if (ptr == NULL) return PieceNone256;\r
-\r
- return piece_from_12(ptr-PieceString);\r
-}\r
-\r
-// char_is_piece()\r
-\r
-bool char_is_piece(int c) {\r
-\r
- return strchr("PNBRQK",c) != NULL;\r
-}\r
-\r
-// end of piece.cpp\r
-\r
+++ /dev/null
-#ifdef _WIN32
-#include "pipe.h"
-#include "util.h"
-
-// functions
-
-DWORD WINAPI ThreadProc(LPVOID lpParam){
- PipeStruct *p=(PipeStruct *) lpParam;
- while(!p->EOF_input()){
- if(p->nReadEnd<LINE_INPUT_MAX_CHAR-1){
- p->ReadInput();
- }else{
- // wait until there is room in buffer
- Sleep(10);
- }
- }
- return 0;
-}
-
-
-
-void PipeStruct::Open(const char *szProcFile) {
- DWORD dwMode, dwThreadId;
- HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite;
- SECURITY_ATTRIBUTES sa;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- int fdInput;
- state=0;
- if (szProcFile == NULL) {
- hInput = GetStdHandle(STD_INPUT_HANDLE);
- hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- bConsole = GetConsoleMode(hInput, &dwMode);
- bPipe=FALSE;
- } else {
- sa.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa.bInheritHandle = TRUE;
- sa.lpSecurityDescriptor = NULL;
- CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0);
- CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0);
- si.cb = sizeof(STARTUPINFO);
- si.lpReserved = si.lpDesktop = si.lpTitle = NULL;
- si.dwFlags = STARTF_USESTDHANDLES;
- si.cbReserved2 = 0;
- si.lpReserved2 = NULL;
- si.hStdInput = hStdinRead;
- si.hStdOutput = hStdoutWrite;
- si.hStdError = hStdoutWrite;
- if(CreateProcess(NULL,
- (LPSTR) szProcFile,
- NULL,
- NULL,
- TRUE,
- DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,
- NULL,
- NULL,
- &si,
- &pi)){
- hProcess=pi.hProcess;
- CloseHandle(pi.hThread);
- CloseHandle(hStdinRead);
- CloseHandle(hStdoutWrite);
- hInput = hStdoutRead;
- hOutput = hStdinWrite;
- bConsole = FALSE;
- bPipe=TRUE;
- }else{
- my_fatal("PipeStruct::Open(): %s",my_error());
- }
- }
- if (bConsole) {
- SetConsoleMode(hInput,
- dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
- FlushConsoleInputBuffer(hInput);
- }
- fdInput=_open_osfhandle((long) hInput,_O_RDONLY);
- if(fdInput==-1){
- my_fatal("PipeStruct::Open(): %s",my_error());
- }
- fpInput=fdopen(fdInput,"r");
- if(fpInput==NULL){
- my_fatal("PipeStruct::Open(): %s",my_error());
- }
- nReadEnd = 0;
- lpFeedEnd = NULL;
- InitializeCriticalSection(&CriticalSection);
- hEvent=CreateEvent(NULL, // default security
- FALSE, // auto reset
- FALSE, // not signaled
- NULL // nameless
- );
- if(!hEvent){
- my_fatal("PipeStruct::Open(): %s",my_error());
- }
- hThread=CreateThread(NULL, // default security
- 0, // default stacksize
- ThreadProc, // worker function
- this, // tell worker about ourselves
- 0, // run immediately
- &dwThreadId // dropped, but needed for the call to work in Win9x
- );
- if(!hThread){
- my_fatal("PipeStruct::Open(): %s",my_error());
- }
- set_Active();
-}
-
-
-void PipeStruct::Close(void) const {
- CloseHandle(hOutput);
-}
-
-void PipeStruct::Kill(void) const {
- CloseHandle(hInput);
- CloseHandle(hOutput);
- DWORD lpexit;
-
- if(GetExitCodeProcess(hProcess,&lpexit)){
- if(lpexit==STILL_ACTIVE)
- //must be java,hammer it down!
- TerminateProcess(hProcess,lpexit);
- }
- CloseHandle(hProcess);
-}
-
-bool PipeStruct::EOF_input(void){ // EOF is defined
- int ret;
- EnterCriticalSection(&CriticalSection);
- ret=state&PIPE_EOF;
- LeaveCriticalSection(&CriticalSection);
- return ret;
-}
-
-void PipeStruct::set_EOF_input(void){
- EnterCriticalSection(&CriticalSection);
- state|=PIPE_EOF;
- LeaveCriticalSection(&CriticalSection);
-}
-
-bool PipeStruct::Active(void){
- int ret;
- EnterCriticalSection(&CriticalSection);
- ret=state&PIPE_ACTIVE;
- LeaveCriticalSection(&CriticalSection);
- return ret;
-}
-
-void PipeStruct::set_Active(void){
- EnterCriticalSection(&CriticalSection);
- state|=PIPE_ACTIVE;
- LeaveCriticalSection(&CriticalSection);
-}
-
-int PipeStruct::ReadData(void){
- DWORD dwBytes;
- char * ret;
- // No protection. Access to nReadEnd is atomic.
- // It is not a problem that nReadEnd becomes smaller after the call.
- // This just means we have read less than we could have.
- ret=fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR-nReadEnd,fpInput);
- if(!ret){
- set_EOF_input();
- lpReadBuffer[0]='\0';
- return 0;
- }
- dwBytes=strlen(lpReadBuffer);
- lpReadBuffer[dwBytes]='\0';
- return dwBytes;
-}
-
-void PipeStruct::ReadInput(void) {
- DWORD dwBytes;
- int ret;
- BOOL bSetEvent=FALSE;
- // ReadData is outside the critical section otherwise everything
- // would block during the blocking read
- ret=ReadData();
- EnterCriticalSection(&CriticalSection);
- if(!EOF_input()){
- if(ret+nReadEnd>=LINE_INPUT_MAX_CHAR){
- my_fatal("PipeStruct::ReadInput(): Internal error: buffer overflow\n");
- }
- memcpy(lpBuffer+nReadEnd,lpReadBuffer,ret+1);
- nReadEnd += ret;
- if(!lpFeedEnd){
- lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
- }
- if(lpFeedEnd){
- bSetEvent=TRUE;
- }else if(nReadEnd>=LINE_INPUT_MAX_CHAR-1){
- my_fatal("PipeStruct::ReadInput(): LINE_INPUT_MAX_CHAR is equal to %d which is too small to contain a full line of engine output or GUI input.\n",LINE_INPUT_MAX_CHAR);
- }
- }
- LeaveCriticalSection(&CriticalSection);
- if(EOF_input() || bSetEvent){
- SetEvent(hEvent);
- }
-}
-
-bool PipeStruct::EOF_(void){
- int ret;
- EnterCriticalSection(&CriticalSection);
- if(lpFeedEnd != NULL){
- ret=FALSE;
- }else if(EOF_input()){
- ret=TRUE;
- }else{
- ret=FALSE;
- }
- LeaveCriticalSection(&CriticalSection);
- return ret;
-}
-
-bool PipeStruct::GetBuffer(char *szLineStr) {
- int nFeedEnd;
- int ret;
- EnterCriticalSection(&CriticalSection);
- if (lpFeedEnd == NULL) {
- ret=FALSE;
- } else {
- nFeedEnd = lpFeedEnd - lpBuffer;
- memcpy(szLineStr, lpBuffer, nFeedEnd);
- if (szLineStr[nFeedEnd - 1] == '\r') {
- szLineStr[nFeedEnd - 1] = '\0';
- } else {
- szLineStr[nFeedEnd] = '\0';
- }
- nFeedEnd ++;
- nReadEnd -= nFeedEnd;
- memcpy(lpBuffer, lpBuffer + nFeedEnd, nReadEnd);
- lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
- ret=TRUE;
- }
- LeaveCriticalSection(&CriticalSection);
- return ret;
-}
-
-
-
-void PipeStruct::LineInput(char *szLineStr) {
- while(!EOF_()){
- if (GetBuffer(szLineStr)) {
- break;
- }else{
- WaitForSingleObject(hEvent,INFINITE);
- }
- }
-}
-
-void PipeStruct::LineOutput(const char *szLineStr) const {
- DWORD dwBytes;
- int nStrLen;
- char szWriteBuffer[LINE_INPUT_MAX_CHAR];
- if(bPipe){
- nStrLen = strlen(szLineStr);
- memcpy(szWriteBuffer, szLineStr, nStrLen);
- szWriteBuffer[nStrLen] = '\r';
- szWriteBuffer[nStrLen + 1] = '\n';
- WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
- }else{
- printf("%s\n",szLineStr);
- fflush(stdout);
- }
-}
-#endif
+++ /dev/null
-#ifndef PIPE_H
-#define PIPE_H
-#ifdef _WIN32
-// includes
-
-#include <windows.h>
-#include <io.h>
-#include <fcntl.h>
-#include <stdio.h>
-
-// constants
-
-// This should be bigger than the maximum length of an engine output or GUI
-// input line.
-const int LINE_INPUT_MAX_CHAR = 40960;
-
-// defines
-
-#define PIPE_EOF 1
-#define PIPE_ACTIVE 2
-
-// types
-
-class PipeStruct {
- friend DWORD WINAPI ThreadProc(LPVOID lpParam);
- public:
- HANDLE hProcess;
- HANDLE hEvent;
- bool GetBuffer(char *szLineStr);
- void LineInput(char *szLineStr);
- void LineOutput(const char *szLineStr) const;
- void Open(const char *szExecFile = NULL);
- void Close(void) const;
- void Kill(void) const;
- bool Active(void);
- bool EOF_(void);
- private:
- HANDLE hInput, hOutput;
- FILE *fpInput;
- HANDLE hThread;
- BOOL bConsole;
- BOOL bPipe;
-
- CRITICAL_SECTION CriticalSection;
-
- volatile DWORD state;
- volatile char * lpFeedEnd;
- volatile int nReadEnd;
- char lpBuffer[LINE_INPUT_MAX_CHAR];
- char lpReadBuffer[LINE_INPUT_MAX_CHAR];
-
- bool EOF_input(void);
- void set_EOF_input(void);
- void set_Active(void);
- void ReadInput(void);
- int ReadData(void);
-
-};
-
-// pipe
-
-#endif
-#endif
+++ /dev/null
-\r
-// posix.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdlib>\r
-#include <cstring>\r
-#include <ctime>\r
-\r
-#ifdef _WIN32\r
-\r
-#include <windows.h>\r
-\r
-#else\r
-\r
-#include <sys/time.h> // Mac OS X needs this one first\r
-#include <sys/resource.h>\r
-#include <sys/types.h>\r
-#include <unistd.h>\r
-\r
-#endif\r
-\r
-#include "posix.h"\r
-#include "util.h"\r
-\r
-#ifndef _WIN32\r
-// prototypes\r
-\r
-static double duration (const struct timeval *t);\r
-\r
-// functions\r
-\r
-\r
-// input_available()\r
-\r
-bool input_available() {\r
-\r
- int val;\r
- fd_set set[1];\r
- struct timeval time_val[1];\r
-\r
- FD_ZERO(set);\r
- FD_SET(STDIN_FILENO,set);\r
-\r
- time_val->tv_sec = 0;\r
- time_val->tv_usec = 0;\r
-\r
- val = select(STDIN_FILENO+1,set,NULL,NULL,time_val);\r
- if (val == -1) my_fatal("input_available(): select(): %s\n",strerror(errno));\r
-\r
- return val != 0;\r
-}\r
-\r
-\r
-// now_real()\r
-\r
-double now_real() {\r
-\r
- struct timeval tv[1];\r
- struct timezone tz[1];\r
-\r
- tz->tz_minuteswest = 0;\r
- tz->tz_dsttime = 0; // DST_NONE not declared in linux\r
-\r
- if (gettimeofday(tv,tz) == -1) {\r
- my_fatal("now_real(): gettimeofday(): %s\n",strerror(errno));\r
- }\r
-\r
- return duration(tv);\r
-}\r
-\r
-// now_cpu()\r
-\r
-double now_cpu() {\r
-\r
- struct rusage ru[1];\r
-\r
- if (getrusage(RUSAGE_SELF,ru) == -1) {\r
- my_fatal("now_cpu(): getrusage(): %s\n",strerror(errno));\r
- }\r
-\r
- return duration(&ru->ru_utime);\r
-}\r
-\r
-// duration()\r
-\r
-static double duration(const struct timeval *tv) {\r
-\r
- return tv->tv_sec + tv->tv_usec * 1E-6;\r
-}\r
-\r
-#else\r
-\r
-double now_real(void) {\r
- return (double) GetTickCount() / 1000.0;\r
-}\r
-\r
-#endif\r
-\r
-// end of posix.cpp\r
+++ /dev/null
-\r
-// posix.h\r
-\r
-#ifndef POSIX_H\r
-#define POSIX_H\r
-\r
-// includes\r
-\r
-#include "util.h"\r
-\r
-// functions\r
-\r
-extern bool input_available ();\r
-\r
-extern double now_real ();\r
-\r
-#endif // !defined POSIX_H\r
-\r
-// end of posix.h\r
-\r
+++ /dev/null
-\r
-// random.cpp\r
-\r
-// includes\r
-\r
-#include "random.h"\r
-#include "util.h"\r
-\r
-// "constants"\r
-\r
-const uint64 Random64[RandomNb] = {\r
- U64(0x9D39247E33776D41), U64(0x2AF7398005AAA5C7), U64(0x44DB015024623547), U64(0x9C15F73E62A76AE2),\r
- U64(0x75834465489C0C89), U64(0x3290AC3A203001BF), U64(0x0FBBAD1F61042279), U64(0xE83A908FF2FB60CA),\r
- U64(0x0D7E765D58755C10), U64(0x1A083822CEAFE02D), U64(0x9605D5F0E25EC3B0), U64(0xD021FF5CD13A2ED5),\r
- U64(0x40BDF15D4A672E32), U64(0x011355146FD56395), U64(0x5DB4832046F3D9E5), U64(0x239F8B2D7FF719CC),\r
- U64(0x05D1A1AE85B49AA1), U64(0x679F848F6E8FC971), U64(0x7449BBFF801FED0B), U64(0x7D11CDB1C3B7ADF0),\r
- U64(0x82C7709E781EB7CC), U64(0xF3218F1C9510786C), U64(0x331478F3AF51BBE6), U64(0x4BB38DE5E7219443),\r
- U64(0xAA649C6EBCFD50FC), U64(0x8DBD98A352AFD40B), U64(0x87D2074B81D79217), U64(0x19F3C751D3E92AE1),\r
- U64(0xB4AB30F062B19ABF), U64(0x7B0500AC42047AC4), U64(0xC9452CA81A09D85D), U64(0x24AA6C514DA27500),\r
- U64(0x4C9F34427501B447), U64(0x14A68FD73C910841), U64(0xA71B9B83461CBD93), U64(0x03488B95B0F1850F),\r
- U64(0x637B2B34FF93C040), U64(0x09D1BC9A3DD90A94), U64(0x3575668334A1DD3B), U64(0x735E2B97A4C45A23),\r
- U64(0x18727070F1BD400B), U64(0x1FCBACD259BF02E7), U64(0xD310A7C2CE9B6555), U64(0xBF983FE0FE5D8244),\r
- U64(0x9F74D14F7454A824), U64(0x51EBDC4AB9BA3035), U64(0x5C82C505DB9AB0FA), U64(0xFCF7FE8A3430B241),\r
- U64(0x3253A729B9BA3DDE), U64(0x8C74C368081B3075), U64(0xB9BC6C87167C33E7), U64(0x7EF48F2B83024E20),\r
- U64(0x11D505D4C351BD7F), U64(0x6568FCA92C76A243), U64(0x4DE0B0F40F32A7B8), U64(0x96D693460CC37E5D),\r
- U64(0x42E240CB63689F2F), U64(0x6D2BDCDAE2919661), U64(0x42880B0236E4D951), U64(0x5F0F4A5898171BB6),\r
- U64(0x39F890F579F92F88), U64(0x93C5B5F47356388B), U64(0x63DC359D8D231B78), U64(0xEC16CA8AEA98AD76),\r
- U64(0x5355F900C2A82DC7), U64(0x07FB9F855A997142), U64(0x5093417AA8A7ED5E), U64(0x7BCBC38DA25A7F3C),\r
- U64(0x19FC8A768CF4B6D4), U64(0x637A7780DECFC0D9), U64(0x8249A47AEE0E41F7), U64(0x79AD695501E7D1E8),\r
- U64(0x14ACBAF4777D5776), U64(0xF145B6BECCDEA195), U64(0xDABF2AC8201752FC), U64(0x24C3C94DF9C8D3F6),\r
- U64(0xBB6E2924F03912EA), U64(0x0CE26C0B95C980D9), U64(0xA49CD132BFBF7CC4), U64(0xE99D662AF4243939),\r
- U64(0x27E6AD7891165C3F), U64(0x8535F040B9744FF1), U64(0x54B3F4FA5F40D873), U64(0x72B12C32127FED2B),\r
- U64(0xEE954D3C7B411F47), U64(0x9A85AC909A24EAA1), U64(0x70AC4CD9F04F21F5), U64(0xF9B89D3E99A075C2),\r
- U64(0x87B3E2B2B5C907B1), U64(0xA366E5B8C54F48B8), U64(0xAE4A9346CC3F7CF2), U64(0x1920C04D47267BBD),\r
- U64(0x87BF02C6B49E2AE9), U64(0x092237AC237F3859), U64(0xFF07F64EF8ED14D0), U64(0x8DE8DCA9F03CC54E),\r
- U64(0x9C1633264DB49C89), U64(0xB3F22C3D0B0B38ED), U64(0x390E5FB44D01144B), U64(0x5BFEA5B4712768E9),\r
- U64(0x1E1032911FA78984), U64(0x9A74ACB964E78CB3), U64(0x4F80F7A035DAFB04), U64(0x6304D09A0B3738C4),\r
- U64(0x2171E64683023A08), U64(0x5B9B63EB9CEFF80C), U64(0x506AACF489889342), U64(0x1881AFC9A3A701D6),\r
- U64(0x6503080440750644), U64(0xDFD395339CDBF4A7), U64(0xEF927DBCF00C20F2), U64(0x7B32F7D1E03680EC),\r
- U64(0xB9FD7620E7316243), U64(0x05A7E8A57DB91B77), U64(0xB5889C6E15630A75), U64(0x4A750A09CE9573F7),\r
- U64(0xCF464CEC899A2F8A), U64(0xF538639CE705B824), U64(0x3C79A0FF5580EF7F), U64(0xEDE6C87F8477609D),\r
- U64(0x799E81F05BC93F31), U64(0x86536B8CF3428A8C), U64(0x97D7374C60087B73), U64(0xA246637CFF328532),\r
- U64(0x043FCAE60CC0EBA0), U64(0x920E449535DD359E), U64(0x70EB093B15B290CC), U64(0x73A1921916591CBD),\r
- U64(0x56436C9FE1A1AA8D), U64(0xEFAC4B70633B8F81), U64(0xBB215798D45DF7AF), U64(0x45F20042F24F1768),\r
- U64(0x930F80F4E8EB7462), U64(0xFF6712FFCFD75EA1), U64(0xAE623FD67468AA70), U64(0xDD2C5BC84BC8D8FC),\r
- U64(0x7EED120D54CF2DD9), U64(0x22FE545401165F1C), U64(0xC91800E98FB99929), U64(0x808BD68E6AC10365),\r
- U64(0xDEC468145B7605F6), U64(0x1BEDE3A3AEF53302), U64(0x43539603D6C55602), U64(0xAA969B5C691CCB7A),\r
- U64(0xA87832D392EFEE56), U64(0x65942C7B3C7E11AE), U64(0xDED2D633CAD004F6), U64(0x21F08570F420E565),\r
- U64(0xB415938D7DA94E3C), U64(0x91B859E59ECB6350), U64(0x10CFF333E0ED804A), U64(0x28AED140BE0BB7DD),\r
- U64(0xC5CC1D89724FA456), U64(0x5648F680F11A2741), U64(0x2D255069F0B7DAB3), U64(0x9BC5A38EF729ABD4),\r
- U64(0xEF2F054308F6A2BC), U64(0xAF2042F5CC5C2858), U64(0x480412BAB7F5BE2A), U64(0xAEF3AF4A563DFE43),\r
- U64(0x19AFE59AE451497F), U64(0x52593803DFF1E840), U64(0xF4F076E65F2CE6F0), U64(0x11379625747D5AF3),\r
- U64(0xBCE5D2248682C115), U64(0x9DA4243DE836994F), U64(0x066F70B33FE09017), U64(0x4DC4DE189B671A1C),\r
- U64(0x51039AB7712457C3), U64(0xC07A3F80C31FB4B4), U64(0xB46EE9C5E64A6E7C), U64(0xB3819A42ABE61C87),\r
- U64(0x21A007933A522A20), U64(0x2DF16F761598AA4F), U64(0x763C4A1371B368FD), U64(0xF793C46702E086A0),\r
- U64(0xD7288E012AEB8D31), U64(0xDE336A2A4BC1C44B), U64(0x0BF692B38D079F23), U64(0x2C604A7A177326B3),\r
- U64(0x4850E73E03EB6064), U64(0xCFC447F1E53C8E1B), U64(0xB05CA3F564268D99), U64(0x9AE182C8BC9474E8),\r
- U64(0xA4FC4BD4FC5558CA), U64(0xE755178D58FC4E76), U64(0x69B97DB1A4C03DFE), U64(0xF9B5B7C4ACC67C96),\r
- U64(0xFC6A82D64B8655FB), U64(0x9C684CB6C4D24417), U64(0x8EC97D2917456ED0), U64(0x6703DF9D2924E97E),\r
- U64(0xC547F57E42A7444E), U64(0x78E37644E7CAD29E), U64(0xFE9A44E9362F05FA), U64(0x08BD35CC38336615),\r
- U64(0x9315E5EB3A129ACE), U64(0x94061B871E04DF75), U64(0xDF1D9F9D784BA010), U64(0x3BBA57B68871B59D),\r
- U64(0xD2B7ADEEDED1F73F), U64(0xF7A255D83BC373F8), U64(0xD7F4F2448C0CEB81), U64(0xD95BE88CD210FFA7),\r
- U64(0x336F52F8FF4728E7), U64(0xA74049DAC312AC71), U64(0xA2F61BB6E437FDB5), U64(0x4F2A5CB07F6A35B3),\r
- U64(0x87D380BDA5BF7859), U64(0x16B9F7E06C453A21), U64(0x7BA2484C8A0FD54E), U64(0xF3A678CAD9A2E38C),\r
- U64(0x39B0BF7DDE437BA2), U64(0xFCAF55C1BF8A4424), U64(0x18FCF680573FA594), U64(0x4C0563B89F495AC3),\r
- U64(0x40E087931A00930D), U64(0x8CFFA9412EB642C1), U64(0x68CA39053261169F), U64(0x7A1EE967D27579E2),\r
- U64(0x9D1D60E5076F5B6F), U64(0x3810E399B6F65BA2), U64(0x32095B6D4AB5F9B1), U64(0x35CAB62109DD038A),\r
- U64(0xA90B24499FCFAFB1), U64(0x77A225A07CC2C6BD), U64(0x513E5E634C70E331), U64(0x4361C0CA3F692F12),\r
- U64(0xD941ACA44B20A45B), U64(0x528F7C8602C5807B), U64(0x52AB92BEB9613989), U64(0x9D1DFA2EFC557F73),\r
- U64(0x722FF175F572C348), U64(0x1D1260A51107FE97), U64(0x7A249A57EC0C9BA2), U64(0x04208FE9E8F7F2D6),\r
- U64(0x5A110C6058B920A0), U64(0x0CD9A497658A5698), U64(0x56FD23C8F9715A4C), U64(0x284C847B9D887AAE),\r
- U64(0x04FEABFBBDB619CB), U64(0x742E1E651C60BA83), U64(0x9A9632E65904AD3C), U64(0x881B82A13B51B9E2),\r
- U64(0x506E6744CD974924), U64(0xB0183DB56FFC6A79), U64(0x0ED9B915C66ED37E), U64(0x5E11E86D5873D484),\r
- U64(0xF678647E3519AC6E), U64(0x1B85D488D0F20CC5), U64(0xDAB9FE6525D89021), U64(0x0D151D86ADB73615),\r
- U64(0xA865A54EDCC0F019), U64(0x93C42566AEF98FFB), U64(0x99E7AFEABE000731), U64(0x48CBFF086DDF285A),\r
- U64(0x7F9B6AF1EBF78BAF), U64(0x58627E1A149BBA21), U64(0x2CD16E2ABD791E33), U64(0xD363EFF5F0977996),\r
- U64(0x0CE2A38C344A6EED), U64(0x1A804AADB9CFA741), U64(0x907F30421D78C5DE), U64(0x501F65EDB3034D07),\r
- U64(0x37624AE5A48FA6E9), U64(0x957BAF61700CFF4E), U64(0x3A6C27934E31188A), U64(0xD49503536ABCA345),\r
- U64(0x088E049589C432E0), U64(0xF943AEE7FEBF21B8), U64(0x6C3B8E3E336139D3), U64(0x364F6FFA464EE52E),\r
- U64(0xD60F6DCEDC314222), U64(0x56963B0DCA418FC0), U64(0x16F50EDF91E513AF), U64(0xEF1955914B609F93),\r
- U64(0x565601C0364E3228), U64(0xECB53939887E8175), U64(0xBAC7A9A18531294B), U64(0xB344C470397BBA52),\r
- U64(0x65D34954DAF3CEBD), U64(0xB4B81B3FA97511E2), U64(0xB422061193D6F6A7), U64(0x071582401C38434D),\r
- U64(0x7A13F18BBEDC4FF5), U64(0xBC4097B116C524D2), U64(0x59B97885E2F2EA28), U64(0x99170A5DC3115544),\r
- U64(0x6F423357E7C6A9F9), U64(0x325928EE6E6F8794), U64(0xD0E4366228B03343), U64(0x565C31F7DE89EA27),\r
- U64(0x30F5611484119414), U64(0xD873DB391292ED4F), U64(0x7BD94E1D8E17DEBC), U64(0xC7D9F16864A76E94),\r
- U64(0x947AE053EE56E63C), U64(0xC8C93882F9475F5F), U64(0x3A9BF55BA91F81CA), U64(0xD9A11FBB3D9808E4),\r
- U64(0x0FD22063EDC29FCA), U64(0xB3F256D8ACA0B0B9), U64(0xB03031A8B4516E84), U64(0x35DD37D5871448AF),\r
- U64(0xE9F6082B05542E4E), U64(0xEBFAFA33D7254B59), U64(0x9255ABB50D532280), U64(0xB9AB4CE57F2D34F3),\r
- U64(0x693501D628297551), U64(0xC62C58F97DD949BF), U64(0xCD454F8F19C5126A), U64(0xBBE83F4ECC2BDECB),\r
- U64(0xDC842B7E2819E230), U64(0xBA89142E007503B8), U64(0xA3BC941D0A5061CB), U64(0xE9F6760E32CD8021),\r
- U64(0x09C7E552BC76492F), U64(0x852F54934DA55CC9), U64(0x8107FCCF064FCF56), U64(0x098954D51FFF6580),\r
- U64(0x23B70EDB1955C4BF), U64(0xC330DE426430F69D), U64(0x4715ED43E8A45C0A), U64(0xA8D7E4DAB780A08D),\r
- U64(0x0572B974F03CE0BB), U64(0xB57D2E985E1419C7), U64(0xE8D9ECBE2CF3D73F), U64(0x2FE4B17170E59750),\r
- U64(0x11317BA87905E790), U64(0x7FBF21EC8A1F45EC), U64(0x1725CABFCB045B00), U64(0x964E915CD5E2B207),\r
- U64(0x3E2B8BCBF016D66D), U64(0xBE7444E39328A0AC), U64(0xF85B2B4FBCDE44B7), U64(0x49353FEA39BA63B1),\r
- U64(0x1DD01AAFCD53486A), U64(0x1FCA8A92FD719F85), U64(0xFC7C95D827357AFA), U64(0x18A6A990C8B35EBD),\r
- U64(0xCCCB7005C6B9C28D), U64(0x3BDBB92C43B17F26), U64(0xAA70B5B4F89695A2), U64(0xE94C39A54A98307F),\r
- U64(0xB7A0B174CFF6F36E), U64(0xD4DBA84729AF48AD), U64(0x2E18BC1AD9704A68), U64(0x2DE0966DAF2F8B1C),\r
- U64(0xB9C11D5B1E43A07E), U64(0x64972D68DEE33360), U64(0x94628D38D0C20584), U64(0xDBC0D2B6AB90A559),\r
- U64(0xD2733C4335C6A72F), U64(0x7E75D99D94A70F4D), U64(0x6CED1983376FA72B), U64(0x97FCAACBF030BC24),\r
- U64(0x7B77497B32503B12), U64(0x8547EDDFB81CCB94), U64(0x79999CDFF70902CB), U64(0xCFFE1939438E9B24),\r
- U64(0x829626E3892D95D7), U64(0x92FAE24291F2B3F1), U64(0x63E22C147B9C3403), U64(0xC678B6D860284A1C),\r
- U64(0x5873888850659AE7), U64(0x0981DCD296A8736D), U64(0x9F65789A6509A440), U64(0x9FF38FED72E9052F),\r
- U64(0xE479EE5B9930578C), U64(0xE7F28ECD2D49EECD), U64(0x56C074A581EA17FE), U64(0x5544F7D774B14AEF),\r
- U64(0x7B3F0195FC6F290F), U64(0x12153635B2C0CF57), U64(0x7F5126DBBA5E0CA7), U64(0x7A76956C3EAFB413),\r
- U64(0x3D5774A11D31AB39), U64(0x8A1B083821F40CB4), U64(0x7B4A38E32537DF62), U64(0x950113646D1D6E03),\r
- U64(0x4DA8979A0041E8A9), U64(0x3BC36E078F7515D7), U64(0x5D0A12F27AD310D1), U64(0x7F9D1A2E1EBE1327),\r
- U64(0xDA3A361B1C5157B1), U64(0xDCDD7D20903D0C25), U64(0x36833336D068F707), U64(0xCE68341F79893389),\r
- U64(0xAB9090168DD05F34), U64(0x43954B3252DC25E5), U64(0xB438C2B67F98E5E9), U64(0x10DCD78E3851A492),\r
- U64(0xDBC27AB5447822BF), U64(0x9B3CDB65F82CA382), U64(0xB67B7896167B4C84), U64(0xBFCED1B0048EAC50),\r
- U64(0xA9119B60369FFEBD), U64(0x1FFF7AC80904BF45), U64(0xAC12FB171817EEE7), U64(0xAF08DA9177DDA93D),\r
- U64(0x1B0CAB936E65C744), U64(0xB559EB1D04E5E932), U64(0xC37B45B3F8D6F2BA), U64(0xC3A9DC228CAAC9E9),\r
- U64(0xF3B8B6675A6507FF), U64(0x9FC477DE4ED681DA), U64(0x67378D8ECCEF96CB), U64(0x6DD856D94D259236),\r
- U64(0xA319CE15B0B4DB31), U64(0x073973751F12DD5E), U64(0x8A8E849EB32781A5), U64(0xE1925C71285279F5),\r
- U64(0x74C04BF1790C0EFE), U64(0x4DDA48153C94938A), U64(0x9D266D6A1CC0542C), U64(0x7440FB816508C4FE),\r
- U64(0x13328503DF48229F), U64(0xD6BF7BAEE43CAC40), U64(0x4838D65F6EF6748F), U64(0x1E152328F3318DEA),\r
- U64(0x8F8419A348F296BF), U64(0x72C8834A5957B511), U64(0xD7A023A73260B45C), U64(0x94EBC8ABCFB56DAE),\r
- U64(0x9FC10D0F989993E0), U64(0xDE68A2355B93CAE6), U64(0xA44CFE79AE538BBE), U64(0x9D1D84FCCE371425),\r
- U64(0x51D2B1AB2DDFB636), U64(0x2FD7E4B9E72CD38C), U64(0x65CA5B96B7552210), U64(0xDD69A0D8AB3B546D),\r
- U64(0x604D51B25FBF70E2), U64(0x73AA8A564FB7AC9E), U64(0x1A8C1E992B941148), U64(0xAAC40A2703D9BEA0),\r
- U64(0x764DBEAE7FA4F3A6), U64(0x1E99B96E70A9BE8B), U64(0x2C5E9DEB57EF4743), U64(0x3A938FEE32D29981),\r
- U64(0x26E6DB8FFDF5ADFE), U64(0x469356C504EC9F9D), U64(0xC8763C5B08D1908C), U64(0x3F6C6AF859D80055),\r
- U64(0x7F7CC39420A3A545), U64(0x9BFB227EBDF4C5CE), U64(0x89039D79D6FC5C5C), U64(0x8FE88B57305E2AB6),\r
- U64(0xA09E8C8C35AB96DE), U64(0xFA7E393983325753), U64(0xD6B6D0ECC617C699), U64(0xDFEA21EA9E7557E3),\r
- U64(0xB67C1FA481680AF8), U64(0xCA1E3785A9E724E5), U64(0x1CFC8BED0D681639), U64(0xD18D8549D140CAEA),\r
- U64(0x4ED0FE7E9DC91335), U64(0xE4DBF0634473F5D2), U64(0x1761F93A44D5AEFE), U64(0x53898E4C3910DA55),\r
- U64(0x734DE8181F6EC39A), U64(0x2680B122BAA28D97), U64(0x298AF231C85BAFAB), U64(0x7983EED3740847D5),\r
- U64(0x66C1A2A1A60CD889), U64(0x9E17E49642A3E4C1), U64(0xEDB454E7BADC0805), U64(0x50B704CAB602C329),\r
- U64(0x4CC317FB9CDDD023), U64(0x66B4835D9EAFEA22), U64(0x219B97E26FFC81BD), U64(0x261E4E4C0A333A9D),\r
- U64(0x1FE2CCA76517DB90), U64(0xD7504DFA8816EDBB), U64(0xB9571FA04DC089C8), U64(0x1DDC0325259B27DE),\r
- U64(0xCF3F4688801EB9AA), U64(0xF4F5D05C10CAB243), U64(0x38B6525C21A42B0E), U64(0x36F60E2BA4FA6800),\r
- U64(0xEB3593803173E0CE), U64(0x9C4CD6257C5A3603), U64(0xAF0C317D32ADAA8A), U64(0x258E5A80C7204C4B),\r
- U64(0x8B889D624D44885D), U64(0xF4D14597E660F855), U64(0xD4347F66EC8941C3), U64(0xE699ED85B0DFB40D),\r
- U64(0x2472F6207C2D0484), U64(0xC2A1E7B5B459AEB5), U64(0xAB4F6451CC1D45EC), U64(0x63767572AE3D6174),\r
- U64(0xA59E0BD101731A28), U64(0x116D0016CB948F09), U64(0x2CF9C8CA052F6E9F), U64(0x0B090A7560A968E3),\r
- U64(0xABEEDDB2DDE06FF1), U64(0x58EFC10B06A2068D), U64(0xC6E57A78FBD986E0), U64(0x2EAB8CA63CE802D7),\r
- U64(0x14A195640116F336), U64(0x7C0828DD624EC390), U64(0xD74BBE77E6116AC7), U64(0x804456AF10F5FB53),\r
- U64(0xEBE9EA2ADF4321C7), U64(0x03219A39EE587A30), U64(0x49787FEF17AF9924), U64(0xA1E9300CD8520548),\r
- U64(0x5B45E522E4B1B4EF), U64(0xB49C3B3995091A36), U64(0xD4490AD526F14431), U64(0x12A8F216AF9418C2),\r
- U64(0x001F837CC7350524), U64(0x1877B51E57A764D5), U64(0xA2853B80F17F58EE), U64(0x993E1DE72D36D310),\r
- U64(0xB3598080CE64A656), U64(0x252F59CF0D9F04BB), U64(0xD23C8E176D113600), U64(0x1BDA0492E7E4586E),\r
- U64(0x21E0BD5026C619BF), U64(0x3B097ADAF088F94E), U64(0x8D14DEDB30BE846E), U64(0xF95CFFA23AF5F6F4),\r
- U64(0x3871700761B3F743), U64(0xCA672B91E9E4FA16), U64(0x64C8E531BFF53B55), U64(0x241260ED4AD1E87D),\r
- U64(0x106C09B972D2E822), U64(0x7FBA195410E5CA30), U64(0x7884D9BC6CB569D8), U64(0x0647DFEDCD894A29),\r
- U64(0x63573FF03E224774), U64(0x4FC8E9560F91B123), U64(0x1DB956E450275779), U64(0xB8D91274B9E9D4FB),\r
- U64(0xA2EBEE47E2FBFCE1), U64(0xD9F1F30CCD97FB09), U64(0xEFED53D75FD64E6B), U64(0x2E6D02C36017F67F),\r
- U64(0xA9AA4D20DB084E9B), U64(0xB64BE8D8B25396C1), U64(0x70CB6AF7C2D5BCF0), U64(0x98F076A4F7A2322E),\r
- U64(0xBF84470805E69B5F), U64(0x94C3251F06F90CF3), U64(0x3E003E616A6591E9), U64(0xB925A6CD0421AFF3),\r
- U64(0x61BDD1307C66E300), U64(0xBF8D5108E27E0D48), U64(0x240AB57A8B888B20), U64(0xFC87614BAF287E07),\r
- U64(0xEF02CDD06FFDB432), U64(0xA1082C0466DF6C0A), U64(0x8215E577001332C8), U64(0xD39BB9C3A48DB6CF),\r
- U64(0x2738259634305C14), U64(0x61CF4F94C97DF93D), U64(0x1B6BACA2AE4E125B), U64(0x758F450C88572E0B),\r
- U64(0x959F587D507A8359), U64(0xB063E962E045F54D), U64(0x60E8ED72C0DFF5D1), U64(0x7B64978555326F9F),\r
- U64(0xFD080D236DA814BA), U64(0x8C90FD9B083F4558), U64(0x106F72FE81E2C590), U64(0x7976033A39F7D952),\r
- U64(0xA4EC0132764CA04B), U64(0x733EA705FAE4FA77), U64(0xB4D8F77BC3E56167), U64(0x9E21F4F903B33FD9),\r
- U64(0x9D765E419FB69F6D), U64(0xD30C088BA61EA5EF), U64(0x5D94337FBFAF7F5B), U64(0x1A4E4822EB4D7A59),\r
- U64(0x6FFE73E81B637FB3), U64(0xDDF957BC36D8B9CA), U64(0x64D0E29EEA8838B3), U64(0x08DD9BDFD96B9F63),\r
- U64(0x087E79E5A57D1D13), U64(0xE328E230E3E2B3FB), U64(0x1C2559E30F0946BE), U64(0x720BF5F26F4D2EAA),\r
- U64(0xB0774D261CC609DB), U64(0x443F64EC5A371195), U64(0x4112CF68649A260E), U64(0xD813F2FAB7F5C5CA),\r
- U64(0x660D3257380841EE), U64(0x59AC2C7873F910A3), U64(0xE846963877671A17), U64(0x93B633ABFA3469F8),\r
- U64(0xC0C0F5A60EF4CDCF), U64(0xCAF21ECD4377B28C), U64(0x57277707199B8175), U64(0x506C11B9D90E8B1D),\r
- U64(0xD83CC2687A19255F), U64(0x4A29C6465A314CD1), U64(0xED2DF21216235097), U64(0xB5635C95FF7296E2),\r
- U64(0x22AF003AB672E811), U64(0x52E762596BF68235), U64(0x9AEBA33AC6ECC6B0), U64(0x944F6DE09134DFB6),\r
- U64(0x6C47BEC883A7DE39), U64(0x6AD047C430A12104), U64(0xA5B1CFDBA0AB4067), U64(0x7C45D833AFF07862),\r
- U64(0x5092EF950A16DA0B), U64(0x9338E69C052B8E7B), U64(0x455A4B4CFE30E3F5), U64(0x6B02E63195AD0CF8),\r
- U64(0x6B17B224BAD6BF27), U64(0xD1E0CCD25BB9C169), U64(0xDE0C89A556B9AE70), U64(0x50065E535A213CF6),\r
- U64(0x9C1169FA2777B874), U64(0x78EDEFD694AF1EED), U64(0x6DC93D9526A50E68), U64(0xEE97F453F06791ED),\r
- U64(0x32AB0EDB696703D3), U64(0x3A6853C7E70757A7), U64(0x31865CED6120F37D), U64(0x67FEF95D92607890),\r
- U64(0x1F2B1D1F15F6DC9C), U64(0xB69E38A8965C6B65), U64(0xAA9119FF184CCCF4), U64(0xF43C732873F24C13),\r
- U64(0xFB4A3D794A9A80D2), U64(0x3550C2321FD6109C), U64(0x371F77E76BB8417E), U64(0x6BFA9AAE5EC05779),\r
- U64(0xCD04F3FF001A4778), U64(0xE3273522064480CA), U64(0x9F91508BFFCFC14A), U64(0x049A7F41061A9E60),\r
- U64(0xFCB6BE43A9F2FE9B), U64(0x08DE8A1C7797DA9B), U64(0x8F9887E6078735A1), U64(0xB5B4071DBFC73A66),\r
- U64(0x230E343DFBA08D33), U64(0x43ED7F5A0FAE657D), U64(0x3A88A0FBBCB05C63), U64(0x21874B8B4D2DBC4F),\r
- U64(0x1BDEA12E35F6A8C9), U64(0x53C065C6C8E63528), U64(0xE34A1D250E7A8D6B), U64(0xD6B04D3B7651DD7E),\r
- U64(0x5E90277E7CB39E2D), U64(0x2C046F22062DC67D), U64(0xB10BB459132D0A26), U64(0x3FA9DDFB67E2F199),\r
- U64(0x0E09B88E1914F7AF), U64(0x10E8B35AF3EEAB37), U64(0x9EEDECA8E272B933), U64(0xD4C718BC4AE8AE5F),\r
- U64(0x81536D601170FC20), U64(0x91B534F885818A06), U64(0xEC8177F83F900978), U64(0x190E714FADA5156E),\r
- U64(0xB592BF39B0364963), U64(0x89C350C893AE7DC1), U64(0xAC042E70F8B383F2), U64(0xB49B52E587A1EE60),\r
- U64(0xFB152FE3FF26DA89), U64(0x3E666E6F69AE2C15), U64(0x3B544EBE544C19F9), U64(0xE805A1E290CF2456),\r
- U64(0x24B33C9D7ED25117), U64(0xE74733427B72F0C1), U64(0x0A804D18B7097475), U64(0x57E3306D881EDB4F),\r
- U64(0x4AE7D6A36EB5DBCB), U64(0x2D8D5432157064C8), U64(0xD1E649DE1E7F268B), U64(0x8A328A1CEDFE552C),\r
- U64(0x07A3AEC79624C7DA), U64(0x84547DDC3E203C94), U64(0x990A98FD5071D263), U64(0x1A4FF12616EEFC89),\r
- U64(0xF6F7FD1431714200), U64(0x30C05B1BA332F41C), U64(0x8D2636B81555A786), U64(0x46C9FEB55D120902),\r
- U64(0xCCEC0A73B49C9921), U64(0x4E9D2827355FC492), U64(0x19EBB029435DCB0F), U64(0x4659D2B743848A2C),\r
- U64(0x963EF2C96B33BE31), U64(0x74F85198B05A2E7D), U64(0x5A0F544DD2B1FB18), U64(0x03727073C2E134B1),\r
- U64(0xC7F6AA2DE59AEA61), U64(0x352787BAA0D7C22F), U64(0x9853EAB63B5E0B35), U64(0xABBDCDD7ED5C0860),\r
- U64(0xCF05DAF5AC8D77B0), U64(0x49CAD48CEBF4A71E), U64(0x7A4C10EC2158C4A6), U64(0xD9E92AA246BF719E),\r
- U64(0x13AE978D09FE5557), U64(0x730499AF921549FF), U64(0x4E4B705B92903BA4), U64(0xFF577222C14F0A3A),\r
- U64(0x55B6344CF97AAFAE), U64(0xB862225B055B6960), U64(0xCAC09AFBDDD2CDB4), U64(0xDAF8E9829FE96B5F),\r
- U64(0xB5FDFC5D3132C498), U64(0x310CB380DB6F7503), U64(0xE87FBB46217A360E), U64(0x2102AE466EBB1148),\r
- U64(0xF8549E1A3AA5E00D), U64(0x07A69AFDCC42261A), U64(0xC4C118BFE78FEAAE), U64(0xF9F4892ED96BD438),\r
- U64(0x1AF3DBE25D8F45DA), U64(0xF5B4B0B0D2DEEEB4), U64(0x962ACEEFA82E1C84), U64(0x046E3ECAAF453CE9),\r
- U64(0xF05D129681949A4C), U64(0x964781CE734B3C84), U64(0x9C2ED44081CE5FBD), U64(0x522E23F3925E319E),\r
- U64(0x177E00F9FC32F791), U64(0x2BC60A63A6F3B3F2), U64(0x222BBFAE61725606), U64(0x486289DDCC3D6780),\r
- U64(0x7DC7785B8EFDFC80), U64(0x8AF38731C02BA980), U64(0x1FAB64EA29A2DDF7), U64(0xE4D9429322CD065A),\r
- U64(0x9DA058C67844F20C), U64(0x24C0E332B70019B0), U64(0x233003B5A6CFE6AD), U64(0xD586BD01C5C217F6),\r
- U64(0x5E5637885F29BC2B), U64(0x7EBA726D8C94094B), U64(0x0A56A5F0BFE39272), U64(0xD79476A84EE20D06),\r
- U64(0x9E4C1269BAA4BF37), U64(0x17EFEE45B0DEE640), U64(0x1D95B0A5FCF90BC6), U64(0x93CBE0B699C2585D),\r
- U64(0x65FA4F227A2B6D79), U64(0xD5F9E858292504D5), U64(0xC2B5A03F71471A6F), U64(0x59300222B4561E00),\r
- U64(0xCE2F8642CA0712DC), U64(0x7CA9723FBB2E8988), U64(0x2785338347F2BA08), U64(0xC61BB3A141E50E8C),\r
- U64(0x150F361DAB9DEC26), U64(0x9F6A419D382595F4), U64(0x64A53DC924FE7AC9), U64(0x142DE49FFF7A7C3D),\r
- U64(0x0C335248857FA9E7), U64(0x0A9C32D5EAE45305), U64(0xE6C42178C4BBB92E), U64(0x71F1CE2490D20B07),\r
- U64(0xF1BCC3D275AFE51A), U64(0xE728E8C83C334074), U64(0x96FBF83A12884624), U64(0x81A1549FD6573DA5),\r
- U64(0x5FA7867CAF35E149), U64(0x56986E2EF3ED091B), U64(0x917F1DD5F8886C61), U64(0xD20D8C88C8FFE65F),\r
- U64(0x31D71DCE64B2C310), U64(0xF165B587DF898190), U64(0xA57E6339DD2CF3A0), U64(0x1EF6E6DBB1961EC9),\r
- U64(0x70CC73D90BC26E24), U64(0xE21A6B35DF0C3AD7), U64(0x003A93D8B2806962), U64(0x1C99DED33CB890A1),\r
- U64(0xCF3145DE0ADD4289), U64(0xD0E4427A5514FB72), U64(0x77C621CC9FB3A483), U64(0x67A34DAC4356550B),\r
- U64(0xF8D626AAAF278509),\r
-};\r
-\r
-// functions\r
-\r
-// random_init()\r
-\r
-void random_init() {\r
-\r
- if ((Random64[RandomNb-1] >> 32) != 0xF8D626AA) { // upper half of the last element of the array\r
- my_fatal("random_init(): broken 64-bit types\n");\r
- }\r
-}\r
-\r
-// random_64()\r
-\r
-uint64 random_64(int n) {\r
-\r
- ASSERT(n>=0&&n<RandomNb);\r
-\r
- return Random64[n];\r
-}\r
-\r
-// end of random.cpp\r
-\r
+++ /dev/null
-\r
-// san.cpp\r
-\r
-// includes\r
-\r
-#include <cctype>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "attack.h"\r
-#include "board.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "move_gen.h"\r
-#include "move_legal.h"\r
-#include "piece.h"\r
-#include "san.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool UseSlowDebug = false;\r
-\r
-enum ambiguity_t {\r
- AMBIGUITY_NONE,\r
- AMBIGUITY_FILE,\r
- AMBIGUITY_RANK,\r
- AMBIGUITY_SQUARE\r
-};\r
-\r
-// functions\r
-\r
-static bool san_to_lan (const char san[], const board_t * board, char string[], int size);\r
-static int move_from_lan (const char string[], const board_t * board);\r
-\r
-static int ambiguity (int move, const board_t * board);\r
-\r
-// move_to_san()\r
-\r
-bool move_to_san(int move, const board_t * board, char string[], int size) {\r
-\r
- int from, to, piece;\r
- char tmp_string[256];\r
-\r
- ASSERT(move_is_ok(move));\r
- ASSERT(board_is_ok(board));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=8);\r
-\r
- ASSERT(move_is_legal(move,board));\r
-\r
- if (size < 8) return false;\r
-\r
- // init\r
-\r
- from = move_from(move);\r
- to = move_to(move);\r
-\r
- string[0] = '\0';\r
-\r
- // castle\r
-\r
- if (move_is_castle(move,board)) {\r
-\r
- if (to > from) {\r
- strcat(string,"O-O");\r
- } else {\r
- strcat(string,"O-O-O");\r
- }\r
-\r
- goto check;\r
- }\r
-\r
- // from\r
-\r
- piece = board->square[from];\r
-\r
- if (piece_is_pawn(piece)) {\r
-\r
- // pawn\r
-\r
- if (move_is_capture(move,board)) {\r
- sprintf(tmp_string,"%c",file_to_char(square_file(from)));\r
- strcat(string,tmp_string);\r
- }\r
-\r
- } else {\r
-\r
- // piece\r
-\r
- sprintf(tmp_string,"%c",toupper(piece_to_char(piece)));\r
- strcat(string,tmp_string);\r
-\r
- // ambiguity\r
-\r
- switch (ambiguity(move,board)) {\r
- case AMBIGUITY_NONE:\r
- break;\r
- case AMBIGUITY_FILE:\r
- sprintf(tmp_string,"%c",file_to_char(square_file(from)));\r
- strcat(string,tmp_string);\r
- break;\r
- case AMBIGUITY_RANK:\r
- sprintf(tmp_string,"%c",rank_to_char(square_rank(from)));\r
- strcat(string,tmp_string);\r
- break;\r
- case AMBIGUITY_SQUARE:\r
- if (!square_to_string(from,tmp_string,256)) return false;\r
- strcat(string,tmp_string);\r
- break;\r
- default:\r
- ASSERT(false);\r
- break;\r
- }\r
- }\r
-\r
- // capture\r
-\r
- if (move_is_capture(move,board)) strcat(string,"x");\r
-\r
- // to\r
-\r
- if (!square_to_string(to,tmp_string,256)) return false;\r
- strcat(string,tmp_string);\r
-\r
- // promote\r
-\r
- if (move_is_promote(move)) {\r
- sprintf(tmp_string,"=%c",toupper(piece_to_char(move_promote(move,board))));\r
- strcat(string,tmp_string);\r
- }\r
-\r
- // check\r
-\r
-check:\r
-\r
- if (move_is_mate(move,board)) {\r
- strcat(string,"#");\r
- } else if (move_is_check(move,board)) {\r
- strcat(string,"+");\r
- }\r
-\r
- return true;\r
-}\r
-\r
-// move_from_san()\r
-\r
-int move_from_san(const char string[], const board_t * board) {\r
-\r
- char s[256];\r
- int move;\r
-\r
- ASSERT(string!=NULL);\r
- ASSERT(board_is_ok(board));\r
-\r
- san_to_lan(string,board,s,256);\r
- move = move_from_lan(s,board);\r
-\r
- ASSERT(!UseSlowDebug||move==move_from_san_debug(string,board));\r
-\r
- return move;\r
-}\r
-\r
-// move_from_san_debug()\r
-\r
-int move_from_san_debug(const char string[], const board_t * board) {\r
-\r
- list_t list[1];\r
- int i, move;\r
- char move_string[256];\r
-\r
- ASSERT(string!=NULL);\r
- ASSERT(board_is_ok(board));\r
-\r
- gen_legal_moves(list,board);\r
-\r
- for (i = 0; i < list_size(list); i++) {\r
- move = list_move(list,i);\r
- if (!move_to_san(move,board,move_string,256)) ASSERT(false);\r
- if (my_string_equal(move_string,string)) return move;\r
- }\r
-\r
- return MoveNone;\r
-}\r
-\r
-// san_to_lan()\r
-\r
-static bool san_to_lan(const char san[], const board_t * board, char string[], int size) {\r
-\r
- int len;\r
- int left, right;\r
- int c;\r
- int king, rook;\r
- char king_string[3], rook_string[3];\r
-\r
- ASSERT(san!=NULL);\r
- ASSERT(board_is_ok(board));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=8);\r
-\r
- // init\r
-\r
- if (size < 8) return false;\r
- strcpy(string,"???????");\r
-\r
- len = strlen(san);\r
-\r
- left = 0;\r
- right = len;\r
-\r
- // skip trailing '+' or '#'\r
-\r
- if (left < right) {\r
- c = san[right-1];\r
- if (c == '+' || c == '#') right--;\r
- }\r
-\r
- // castling\r
-\r
- ASSERT(left==0);\r
-\r
- if (false) {\r
-\r
- } else if (right == 3 && strncmp(san,"O-O",3) == 0) {\r
-\r
- if (board->castle[board->turn][SideH] == SquareNone) return false;\r
-\r
- king = king_pos(board,board->turn);\r
- rook = board->castle[board->turn][SideH];\r
-\r
- square_to_string(king,king_string,3);\r
- square_to_string(rook,rook_string,3);\r
-\r
- sprintf(string,"K%s?%s?",king_string,rook_string);\r
-\r
- } else if (right == 5 && strncmp(san,"O-O-O",5) == 0) {\r
-\r
- if (board->castle[board->turn][SideA] == SquareNone) return false;\r
-\r
- king = king_pos(board,board->turn);\r
- rook = board->castle[board->turn][SideA];\r
-\r
- square_to_string(king,king_string,3);\r
- square_to_string(rook,rook_string,3);\r
-\r
- sprintf(string,"K%s?%s?",king_string,rook_string);\r
-\r
- } else {\r
-\r
- // moved piece\r
-\r
- if (left < right) {\r
-\r
- c = san[left];\r
-\r
- if (char_is_piece(c)) {\r
- string[0] = c;\r
- left++;\r
- }\r
- }\r
-\r
- // promotion\r
-\r
- if (left < right) {\r
-\r
- c = toupper(san[right-1]);\r
-\r
- if (char_is_piece(c)) {\r
-\r
- string[6] = c;\r
- right--;\r
-\r
- // skip '='\r
-\r
- if (left < right && san[right-1] == '=') right--;\r
- }\r
- }\r
-\r
- // to-square rank\r
-\r
- if (left < right) {\r
-\r
- c = san[right-1];\r
-\r
- if (char_is_rank(c)) {\r
- string[5] = c;\r
- right--;\r
- }\r
- }\r
-\r
- // to-square file\r
-\r
- if (left < right) {\r
-\r
- c = san[right-1];\r
-\r
- if (char_is_file(c)) {\r
- string[4] = c;\r
- right--;\r
- }\r
- }\r
-\r
- // captured piece\r
-\r
- if (left < right) {\r
-\r
- c = san[right-1];\r
-\r
- if (char_is_piece(c)) {\r
- string[3] = c;\r
- right--;\r
- }\r
- }\r
-\r
- // skip middle '-' or 'x'\r
-\r
- if (left < right) {\r
- c = san[right-1];\r
- if (c == '-' || c == 'x') right--;\r
- }\r
-\r
- // from-square file\r
-\r
- if (left < right) {\r
-\r
- c = san[left];\r
-\r
- if (char_is_file(c)) {\r
- string[1] = c;\r
- left++;\r
- }\r
- }\r
-\r
- // from-square rank\r
-\r
- if (left < right) {\r
-\r
- c = san[left];\r
-\r
- if (char_is_rank(c)) {\r
- string[2] = c;\r
- left++;\r
- }\r
- }\r
-\r
- if (left != right) return false;\r
- }\r
-\r
- // end\r
-\r
- return true;\r
-}\r
-\r
-// move_from_lan()\r
-\r
-static int move_from_lan(const char string[], const board_t * board) {\r
-\r
- int len;\r
- int move;\r
- int promote;\r
- char s[256];\r
- int from, to;\r
- int colour;\r
- int inc;\r
- int piece_char;\r
- int n;\r
- const uint8 * ptr;\r
- int piece;\r
- int side;\r
-\r
- ASSERT(string!=NULL);\r
- ASSERT(board_is_ok(board));\r
-\r
- // init\r
-\r
- len = strlen(string);\r
- if (len != 7) return MoveNone;\r
-\r
- move = MoveNone;\r
- colour = board->turn;\r
-\r
- // promote\r
-\r
- promote = 0;\r
-\r
- switch (string[6]) {\r
- case '?': // not a promotion\r
- break;\r
- case 'N':\r
- promote = MovePromoteKnight;\r
- break;\r
- case 'B':\r
- promote = MovePromoteBishop;\r
- break;\r
- case 'R':\r
- promote = MovePromoteRook;\r
- break;\r
- case 'Q':\r
- promote = MovePromoteQueen;\r
- break;\r
- default:\r
- return MoveNone;\r
- break;\r
- }\r
-\r
- // to square\r
-\r
- s[0] = string[4];\r
- s[1] = string[5];\r
- s[2] = '\0';\r
-\r
- to = square_from_string(s);\r
- if (to == SquareNone) return MoveNone;\r
-\r
- // known from square?\r
-\r
- if (string[1] != '?' && string[2] != '?') {\r
-\r
- // from square\r
-\r
- s[0] = string[1];\r
- s[1] = string[2];\r
- s[2] = '\0';\r
-\r
- from = square_from_string(s);\r
- if (from == SquareNone) return MoveNone;\r
-\r
- // convert "king slide" castling to KxR\r
-\r
- if (piece_is_king(board->square[from])\r
- && square_rank(to) == square_rank(from)\r
- && abs(to-from) > 1) {\r
- side = (to > from) ? SideH : SideA;\r
- to = board->castle[colour][side];\r
- if (to == SquareNone) return MoveNone;\r
- }\r
-\r
- // move\r
-\r
- move = move_make(from,to) | promote;\r
-\r
- return move;\r
- }\r
-\r
- // pawn non-capture?\r
-\r
- if (string[0] == '?' && string[1] == '?') {\r
-\r
- if (board->square[to] != Empty) return MoveNone; // useful?\r
-\r
- inc = (colour_is_white(colour)) ? +16 : -16;\r
-\r
- from = to - inc;\r
- if (board->square[from] == Empty && square_side_rank(to,colour) == Rank4) {\r
- from -= inc;\r
- }\r
-\r
- if (board->square[from] != piece_make_pawn(colour)) { // useful?\r
- return MoveNone;\r
- }\r
-\r
- // move\r
-\r
- move = move_make(from,to) | promote;\r
-\r
- return move;\r
- }\r
-\r
- // pawn capture?\r
-\r
- piece_char = string[0];\r
-\r
- if (piece_char == '?' && string[1] != '?') {\r
- piece_char = 'P';\r
- }\r
-\r
- // attack loop\r
-\r
- n = 0;\r
-\r
- for (ptr = board->list[colour]; (from=*ptr) != SquareNone; ptr++) {\r
-\r
- piece = board->square[from];\r
-\r
- if (toupper(piece_to_char(piece)) == piece_char) {\r
- if (piece_attack(board,piece,from,to)) {\r
- if (true\r
- && (string[1] == '?' || file_to_char(square_file(from)) == string[1])\r
- && (string[2] == '?' || rank_to_char(square_rank(from)) == string[2])) {\r
- if (!is_pinned(board,from,to,colour)) {\r
- move = move_make(from,to) | promote;\r
- n++;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (n != 1) move = MoveNone;\r
-\r
- return move;\r
-}\r
-\r
-// ambiguity()\r
-\r
-static int ambiguity(int move, const board_t * board) {\r
-\r
- int from, to, piece;\r
- list_t list[1];\r
- int i, n, m;\r
-\r
- // init\r
-\r
- from = move_from(move);\r
- to = move_to(move);\r
- piece = move_piece(move,board);\r
-\r
- gen_legal_moves(list,board);\r
-\r
- // no ambiguity?\r
-\r
- n = 0;\r
-\r
- for (i = 0; i < list_size(list); i++) {\r
- m = list_move(list,i);\r
- if (move_piece(m,board) == piece && move_to(m) == to) {\r
- n++;\r
- }\r
- }\r
-\r
- if (n == 1) return AMBIGUITY_NONE;\r
-\r
- // file ambiguity?\r
-\r
- n = 0;\r
-\r
- for (i = 0; i < list_size(list); i++) {\r
- m = list_move(list,i);\r
- if (move_piece(m,board) == piece && move_to(m) == to) {\r
- if (square_file(move_from(m)) == square_file(from)) n++;\r
- }\r
- }\r
-\r
- if (n == 1) return AMBIGUITY_FILE;\r
-\r
- // rank ambiguity?\r
-\r
- n = 0;\r
-\r
- for (i = 0; i < list_size(list); i++) {\r
- m = list_move(list,i);\r
- if (move_piece(m,board) == piece && move_to(m) == to) {\r
- if (square_rank(move_from(m)) == square_rank(from)) n++;\r
- }\r
- }\r
-\r
- if (n == 1) return AMBIGUITY_RANK;\r
-\r
- // square ambiguity\r
-\r
- return AMBIGUITY_SQUARE;\r
-}\r
-\r
-// end of san.cpp\r
-\r
+++ /dev/null
-// search.cpp\r
-\r
-// includes\r
-\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "attack.h"\r
-#include "board.h"\r
-#include "colour.h"\r
-#include "engine.h"\r
-#include "fen.h"\r
-#include "line.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_gen.h"\r
-#include "move_legal.h"\r
-#include "option.h"\r
-#include "parse.h"\r
-#include "san.h"\r
-#include "search.h"\r
-#include "uci.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const int StringSize = 4096;\r
-\r
-// variables\r
-\r
-static int Depth;\r
-\r
-static int BestMove;\r
-static int BestValue;\r
-static move_t BestPV[LineSize];\r
-\r
-static sint64 NodeNb;\r
-static sint64 LeafNb;\r
-static double Time;\r
-\r
-static int Move;\r
-static int MovePos;\r
-static int MoveNb;\r
-\r
-// prototypes\r
-\r
-static bool depth_is_ok (int depth);\r
-static void perft (const board_t * board, int depth);\r
-\r
-// functions\r
-\r
-// depth_is_ok()\r
-\r
-static bool depth_is_ok(int depth) {\r
-\r
- return depth >= 0 && depth < DepthMax;\r
-}\r
-\r
-// search()\r
-\r
-void search(const board_t * board, int depth_max, double time_max) {\r
-\r
- char string[256];\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(depth_max>=1&&depth_max<DepthMax);\r
- ASSERT(time_max>=0.0);\r
-\r
- // engine\r
-\r
- Depth = 0;\r
-\r
- BestMove = MoveNone;\r
- BestValue = 0;\r
- line_clear(BestPV);\r
-\r
- NodeNb = 0;\r
- LeafNb = 0;\r
- Time = 0.0;\r
-\r
- Move = MoveNone;\r
- MovePos = 0;\r
- MoveNb = 0;\r
-\r
- // init\r
-\r
- uci_send_ucinewgame(Uci);\r
- uci_send_isready_sync(Uci);\r
-\r
- // position\r
-\r
- if (!board_to_fen(board,string,256)) ASSERT(false);\r
- engine_send(Engine,"position fen %s",string);\r
-\r
- // search\r
-\r
- engine_send_queue(Engine,"go");\r
-\r
- engine_send_queue(Engine," movetime %.0f",time_max*1000.0);\r
- engine_send_queue(Engine," depth %d",depth_max);\r
-\r
- engine_send(Engine,""); // newline\r
-\r
- // wait for feed-back\r
-\r
- while (!engine_eof(Engine)) {\r
-\r
- engine_get(Engine,string,256);\r
-\r
- if (false) {\r
-\r
- } else if (match(string,"bestmove * ponder *")) {\r
-\r
- BestMove = move_from_can(Star[0],board);\r
- ASSERT(BestMove!=MoveNone&&move_is_legal(BestMove,board));\r
-\r
- break;\r
-\r
- } else if (match(string,"bestmove *")) {\r
-\r
- BestMove = move_from_can(Star[0],board);\r
- ASSERT(BestMove!=MoveNone&&move_is_legal(BestMove,board));\r
-\r
- break;\r
- }\r
- }\r
-\r
- printf("\n");\r
-}\r
-\r
-// do_perft()\r
-\r
-void do_perft(int argc,char * argv[]){\r
- const char * fen=NULL;\r
- int depth=1;\r
- board_t board[1];\r
- int i;\r
- for (i = 1; i < argc; i++) {\r
- if (false) {\r
- } else if (my_string_equal(argv[i],"perft")) {\r
- // skip\r
- } else if (my_string_equal(argv[i],"-fen")) {\r
- i++;\r
- if (argv[i] == NULL) my_fatal("do_perft(): missing argument\n");\r
- my_string_set(&fen,argv[i]);\r
- } else if (my_string_equal(argv[i],"-max-depth")){\r
- i++;\r
- if (argv[i] == NULL) my_fatal("do_perft(): missing argument\n");\r
- depth=atoi(argv[i]);\r
- if(depth<1) my_fatal("do_perft(): illegal depth %d\n",depth);\r
- } else {\r
- my_fatal("do_perft(): unknown option \"%s\"\n",argv[i]);\r
- }\r
- }\r
- if(fen==NULL){\r
- my_string_set(&fen,StartFen);\r
- }\r
- board_from_fen(board,fen);\r
- search_perft(board,depth);\r
-}\r
-\r
-// search_perft()\r
-\r
-void search_perft(const board_t * board, int depth_max) {\r
-\r
- int depth;\r
- my_timer_t timer[1];\r
- double time, speed;\r
- char node_string[StringSize];\r
- char leafnode_string[StringSize];\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(depth_max>=1&&depth_max<DepthMax);\r
-\r
- // init\r
-\r
- board_disp(board);\r
-\r
- // iterative deepening\r
-\r
- for (depth = 1; depth <= depth_max; depth++) {\r
-\r
- // init\r
-\r
- NodeNb = 0;\r
- LeafNb = 0;\r
-\r
- my_timer_reset(timer);\r
-\r
- my_timer_start(timer);\r
- perft(board,depth);\r
- my_timer_stop(timer);\r
-\r
- time = my_timer_elapsed_real(timer);//my_timer_elapsed_cpu(timer);\r
- speed = (time < 0.01) ? 0.0 : double(NodeNb) / time;\r
-\r
- snprintf(node_string,StringSize,S64_FORMAT,NodeNb);\r
- snprintf(leafnode_string,StringSize,S64_FORMAT,LeafNb);\r
-\r
- printf("depth=%2d nodes=%12s leafnodes=%12s time=%7.2fs nps=%8.0f\n",depth,node_string,leafnode_string,time,speed);\r
- }\r
-\r
-}\r
-\r
-// perft()\r
-\r
-static void perft(const board_t * board, int depth) {\r
-\r
- int me;\r
- list_t list[1];\r
- int i, move;\r
- board_t new_board[1];\r
-\r
- ASSERT(board_is_ok(board));\r
- ASSERT(depth_is_ok(depth));\r
-\r
- ASSERT(!is_in_check(board,colour_opp(board->turn)));\r
-\r
- // init\r
-\r
- NodeNb++;\r
-\r
- // leaf\r
-\r
- if (depth == 0) {\r
- LeafNb++;\r
- return;\r
- }\r
-\r
- // more init\r
-\r
- me = board->turn;\r
-\r
- // move loop\r
-\r
- gen_moves(list,board);\r
-\r
- for (i = 0; i < list_size(list); i++) {\r
-\r
- move = list_move(list,i);\r
-\r
- board_copy(new_board,board);\r
- move_do(new_board,move);\r
-\r
- if (!is_in_check(new_board,me)) perft(new_board,depth-1);\r
- }\r
-}\r
-\r
-// end of search.cpp\r
-\r
+++ /dev/null
-\r
-// square.cpp\r
-\r
-// includes\r
-\r
-#include "colour.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// "constants"\r
-\r
-static const uint8 SquareFrom64[64] = {\r
- A1, B1, C1, D1, E1, F1, G1, H1,\r
- A2, B2, C2, D2, E2, F2, G2, H2,\r
- A3, B3, C3, D3, E3, F3, G3, H3,\r
- A4, B4, C4, D4, E4, F4, G4, H4,\r
- A5, B5, C5, D5, E5, F5, G5, H5,\r
- A6, B6, C6, D6, E6, F6, G6, H6,\r
- A7, B7, C7, D7, E7, F7, G7, H7,\r
- A8, B8, C8, D8, E8, F8, G8, H8,\r
-};\r
-\r
-// variables\r
-\r
-static sint8 SquareTo64[SquareNb];\r
-\r
-// functions\r
-\r
-// square_init()\r
-\r
-void square_init() {\r
-\r
- int sq;\r
-\r
- for (sq = 0; sq < SquareNb; sq++) SquareTo64[sq] = -1;\r
-\r
- for (sq = 0; sq < 64; sq++) {\r
- SquareTo64[SquareFrom64[sq]] = sq;\r
- }\r
-}\r
-\r
-// square_is_ok()\r
-\r
-bool square_is_ok(int square) {\r
-\r
- if (square < 0 || square >= SquareNb) return false;\r
-\r
- if (SquareTo64[square] < 0) return false;\r
-\r
- return true;\r
-}\r
-\r
-// square_make()\r
-\r
-int square_make(int file, int rank) {\r
-\r
- int sq_64;\r
-\r
- ASSERT(file>=0&&file<8);\r
- ASSERT(rank>=0&&rank<8);\r
-\r
- sq_64 = (rank << 3) | file;\r
-\r
- return square_from_64(sq_64);\r
-}\r
-\r
-// square_file()\r
-\r
-int square_file(int square) {\r
-\r
- int file;\r
-\r
- ASSERT(square_is_ok(square));\r
-\r
- file = (square - 4) & 7;\r
- ASSERT(file==(square_to_64(square)&7));\r
-\r
- return file;\r
-}\r
-\r
-// square_rank()\r
-\r
-int square_rank(int square) {\r
-\r
- int rank;\r
-\r
- ASSERT(square_is_ok(square));\r
-\r
- rank = (square >> 4) - 2;\r
- ASSERT(rank==square_to_64(square)>>3);\r
-\r
- return rank;\r
-}\r
-\r
-// square_side_rank()\r
-\r
-int square_side_rank(int square, int colour) {\r
-\r
- int rank;\r
-\r
- ASSERT(square_is_ok(square));\r
- ASSERT(colour_is_ok(colour));\r
-\r
- rank = square_rank(square);\r
- if (colour_is_black(colour)) rank = 7-rank;\r
-\r
- return rank;\r
-}\r
-\r
-// square_from_64()\r
-\r
-int square_from_64(int square) {\r
-\r
- ASSERT(square>=0&&square<64);\r
-\r
- return SquareFrom64[square];\r
-}\r
-\r
-// square_to_64()\r
-\r
-int square_to_64(int square) {\r
-\r
- ASSERT(square_is_ok(square));\r
-\r
- return SquareTo64[square];\r
-}\r
-\r
-// square_is_promote()\r
-\r
-bool square_is_promote(int square) {\r
-\r
- int rank;\r
-\r
- ASSERT(square_is_ok(square));\r
-\r
- rank = square_rank(square);\r
-\r
- return rank == Rank1 || rank == Rank8;\r
-}\r
-\r
-// square_ep_dual()\r
-\r
-int square_ep_dual(int square) {\r
-\r
- ASSERT(square_is_ok(square));\r
- ASSERT(square_rank(square)>=2&&square_rank(square)<=5);\r
-\r
- return square ^ 16;\r
-}\r
-\r
-// square_colour()\r
-\r
-int square_colour(int square) {\r
-\r
- ASSERT(square_is_ok(square));\r
-\r
- return (square ^ (square >> 4)) & 1;\r
-}\r
-\r
-// file_from_char()\r
-\r
-int file_from_char(int c) {\r
-\r
- ASSERT(c>='a'&&c<='h');\r
-\r
- return c - 'a';\r
-}\r
-\r
-// rank_from_char()\r
-\r
-int rank_from_char(int c) {\r
-\r
- ASSERT(c>='1'&&c<='8');\r
-\r
- return c - '1';\r
-}\r
-\r
-// file_to_char()\r
-\r
-int file_to_char(int file) {\r
-\r
- ASSERT(file>=0&&file<8);\r
-\r
- return 'a' + file;\r
-}\r
-\r
-// rank_to_char()\r
-\r
-int rank_to_char(int rank) {\r
-\r
- ASSERT(rank>=0&&rank<8);\r
-\r
- return '1' + rank;\r
-}\r
-\r
-// char_is_file()\r
-\r
-bool char_is_file(int c) {\r
-\r
- return c >= 'a' && c <= 'h';\r
-}\r
-\r
-// char_is_rank()\r
-\r
-bool char_is_rank(int c) {\r
-\r
- return c >= '1' && c <= '8';\r
-}\r
-\r
-// square_to_string()\r
-\r
-bool square_to_string(int square, char string[], int size) {\r
-\r
- ASSERT(square_is_ok(square));\r
- ASSERT(string!=NULL);\r
- ASSERT(size>=3);\r
-\r
- if (size < 3) return false;\r
-\r
- string[0] = 'a' + square_file(square);\r
- string[1] = '1' + square_rank(square);\r
- string[2] = '\0';\r
-\r
- return true;\r
-}\r
-\r
-// square_from_string()\r
-\r
-int square_from_string(const char string[]) {\r
-\r
- int file, rank;\r
-\r
- ASSERT(string!=NULL);\r
-\r
- if (string[0] < 'a' || string[0] > 'h') return SquareNone;\r
- if (string[1] < '1' || string[1] > '8') return SquareNone;\r
- if (string[2] != '\0') return SquareNone;\r
-\r
- file = file_from_char(string[0]);\r
- rank = rank_from_char(string[1]);\r
-\r
- return square_make(file,rank);\r
-}\r
-\r
-// end of square.cpp\r
-\r
+++ /dev/null
-\r
-// uci.cpp\r
-\r
-// includes\r
-\r
-#include <cstdarg>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-\r
-#include "board.h"\r
-#include "engine.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_legal.h"\r
-#include "option.h"\r
-#include "parse.h"\r
-#include "line.h"\r
-#include "uci.h"\r
-\r
-// constants\r
-\r
-static const bool UseDebug = false;\r
-\r
-static const int StringSize = 4096;\r
-\r
-// variables\r
-\r
-uci_t Uci[1];\r
-\r
-// Hopefully the following confusion is temporary\r
-// Normally we should check for the engine name but this is a hack anyway\r
-// Some of there where provided by Marc Lacrosse\r
-\r
-const char * thread_options[]={\r
- "number of threads", // toga\r
- "number threads", // Deep Learning Toga\r
- "threads", // glaurung, zappa, cyclone, grapefruit,\r
- // Deep Shredder, Deep Junior\r
- "core threads", // HIARCS\r
- "max cpus", // rybka\r
- "cpus", // Deep Sjeng, Fruit2.3.5\r
- "maxthreads", // Naum \r
- NULL\r
-};\r
-\r
-// prototypes\r
-\r
-static bool uci_is_ok (const uci_t * uci);\r
-\r
-static int parse_bestmove (uci_t * uci, const char string[]);\r
-static void parse_id (uci_t * uci, const char string[]);\r
-static int parse_info (uci_t * uci, const char string[]);\r
-static void parse_option (uci_t * uci, const char string[]);\r
-static void parse_score (uci_t * uci, const char string[]);\r
-\r
-static int mate_score (int dist);\r
-\r
-// functions\r
-\r
-// uci_set_threads()\r
-\r
-void uci_set_threads(uci_t * uci, int n) {\r
- const char **thread_options_copy = thread_options;\r
- const char *thread_option;\r
- ASSERT(n>=1);\r
- while((thread_option = *(thread_options_copy++))){\r
- uci_send_option(uci,thread_option,"%d",n); // checks also for existence\r
- }\r
-}\r
-\r
-// uci_thread_option_exists()\r
-\r
-bool uci_thread_option_exist(uci_t * uci) {\r
- const char **thread_options_copy = thread_options;\r
- const char *thread_option;\r
- while((thread_option = *(thread_options_copy++))){\r
- if(uci_option_exist(uci,thread_option)) return true;\r
- }\r
- return false;\r
-}\r
-\r
-const char * uci_thread_option(uci_t * uci){\r
- const char **thread_options_copy = thread_options;\r
- const char *thread_option;\r
- int i;\r
- while((thread_option = *(thread_options_copy++))){\r
- i=uci_get_option(uci,thread_option);\r
- if(i>=0){\r
- return Uci->option[i].name;\r
- break;\r
- }\r
- }\r
- return NULL;\r
-}\r
-\r
-// uci_is_ok()\r
-\r
-static bool uci_is_ok(const uci_t * uci) {\r
-\r
- if (uci == NULL) return false;\r
- if (uci->engine == NULL) return false;\r
- if (uci->option_nb < 0 || uci->option_nb >= OptionNb) return false;\r
-\r
- return true;\r
-}\r
-\r
-// uci_open()\r
-\r
-void uci_open(uci_t * uci, engine_t * engine) {\r
-\r
- char string[StringSize];\r
- int event;\r
-\r
- ASSERT(uci!=NULL);\r
- ASSERT(engine!=NULL);\r
-\r
- // init\r
-\r
- uci->engine = engine;\r
-\r
- uci->name = NULL;\r
- my_string_set(&uci->name,"<empty>");\r
- uci->author = NULL;\r
- my_string_set(&uci->author,"<empty>");\r
- uci->option_nb = 0;\r
-\r
- uci->ready_nb = 0;\r
- uci->searching = 0;\r
- uci->pending_nb = 0;\r
- uci->multipv_mode = false;\r
- board_start(uci->board);\r
- uci_clear(uci);\r
-\r
- // send "uci" and wait for "uciok"\r
-\r
- engine_send(uci->engine,"uci");\r
-\r
- do {\r
- engine_get(uci->engine,string,StringSize);\r
- event = uci_parse(uci,string);\r
- } while (!engine_eof(Engine) && (event & EVENT_UCI) == 0);\r
-}\r
-\r
-// uci_close()\r
-\r
-void uci_close(uci_t * uci) {\r
-\r
- int i;\r
- option_t * opt;\r
-\r
- ASSERT(uci_is_ok(uci));\r
- engine_close(uci->engine);\r
- uci->engine = NULL;\r
- my_string_clear(&uci->name);\r
- my_string_clear(&uci->author);\r
-\r
- for (i = 0; i < uci->option_nb; i++) {\r
- opt = &uci->option[i];\r
- my_string_clear(&opt->name);\r
- my_string_clear(&opt->default_);\r
- }\r
-\r
- uci->option_nb = 0;\r
-}\r
-\r
-// uci_clear()\r
-\r
-void uci_clear(uci_t * uci) {\r
-\r
- ASSERT(uci_is_ok(uci));\r
-\r
- ASSERT(!uci->searching);\r
-\r
- uci->best_move = MoveNone;\r
- uci->ponder_move = MoveNone;\r
-\r
- uci->score = 0;\r
- uci->depth = 0;\r
- uci->sel_depth = 0;\r
- line_clear(uci->pv);\r
-\r
- uci->best_score = 0;\r
- uci->best_depth = 0;\r
- uci->best_sel_depth = 0;\r
- line_clear(uci->best_pv);\r
-\r
- uci->node_nb = 0;\r
- uci->time = 0.0;\r
- uci->speed = 0.0;\r
- uci->cpu = 0.0;\r
- uci->hash = 0.0;\r
- line_clear(uci->current_line);\r
-\r
- uci->root_move = MoveNone;\r
- uci->root_move_pos = 0;\r
- uci->root_move_nb = board_mobility(uci->board);\r
-}\r
-\r
-// uci_send_isready()\r
-\r
-void uci_send_isready(uci_t * uci) {\r
-\r
- ASSERT(uci!=NULL);\r
-\r
- engine_send(uci->engine,"isready");\r
- uci->ready_nb++;\r
-}\r
-\r
-// uci_send_isready_sync()\r
-\r
-void uci_send_isready_sync(uci_t * uci) {\r
-\r
- char string[StringSize];\r
- int event;\r
-\r
- ASSERT(uci_is_ok(uci));\r
-\r
- // send "isready" and wait for "readyok"\r
-\r
- uci_send_isready(uci);\r
-\r
- do {\r
- engine_get(uci->engine,string,StringSize);\r
- event = uci_parse(uci,string);\r
- } while (!engine_eof(Engine) && (event & EVENT_READY) == 0);\r
-}\r
-\r
-// uci_send_stop()\r
-\r
-void uci_send_stop(uci_t * uci) {\r
-\r
- ASSERT(uci_is_ok(uci));\r
-\r
- ASSERT(uci->searching);\r
- ASSERT(uci->pending_nb>=1);\r
-\r
- engine_send(Engine,"stop");\r
- uci->searching = false;\r
-}\r
-\r
-// uci_send_stop_sync()\r
-\r
-void uci_send_stop_sync(uci_t * uci) {\r
-\r
- char string[StringSize];\r
- int event;\r
-\r
- ASSERT(uci_is_ok(uci));\r
-\r
- ASSERT(uci->searching);\r
- ASSERT(uci->pending_nb>=1);\r
-\r
- // send "stop" and wait for "bestmove"\r
-\r
- uci_send_stop(uci);\r
-\r
- do {\r
- engine_get(uci->engine,string,StringSize);\r
- event = uci_parse(uci,string);\r
- } while (!engine_eof(Engine) && (event & EVENT_STOP) == 0);\r
-}\r
-\r
-// uci_send_ucinewgame()\r
-\r
-void uci_send_ucinewgame(uci_t * uci) {\r
-\r
- ASSERT(uci!=NULL);\r
-\r
- if (option_get_int("UCIVersion") >= 2) {\r
- engine_send(uci->engine,"ucinewgame");\r
- }\r
-}\r
-\r
-// uci_option_exist()\r
-\r
-bool uci_option_exist(uci_t * uci, const char option[]) {\r
-\r
- int i;\r
- option_t * opt;\r
-\r
- ASSERT(uci_is_ok(uci));\r
- ASSERT(option!=NULL);\r
-\r
- // scan options\r
-\r
- for (i = 0; i < uci->option_nb; i++) {\r
- opt = &uci->option[i];\r
- if (my_string_case_equal(opt->name,option)) return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-// uci_send_option()\r
-\r
-void uci_send_option(uci_t * uci, const char option[], const char format[], ...) {\r
-\r
- va_list arg_list;\r
- char value[StringSize];\r
- int i;\r
- option_t * opt;\r
-\r
- ASSERT(uci_is_ok(uci));\r
- ASSERT(option!=NULL);\r
- ASSERT(format!=NULL);\r
-\r
- // format\r
-\r
- va_start(arg_list,format);\r
- vsprintf(value,format,arg_list);\r
- va_end(arg_list);\r
-\r
- if (UseDebug) my_log("POLYGLOT OPTION %s VALUE %s\n",option,value);\r
-\r
- // scan options\r
-\r
- for (i = 0; i < uci->option_nb; i++) {\r
-\r
- opt = &uci->option[i];\r
-\r
- if (my_string_case_equal(opt->name,option) && !my_string_equal(opt->default_,value)) {\r
- engine_send(uci->engine,"setoption name %s value %s",opt->name,value);\r
- my_string_set(&opt->default_,value);\r
- break;\r
- }\r
- }\r
-}\r
-\r
-// uci_parse()\r
-\r
-int uci_parse(uci_t * uci, const char string[]) {\r
-\r
- int event;\r
- parse_t parse[1];\r
- char command[StringSize];\r
- char argument[StringSize];\r
-\r
- ASSERT(uci_is_ok(uci));\r
- ASSERT(string!=NULL);\r
-\r
- // init\r
-\r
- event = EVENT_NONE;\r
-\r
- // parse\r
-\r
- parse_open(parse,string);\r
-\r
- if (parse_get_word(parse,command,StringSize)) {\r
-\r
- parse_get_string(parse,argument,StringSize);\r
- if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" ARGUMENT \"%s\"\n",command,argument);\r
-\r
- if (false) {\r
-\r
- } else if (my_string_equal(command,"bestmove")) {\r
-\r
- // search end\r
-\r
- ASSERT(uci->pending_nb>0);\r
-\r
- if (uci->searching && uci->pending_nb == 1) {\r
-\r
- // current search\r
-\r
- uci->searching = false;\r
- uci->pending_nb--;\r
-\r
- event = parse_bestmove(uci,argument); // updates uci->best_move and uci->ponder_move\r
-\r
- } else {\r
-\r
- // obsolete search\r
-\r
- if (uci->pending_nb > 0) {\r
- uci->pending_nb--;\r
- if (uci->pending_nb == 0) event = EVENT_STOP;\r
- }\r
- }\r
-\r
- } else if (my_string_equal(command,"id")) {\r
-\r
- parse_id(uci,argument);\r
-\r
- } else if (my_string_equal(command,"info")) {\r
-\r
- // search information\r
-\r
- if (uci->searching && uci->pending_nb == 1) { // current search\r
- event = parse_info(uci,argument);\r
- }\r
-\r
- } else if (my_string_equal(command,"option")) {\r
-\r
- parse_option(uci,argument);\r
-\r
- } else if (my_string_equal(command,"readyok")) {\r
-\r
- // engine is ready\r
-\r
- ASSERT(uci->ready_nb>0);\r
-\r
- if (uci->ready_nb > 0) {\r
- uci->ready_nb--;\r
- if (uci->ready_nb == 0) event = EVENT_READY;\r
- }\r
-\r
- } else if (my_string_equal(command,"uciok")) {\r
-\r
- event = EVENT_UCI;\r
-\r
- } else {\r
-\r
- if (UseDebug) my_log("POLYGLOT unknown command \"%s\"\n",command);\r
- }\r
- }\r
-\r
- parse_close(parse);\r
-\r
- return event;\r
-}\r
-\r
-// parse_bestmove()\r
-\r
-static int parse_bestmove(uci_t * uci, const char string[]) {\r
-\r
- parse_t parse[1];\r
- char command[StringSize];\r
- char option[StringSize];\r
- char argument[StringSize];\r
- board_t board[1];\r
-\r
- ASSERT(uci_is_ok(uci));\r
- ASSERT(string!=NULL);\r
-\r
- // init\r
-\r
- strcpy(command,"bestmove");\r
-\r
- parse_open(parse,string);\r
- parse_add_keyword(parse,"ponder");\r
-\r
- // bestmove\r
-\r
- if (!parse_get_string(parse,argument,StringSize)) {\r
- my_fatal("parse_bestmove(): missing argument\n");\r
- }\r
-\r
- uci->best_move = move_from_can(argument,uci->board);\r
- if (uci->best_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
-\r
- ASSERT(uci->best_move!=MoveNone);\r
- ASSERT(move_is_legal(uci->best_move,uci->board));\r
-\r
- // loop\r
-\r
- while (parse_get_word(parse,option,StringSize)) {\r
-\r
- parse_get_string(parse,argument,StringSize);\r
-\r
- if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
-\r
- if (false) {\r
-\r
- } else if (my_string_equal(option,"ponder")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- board_copy(board,uci->board);\r
- move_do(board,uci->best_move);\r
-\r
- uci->ponder_move = move_from_can(argument,board);\r
- // if (uci->ponder_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument);\r
-\r
- ASSERT(uci->ponder_move!=MoveNone);\r
- ASSERT(move_is_legal(uci->ponder_move,board));\r
-\r
- } else {\r
-\r
- my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
- }\r
- }\r
-\r
- parse_close(parse);\r
-\r
- return EVENT_MOVE;\r
-}\r
-\r
-// parse_id()\r
-\r
-static void parse_id(uci_t * uci, const char string[]) {\r
-\r
- parse_t parse[1];\r
- char command[StringSize];\r
- char option[StringSize];\r
- char argument[StringSize];\r
-\r
- ASSERT(uci!=NULL);\r
- ASSERT(string!=NULL);\r
-\r
- // init\r
-\r
- strcpy(command,"id");\r
-\r
- parse_open(parse,string);\r
- parse_add_keyword(parse,"author");\r
- parse_add_keyword(parse,"name");\r
-\r
- // loop\r
-\r
- while (parse_get_word(parse,option,StringSize)) {\r
-\r
- parse_get_string(parse,argument,StringSize);\r
- if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
-\r
- if (false) {\r
- } else if (my_string_equal(option,"author")) {\r
- ASSERT(!my_string_empty(argument));\r
- my_string_set(&uci->author,argument);\r
- } else if (my_string_equal(option,"name")) {\r
- ASSERT(!my_string_empty(argument));\r
- my_string_set(&uci->name,argument);\r
- } else {\r
- my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
- }\r
- }\r
-\r
- parse_close(parse);\r
-\r
- if (UseDebug) my_log("POLYGLOT engine name \"%s\" author \"%s\"\n",uci->name,uci->author);\r
-}\r
-\r
-// parse_info()\r
-\r
-static int parse_info(uci_t * uci, const char string[]) {\r
-\r
- int event;\r
- parse_t parse[1];\r
- char command[StringSize];\r
- char option[StringSize];\r
- char argument[StringSize];\r
- int n;\r
- int multipvline=0;\r
- sint64 ln;\r
-\r
- ASSERT(uci_is_ok(uci));\r
- ASSERT(string!=NULL);\r
-\r
- // init\r
-\r
- event = EVENT_NONE;\r
-\r
- strcpy(command,"info");\r
-\r
- parse_open(parse,string);\r
- parse_add_keyword(parse,"cpuload");\r
- parse_add_keyword(parse,"currline");\r
- parse_add_keyword(parse,"currmove");\r
- parse_add_keyword(parse,"currmovenumber");\r
- parse_add_keyword(parse,"depth");\r
- parse_add_keyword(parse,"hashfull");\r
- parse_add_keyword(parse,"multipv");\r
- parse_add_keyword(parse,"nodes");\r
- parse_add_keyword(parse,"nps");\r
- parse_add_keyword(parse,"pv");\r
- parse_add_keyword(parse,"refutation");\r
- parse_add_keyword(parse,"score");\r
- parse_add_keyword(parse,"seldepth");\r
- parse_add_keyword(parse,"string");\r
- parse_add_keyword(parse,"tbhits");\r
- parse_add_keyword(parse,"time");\r
-\r
- // loop\r
-\r
- while (parse_get_word(parse,option,StringSize)) {\r
-\r
- parse_get_string(parse,argument,StringSize);\r
-\r
- if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
-\r
- if (false) {\r
-\r
- } else if (my_string_equal(option,"cpuload")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- ASSERT(n>=0);\r
-\r
- if (n >= 0) uci->cpu = double(n) / 1000.0;\r
-\r
- } else if (my_string_equal(option,"currline")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- line_from_can(uci->current_line,uci->board,argument,LineSize);\r
-\r
- } else if (my_string_equal(option,"currmove")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- uci->root_move = move_from_can(argument,uci->board);\r
- ASSERT(uci->root_move!=MoveNone);\r
-\r
- } else if (my_string_equal(option,"currmovenumber")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- ASSERT(n>=1&&n<=uci->root_move_nb);\r
-\r
- if (n >= 1 && n <= uci->root_move_nb) {\r
- uci->root_move_pos = n - 1;\r
- ASSERT(uci->root_move_pos>=0&&uci->root_move_pos<uci->root_move_nb);\r
- }\r
-\r
- } else if (my_string_equal(option,"depth")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- ASSERT(n>=1);\r
-\r
- if (n >= 0) {\r
- if (n > uci->depth) event |= EVENT_DEPTH;\r
- uci->depth = n;\r
- }\r
-\r
- } else if (my_string_equal(option,"hashfull")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- ASSERT(n>=0);\r
-\r
- if (n >= 0) uci->hash = double(n) / 1000.0;\r
-\r
- } else if (my_string_equal(option,"multipv")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- if(Uci->multipv_mode) multipvline=n;\r
- \r
- ASSERT(n>=1);\r
-\r
- } else if (my_string_equal(option,"nodes")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- ln = my_atoll(argument);\r
- ASSERT(ln>=0);\r
-\r
- if (ln >= 0) uci->node_nb = ln;\r
-\r
- } else if (my_string_equal(option,"nps")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- ASSERT(n>=0);\r
-\r
- if (n >= 0) uci->speed = double(n);\r
-\r
- } else if (my_string_equal(option,"pv")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- line_from_can(uci->pv,uci->board,argument,LineSize);\r
- event |= EVENT_PV;\r
-\r
- } else if (my_string_equal(option,"refutation")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- line_from_can(uci->pv,uci->board,argument,LineSize);\r
-\r
- } else if (my_string_equal(option,"score")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- parse_score(uci,argument);\r
-\r
- } else if (my_string_equal(option,"seldepth")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- ASSERT(n>=0);\r
-\r
- if (n >= 0) uci->sel_depth = n;\r
-\r
- } else if (my_string_equal(option,"string")) {\r
- if(!strncmp(argument,"DrawOffer",9))\r
- event |= EVENT_DRAW;\r
- if(!strncmp(argument,"Resign",6))\r
- event |= EVENT_RESIGN;\r
-\r
- // TODO: argument to EOS\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- } else if (my_string_equal(option,"tbhits")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- ln = my_atoll(argument);\r
- ASSERT(ln>=0);\r
-\r
- } else if (my_string_equal(option,"time")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- ASSERT(n>=0);\r
-\r
- if (n >= 0) uci->time = double(n) / 1000.0;\r
-\r
- } else {\r
-\r
- my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
- }\r
- }\r
-\r
- parse_close(parse);\r
-\r
- // update display\r
- //lousy uci,filter out lower depth multipv lines that have been repeated from the engine \r
- if(multipvline>1 && uci->depth<uci->best_depth) event &= ~EVENT_PV;\r
- if ((event & EVENT_PV) != 0) {\r
- uci->best_score = uci->score; \r
- uci->best_depth = uci->depth;\r
- if(multipvline==1)uci->depth=-1; //HACK ,clears the engine outpout window,see send_pv in adapter.cpp \r
- uci->best_sel_depth = uci->sel_depth;\r
- line_copy(uci->best_pv,uci->pv);\r
- }\r
- return event;\r
-}\r
-\r
-int uci_get_option(uci_t * uci, const char * name){\r
- int i;\r
- for(i=0;i<Uci->option_nb;i++){\r
- if(my_string_case_equal(Uci->option[i].name,name)){\r
- return i;\r
- }\r
- }\r
- return -1;\r
-}\r
-\r
-\r
-\r
-// uci_set_option()\r
-\r
-void uci_set_option(uci_t * uci,\r
- const char * name,\r
- const char * default_,\r
- const char * type,\r
- const char * max,\r
- const char * min,\r
- int var_nb,\r
- const char * var[]){\r
- int i,j;\r
- for(i=0;i<Uci->option_nb;i++){\r
- if(my_string_equal(Uci->option[i].name,name)){\r
- break;\r
- }\r
- }\r
- if(i<OptionNb){\r
- my_string_set(&(Uci->option[i].name),name);\r
- my_string_set(&(Uci->option[i].default_),default_);\r
- my_string_set(&(Uci->option[i].type),type);\r
- my_string_set(&(Uci->option[i].min),min);\r
- my_string_set(&(Uci->option[i].max),max);\r
- Uci->option[i].var_nb=var_nb;\r
- for(j=0;j<var_nb;j++){\r
- my_string_set(&(Uci->option[i].var[j]),var[j]);\r
- }\r
- if(i==Uci->option_nb){\r
- Uci->option_nb++;\r
- }\r
- }\r
-}\r
-\r
-// parse_option()\r
-\r
-static void parse_option(uci_t * uci, const char string[]) {\r
-\r
- option_t * opt;\r
- parse_t parse[1];\r
- char command[StringSize];\r
- char option[StringSize];\r
- char argument[StringSize];\r
-\r
- ASSERT(uci!=NULL);\r
- ASSERT(string!=NULL);\r
-\r
- // init\r
-\r
- strcpy(command,"option");\r
-\r
- if (uci->option_nb >= OptionNb) return;\r
-\r
- opt = &uci->option[uci->option_nb];\r
- uci->option_nb++;\r
-\r
- opt->value=NULL;\r
- my_string_set(&opt->value,"<empty>");\r
- opt->mode=0;\r
-\r
- opt->name = NULL;\r
- my_string_set(&opt->name,"<empty>");\r
-\r
- \r
- opt->default_ = NULL;\r
- my_string_set(&opt->default_,"<empty>");\r
-\r
- opt->max = NULL;\r
- my_string_set(&opt->max,"<empty>");\r
-\r
- opt->min = NULL;\r
- my_string_set(&opt->min,"<empty>");\r
-\r
- opt->type = NULL;\r
- my_string_set(&opt->type,"<empty>");\r
-\r
- opt->var_nb=0;\r
- \r
- parse_open(parse,string);\r
- parse_add_keyword(parse,"default");\r
- parse_add_keyword(parse,"max");\r
- parse_add_keyword(parse,"min");\r
- parse_add_keyword(parse,"name");\r
- parse_add_keyword(parse,"type");\r
- parse_add_keyword(parse,"var");\r
-\r
- // loop\r
-\r
- while (parse_get_word(parse,option,StringSize)) {\r
- parse_get_string(parse,argument,StringSize);\r
- if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
-\r
- if (false) {\r
-\r
- } else if (my_string_equal(option,"default")) {\r
-\r
- // ASSERT(!my_string_empty(argument)); // HACK for Pepito\r
-\r
- if (!my_string_empty(argument)) {\r
- my_string_set(&opt->default_,argument);\r
- my_string_set(&opt->value,argument);\r
- }\r
-\r
- } else if (my_string_equal(option,"max")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
- my_string_set(&opt->max,argument);\r
-\r
- } else if (my_string_equal(option,"min")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
- my_string_set(&opt->min,argument);\r
-\r
- } else if (my_string_equal(option,"name")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- if (!my_string_empty(argument)) {\r
- my_string_set(&opt->name,argument);\r
- }\r
-\r
- } else if (my_string_equal(option,"type")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
- my_string_set(&opt->type,argument);\r
-\r
- } else if (my_string_equal(option,"var")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
- my_string_set(&opt->var[opt->var_nb++],argument);\r
- if(opt->var_nb==VarNb) break;\r
-\r
- } else {\r
-\r
- my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
- }\r
- }\r
-\r
- parse_close(parse);\r
-\r
- if (UseDebug) my_log("POLYGLOT option name \"%s\" default \"%s\"\n",opt->name,opt->default_);\r
-}\r
-\r
-// parse_score()\r
-\r
-static void parse_score(uci_t * uci, const char string[]) {\r
-\r
- parse_t parse[1];\r
- char command[StringSize];\r
- char option[StringSize];\r
- char argument[StringSize];\r
- int n;\r
-\r
- ASSERT(uci_is_ok(uci));\r
- ASSERT(string!=NULL);\r
-\r
- // init\r
-\r
- strcpy(command,"score");\r
-\r
- parse_open(parse,string);\r
- parse_add_keyword(parse,"cp");\r
- parse_add_keyword(parse,"lowerbound");\r
- parse_add_keyword(parse,"mate");\r
- parse_add_keyword(parse,"upperbound");\r
-\r
- // loop\r
-\r
- while (parse_get_word(parse,option,StringSize)) {\r
-\r
- parse_get_string(parse,argument,StringSize);\r
-\r
- if (UseDebug) my_log("POLYGLOT COMMAND \"%s\" OPTION \"%s\" ARGUMENT \"%s\"\n",command,option,argument);\r
-\r
- if (false) {\r
-\r
- } else if (my_string_equal(option,"cp")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
-\r
- uci->score = n;\r
-\r
- } else if (my_string_equal(option,"lowerbound")) {\r
-\r
- ASSERT(my_string_empty(argument));\r
-\r
- } else if (my_string_equal(option,"mate")) {\r
-\r
- ASSERT(!my_string_empty(argument));\r
-\r
- n = atoi(argument);\r
- ASSERT(n!=0);\r
-\r
- uci->score = mate_score(n);\r
-\r
- } else if (my_string_equal(option,"upperbound")) {\r
-\r
- ASSERT(my_string_empty(argument));\r
-\r
- } else {\r
-\r
- my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command);\r
- }\r
- }\r
-\r
- parse_close(parse);\r
-}\r
-\r
-// mate_score()\r
-\r
-static int mate_score(int dist) {\r
-\r
- ASSERT(dist!=0);\r
-\r
- if (false) {\r
- } else if (dist > 0) {\r
- return +option_get_int("MateScore") - (+dist) * 2 + 1;\r
- } else if (dist < 0) {\r
- return -option_get_int("MateScore") + (-dist) * 2;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-// end of uci.cpp\r
-\r
+++ /dev/null
-// uci2uci.cpp
-
-// includes
-
-#include <cstring>
-#include <cstdlib>
-
-#include "util.h"
-#include "board.h"
-#include "engine.h"
-#include "fen.h"
-#include "gui.h"
-#include "move.h"
-#include "move_do.h"
-#include "move_legal.h"
-#include "parse.h"
-#include "option.h"
-#include "book.h"
-#include "main.h"
-#include "uci.h"
-
-// constants
-
-static const int StringSize = 4096;
-
-// variables
-
-static board_t UCIboard[1];
-static bool Init=true;
-static int SavedMove=MoveNone;
-
-// prototypes
-
-static void send_uci_options();
-
-// parse_position()
-
-static void parse_position(const char string[]) {
-
-/* This is borrowed from Toga II. This code is quite hacky and will be
- rewritten using the routines in parse.cpp.
-*/
-
- const char * fen;
- char * moves;
- const char * ptr;
- char move_string[256];
- int move;
- char * string_copy;
-
- // init
-
- string_copy=my_strdup(string);
-
- fen = strstr(string_copy,"fen ");
- moves = strstr(string_copy,"moves ");
-
- // start position
-
- if (fen != NULL) { // "fen" present
-
- if (moves != NULL) { // "moves" present
- ASSERT(moves>fen);
- moves[-1] = '\0'; // dirty, but so is UCI
- }
-
- board_from_fen(UCIboard,fen+4); // CHANGE ME
-
- } else {
-
- // HACK: assumes startpos
-
- board_from_fen(UCIboard,StartFen);
- }
-
- // moves
-
- if (moves != NULL) { // "moves" present
-
- ptr = moves + 6;
-
- while (*ptr != '\0') {
-
- while (*ptr == ' ') ptr++;
-
- move_string[0] = *ptr++;
- move_string[1] = *ptr++;
- move_string[2] = *ptr++;
- move_string[3] = *ptr++;
-
- if (*ptr == '\0' || *ptr == ' ') {
- move_string[4] = '\0';
- } else { // promote
- move_string[4] = *ptr++;
- move_string[5] = '\0';
- }
- move = move_from_can(move_string,UCIboard);
-
- move_do(UCIboard,move);
-
- }
- }
- free(string_copy);
-}
-
-
-// send_book_move()
-
-static void send_book_move(int move){
- char move_string[256];
- my_log("POLYGLOT *BOOK MOVE*\n");
- move_to_can(move,UCIboard,move_string,256);
- // bogus info lines
- gui_send(GUI,"info depth 1 time 0 nodes 0 nps 0 cpuload 0");
- gui_send(GUI,"bestmove %s",move_string);
-}
-
-// format_uci_option_line()
-
-static void format_uci_option_line(char * option_line,option_t *opt){
- char option_string[StringSize];
- int j;
- strcpy(option_line,"");
- strcat(option_line,"option name");
- if(opt->mode&PG){
- strcat(option_line," Polyglot");
- }
- sprintf(option_string," %s",opt->name);
- strcat(option_line,option_string);
- sprintf(option_string," type %s",opt->type);
- strcat(option_line,option_string);
- if(strcmp(opt->type,"button")){
- sprintf(option_string," default %s",opt->default_);
- strcat(option_line,option_string);
- }
- if(!strcmp(opt->type,"spin")){
- sprintf(option_string," min %s",opt->min);
- strcat(option_line,option_string);
- }
- if(!strcmp(opt->type,"spin")){
- sprintf(option_string," max %s",opt->max);
- strcat(option_line,option_string);
- }
- for(j=0;j<opt->var_nb;j++){
- sprintf(option_string," var %s",opt->var[j]);
- strcat(option_line,option_string);
- }
-}
-
-// send_uci_options()
-
-static void send_uci_options() {
- int i;
- option_t *p=Option;
- char option_line[StringSize]="";
- gui_send(GUI,"id name %s", Uci->name);
- gui_send(GUI,"id author %s", Uci->author);
- for(i=0;i<Uci->option_nb;i++){
- format_uci_option_line(option_line,Uci->option+i);
- gui_send(GUI,"%s",option_line);
- }
- while(p->name){
- if(p->mode &UCI){
- format_uci_option_line(option_line,p);
- gui_send(GUI,"%s",option_line);
- }
- p++;
- }
- gui_send(GUI,"uciok");
-}
-
-// parse_setoption()
-
-
-
-static void parse_setoption(const char string[]) {
- char *name;
- char *pg_name;
- char *value;
- char * string_copy;
- string_copy=my_strdup(string);
- if(match(string_copy,"setoption name * value *")){
- name=Star[0];
- value=Star[1];
- if(match(name, "Polyglot *")){
- pg_name=Star[0];
- polyglot_set_option(pg_name,value);
- }else{
- engine_send(Engine,"%s",string);
- }
- }else{
- engine_send(Engine,"%s",string);
- }
- free(string_copy);
-}
-
-
-// uci2uci_gui_step()
-
-void uci2uci_gui_step(char string[]) {
- int move;
- if(false){
- }else if(match(string,"uci")){
- send_uci_options();
- return;
- }else if(match(string,"setoption *")){
- parse_setoption(string);
- return;
- }else if(match(string,"position *")){
- parse_position(string);
- Init=false;
- }else if(match(string,"go *")){
- if(Init){
- board_from_fen(UCIboard,StartFen);
- Init=false;
- }
- SavedMove=MoveNone;
- if(!strstr(string,"infinite")){
- move=book_move(UCIboard,option_get_bool("BookRandom"));
- if (move != MoveNone && move_is_legal(move,UCIboard)) {
- if(strstr(string,"ponder")){
- SavedMove=move;
- return;
- }else{
- send_book_move(move);
- return;
- }
- }
- }
- }else if(match(string,"ponderhit") || match(string,"stop")){
- if(SavedMove!=MoveNone){
- send_book_move(SavedMove);
- SavedMove=MoveNone;
- return;
- }
- }else if(match(string,"quit")){
- my_log("POLYGLOT *** \"quit\" from GUI ***\n");
- quit();
- }
- engine_send(Engine,"%s",string);
-}
-
-void uci2uci_engine_step(char string[]) {
- gui_send(GUI,string);
-}
-
-// end of uci2uci.cpp
+++ /dev/null
-\r
-// util.cpp\r
-\r
-// includes\r
-\r
-#include <cctype>\r
-#include <cerrno>\r
-#include <cmath>\r
-#include <cstdarg>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-#include <ctime>\r
-\r
-#include "main.h"\r
-#include "posix.h"\r
-#include "util.h"\r
-\r
-//\r
-\r
-const int ErrorBufferSize=4096;\r
-\r
-// variables\r
-\r
-static bool Error;\r
-static char ErrorBuffer[ErrorBufferSize];\r
-\r
-FILE * LogFile=NULL;\r
-\r
-\r
-// functions\r
-\r
-// util_init()\r
-\r
-void util_init() {\r
-\r
- Error = false;\r
-\r
- // init log file\r
-\r
- LogFile = NULL;\r
-\r
- // switch file buffering off\r
-\r
- setbuf(stdin,NULL);\r
- setbuf(stdout,NULL);\r
-}\r
-\r
-// my_random_init()\r
-\r
-void my_random_init() {\r
- srand(time(NULL));\r
-}\r
-\r
-// my_random_int()\r
-\r
-int my_random_int(int n) {\r
-\r
- int r;\r
-\r
- ASSERT(n>0);\r
-\r
- r = int(floor(my_random_double()*double(n)));\r
- ASSERT(r>=0&&r<n);\r
-\r
- return r;\r
-}\r
-\r
-// my_random_double()\r
-\r
-double my_random_double() {\r
-\r
- double r;\r
-\r
- r = double(rand()) / (double(RAND_MAX) + 1.0);\r
- ASSERT(r>=0.0&&r<1.0);\r
-\r
- return r;\r
-}\r
-\r
-// my_atoll()\r
-\r
-sint64 my_atoll(const char string[]) {\r
-\r
- sint64 n;\r
-\r
- sscanf(string,S64_FORMAT,&n);\r
-\r
- return n;\r
-}\r
-\r
-// my_round()\r
-\r
-int my_round(double x) {\r
-\r
- return int(floor(x+0.5));\r
-}\r
-\r
-// my_malloc()\r
-\r
-void * my_malloc(size_t size) {\r
-\r
- void * address;\r
-\r
- ASSERT(size>0);\r
-\r
- address = malloc(size);\r
- if (address == NULL) my_fatal("my_malloc(): malloc(): %s\n",strerror(errno));\r
-\r
- return address;\r
-}\r
-\r
-// my_realloc()\r
-\r
-void * my_realloc(void * address, size_t size) {\r
-\r
- ASSERT(address!=NULL);\r
- ASSERT(size>0);\r
-\r
- address = realloc(address,size);\r
- if (address == NULL) my_fatal("my_realloc(): realloc(): %s\n",strerror(errno));\r
-\r
- return address;\r
-}\r
-\r
-// my_free()\r
-\r
-void my_free(void * address) {\r
-\r
- ASSERT(address!=NULL);\r
-\r
- free(address);\r
-}\r
-\r
-// my_log_open()\r
-\r
-void my_log_open(const char file_name[]) {\r
-\r
- ASSERT(file_name!=NULL);\r
-\r
- LogFile = fopen(file_name,"a");\r
-#ifndef _WIN32\r
-//line buffering doesn't work too well in MSVC and/or windows \r
- if (LogFile != NULL) setvbuf(LogFile,NULL,_IOLBF,0); // line buffering\r
-#endif\r
-}\r
-\r
-// my_log_close()\r
-\r
-void my_log_close() {\r
-\r
- if (LogFile != NULL) fclose(LogFile);\r
- LogFile=NULL;\r
-}\r
-\r
-// my_log()\r
-\r
-void my_log(const char format[], ...) {\r
-\r
- va_list ap;\r
-\r
- ASSERT(format!=NULL);\r
-\r
- if (LogFile != NULL) {\r
- fprintf(LogFile,"%.3f ",now_real());\r
- va_start(ap,format);\r
-\r
- vfprintf(LogFile,format,ap);\r
- va_end(ap);\r
-#ifdef _WIN32\r
- fflush(LogFile);\r
-#endif\r
- }\r
-}\r
-\r
-// my_fatal()\r
-\r
-void my_fatal(const char format[], ...) {\r
-\r
- va_list ap;\r
-\r
- ASSERT(format!=NULL);\r
-\r
- va_start(ap,format);\r
-\r
- vfprintf(stderr,format,ap);\r
- if (LogFile != NULL) vfprintf(LogFile,format,ap);\r
-\r
- va_end(ap);\r
- if (Error) { // recursive error\r
- my_log("POLYGLOT *** RECURSIVE ERROR ***\n");\r
- exit(EXIT_FAILURE);\r
- // abort();\r
- } else {\r
- Error = true;\r
- quit();\r
- }\r
-}\r
-\r
-// my_file_read_line()\r
-\r
-bool my_file_read_line(FILE * file, char string[], int size) {\r
-\r
- int src, dst;\r
- int c;\r
-\r
- ASSERT(file!=NULL);\r
- ASSERT(string!=NULL);\r
- ASSERT(size>0);\r
-\r
- if (fgets(string,size,file) == NULL) {\r
- if (feof(file)) {\r
- return false;\r
- } else { // error\r
- my_fatal("my_file_read_line(): fgets(): %s\n",strerror(errno));\r
- }\r
- }\r
-\r
- // remove CRs and LFs\r
-\r
- src = 0;\r
- dst = 0;\r
- \r
- while ((c=string[src++]) != '\0') {\r
- if (c != '\r' && c != '\n') string[dst++] = c;\r
- }\r
-\r
- string[dst] = '\0';\r
-\r
- return true;\r
-}\r
-\r
-// my_string_empty()\r
-\r
-bool my_string_empty(const char string[]) {\r
-\r
- return string == NULL || string[0] == '\0';\r
-}\r
-\r
-// my_string_whitespace()\r
-\r
-bool my_string_whitespace(const char string[]){\r
- int pos=0;\r
- while(string[pos]!='\0'){\r
- if(string[pos]!=' ' && string[pos]!='\t'){\r
- return false;\r
- }\r
- pos++;\r
- }\r
- return true;\r
-}\r
-\r
-// my_string_equal()\r
-\r
-bool my_string_equal(const char string_1[], const char string_2[]) {\r
-\r
- ASSERT(string_1!=NULL);\r
- ASSERT(string_2!=NULL);\r
-\r
- return strcmp(string_1,string_2) == 0;\r
-}\r
-\r
-// my_string_case_equal()\r
-\r
-bool my_string_case_equal(const char string_1[], const char string_2[]) {\r
-\r
- int c1, c2;\r
-\r
- ASSERT(string_1!=NULL);\r
- ASSERT(string_2!=NULL);\r
-\r
- while (true) {\r
-\r
- c1 = *string_1++;\r
- c2 = *string_2++;\r
-\r
- if (tolower(c1) != tolower(c2)) return false;\r
- if (c1 == '\0') return true;\r
- }\r
-\r
- return false;\r
-}\r
-\r
-// my_strdup()\r
-\r
-char * my_strdup(const char string[]) {\r
-\r
- char * address;\r
-\r
- ASSERT(string!=NULL);\r
-\r
- // strdup() is not ANSI C\r
-\r
- address = (char *) my_malloc(strlen(string)+1);\r
- strcpy(address,string);\r
-\r
- return address;\r
-}\r
-\r
-// my_string_clear()\r
-\r
-void my_string_clear(const char * * variable) {\r
-\r
- ASSERT(variable!=NULL);\r
-\r
- if (*variable != NULL) {\r
- my_free((void*)(*variable));\r
- *variable = NULL;\r
- }\r
-}\r
-\r
-// my_string_set()\r
-\r
-void my_string_set(const char * * variable, const char string[]) {\r
-\r
- ASSERT(variable!=NULL);\r
- ASSERT(string!=NULL);\r
-\r
- if (*variable != NULL) my_free((void*)(*variable));\r
- *variable = my_strdup(string);\r
-}\r
-\r
-// my_timer_reset()\r
-\r
-void my_timer_reset(my_timer_t * timer) {\r
-\r
- ASSERT(timer!=NULL);\r
-\r
- timer->start_real = 0.0;\r
- timer->elapsed_real = 0.0;\r
- timer->running = false;\r
-}\r
-\r
-// my_timer_start()\r
-\r
-void my_timer_start(my_timer_t * timer) {\r
-// timer->start_real = 0.0;\r
- timer->elapsed_real = 0.0;\r
-// timer->running = false;\r
- ASSERT(timer!=NULL);\r
-\r
- timer->running = true;\r
- timer->start_real = now_real();\r
-}\r
-\r
-// my_timer_stop()\r
-\r
-void my_timer_stop(my_timer_t * timer) {\r
-\r
- ASSERT(timer!=NULL);\r
-\r
- ASSERT(timer->running);\r
-\r
- timer->elapsed_real += now_real() - timer->start_real;\r
- timer->start_real = 0.0;\r
- timer->running = false;\r
-}\r
-\r
-// my_timer_elapsed_real()\r
-\r
-double my_timer_elapsed_real(const my_timer_t * timer) {\r
-\r
- double elapsed;\r
-\r
- ASSERT(timer!=NULL);\r
-\r
- elapsed = timer->elapsed_real;\r
- if (timer->running) elapsed += now_real() - timer->start_real;\r
-\r
- if (elapsed < 0.0) elapsed = 0.0;\r
-\r
- return elapsed;\r
-}\r
-\r
-// my_timer()\r
-\r
-char * my_error(){\r
-#ifdef _WIN32\r
- FormatMessage(\r
- FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL,\r
- GetLastError(),\r
- LANG_USER_DEFAULT,\r
- ErrorBuffer,\r
- ErrorBufferSize,\r
- NULL);\r
- return ErrorBuffer;\r
-#else\r
- return strerror(errno);\r
-#endif\r
-}\r
-\r
+++ /dev/null
-\r
-// xboard2uci.cpp\r
-\r
-// includes\r
-\r
-#include <cerrno>\r
-#include <cstdio>\r
-#include <cstdlib>\r
-#include <cstring>\r
-#include <ctime>\r
-\r
-#include "board.h"\r
-#include "book.h"\r
-#include "colour.h"\r
-#include "engine.h"\r
-#include "fen.h"\r
-#include "game.h"\r
-#include "gui.h"\r
-#include "line.h"\r
-#include "main.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_legal.h"\r
-#include "option.h"\r
-#include "parse.h"\r
-#include "san.h"\r
-#include "uci.h"\r
-#include "uci2uci.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool UseDebug = false;\r
-static const bool DelayPong = false;\r
-\r
-static const int StringSize = 4096;\r
-\r
-// types\r
-\r
-struct state_t {\r
- int state;\r
- bool computer[ColourNb];\r
- int exp_move;\r
- int resign_nb;\r
- my_timer_t timer[1];\r
-};\r
-\r
-struct xb_t {\r
- bool has_feature_memory;\r
- bool has_feature_smp;\r
- bool has_feature_egt;\r
- bool analyse;\r
- bool computer;\r
- const char * name;\r
- bool ics;\r
- bool new_hack; // "new" is a C++ keyword\r
- bool ponder;\r
- int ping;\r
- bool post;\r
- int proto_ver;\r
- bool result;\r
-\r
- int mps;\r
- double base;\r
- double inc;\r
- \r
- bool time_limit;\r
- double time_max;\r
- \r
- bool depth_limit;\r
- int depth_max;\r
- \r
- double my_time;\r
- double opp_time;\r
-};\r
-\r
-enum dummy_state_t { WAIT, THINK, PONDER, ANALYSE };\r
-\r
-// variables\r
-\r
-static state_t State[1];\r
-static xb_t XB[1];\r
-\r
-// prototypes\r
-\r
-static void comp_move (int move);\r
-static void move_step (int move);\r
-static void board_update ();\r
-\r
-static void mess ();\r
-static void no_mess (int move);\r
-\r
-static void search_update ();\r
-static void search_clear ();\r
-static void update_remaining_time();\r
-static int report_best_score();\r
-static bool kibitz_throttle (bool searching);\r
-static void start_protected_command();\r
-static void end_protected_command();\r
-\r
-static bool active ();\r
-static bool ponder ();\r
-static bool ponder_ok (int ponder_move);\r
-\r
-static void stop_search ();\r
-\r
-static void send_board (int extra_move);\r
-static void send_pv ();\r
-\r
-static void send_xboard_options ();\r
-\r
-static void learn (int result);\r
-\r
-\r
-// functions\r
-\r
-// xboard2uci_init()\r
-\r
-void xboard2uci_init() {\r
- // init\r
-\r
- game_clear(Game);\r
-\r
- // state\r
-\r
- State->state = WAIT;\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = true;\r
-\r
- State->exp_move = MoveNone;\r
- State->resign_nb = 0;\r
- my_timer_reset(State->timer);\r
-\r
- // yes there are engines that do not have the "Hash" option....\r
- XB->has_feature_memory= uci_option_exist(Uci,"Hash");\r
- XB->has_feature_smp = uci_thread_option_exist(Uci);\r
- // TODO: support for other types of table bases\r
- XB->has_feature_egt = uci_option_exist(Uci,"NalimovPath");\r
- XB->analyse = false;\r
- XB->computer = false;\r
- XB->name = NULL;\r
- my_string_set(&XB->name,"<empty>");\r
- XB->ics = false;\r
- XB->new_hack = true;\r
- XB->ping = -1;\r
- XB->ponder = false;\r
- XB->post = false;\r
- XB->proto_ver = 1;\r
- XB->result = false;\r
-\r
- XB->mps = 0;\r
- XB->base = 300.0;\r
- XB->inc = 0.0;\r
-\r
- XB->time_limit = false;\r
- XB->time_max = 5.0;\r
-\r
- XB->depth_limit = false;\r
- XB->depth_max = 127;\r
-\r
- XB->my_time = 300.0;\r
- XB->opp_time = 300.0;\r
-}\r
-\r
-// xboard2uci_gui_step()\r
-\r
-void xboard2uci_gui_step(char string[]) {\r
-\r
- int move;\r
- char move_string[256];\r
- board_t board[1];\r
-\r
- if (false) {\r
- \r
- } else if (match(string,"accepted *")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,"analyze")) {\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
-\r
- XB->analyse = true;\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"bk")) {\r
-\r
- if (option_get_bool("Book")) {\r
- game_get_board(Game,board);\r
- book_disp(board);\r
- }\r
-\r
- } else if (match(string,"black")) {\r
-\r
- if (colour_is_black(game_turn(Game))) {\r
-\r
- State->computer[White] = true;\r
- State->computer[Black] = false;\r
-\r
- XB->new_hack = true;\r
- XB->result = false;\r
-\r
- mess();\r
- }\r
-\r
- } else if (match(string,"computer")) {\r
-\r
- XB->computer = true;\r
-\r
- } else if (match(string,"draw")) {\r
- if(uci_option_exist(Uci,"UCI_DrawOffers")){\r
- my_log("POLYGLOT draw from XB received");\r
- uci_send_option(Uci,"DrawOffer","%s","draw");}\r
- } else if (match(string,"easy")) {\r
-\r
- XB->ponder = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"edit")) {\r
-\r
- // refuse\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
-\r
- } else if (match(string,"exit")) {\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
-\r
- XB->analyse = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"force")) {\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"go")) {\r
-\r
- State->computer[game_turn(Game)] = true;\r
- State->computer[colour_opp(game_turn(Game))] = false;\r
-\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"hard")) {\r
-\r
- XB->ponder = true;\r
-\r
- mess();\r
-\r
- } else if (match(string,"hint")) {\r
-\r
- if (option_get_bool("Book")) {\r
-\r
- game_get_board(Game,board);\r
- move = book_move(board,false);\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
- move_to_san(move,board,move_string,256);\r
- gui_send(GUI,"Hint: %s",move_string);\r
- }\r
- }\r
-\r
- } else if (match(string,"ics *")) {\r
-\r
- XB->ics = true;\r
-\r
- } else if (match(string,"level * *:* *")) {\r
-\r
- XB->mps = atoi(Star[0]);\r
- XB->base = double(atoi(Star[1])) * 60.0 + double(atoi(Star[2]));\r
- XB->inc = double(atoi(Star[3]));\r
-\r
- } else if (match(string,"level * * *")) {\r
-\r
- XB->mps = atoi(Star[0]);\r
- XB->base = double(atoi(Star[1])) * 60.0;\r
- XB->inc = double(atoi(Star[2]));\r
-\r
- } else if (match(string,"name *")) {\r
-\r
- my_string_set(&XB->name,Star[0]);\r
-\r
- } else if (match(string,"new")) {\r
-\r
- uci_send_isready(Uci);\r
- my_log("POLYGLOT NEW GAME\n");\r
-\r
- option_set("Chess960","false");\r
-\r
- game_clear(Game);\r
-\r
- if (XB->analyse) {\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
- } else {\r
- State->computer[White] = false;\r
- State->computer[Black] = true;\r
- }\r
-\r
- XB->new_hack = true;\r
- XB->result = false;\r
-\r
- XB->depth_limit = false;\r
-\r
- XB->computer = false;\r
- my_string_set(&XB->name,"<empty>");\r
-\r
- board_update();\r
- mess();\r
-\r
- uci_send_ucinewgame(Uci);\r
-\r
- } else if (match(string,"nopost")) {\r
-\r
- XB->post = false;\r
-\r
- } else if (match(string,"otim *")) {\r
-\r
- XB->opp_time = double(atoi(Star[0])) / 100.0;\r
- if (XB->opp_time < 0.0) XB->opp_time = 0.0;\r
-\r
- } else if (match(string,"pause")) {\r
-\r
- // refuse\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
-\r
- } else if (match(string,"ping *")) {\r
-\r
- // HACK; TODO: answer only after an engine move\r
-\r
- if (DelayPong) {\r
- if (XB->ping >= 0) gui_send(GUI,"pong %d",XB->ping); // HACK: get rid of old ping\r
- XB->ping = atoi(Star[0]);\r
- uci_send_isready(Uci);\r
- } else {\r
- ASSERT(XB->ping==-1);\r
- gui_send(GUI,"pong %s",Star[0]);\r
- }\r
-\r
- } else if (match(string,"playother")) {\r
-\r
- State->computer[game_turn(Game)] = false;\r
- State->computer[colour_opp(game_turn(Game))] = true;\r
-\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- mess();\r
-\r
- } else if (match(string,"post")) {\r
-\r
- XB->post = true;\r
-\r
- } else if (match(string,"protover *")) {\r
-\r
- send_xboard_options();\r
-\r
- } else if (match(string,"quit")) {\r
- my_log("POLYGLOT *** \"quit\" from GUI ***\n");\r
- quit();\r
- } else if (match(string,"random")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,"rating * *")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,"remove")) {\r
-\r
- if (game_pos(Game) >= 2) {\r
-\r
- game_goto(Game,game_pos(Game)-2);\r
-\r
- ASSERT(!XB->new_hack);\r
- XB->new_hack = false; // HACK?\r
- XB->result = false;\r
-\r
- board_update();\r
- mess();\r
- }\r
-\r
- } else if (match(string,"rejected *")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,"reset")) { // protover 3?\r
-\r
- // refuse\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
-\r
- } else if (false\r
- || match(string,"result * {*}")\r
- || match(string,"result * {* }")\r
- || match(string,"result * { *}")\r
- || match(string,"result * { * }")) {\r
-\r
- my_log("POLYGLOT GAME END\n");\r
-\r
- XB->result = true;\r
-\r
- mess();\r
-\r
- // book learning\r
-\r
- if (option_get_bool("Book") && option_get_bool("BookLearn")) {\r
-\r
- if (false) {\r
- } else if (my_string_equal(Star[0],"1-0")) {\r
- learn(+1);\r
- } else if (my_string_equal(Star[0],"0-1")) {\r
- learn(-1);\r
- } else if (my_string_equal(Star[0],"1/2-1/2")) {\r
- learn(0);\r
- }\r
- }\r
- } else if (match(string,"resume")) {\r
-\r
- // refuse\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
-\r
- } else if (match(string,"option *=*")){\r
- char *name=Star[0];\r
- char *value=Star[1];\r
- if(match(name, "Polyglot *")){\r
- char *pg_name=Star[0];\r
- polyglot_set_option(pg_name,value);\r
- }else{\r
- start_protected_command();\r
- engine_send(Engine,"setoption name %s value %s",name,value);\r
- end_protected_command();\r
- }\r
- } else if (match(string,"option *")){\r
- char *name=Star[0];\r
- start_protected_command();\r
- engine_send(Engine,"setoption name %s",name);\r
- end_protected_command();\r
- } else if (XB->has_feature_smp && match(string,"cores *")){\r
- int cores=atoi(Star[0]);\r
- if(cores>=1){\r
- // updating the number of cores\r
- my_log("POLYGLOT setting the number of cores to %d\n",cores);\r
- start_protected_command();\r
- uci_set_threads(Uci,cores); \r
- end_protected_command();\r
- } else{\r
- // refuse\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
- }\r
- } else if (XB->has_feature_egt && match(string,"egtpath * *")){\r
- char *type=Star[0];\r
- char *path=Star[1];\r
- if(!my_string_case_equal(type,"nalimov")){\r
- // refuse\r
- gui_send(GUI,"Error (unsupported table base format): %s",string);\r
- }else if(my_string_empty(path)){\r
- // refuse\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
- }else{\r
- // updating NalimovPath\r
- my_log("POLYGLOT setting the Nalimov path to %s\n",path);\r
- start_protected_command();\r
- uci_send_option(Uci,"NalimovPath","%s",path);\r
- end_protected_command();\r
- }\r
- } else if (XB->has_feature_memory && match(string,"memory *")){\r
- int memory = atoi(Star[0]);\r
- int nalimov_cache;\r
- int real_memory;\r
- if(memory>=1){\r
- // updating the available memory\r
- my_log("POLYGLOT setting the amount of memory to %dMb\n",memory);\r
- if(uci_get_option(Uci,"NalimovCache")>=0){\r
- nalimov_cache=atoi(Uci->option[uci_get_option(Uci,"NalimovCache")].value);\r
- }else{\r
- nalimov_cache=0;\r
- }\r
- my_log("POLYGLOT Nalimov Cache is %dMb\n",nalimov_cache);\r
- real_memory=memory-nalimov_cache;\r
- if(real_memory>0){\r
- start_protected_command();\r
- uci_send_option(Uci,"Hash", "%d", real_memory);\r
- end_protected_command();\r
- }\r
- }else{\r
- // refuse\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
- }\r
-\r
- } else if (match(string,"sd *")) {\r
-\r
- XB->depth_limit = true;\r
- XB->depth_max = atoi(Star[0]);\r
-\r
- } else if (match(string,"setboard *")) {\r
-\r
- my_log("POLYGLOT FEN %s\n",Star[0]);\r
-\r
- if (!game_init(Game,Star[0])) my_fatal("xboard_step(): bad FEN \"%s\"\n",Star[0]);\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = false;\r
-\r
- XB->new_hack = true; // HACK?\r
- XB->result = false;\r
-\r
- board_update();\r
- mess();\r
-\r
- } else if (match(string,"st *")) {\r
-\r
- XB->time_limit = true;\r
- XB->time_max = double(atoi(Star[0]));\r
-\r
- } else if (match(string,"time *")) {\r
-\r
- XB->my_time = double(atoi(Star[0])) / 100.0;\r
- if (XB->my_time < 0.0) XB->my_time = 0.0;\r
-\r
- } else if (match(string,"undo")) {\r
-\r
- if (game_pos(Game) >= 1) {\r
-\r
- game_goto(Game,game_pos(Game)-1);\r
-\r
- ASSERT(!XB->new_hack);\r
- XB->new_hack = false; // HACK?\r
- XB->result = false;\r
-\r
- board_update();\r
- mess();\r
- }\r
-\r
- } else if (match(string,"usermove *")) {\r
-\r
- game_get_board(Game,board);\r
- move = move_from_san(Star[0],board);\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
-\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- move_step(move);\r
- no_mess(move);\r
-\r
- } else {\r
-\r
- gui_send(GUI,"Illegal move: %s",Star[0]);\r
- }\r
-\r
- } else if (match(string,"variant *")) {\r
-\r
- if (my_string_equal(Star[0],"fischerandom")) {\r
- option_set("Chess960","true");\r
- } else {\r
- option_set("Chess960","false");\r
- }\r
-\r
- } else if (match(string,"white")) {\r
-\r
- if (colour_is_white(game_turn(Game))) {\r
-\r
- State->computer[White] = false;\r
- State->computer[Black] = true;\r
-\r
- XB->new_hack = true;\r
- XB->result = false;\r
-\r
- mess();\r
- }\r
-\r
- } else if (match(string,"xboard")) {\r
-\r
- // ignore\r
-\r
- } else if (match(string,".")) { // analyse info\r
-\r
- if (State->state == ANALYSE) {\r
- int depth=Uci->best_depth;//HACK: don't clear engine-output window...\r
-\r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
-\r
- if (Uci->root_move != MoveNone && move_is_legal(Uci->root_move,Uci->board)) {\r
- move_to_san(Uci->root_move,Uci->board,move_string,256);\r
- 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);\r
- } else {\r
- gui_send(GUI,"stat01: %.0f "S64_FORMAT" %d %d %d",Uci->time*100.0,Uci->node_nb,/*Uci->*/depth,0,0); // HACK\r
- }\r
- }\r
-\r
- } else if (match(string,"?")) { // move now\r
-\r
- if (State->state == THINK) {\r
-\r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
-\r
- // HACK: just send "stop" to the engine\r
-\r
- if (Uci->searching) {\r
- my_log("POLYGLOT STOP SEARCH\n");\r
- engine_send(Engine,"stop");\r
- }\r
- }\r
-\r
- } else { // unknown command, maybe a move?\r
-\r
- game_get_board(Game,board);\r
- move = move_from_san(string,board);\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
-\r
- XB->new_hack = false;\r
- ASSERT(!XB->result);\r
- XB->result = false;\r
-\r
- move_step(move);\r
- no_mess(move);\r
-\r
- } else if (move != MoveNone) {\r
-\r
- gui_send(GUI,"Illegal move: %s",string);\r
-\r
- } else {\r
-\r
- gui_send(GUI,"Error (unknown command): %s",string);\r
- }\r
- }\r
- return;\r
-}\r
-\r
-// xboard2uci_engine_step()\r
-\r
-void xboard2uci_engine_step(char string[]) {\r
-\r
- int event;\r
- event = uci_parse(Uci,string);\r
-\r
- // react to events\r
-\r
- if ((event & EVENT_READY) != 0) {\r
-\r
- // the engine is now ready\r
-\r
- if (!Uci->ready) {\r
- Uci->ready = true;\r
- // if (XB->proto_ver >= 2) xboard_send(XBoard,"feature done=1");\r
- }\r
-\r
- if (!DelayPong && XB->ping >= 0) {\r
- gui_send(GUI,"pong %d",XB->ping);\r
- XB->ping = -1;\r
- }\r
- }\r
-\r
- if ((event & EVENT_MOVE) != 0 && State->state == THINK) {\r
-\r
- // the engine is playing a move\r
-\r
- // MEGA HACK: estimate remaining time because XBoard won't send it!\r
-\r
- my_timer_stop(State->timer);\r
-\r
- XB->my_time -= my_timer_elapsed_real(State->timer);\r
- XB->my_time += XB->inc;\r
- if (XB->mps != 0 && (game_move_nb(Game) + 1) % XB->mps == 0) XB->my_time += XB->base;\r
-\r
- if (XB->my_time < 0.0) XB->my_time = 0.0;\r
-\r
- // play the engine move\r
-\r
- comp_move(Uci->best_move);\r
- }\r
-\r
- if ((event & EVENT_PV) != 0) {\r
-\r
- // the engine has sent a new PV\r
-\r
- send_pv();\r
- }\r
- if((event & (EVENT_DRAW|EVENT_RESIGN))!=0){\r
- my_log("POYGLOT draw offer/resign from engine\n");\r
- if(uci_option_exist(Uci,"UCI_DrawOffers")){\r
- if(event & EVENT_DRAW)\r
- gui_send(GUI,"offer draw");\r
- else\r
- gui_send(GUI,"resign");\r
- }\r
- }\r
-}\r
-\r
-// format_xboard_option_line\r
-\r
-void format_xboard_option_line(char * option_line, option_t *opt){\r
- int j;\r
- char option_string[StringSize];\r
- strcpy(option_line,"");\r
- strcat(option_line,"feature option=\"");\r
- if(opt->mode&PG){\r
- strcat(option_line,"Polyglot ");\r
- }\r
- sprintf(option_string,"%s",opt->name);\r
- strcat(option_line,option_string);\r
- sprintf(option_string," -%s",opt->type);\r
- strcat(option_line,option_string);\r
- if(strcmp(opt->type,"button") && strcmp(opt->type,"combo")){\r
- if(strcmp(opt->type,"check")){\r
- sprintf(option_string," %s",opt->default_);\r
- }else{\r
- sprintf(option_string," %d",\r
- strcmp(opt->default_,"true")?0:1);\r
- }\r
- strcat(option_line,option_string);\r
- }\r
- if(!strcmp(opt->type,"spin")){\r
- sprintf(option_string," %s",opt->min);\r
- strcat(option_line,option_string);\r
- }\r
- if(!strcmp(opt->type,"spin")){\r
- sprintf(option_string," %s",opt->max);\r
- strcat(option_line,option_string);\r
- }\r
- for(j=0;j<opt->var_nb;j++){\r
- if(!strcmp(opt->var[j],opt->default_)){\r
- sprintf(option_string," *%s",opt->var[j]);\r
- }else{\r
- sprintf(option_string," %s",opt->var[j]);\r
- }\r
- strcat(option_line,option_string);\r
- if(j!=opt->var_nb-1){\r
- strcat(option_line," ///");\r
- }\r
- }\r
- strcat(option_line,"\"");\r
-}\r
-\r
-// send_xboard_options\r
-\r
-static void send_xboard_options(){\r
- int i;\r
- char option_line[StringSize]="";\r
- option_t *p=Option;\r
- const char * name;\r
- XB->proto_ver = atoi(Star[0]);\r
- ASSERT(XB->proto_ver>=2);\r
- \r
- gui_send(GUI,"feature done=0");\r
- \r
- gui_send(GUI,"feature analyze=1");\r
- gui_send(GUI,"feature colors=0");\r
- gui_send(GUI,"feature draw=1");\r
- gui_send(GUI,"feature ics=1");\r
- gui_send(GUI,"feature myname=\"%s\"",option_get_string("EngineName"));\r
- gui_send(GUI,"feature name=1");\r
- gui_send(GUI,"feature pause=0");\r
- gui_send(GUI,"feature ping=1");\r
- gui_send(GUI,"feature playother=1");\r
- gui_send(GUI,"feature reuse=1");\r
- gui_send(GUI,"feature san=0");\r
- gui_send(GUI,"feature setboard=1");\r
- gui_send(GUI,"feature sigint=0");\r
- gui_send(GUI,"feature sigterm=0");\r
- gui_send(GUI,"feature time=1");\r
- gui_send(GUI,"feature usermove=1");\r
- if (XB->has_feature_memory){\r
- gui_send(GUI,"feature memory=1");\r
- }else{\r
- gui_send(GUI,"feature memory=0");\r
- }\r
- if (XB->has_feature_smp){\r
- gui_send(GUI,"feature smp=1");\r
- }else{\r
- gui_send(GUI,"feature smp=0");\r
- }\r
- if (XB->has_feature_egt){\r
- // TODO: support for other types of table bases\r
- gui_send(GUI,"feature egt=\"nalimov\"");\r
- }else{\r
- gui_send(GUI,"feature egt=\"\"");\r
- }\r
- \r
- if (uci_option_exist(Uci,"UCI_Chess960")) {\r
- gui_send(GUI,"feature variants=\"normal,fischerandom\"");\r
- } else {\r
- gui_send(GUI,"feature variants=\"normal\"");\r
- }\r
- \r
- for(i=0;i<Uci->option_nb;i++){\r
- if(my_string_case_equal(Uci->option[i].name,"UCI_AnalyseMode")) continue;\r
- if(my_string_case_equal(Uci->option[i].name,"Ponder")) continue;\r
- if(my_string_case_equal(Uci->option[i].name,"Hash")) continue;\r
- if(my_string_case_equal(Uci->option[i].name,"NalimovPath")) continue;\r
- if((name=uci_thread_option(Uci))!=NULL && my_string_case_equal(Uci->option[i].name,name)) continue;\r
- format_xboard_option_line(option_line,Uci->option+i);\r
-\r
- gui_send(GUI,"%s",option_line);\r
-\r
- }\r
- while(p->name){\r
- if(p->mode &XBOARD){\r
- format_xboard_option_line(option_line,p);\r
- gui_send(GUI,"%s",option_line);\r
- }\r
- p++;\r
- } \r
- gui_send(GUI,"feature done=1"); \r
- \r
-}\r
-\r
-// report_best_score()\r
-\r
-static int report_best_score(){\r
- if(!option_get_bool("ScoreWhite") || colour_is_white(Uci->board->turn)){\r
- return Uci->best_score;\r
- }else{\r
- return -Uci->best_score;\r
- }\r
-}\r
-\r
-// comp_move()\r
-\r
-static void comp_move(int move) {\r
-\r
- board_t board[1];\r
- char string[256];\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- ASSERT(State->state==THINK);\r
- ASSERT(!XB->analyse);\r
-\r
- if(option_get_bool("RepeatPV"))\r
- send_pv(); // to update time and nodes\r
-\r
- // send the move\r
-\r
- game_get_board(Game,board);\r
-\r
- if (move_is_castle(move,board) && option_get_bool("Chess960")) {\r
- if (!move_to_san(move,board,string,256)) my_fatal("comp_move(): move_to_san() failed\n"); // O-O/O-O-O\r
- } else {\r
- if (!move_to_can(move,board,string,256)) my_fatal("comp_move(): move_to_can() failed\n");\r
- }\r
-\r
- gui_send(GUI,"move %s",string);\r
-\r
- // resign?\r
-\r
- if (option_get_bool("Resign") && Uci->root_move_nb > 1) {\r
-\r
- if (Uci->best_score <= -abs(option_get_int("ResignScore"))) {\r
-\r
- State->resign_nb++;\r
- my_log("POLYGLOT %d move%s with resign score\n",State->resign_nb,(State->resign_nb>1)?"s":"");\r
-\r
- if (State->resign_nb >= option_get_int("ResignMoves")) {\r
- my_log("POLYGLOT *** RESIGN ***\n");\r
- gui_send(GUI,"resign");\r
- }\r
-\r
- } else {\r
-\r
- if (State->resign_nb > 0) my_log("POLYGLOT resign reset (State->resign_nb=%d)\n",State->resign_nb);\r
- State->resign_nb = 0;\r
- }\r
- }\r
-\r
- // play the move\r
-\r
- move_step(move);\r
- no_mess(move);\r
-}\r
-\r
-// move_step()\r
-\r
-static void move_step(int move) {\r
-\r
- board_t board[1];\r
- char move_string[256];\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- // log\r
-\r
- game_get_board(Game,board);\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
-\r
- move_to_san(move,board,move_string,256);\r
- my_log("POLYGLOT MOVE %s\n",move_string);\r
-\r
- } else {\r
-\r
- move_to_can(move,board,move_string,256);\r
- my_log("POLYGLOT ILLEGAL MOVE \"%s\"\n",move_string);\r
- board_disp(board);\r
-\r
- my_fatal("move_step(): illegal move \"%s\"\n",move_string);\r
- }\r
-\r
- // play the move\r
-\r
- game_add_move(Game,move);\r
- board_update();\r
-}\r
-\r
-// board_update()\r
-\r
-static void board_update() {\r
-\r
- // handle game end\r
-\r
- ASSERT(!XB->result);\r
-\r
- switch (game_status(Game)) {\r
- case PLAYING:\r
- break;\r
- case WHITE_MATES:\r
- gui_send(GUI,"1-0 {White mates}");\r
- break;\r
- case BLACK_MATES:\r
- gui_send(GUI,"0-1 {Black mates}");\r
- break;\r
- case STALEMATE:\r
- gui_send(GUI,"1/2-1/2 {Stalemate}");\r
- break;\r
- case DRAW_MATERIAL:\r
- gui_send(GUI,"1/2-1/2 {Draw by insufficient material}");\r
- break;\r
- case DRAW_FIFTY:\r
- gui_send(GUI,"1/2-1/2 {Draw by fifty-move rule}");\r
- break;\r
- case DRAW_REPETITION:\r
- gui_send(GUI,"1/2-1/2 {Draw by repetition}");\r
- break;\r
- default:\r
- ASSERT(false);\r
- break;\r
- }\r
-}\r
-\r
-// mess()\r
-\r
-static void mess() {\r
-\r
- // clear state variables\r
-\r
- State->resign_nb = 0;\r
- State->exp_move = MoveNone;\r
- my_timer_reset(State->timer);\r
-\r
- // abort a possible search\r
-\r
- stop_search();\r
-\r
- // calculate the new state\r
-\r
- if (false) {\r
- } else if (!active()) {\r
- State->state = WAIT;\r
- my_log("POLYGLOT WAIT\n");\r
- } else if (XB->analyse) {\r
- State->state = ANALYSE;\r
- my_log("POLYGLOT ANALYSE\n");\r
- } else if (State->computer[game_turn(Game)]) {\r
- State->state = THINK;\r
- my_log("POLYGLOT THINK\n");\r
- } else {\r
- State->state = WAIT;\r
- my_log("POLYGLOT WAIT\n");\r
- }\r
-\r
- search_update();\r
-}\r
-\r
-// no_mess()\r
-\r
-static void no_mess(int move) {\r
-\r
- ASSERT(move_is_ok(move));\r
-\r
- // just received a move, calculate the new state\r
-\r
- if (false) {\r
-\r
- } else if (!active()) {\r
-\r
- stop_search(); // abort a possible search\r
-\r
- State->state = WAIT;\r
- State->exp_move = MoveNone;\r
-\r
- my_log("POLYGLOT WAIT\n");\r
-\r
- } else if (State->state == WAIT) {\r
-\r
- ASSERT(State->computer[game_turn(Game)]);\r
- ASSERT(!State->computer[colour_opp(game_turn(Game))]);\r
- ASSERT(!XB->analyse);\r
-\r
- my_log("POLYGLOT WAIT -> THINK\n");\r
-\r
- State->state = THINK;\r
- State->exp_move = MoveNone;\r
-\r
- } else if (State->state == THINK) {\r
-\r
- ASSERT(!State->computer[game_turn(Game)]);\r
- ASSERT(State->computer[colour_opp(game_turn(Game))]);\r
- ASSERT(!XB->analyse);\r
-\r
- if (ponder() && ponder_ok(Uci->ponder_move)) {\r
-\r
- my_log("POLYGLOT THINK -> PONDER\n");\r
-\r
- State->state = PONDER;\r
- State->exp_move = Uci->ponder_move;\r
-\r
- } else {\r
-\r
- my_log("POLYGLOT THINK -> WAIT\n");\r
-\r
- State->state = WAIT;\r
- State->exp_move = MoveNone;\r
- }\r
-\r
- } else if (State->state == PONDER) {\r
-\r
- ASSERT(State->computer[game_turn(Game)]);\r
- ASSERT(!State->computer[colour_opp(game_turn(Game))]);\r
- ASSERT(!XB->analyse);\r
-\r
- if (move == State->exp_move && Uci->searching) {\r
-\r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
-\r
- my_timer_start(State->timer);//also resets\r
-\r
- my_log("POLYGLOT PONDER -> THINK (*** HIT ***)\n");\r
- engine_send(Engine,"ponderhit");\r
-\r
- State->state = THINK;\r
- State->exp_move = MoveNone;\r
-\r
- send_pv(); // update display\r
-\r
- return; // do not launch a new search\r
-\r
- } else {\r
-\r
- my_log("POLYGLOT PONDER -> THINK (miss)\n");\r
-\r
- stop_search();\r
-\r
- State->state = THINK;\r
- State->exp_move = MoveNone;\r
- }\r
-\r
- } else if (State->state == ANALYSE) {\r
-\r
- ASSERT(XB->analyse);\r
-\r
- my_log("POLYGLOT ANALYSE -> ANALYSE\n");\r
-\r
- stop_search();\r
-\r
- } else {\r
-\r
- ASSERT(false);\r
- }\r
-\r
- search_update();\r
-}\r
-\r
-// start_protected_command()\r
-\r
-static void start_protected_command(){\r
- stop_search();\r
-}\r
-\r
-static void end_protected_command(){\r
- if(Uci->ready){ // not init faze\r
- uci_send_isready_sync(Uci); // gobble up spurious "bestmove"\r
- }\r
- update_remaining_time();\r
- search_update(); // relaunch search if necessary\r
-}\r
-\r
-// update_remaining_time()\r
-\r
-static void update_remaining_time(){\r
- double reduce;\r
- if(State->timer->running){\r
- my_timer_stop(State->timer);\r
- reduce = my_timer_elapsed_real(State->timer);\r
- my_log("POLYGLOT reducing remaing time by %f seconds\n",reduce);\r
- XB->my_time -= reduce;\r
- if(XB->my_time<0.0){\r
- XB->my_time=0.0;\r
- }\r
- }\r
-}\r
-\r
-\r
-// search_update()\r
-\r
-static void search_update() {\r
-\r
- int move;\r
- int move_nb;\r
- board_t board[1];\r
-\r
- ASSERT(!Uci->searching);\r
-\r
-\r
-\r
- \r
- // launch a new search if needed\r
-\r
- \r
-\r
- if (State->state == THINK || State->state == PONDER || State->state == ANALYSE) {\r
-\r
- // opening book\r
-\r
- if (State->state == THINK && option_get_bool("Book")) {\r
-\r
- game_get_board(Game,Uci->board);\r
-\r
- move = book_move(Uci->board,option_get_bool("BookRandom"));\r
-\r
- if (move != MoveNone && move_is_legal(move,Uci->board)) {\r
-\r
- my_log("POLYGLOT *BOOK MOVE*\n");\r
-\r
- search_clear(); // clears Uci->ponder_move\r
- Uci->best_move = move;\r
-\r
- board_copy(board,Uci->board);\r
- move_do(board,move);\r
- Uci->ponder_move = book_move(board,false); // expected move = best book move\r
-\r
- Uci->best_pv[0] = Uci->best_move;\r
- Uci->best_pv[1] = Uci->ponder_move; // can be MoveNone\r
- Uci->best_pv[2] = MoveNone;\r
-\r
- comp_move(Uci->best_move);\r
-\r
- return;\r
- }\r
- }\r
-\r
- // engine search\r
-\r
- my_log("POLYGLOT START SEARCH\n");\r
-\r
- // options\r
-\r
- uci_send_option(Uci,"UCI_Chess960","%s",option_get_bool("Chess960")?"true":"false");\r
-\r
- if (option_get_int("UCIVersion") >= 2) {\r
- uci_send_option(Uci,"UCI_Opponent","none none %s %s",(XB->computer)?"computer":"human",XB->name);\r
- uci_send_option(Uci,"UCI_AnalyseMode","%s",(XB->analyse)?"true":"false");\r
- }\r
-\r
- uci_send_option(Uci,"Ponder","%s",ponder()?"true":"false");\r
-\r
- // position\r
-\r
- move = (State->state == PONDER) ? State->exp_move : MoveNone;\r
- send_board(move); // updates Uci->board global variable\r
-\r
- // search\r
-\r
- if (State->state == THINK || State->state == PONDER) {\r
-\r
- engine_send_queue(Engine,"go");\r
-\r
- if (XB->time_limit) {\r
-\r
- // fixed time per move\r
-\r
- engine_send_queue(Engine," movetime %.0f",XB->time_max*1000.0);\r
-\r
- } else {\r
-\r
- // time controls\r
-\r
- if (colour_is_white(Uci->board->turn)) {\r
- engine_send_queue(Engine," wtime %.0f btime %.0f",XB->my_time*1000.0,XB->opp_time*1000.0);\r
- } else {\r
- engine_send_queue(Engine," wtime %.0f btime %.0f",XB->opp_time*1000.0,XB->my_time*1000.0);\r
- }\r
-\r
- if (XB->inc != 0.0) engine_send_queue(Engine," winc %.0f binc %.0f",XB->inc*1000.0,XB->inc*1000.0);\r
-\r
- if (XB->mps != 0) {\r
-\r
- move_nb = XB->mps - (Uci->board->move_nb % XB->mps);\r
- ASSERT(move_nb>=1&&move_nb<=XB->mps);\r
-\r
- engine_send_queue(Engine," movestogo %d",move_nb);\r
- }\r
- }\r
-\r
- if (XB->depth_limit) engine_send_queue(Engine," depth %d",XB->depth_max);\r
-\r
- if (State->state == PONDER) engine_send_queue(Engine," ponder");\r
-\r
- engine_send(Engine,""); // newline\r
-\r
- } else if (State->state == ANALYSE) {\r
-\r
- engine_send(Engine,"go infinite");\r
-\r
- } else {\r
-\r
- ASSERT(false);\r
- }\r
-\r
- // init search info\r
-\r
- ASSERT(!Uci->searching);\r
-\r
- search_clear();\r
-\r
- Uci->searching = true;\r
- Uci->pending_nb++;\r
- }\r
-}\r
-\r
-// search_clear()\r
-\r
-static void search_clear() {\r
-\r
- uci_clear(Uci);\r
-\r
- // TODO: MOVE ME\r
-\r
- my_timer_start(State->timer);//also resets\r
-}\r
-\r
-// active()\r
-\r
-static bool active() {\r
-\r
- // position state\r
-\r
- if (game_status(Game) != PLAYING) return false; // game ended\r
-\r
- // xboard state\r
-\r
- if (XB->analyse) return true; // analysing\r
- if (!State->computer[White] && !State->computer[Black]) return false; // force mode\r
- if (XB->new_hack || XB->result) return false; // unstarted or ended game\r
-\r
- return true; // playing\r
-}\r
-\r
-// ponder()\r
-\r
-static bool ponder() {\r
-\r
- return XB->ponder && (option_get_bool("CanPonder") || uci_option_exist(Uci,"Ponder"));\r
-}\r
-// ponder_ok()\r
-\r
-static bool ponder_ok(int move) {\r
- int status;\r
- board_t board[1];\r
-\r
- ASSERT(move==MoveNone||move_is_ok(move));\r
-\r
- // legal ponder move?\r
-\r
- if (move == MoveNone) return false;\r
-\r
- game_get_board(Game,board);\r
- if (!move_is_legal(move,board)) return false;\r
-\r
- // UCI-legal resulting position?\r
-\r
- game_add_move(Game,move);\r
-\r
- game_get_board(Game,board);\r
- status = game_status(Game);\r
-\r
- game_rem_move(Game);\r
-\r
- if (status != PLAYING) return false; // game ended\r
-\r
- if (option_get_bool("Book") && is_in_book(board)) {\r
- return false;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-// stop_search()\r
-\r
-static void stop_search() {\r
-\r
- if (Uci->searching) {\r
-\r
- ASSERT(Uci->searching);\r
- ASSERT(Uci->pending_nb>=1);\r
-\r
- my_log("POLYGLOT STOP SEARCH\n");\r
-\r
-/*\r
- engine_send(Engine,"stop");\r
- Uci->searching = false;\r
-*/\r
-\r
- if (option_get_bool("SyncStop")) {\r
- uci_send_stop_sync(Uci);\r
- } else {\r
- uci_send_stop(Uci);\r
- }\r
- }\r
-}\r
-\r
-// send_board()\r
-\r
-static void send_board(int extra_move) {\r
-\r
- char fen[256];\r
- int start, end;\r
- board_t board[1];\r
- int pos;\r
- int move;\r
- char string[256];\r
-\r
- ASSERT(extra_move==MoveNone||move_is_ok(extra_move));\r
-\r
- ASSERT(!Uci->searching);\r
-\r
- // init\r
-\r
- game_get_board(Game,Uci->board);\r
- if (extra_move != MoveNone) move_do(Uci->board,extra_move);\r
-\r
- board_to_fen(Uci->board,fen,256);\r
- my_log("POLYGLOT FEN %s\n",fen);\r
-\r
- ASSERT(board_can_play(Uci->board));\r
-\r
- // more init\r
-\r
- start = 0;\r
- end = game_pos(Game);\r
- ASSERT(end>=start);\r
-\r
- // position\r
-\r
- game_get_board(Game,board,start);\r
- board_to_fen(board,string,256);\r
-\r
- engine_send_queue(Engine,"position");\r
-\r
- if (my_string_equal(string,StartFen)) {\r
- engine_send_queue(Engine," startpos");\r
- } else {\r
- engine_send_queue(Engine," fen %s",string);\r
- }\r
-\r
- // move list\r
-\r
- if (end > start || extra_move != MoveNone) engine_send_queue(Engine," moves");\r
-\r
- for (pos = start; pos < end; pos++) { // game moves\r
-\r
- move = game_move(Game,pos);\r
-\r
- move_to_can(move,board,string,256);\r
- engine_send_queue(Engine," %s",string);\r
-\r
- move_do(board,move);\r
- }\r
-\r
- if (extra_move != MoveNone) { // move to ponder on\r
- move_to_can(extra_move,board,string,256);\r
- engine_send_queue(Engine," %s",string);\r
- }\r
-\r
- // end\r
-\r
- engine_send(Engine,""); // newline\r
-}\r
-\r
-// send_pv()\r
-\r
-static void send_pv() {\r
-\r
- char pv_string[StringSize];\r
- board_t board[1];\r
- int move;\r
- char move_string[StringSize];\r
-\r
- ASSERT(State->state!=WAIT);\r
-\r
- if (Uci->best_depth == 0) return;\r
-\r
- // xboard search information\r
-\r
- if (XB->post) {\r
-\r
- if (State->state == THINK || State->state == ANALYSE) {\r
-\r
- line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
-\r
- if(Uci->depth==-1) //hack to clear the engine output window\r
- gui_send(GUI,"%d %+d %.0f "S64_FORMAT" ",0,report_best_score(),Uci->time*100.0,Uci->node_nb);\r
-\r
- gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth,report_best_score(),Uci->time*100.0,Uci->node_nb,pv_string);\r
-\r
- } else if (State->state == PONDER && option_get_bool("ShowPonder")) {\r
-\r
- game_get_board(Game,board);\r
- move = State->exp_move;\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
- move_to_san(move,board,move_string,256);\r
- line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
- gui_send(GUI,"%d %+d %.0f "S64_FORMAT" (%s) %s",Uci->best_depth,report_best_score(),Uci->time*100.0,Uci->node_nb,move_string,pv_string);\r
- }\r
- }\r
- }\r
-\r
- // kibitz\r
-\r
- if ((Uci->searching && option_get_bool("KibitzPV") && Uci->time >= option_get_double("KibitzDelay"))\r
- || (!Uci->searching && option_get_bool("KibitzMove"))) {\r
-\r
- if (State->state == THINK || State->state == ANALYSE) {\r
-\r
- line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
- if(kibitz_throttle(Uci->searching)){\r
- gui_send(GUI,"%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(report_best_score())/100.0,pv_string);\r
- }\r
- } else if (State->state == PONDER) {\r
-\r
- game_get_board(Game,board);\r
- move = State->exp_move;\r
-\r
- if (move != MoveNone && move_is_legal(move,board)) {\r
- move_to_san(move,board,move_string,256);\r
- line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize);\r
- if(kibitz_throttle(Uci->searching)){\r
- gui_send(GUI,"%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(report_best_score())/100.0,move_string,pv_string);\r
- }\r
- }\r
- }\r
- }\r
-}\r
-\r
-// kibitz_throttle()\r
-\r
-static bool kibitz_throttle(bool searching){\r
- time_t curr_time;\r
- static time_t lastKibitzMove=0;\r
- static time_t lastKibitzPV=0;\r
- curr_time = time(NULL);\r
- if(searching){ // KibitzPV\r
- if(curr_time >= (option_get_int("KibitzInterval") + lastKibitzPV)){\r
- lastKibitzPV=curr_time;\r
- return true;\r
- }\r
- }else{ // KibitzMove\r
- if(curr_time >= (option_get_int("KibitzInterval") + lastKibitzMove)){\r
- lastKibitzPV=curr_time;\r
- lastKibitzMove=curr_time;\r
- return true;\r
- } \r
- }\r
- return false;\r
-}\r
-\r
-// learn()\r
-\r
-static void learn(int result) {\r
-\r
- int pos;\r
- board_t board[1];\r
- int move;\r
-\r
- ASSERT(result>=-1&&result<=+1);\r
-\r
- ASSERT(XB->result);\r
- ASSERT(State->computer[White]||State->computer[Black]);\r
-\r
- // init\r
-\r
- pos = 0;\r
-\r
- if (false) {\r
- } else if (State->computer[White]) {\r
- pos = 0;\r
- } else if (State->computer[Black]) {\r
- pos = 1;\r
- result = -result;\r
- } else {\r
- my_fatal("learn(): unknown side\n");\r
- }\r
-\r
- if (false) {\r
- } else if (result > 0) {\r
- my_log("POLYGLOT *LEARN WIN*\n");\r
- } else if (result < 0) {\r
- my_log("POLYGLOT *LEARN LOSS*\n");\r
- } else {\r
- my_log("POLYGLOT *LEARN DRAW*\n");\r
- }\r
-\r
- // loop\r
-\r
- for (; pos < Game->size; pos += 2) {\r
-\r
- game_get_board(Game,board,pos);\r
- move = game_move(Game,pos);\r
-\r
- book_learn_move(board,move,result);\r
- }\r
-\r
- book_flush();\r
-}\r
-\r
-// end of adapter.cpp\r