// includes\r
\r
#include <cerrno>\r
-#include <csignal>\r
#include <cstdio>\r
#include <cstdlib>\r
#include <cstring>\r
\r
-#ifdef _WIN32\r
- #include <windows.h>\r
-#else\r
- #include <unistd.h>\r
-#endif\r
-\r
-#include "adapter.h"\r
#include "attack.h"\r
#include "board.h"\r
#include "book.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 "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.4W10UCIb16";\r
+static const char * const Version = "1.4W10UCIb17";\r
static const char * const HelpMessage = "\\r
SYNTAX\n\\r
polyglot [configfile]\n\\r
polyglot perft [-fen fen] [-max-depth depth]\\r
";\r
\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
}\r
// init\r
\r
- Init = false;\r
-\r
- signal(SIGINT,sig_quit);\r
-\r
-#ifdef _WIN32\r
- signal(SIGTERM,SIG_IGN);\r
-#ifdef SIGPIPE\r
- signal(SIGPIPE,SIG_IGN);\r
-#endif\r
-#endif\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],"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
- Init=true;\r
- engine_open(Engine);\r
- gui_init(GUI);\r
- uci_open(Uci,Engine);\r
- if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\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],"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
- adapter_loop();\r
- return EXIT_SUCCESS; // we don't get here\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
+ 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
- // 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
- init_book();\r
- // adapter\r
- \r
- gui_init(GUI);\r
- adapter_loop();\r
- return EXIT_SUCCESS; // we never get here....\r
+ init_book();\r
+ gui_init(GUI);\r
+ mainloop();\r
+ return EXIT_SUCCESS; \r
}\r
\r
// polyglot_set_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
+ 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
+ \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(line[0]=='#') continue;\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
+ if (!my_file_read_line(file,line,256)) {\r
+ my_fatal("parse_option(): missing [Engine] section\n");\r
+ }\r
+ \r
+ if(line[0]=='#') continue;\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
+ \r
if (option_get_bool("Log")) {\r
- my_log_open(option_get_string("LogFile"));\r
+ my_log_open(option_get_string("LogFile"));\r
}\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\"",option_get("EngineCommand"));\r
+ }\r
+\r
if (option_get_bool("UCI")) {\r
my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
}\r
-\r
- \r
- Init = true;\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 (line[0]=='#') continue;\r
}\r
}\r
if (my_string_equal(option_get_string("EngineName"),"<empty>")) {\r
- option_set("EngineName",Uci->name);\r
+ option_set("EngineName",Uci->name);\r
}\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
-static void sig_quit(int dummy){\r
- my_log("POLYGLOT *** SIGINT Received ***\n");\r
- quit();\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
-\r
// quit()\r
\r
void quit() {\r
\r
- char string[StringSize];\r
-\r
- my_log("POLYGLOT *** QUIT ***\n");\r
-\r
- if (Init) {\r
-\r
- stop_search();\r
- engine_send(Engine,"quit");\r
-\r
- // wait for the engine to quit\r
- while (true) {\r
- engine_get(Engine,string,StringSize); // HACK: calls exit() on receiving EOF\r
- }\r
- }\r
- exit(EXIT_SUCCESS);\r
+ my_log("POLYGLOT *** QUIT ***\n");\r
+ \r
+ if (Init) {\r
+ \r
+ stop_search();\r
+ engine_send(Engine,"quit");\r
+ engine_close(Engine);\r
+ \r
+ }\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
-/*\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
+ 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
+\r
+// xboard2uci.cpp\r
+\r
+// includes\r
+\r
+#include <cerrno>\r
+#include <cstdio>\r
+#include <cstdlib>\r
+#include <cstring>\r
+\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 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
+// xboard_init()\r
+\r
+void xboard_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
+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
+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(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