From a0f731f21d6aa26dbf7246039a1c66c2ade0533f Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Thu, 9 Jun 2011 09:57:41 +0200 Subject: [PATCH] version 1.4.34b --- ChangeLog | 8 ++ README | 22 +++--- TODO | 11 +++- book.c | 2 +- config.h | 6 +- configure | 20 +++--- configure.ac | 2 +- engine.c | 57 ++++----------- engine.h | 1 - epd.c | 9 ++- fen.c | 2 +- gui.c | 9 +-- io.c | 14 +--- main.c | 70 ++++++++++--------- mainloop.c | 8 +- move.c | 4 +- option.c | 169 +++++++++++++++++++++++++++++++++++--------- option.h | 56 +++++++++++---- pipex.h | 4 + pipex_posix.c | 19 +++++- pipex_win32.c | 63 ++++++++++++++--- polyglot.man | 18 ++--- polyglot.pod | 14 ++-- polyglot.spec | 2 +- uci.c | 216 ++++++++++++++++++--------------------------------------- uci.h | 54 ++++++--------- uci2uci.c | 22 +++--- util.c | 66 +++++++----------- util.h | 23 +++++- xboard2uci.c | 181 +++++++++++++++++++++++++++++++----------------- 30 files changed, 642 insertions(+), 510 deletions(-) diff --git a/ChangeLog b/ChangeLog index 070eeb7..b63a77a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +=========1.4.34b================ +- Warning: this release is less well tested as usual +- Allow spaces around "=" in "option =" commands. +- WbWorkArounds is now true by default. +- Trying to set a non existent UCI option gives an error. +- PG will now resign in case of an illegal engine move. +- More code has been put in "pipex". +- info strings and unrecognized info lines are relayed to the GUI. =========1.4.33b================ - New option: "WbWorkArounds". Currently it blocks options which contain "Draw" in their name from being sent to the GUI. Engines that have such options are Rybka and HIARCS. - Bugfix for ASSERT failure in bright. Now another ASSERT failure has appeared which seems to be bright's fault however. diff --git a/README b/README index f36abee..df31a94 100644 --- a/README +++ b/README @@ -399,12 +399,11 @@ CONFIG FILE FORMAT Work arounds are identical to options except that they should be used only when necessary. Their purpose is to try to hide problems with - various software (not just engines). The default value is always cor- - rect for bug-free software. + various software (not just engines). - IMPORTANT: Any of these work arounds might be removed in future ver- - sions of PolyGlot. You are strongly recommended to contact the author - of faulty software and truly fix the problem. + IMPORTANT: Any of these work arounds might be removed in future + versions of PolyGlot. You are strongly recommended to contact the + author of faulty software and truly fix the problem. PolyGlot supports the following work arounds: @@ -440,13 +439,12 @@ CONFIG FILE FORMAT to the way kibitzing is implemented, KibitzMove is disabled in that case. - WbWorkArounds (default: false) + WbWorkArounds (default: true) The intention of this option is to provide work arounds for - xboard/winboard bugs should they arise. Currently it only prevents - "feature option=" commands which contain "Draw" in their name from - being sent to the GUI. Some versions of xboard/winboard contain a - bug which causes such options to be interpreted as draw claims by - the engine. + xboard/winboard bugs should they arise. Currently it decapitalizes + the word Draw in options that contain this word. Some versions of + xboard/winboard contain a bug which causes such options to be + interpreted as draw claims by the engine. Engines that send options with "Draw" in their name are Rybka and HIARCS. @@ -523,4 +521,4 @@ SEE ALSO - 2009-08-06 POLYGLOT(6) + 2009-08-07 POLYGLOT(6) diff --git a/TODO b/TODO index 4791f92..d01fa69 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,9 @@ -Better check for legality of arguments (i.e. stuff after [configfile]). -Implementation of Marc Lacrosse's utility +Move static queue for engine writing to engine struct +Continue refactoring of option stuff (search for option_nb) +Make _ex versions the default (more object oriented). +Remove most uci option commands. Refer directly to Uci->option. It will make the code more +readable. +Replace "append_option" by "insert_option". +Inifile handling. +Refactor removinging of trailing EOL and white space from string (see util.c and ini file parsing). +ML's utility diff --git a/book.c b/book.c index 73fb2d2..5821451 100644 --- a/book.c +++ b/book.c @@ -60,7 +60,7 @@ bool book_is_open(){ void book_open(const char file_name[]) { ASSERT(file_name!=NULL); - if(option_get_bool("BookLearn")){ + if(option_get_bool(Option,"BookLearn")){ BookFile = fopen(file_name,"rb+"); }else{ BookFile = fopen(file_name,"rb"); diff --git a/config.h b/config.h index 47ea08c..10f758d 100644 --- a/config.h +++ b/config.h @@ -115,13 +115,13 @@ #define PACKAGE_NAME "polyglot" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "polyglot 1.4.33b" +#define PACKAGE_STRING "polyglot 1.4.34b" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "polyglot" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.4.33b" +#define PACKAGE_VERSION "1.4.34b" /* Define to 1 if the C compiler supports function prototypes. */ #define PROTOTYPES 1 @@ -150,7 +150,7 @@ #define TIME_WITH_SYS_TIME 1 /* Version number of package */ -#define VERSION "1.4.33b" +#define VERSION "1.4.34b" /* Define like PROTOTYPES; this can be used by system headers. */ #define __PROTOTYPES 1 diff --git a/configure b/configure index 264d016..e4d62f1 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for polyglot 1.4.33b. +# Generated by GNU Autoconf 2.61 for polyglot 1.4.34b. # # Report bugs to . # @@ -574,8 +574,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='polyglot' PACKAGE_TARNAME='polyglot' -PACKAGE_VERSION='1.4.33b' -PACKAGE_STRING='polyglot 1.4.33b' +PACKAGE_VERSION='1.4.34b' +PACKAGE_STRING='polyglot 1.4.34b' PACKAGE_BUGREPORT='michel.vandenbergh@uhasselt.be' ac_unique_file="mainloop.c" @@ -1207,7 +1207,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures polyglot 1.4.33b to adapt to many kinds of systems. +\`configure' configures polyglot 1.4.34b to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1273,7 +1273,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of polyglot 1.4.33b:";; + short | recursive ) echo "Configuration of polyglot 1.4.34b:";; esac cat <<\_ACEOF @@ -1357,7 +1357,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -polyglot configure 1.4.33b +polyglot configure 1.4.34b generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1371,7 +1371,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by polyglot $as_me 1.4.33b, which was +It was created by polyglot $as_me 1.4.34b, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -2061,7 +2061,7 @@ fi # Define the identity of the package. PACKAGE='polyglot' - VERSION='1.4.33b' + VERSION='1.4.34b' cat >>confdefs.h <<_ACEOF @@ -6848,7 +6848,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by polyglot $as_me 1.4.33b, which was +This file was extended by polyglot $as_me 1.4.34b, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6901,7 +6901,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -polyglot config.status 1.4.33b +polyglot config.status 1.4.34b configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.ac b/configure.ac index 91b66f3..5cec935 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([polyglot], [1.4.33b], [michel.vandenbergh@uhasselt.be]) +AC_INIT([polyglot], [1.4.34b], [michel.vandenbergh@uhasselt.be]) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([mainloop.c]) AC_CONFIG_HEADER([config.h]) diff --git a/engine.c b/engine.c index bf7bd49..a42c36e 100644 --- a/engine.c +++ b/engine.c @@ -7,21 +7,15 @@ #include #include - #include "engine.h" #include "option.h" #include "pipex.h" #include "util.h" -// defines - -#define StringSize 4096 - // variables -static int write_index = 0; -static char write_buffer[StringSize]; engine_t Engine[1]; +static const int StringSize=4096; // functions @@ -40,33 +34,17 @@ void engine_set_nice_value(engine_t *engine, int value){ // engine_send_queue() void engine_send_queue(engine_t * engine, const char *format, ...) { - va_list arg_list; - if(write_index>=StringSize){ - my_fatal("engine_send_queue(): write_buffer overflow\n"); - } - va_start(arg_list,format); - write_index += vsnprintf(write_buffer + write_index, - StringSize-write_index, - format, - arg_list); - va_end(arg_list); + char buf[FormatBufferSize]; + CONSTRUCT_ARG_STRING(format,buf); + pipex_write(engine->pipex,buf); } // engine_send() void engine_send(engine_t * engine, const char *format, ...) { - va_list arg_list; - if(write_index>=StringSize){ - my_fatal("engine_send(): write_buffer overflow\n"); - } - va_start(arg_list,format); - vsnprintf(write_buffer + write_index, - StringSize-write_index, - format, - arg_list); - va_end(arg_list); - pipex_writeln(engine->pipex,write_buffer); - write_index = 0; + char buf[FormatBufferSize]; + CONSTRUCT_ARG_STRING(format,buf); + pipex_writeln(engine->pipex,buf); } // engine_close() @@ -76,7 +54,7 @@ void engine_close(engine_t * engine){ pipex_send_eof(engine->pipex); // TODO: Timeout while (!engine_eof(engine)) { - engine_get(Engine,string); + engine_get(engine,string); } pipex_exit(engine->pipex); } @@ -85,23 +63,18 @@ void engine_close(engine_t * engine){ void engine_open(engine_t * engine){ int affinity; - char *my_dir; - if( (my_dir = my_getcwd( NULL, 0 )) == NULL ) - my_fatal("engine_open(): no current directory: %s\n",strerror(errno)); - if(my_chdir(option_get_string("EngineDir"))){ - my_fatal("engine_open(): cannot change directory: %s\n",strerror(errno)); - } - pipex_open(engine->pipex,"Engine",option_get_string("EngineCommand")); + pipex_open(engine->pipex, + "Engine", + option_get_string(Option,"EngineDir"), + option_get_string(Option,"EngineCommand")); if(pipex_active(engine->pipex)){ //play with affinity (bad idea) - affinity=option_get_int("Affinity"); + affinity=option_get_int(Option,"Affinity"); if(affinity!=-1) set_affinity(engine,affinity); //AAA - //lets go back - my_chdir(my_dir); // set a low priority - if (option_get_bool("UseNice")){ + if (option_get_bool(Option,"UseNice")){ my_log("POLYGLOT Adjust Engine Piority\n"); - engine_set_nice_value(engine, option_get_int("NiceValue")); + engine_set_nice_value(engine, option_get_int(Option,"NiceValue")); } } diff --git a/engine.h b/engine.h index 2a408e3..70e366b 100644 --- a/engine.h +++ b/engine.h @@ -5,7 +5,6 @@ // includes -#include "io.h" #include "util.h" #include "pipex.h" diff --git a/epd.c b/epd.c index c79c399..af427ad 100644 --- a/epd.c +++ b/epd.c @@ -22,13 +22,16 @@ #include "uci.h" #include "util.h" + +// macros + +#define StringSize 4096 + // constants static const bool UseDebug = FALSE; static const bool UseTrace = FALSE; -static const int StringSize = 4096; - // variables static int MinDepth; @@ -179,7 +182,7 @@ static void epd_test_file(const char file_name[]) { time_tot = 0.0; node_tot = 0.0; - printf("\nEngineName=%s\n",option_get_string("EngineName")); + printf("\nEngineName=%s\n",option_get_string(Option,"EngineName")); printf("\n[Search parameters: MaxDepth=%d MaxTime=%.1f DepthDelta=%d MinDepth=%d MinTime=%.1f]\n\n",MaxDepth,MaxTime,DepthDelta,MinDepth,MinTime); diff --git a/fen.c b/fen.c index be3ec17..180bdf3 100644 --- a/fen.c +++ b/fen.c @@ -336,7 +336,7 @@ bool board_to_fen(const board_t * board, char string[], int size) { old_pos = pos; - if (option_get_bool("Chess960")) { + if (option_get_bool(Option,"Chess960")) { // FEN-960 diff --git a/gui.c b/gui.c index 9dbe6f5..44abc37 100644 --- a/gui.c +++ b/gui.c @@ -52,7 +52,7 @@ void gui_init(gui_t *gui){ #ifdef SIGPIPE signal(SIGPIPE,sig_pipe); #endif - pipex_open(gui->pipex,"GUI",NULL); + pipex_open(gui->pipex,"GUI",NULL,NULL); } @@ -84,17 +84,14 @@ void gui_get(gui_t * gui, char *string) { void gui_send(gui_t * gui, const char format[], ...) { - va_list arg_list; - char string[StringSize]; + char string[FormatBufferSize]; ASSERT(gui!=NULL); ASSERT(format!=NULL); // format - va_start(arg_list,format); - vsprintf(string,format,arg_list); - va_end(arg_list); + CONSTRUCT_ARG_STRING(format,string); // send diff --git a/io.c b/io.c index 88eb045..92d1518 100644 --- a/io.c +++ b/io.c @@ -196,8 +196,7 @@ bool io_get_line(io_t * io, char string[], int size) { void io_send(io_t * io, const char format[], ...) { - va_list arg_list; - char string[StringSize]; + char string[FormatBufferSize]; int len; ASSERT(io_is_ok(io)); @@ -207,9 +206,7 @@ void io_send(io_t * io, const char format[], ...) { // format - va_start(arg_list,format); - vsprintf(string,format,arg_list); - va_end(arg_list); + CONSTRUCT_ARG_STRING(format,string); // append string to buffer @@ -245,8 +242,7 @@ void io_send(io_t * io, const char format[], ...) { void io_send_queue(io_t * io, const char format[], ...) { - va_list arg_list; - char string[StringSize]; + char string[FormatBufferSize]; int len; ASSERT(io_is_ok(io)); @@ -256,9 +252,7 @@ void io_send_queue(io_t * io, const char format[], ...) { // format - va_start(arg_list,format); - vsprintf(string,format,arg_list); - va_end(arg_list); + CONSTRUCT_ARG_STRING(format,string); // append string to buffer diff --git a/main.c b/main.c index 3dc5c20..e2f4c64 100644 --- a/main.c +++ b/main.c @@ -35,7 +35,7 @@ // constants -static const char * const Version = "1.4.33b"; +static const char * const Version = "1.4.34b"; static const char * const HelpMessage = "\ SYNTAX\n\ * polyglot [configfile]\n\ @@ -85,7 +85,7 @@ int main(int argc, char * argv[]) { Init = FALSE; util_init(); - option_init(); + option_init_pg(); square_init(); piece_init(); @@ -128,24 +128,26 @@ int main(int argc, char * argv[]) { } if (argc >= 3 && my_string_equal(argv[1],"-ec")) { - option_set("EngineCommand",argv[2]); + option_set(Option,"EngineCommand",argv[2]); engine_open(Engine); if(!engine_active(Engine)){ - my_fatal("Could not start \"%s\"\n",option_get("EngineCommand")); + my_fatal("Could not start \"%s\"\n", + option_get(Option,"EngineCommand")); } Init=TRUE; gui_init(GUI); uci_open(Uci,Engine); - if (my_string_equal(option_get_string("EngineName"),"")) { - option_set("EngineName",Uci->name); + if (my_string_equal(option_get_string(Option,"EngineName"),"")) { + option_set(Option,"EngineName",Uci->name); } mainloop(); return EXIT_SUCCESS; } // read options + - if (argc == 2) option_set("OptionFile",argv[1]); // HACK for compatibility + if (argc == 2) option_set(Option,"OptionFile",argv[1]); // HACK for compatibility parse_option(); // HACK: also launches the engine @@ -171,31 +173,31 @@ int main(int argc, char * argv[]) { // polyglot_set_option void polyglot_set_option(char *name, char *value){ // this must be cleaned up! - option_set(name,value); - if(option_get_bool("Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){ + option_set(Option,name,value); + if(option_get_bool(Option,"Book")&&(my_string_case_equal(name,"BookFile")||my_string_case_equal(name,"Book"))){ my_log("POLYGLOT *** SETTING BOOK ***\n"); - my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile")); + my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile")); book_close(); book_clear(); - book_open(option_get_string("BookFile")); + book_open(option_get_string(Option,"BookFile")); if(!book_is_open()){ - my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string("BookFile")); + my_log("POLYGLOT Unable to open book \"%s\"\n",option_get_string(Option,"BookFile")); } - }else if(option_get_bool("Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){ + }else if(option_get_bool(Option,"Log")&&(my_string_case_equal(name,"LogFile") ||my_string_case_equal(name,"Log"))){ my_log("POLYGLOT *** SETTING LOGFILE ***\n"); - my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string("LogFile")); + my_log("POLYGLOT LOGFILE \"%s\"\n",option_get_string(Option,"LogFile")); my_log_close(); - my_log_open(option_get_string("LogFile")); - }else if(option_get_bool("UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){ + my_log_open(option_get_string(Option,"LogFile")); + }else if(option_get_bool(Option,"UseNice") &&(my_string_case_equal(name,"NiceValue")||my_string_case_equal(name,"UseNice"))){ my_log("POLYGLOT Adjust Engine Piority\n"); - engine_set_nice_value(Engine,atoi(option_get_string("NiceValue"))); - }else if(my_string_case_equal(name,"Book") && !option_get_bool("Book")){ + engine_set_nice_value(Engine,atoi(option_get_string(Option,"NiceValue"))); + }else if(my_string_case_equal(name,"Book") && !option_get_bool(Option,"Book")){ book_close(); book_clear(); - }else if(my_string_case_equal(name,"UseNice") && !option_get_bool("UseNice")){ + }else if(my_string_case_equal(name,"UseNice") && !option_get_bool(Option,"UseNice")){ my_log("POLYGLOT Adjust Engine Piority\n"); engine_set_nice_value(Engine,0); - }else if(my_string_case_equal(name,"Log") && !option_get_bool("Log")){ + }else if(my_string_case_equal(name,"Log") && !option_get_bool(Option,"Log")){ my_log("POLYGLOT QUIT LOGGING\n"); my_log_close(); } @@ -206,13 +208,13 @@ void polyglot_set_option(char *name, char *value){ // this must be cleaned up! static void init_book(){ book_clear(); - if (option_get_bool("Book")){ + if (option_get_bool(Option,"Book")){ my_log("POLYGLOT *** SETTING BOOK ***\n"); - my_log("POLYGLOT BOOK \"%s\"\n",option_get_string("BookFile")); - book_open(option_get_string("BookFile")); + my_log("POLYGLOT BOOK \"%s\"\n",option_get_string(Option,"BookFile")); + book_open(option_get_string(Option,"BookFile")); if(!book_is_open()){ my_log("POLYGLOT Unable to open book \"%s\"\n", - option_get_string("BookFile")); + option_get_string(Option,"BookFile")); } } } @@ -225,7 +227,7 @@ static void parse_option() { FILE * file; char line[256]; char * name, * value; - file_name = option_get_string("OptionFile"); + file_name = option_get_string(Option,"OptionFile"); file = fopen(file_name,"r"); if (file == NULL) { @@ -243,13 +245,13 @@ static void parse_option() { if (my_string_case_equal(line,"[engine]")) break; if (parse_line(line,&name,&value)) { - option_set(name,value); - option_set_default(name,value); + option_set(Option,name,value); + option_set_default(Option,name,value); } } - if (option_get_bool("Log")) { - my_log_open(option_get_string("LogFile")); + if (option_get_bool(Option,"Log")) { + my_log_open(option_get_string(Option,"LogFile")); } if(!DEBUG){ @@ -262,10 +264,10 @@ static void parse_option() { my_log("POLYGLOT INI file \"%s\"\n",file_name); engine_open(Engine); if(!engine_active(Engine)){ - my_fatal("Could not start \"%s\"\n",option_get("EngineCommand")); + my_fatal("Could not start \"%s\"\n",option_get(Option,"EngineCommand")); } - if (option_get_bool("UCI")) { + if (option_get_bool(Option,"UCI")) { my_log("POLYGLOT *** Switching to UCI mode ***\n"); } uci_open(Uci,Engine); @@ -280,8 +282,8 @@ static void parse_option() { if(my_string_case_equal(name,"MultiPV") && atoi(value)>1) Uci->multipv_mode=TRUE; } } - if (my_string_equal(option_get_string("EngineName"),"")) { - option_set("EngineName",Uci->name); + if (my_string_equal(option_get_string(Option,"EngineName"),"")) { + option_set(Option,"EngineName",Uci->name); } fclose(file); @@ -371,7 +373,7 @@ static void stop_search() { my_log("POLYGLOT STOP SEARCH\n"); - if (option_get_bool("SyncStop")) { + if (option_get_bool(Option,"SyncStop")) { uci_send_stop_sync(Uci); } else { uci_send_stop(Uci); diff --git a/mainloop.c b/mainloop.c index de590cc..1fc4c1b 100644 --- a/mainloop.c +++ b/mainloop.c @@ -30,7 +30,7 @@ static void mainloop_gui_step(char * string); // mainloop_init() static void mainloop_init(){ - if(!option_get_bool("UCI")){ + if(!option_get_bool(Option,"UCI")){ xboard2uci_init(); // the default } } @@ -38,7 +38,7 @@ static void mainloop_init(){ // mainloop_engine_step() static void mainloop_engine_step(char * string){ - if(option_get_bool("UCI")){ + if(option_get_bool(Option,"UCI")){ uci2uci_engine_step(string); }else{ xboard2uci_engine_step(string); @@ -48,11 +48,11 @@ static void mainloop_engine_step(char * string){ // mainloop_gui_step() static void mainloop_gui_step(char * string){ - if(option_get_bool("UCI")){ + if(option_get_bool(Option,"UCI")){ uci2uci_gui_step(string); }else if(my_string_equal(string,"uci")){ // mode auto detection my_log("POLYGLOT *** Switching to UCI mode ***\n"); - option_set("UCI","true"); + option_set(Option,"UCI","true"); uci2uci_gui_step(string); }else{ xboard2uci_gui_step(string); diff --git a/move.c b/move.c index 8d5699f..116f11d 100644 --- a/move.c +++ b/move.c @@ -239,7 +239,7 @@ bool move_to_can(int move, const board_t * board, char string[], int size) { // king-slide castling - if (move_is_castle(move,board) && !option_get_bool("Chess960")) { + if (move_is_castle(move,board) && !option_get_bool(Option,"Chess960")) { if (FALSE) { } else if (from == E1 && to == H1) { to = G1; @@ -320,7 +320,7 @@ int move_from_can(const char string[], const board_t * board) { case '\0': // not a promotion if (piece_is_pawn(board->square[from]) && square_side_rank(to,board->turn) == Rank8 - && option_get_bool("PromoteWorkAround")) { + && option_get_bool(Option,"PromoteWorkAround")) { move |= MovePromoteQueen; } break; diff --git a/option.c b/option.c index 07b36cf..8d067b8 100644 --- a/option.c +++ b/option.c @@ -17,8 +17,10 @@ static const bool UseDebug = FALSE; // variables #define NNB { NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL } -option_t Option[] = { +option_list_t Option[1]; + +option_t DefaultOptions[] = { { "OptionFile", "string","0","0", "polyglot.ini", NULL,0,NNB, PG}, // options @@ -68,38 +70,94 @@ option_t Option[] = { { "RepeatPV", "check","0","0", "true" , NULL,0,NNB, PG|XBOARD}, { "PromoteWorkAround","check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, - { "WbWorkArounds", "check","0","0", "false" , NULL,0,NNB, PG|XBOARD}, + { "WbWorkArounds", "check","0","0", "true" , NULL,0,NNB, PG|XBOARD}, { NULL, NULL,"0","0", NULL , NULL,0,NNB, 0}, -}; -// prototypes +}; -static option_t * option_find (const char var[]); // functions -// option_init() - -void option_init() { +// option_is_ok() - option_t *p=Option; - const char * name; +bool option_is_ok(const option_list_t *option) { + if(option->option_nb<0 || option->option_nb>=OptionNb){ + return FALSE; + } + return TRUE; +} - while((name=(p++)->name)){ - option_set(name,option_get_default(name)); +// option_init_pg() + +void option_init_pg() { + + int i; + option_t *p=DefaultOptions; + + option_init(Option); + while(p){ + if(p->name){ + option_insert(Option,p); + p++; + }else{ + break; + } + } + for(i=0;ioption_nb;i++){ + Option->options[i].value=my_strdup(Option->options[i].default_); } } +// option_init() + +void option_init(option_list_t *option){ + ASSERT(option!=NULL); + option->option_nb=0; + option->iter=0; + memset(option->options,0,sizeof(option->options)); +} + +// option_insert() + +void option_insert(option_list_t *option, option_t *new_option){ + ASSERT(option!=NULL); + ASSERT(new_option!=NULL); + ASSERT(new_option->name!=NULL); + option_t *opt; + opt=option_find(option,new_option->name); + if(!opt){ + opt=&option->options[option->option_nb]; + option->option_nb++; + } + int i; + if(option->option_nb>=OptionNb){ + my_fatal("option_insert(): option list overflow\n"); + } + if(new_option->name) my_string_set(&opt->name, new_option->name); + if(new_option->value) my_string_set(&opt->value, new_option->value); + if(new_option->min) my_string_set(&opt->min, new_option->min); + if(new_option->max) my_string_set(&opt->max, new_option->max); + if(new_option->default_) my_string_set(&opt->default_, new_option->default_); + if(new_option->type) my_string_set(&opt->type, new_option->type); + opt->var_nb=new_option->var_nb; + for(i=0;ivar_nb;i++){ + my_string_set(&opt->var[i], new_option->var[i]); + } + opt->mode=new_option->mode; +} // option_set() -bool option_set(const char name[], const char value[]) { +bool option_set(option_list_t *option, + const char name[], + const char value[]) { option_t * opt; + ASSERT(option!=NULL); ASSERT(name!=NULL); ASSERT(value!=NULL); - opt = option_find(name); + opt = option_find(option,name); if (opt == NULL) return FALSE; my_string_set(&opt->value,value); @@ -108,15 +166,18 @@ bool option_set(const char name[], const char value[]) { return TRUE; } -// option_set() -bool option_set_default(const char name[], const char value[]) { +// option_set_default() + +bool option_set_default(option_list_t *option, + const char name[], + const char value[]) { option_t * opt; ASSERT(name!=NULL); ASSERT(value!=NULL); - opt = option_find(name); + opt = option_find(option,name); if (opt == NULL) return FALSE; opt->default_=my_strdup(value); @@ -128,15 +189,14 @@ bool option_set_default(const char name[], const char value[]) { // option_get() -const char * option_get(const char name[]) { +const char * option_get(option_list_t *option, const char name[]) { option_t * opt; ASSERT(name!=NULL); - opt = option_find(name); + opt = option_find(option,name); if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",name); - if (UseDebug) my_log("POLYGLOT OPTION GET \"%s\" -> \"%s\"\n",opt->name,opt->value); return opt->value; @@ -144,13 +204,13 @@ const char * option_get(const char name[]) { // option_get_default() -const char * option_get_default(const char name[]) { +const char * option_get_default(option_list_t *option, const char name[]) { option_t * opt; ASSERT(name!=NULL); - opt = option_find(name); + opt = option_find(option,name); if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",name); if (UseDebug) my_log("POLYGLOT OPTION GET \"%s\" -> \"%s\"\n",opt->name,opt->value); @@ -160,11 +220,11 @@ const char * option_get_default(const char name[]) { // option_get_bool() -bool option_get_bool(const char name[]) { +bool option_get_bool(option_list_t *option, const char name[]) { const char * value; - value = option_get(name); + value = option_get(option,name); if (FALSE) { } else if (my_string_case_equal(value,"true") || my_string_case_equal(value,"yes") || my_string_equal(value,"1")) { @@ -178,53 +238,92 @@ bool option_get_bool(const char name[]) { return FALSE; } + // option_get_double() -double option_get_double(const char name[]) { +double option_get_double(option_list_t *option, const char name[]) { const char * value; - value = option_get(name); + value = option_get(option,name); return atof(value); } // option_get_int() -int option_get_int(const char name[]) { +int option_get_int(option_list_t *option, const char name[]) { const char * value; - value = option_get(name); + value = option_get(option,name); return atoi(value); } // option_get_string() -const char * option_get_string(const char name[]) { +const char * option_get_string(option_list_t *option, const char name[]) { const char * value; - value = option_get(name); + value = option_get(option,name); return value; } // option_find() -static option_t * option_find(const char name[]) { +option_t * option_find(option_list_t *option, const char name[]) { option_t * opt; + int i; ASSERT(name!=NULL); + for (i=0; ioption_nb; i++){ + opt=option->options+i; + if (my_string_case_equal(opt->name,name)){ + return opt; + } + } + + return NULL; +} +void option_start_iter(option_list_t *option){ + option->iter=0; +} - for (opt = &Option[0]; opt->name != NULL; opt++) { - if (my_string_case_equal(opt->name,name)) return opt; - } +option_t * option_next(option_list_t *option){ + ASSERT(option->iter<=option->option_nb); + if(option->iter==option->option_nb){ + return NULL; + } + return &option->options[option->iter++]; + +} - return NULL; +void option_free(option_t *option){ + int i; + my_string_clear(&option->name); + my_string_clear(&option->type); + my_string_clear(&option->min); + my_string_clear(&option->max); + my_string_clear(&option->default_); + my_string_clear(&option->value); + for(i=0;ivar_nb;i++){ + my_string_clear(&option->var[i]); + } + option->var_nb=0; + option->mode=0; +} + +void option_clear(option_list_t *option){ + int i; + for (i = 0; i < option->option_nb; i++) { + option_free(option->options+i); + } + option->option_nb=0; } // end of option.cpp diff --git a/option.h b/option.h index 050ae0e..1d5eab0 100644 --- a/option.h +++ b/option.h @@ -10,10 +10,11 @@ // defines -#define VarNb 16 -#define XBOARD (1<<0) -#define UCI (1<<1) -#define PG (1<<2) +#define VarNb 16 +#define XBOARD (1<<0) +#define UCI (1<<1) +#define PG (1<<2) +#define OptionNb 256 // types @@ -29,23 +30,50 @@ typedef struct { // TODO: put back in more logical order int mode; } option_t; +// all non NULL data in an option_list_t should be malloc'ed +// use "my_string_set" to fill it. + +typedef struct { + option_t options[OptionNb]; + int option_nb; + int iter; +} option_list_t; + // variables -extern option_t Option[]; +extern option_list_t Option[1]; // functions -extern void option_init (); -extern bool option_set (const char var[], const char val[]); -extern bool option_set_default(const char var[], const char val[]); -extern const char * option_get (const char var[]); -extern const char * option_get_default(const char var[]); +extern void option_init (option_list_t *option); + +extern void option_init_pg (); + +extern bool option_set (option_list_t *option, + const char var[], + const char val[]); +extern bool option_set_default (option_list_t *option, + const char var[], + const char val[]); + +extern const char * option_get (option_list_t *option, const char var[]); +extern const char * option_get_default (option_list_t *option, const char var[]); + +extern bool option_get_bool (option_list_t *option, const char var[]); +extern double option_get_double (option_list_t *option, const char var[]); +extern int option_get_int (option_list_t *option, const char var[]); +extern const char * option_get_string (option_list_t *option, const char var[]); + +extern bool option_is_ok (const option_list_t *option); +extern option_t * option_find (option_list_t *option, const char var[]); +extern void option_clear (option_list_t *option); +extern void option_insert (option_list_t *option, option_t *new_option); + +extern void option_start_iter (option_list_t *option); +extern option_t * option_next (option_list_t *option); -extern bool option_get_bool (const char var[]); -extern double option_get_double (const char var[]); -extern int option_get_int (const char var[]); -extern const char * option_get_string (const char var[]); +extern void option_free (option_t *option); #endif // !defined OPTION_H diff --git a/pipex.h b/pipex.h index e96457f..e1a3618 100644 --- a/pipex.h +++ b/pipex.h @@ -36,6 +36,8 @@ typedef struct { volatile int nReadEnd; char lpBuffer[LINE_INPUT_MAX_CHAR]; char lpReadBuffer[LINE_INPUT_MAX_CHAR]; + char szWriteBuffer[LINE_INPUT_MAX_CHAR]; + DWORD dwWriteIndex; const char *name; } pipex_t; @@ -76,11 +78,13 @@ typedef struct { extern void pipex_open (pipex_t *pipex, const char *name, + const char *working_dir, const char *command); extern bool pipex_active (pipex_t *pipex); extern bool pipex_readln (pipex_t *pipex, char *string); extern bool pipex_readln_nb (pipex_t *pipex, char *string); extern void pipex_writeln (pipex_t *pipex, const char *string); +extern void pipex_write (pipex_t *pipex, const char *string); extern bool pipex_eof (pipex_t *pipex); extern void pipex_send_eof (pipex_t *pipex); extern void pipex_exit (pipex_t *pipex); diff --git a/pipex_posix.c b/pipex_posix.c index 5d2edfa..34b32cc 100644 --- a/pipex_posix.c +++ b/pipex_posix.c @@ -19,7 +19,10 @@ static void my_dup2(int old_fd, int new_fd) ; // pipex_open() -void pipex_open(pipex_t *pipex, const char *name, const char *command){ +void pipex_open(pipex_t *pipex, + const char *name, + const char *working_dir, + const char *command){ char string[StringSize]; int argc; char * ptr; @@ -93,8 +96,13 @@ void pipex_open(pipex_t *pipex, const char *name, const char *command){ /* my_dup2(STDOUT_FILENO,STDERR_FILENO); */ - // launch the new executable file + if(chdir(working_dir)){ + my_fatal("pipex_open(): cannot change directory: %s\n", + strerror(errno)); + } + // launch the new executable file + execvp(argv[0],&argv[0]); // execvp() only returns when an error has occured @@ -226,6 +234,13 @@ bool pipex_readln_nb(pipex_t *pipex, char *string){ } } +// pipex_write() + +void pipex_write(pipex_t *pipex, const char *string){ + io_send_queue(pipex->io,"%s",string); +} + + // pipex_writeln() void pipex_writeln(pipex_t *pipex, const char *string){ diff --git a/pipex_win32.c b/pipex_win32.c index 13adfeb..3f9ed90 100644 --- a/pipex_win32.c +++ b/pipex_win32.c @@ -59,13 +59,17 @@ static DWORD WINAPI ThreadProc(LPVOID lpParam){ // pipex_open() -void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) { +void pipex_open(pipex_t *pipex, + const char *szName, + const char *szWorkingDir, + const char *szProcFile) { DWORD dwMode, dwThreadId; HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite, hThread; SECURITY_ATTRIBUTES sa; STARTUPINFO si; PROCESS_INFORMATION pi; int fdInput; + char *szCurrentDir; pipex->state=0; pipex->name=szName; pipex->hProcess=NULL; @@ -88,6 +92,13 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) { si.hStdInput = hStdinRead; si.hStdOutput = hStdoutWrite; si.hStdError = hStdoutWrite; + if((szCurrentDir = _getcwd( NULL, 0 )) == NULL ) + my_fatal("pipex_open(): no current directory: %s\n", + strerror(errno)); + if(_chdir(szWorkingDir)){ + my_fatal("pipex_open(): cannot change directory: %s\n", + strerror(errno)); + } if(CreateProcess(NULL, (LPSTR) szProcFile, NULL, @@ -109,6 +120,7 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) { }else{ my_fatal("pipex_open(): %s",win32_error()); } + _chdir(szCurrentDir); } if (pipex->bConsole) { SetConsoleMode(pipex->hInput, @@ -144,9 +156,11 @@ void pipex_open(pipex_t *pipex, const char *szName, const char *szProcFile) { if(!hThread){ my_fatal("pipex_open(): %s",win32_error()); } + pipex->dwWriteIndex=0; pipex_set_active(pipex); } + // pipex_wait_event(pipex) void pipex_wait_event(pipex_t *pipex[]){ @@ -167,7 +181,6 @@ void pipex_wait_event(pipex_t *pipex[]){ ); } - // pipex_send_eof() void pipex_send_eof(pipex_t *pipex) { @@ -435,22 +448,50 @@ void pipex_set_affinity(pipex_t *pipex, int value){ } } +// pipex_write() + +void pipex_write(pipex_t *pipex, const char *szLineStr) { + int size,written; + size=sizeof(pipex->szWriteBuffer)-pipex->dwWriteIndex; + written=snprintf(pipex->szWriteBuffer + pipex->dwWriteIndex, + size, + "%s", + szLineStr); + // snprintf returns how many bytes should have been written + // (not including the trailing zero) + // old versions of glibc and msvcrt return -1 in + // case of truncated output. + if(written>=size || written<0){ + my_fatal("engine_send(): write_buffer overflow\n"); + } + pipex->dwWriteIndex+=written; + +} + + // pipex_writeln() void pipex_writeln(pipex_t *pipex, const char *szLineStr) { DWORD dwBytes; - int nStrLen; - char szWriteBuffer[LINE_INPUT_MAX_CHAR]; - my_log("Adapter->%s: %s\n",pipex->name,szLineStr); + DWORD dwLengthWriteBuffer; + my_log("Adapter->%s: %s\n",pipex->name,pipex->szWriteBuffer); + pipex_write(pipex, szLineStr); if(pipex->bPipe){ - nStrLen = strlen(szLineStr); - memcpy(szWriteBuffer, szLineStr, nStrLen); - szWriteBuffer[nStrLen] = '\r'; - szWriteBuffer[nStrLen + 1] = '\n'; - WriteFile(pipex->hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL); + dwLengthWriteBuffer = strlen(pipex->szWriteBuffer); + if(dwLengthWriteBuffer>=sizeof(pipex->szWriteBuffer)-3){ + my_fatal("pipex_writeln(): write buffer overflow\n"); + } + pipex->szWriteBuffer[dwLengthWriteBuffer] = '\r'; + pipex->szWriteBuffer[dwLengthWriteBuffer + 1] = '\n'; + // for easy debugging + pipex->szWriteBuffer[dwLengthWriteBuffer + 2] = '\0'; + WriteFile(pipex->hOutput, pipex->szWriteBuffer, + dwLengthWriteBuffer + 2, + &dwBytes, NULL); }else{ - printf("%s\n",szLineStr); + printf("%s\n",pipex->szWriteBuffer); fflush(stdout); } + pipex->dwWriteIndex = 0; } #endif diff --git a/polyglot.man b/polyglot.man index db0bd7e..c6f8e49 100644 --- a/polyglot.man +++ b/polyglot.man @@ -129,7 +129,7 @@ .\" ======================================================================== .\" .IX Title "POLYGLOT 6" -.TH POLYGLOT 6 "2009-08-06" "" "" +.TH POLYGLOT 6 "2009-08-07" "" "" .SH "NAME" PolyGlot \- Winboard protocol to UCI protocol adapter \- book engine for Polyglot books @@ -515,8 +515,7 @@ process is allowed to run on. This option works only on Windows. .IX Subsection "Work arounds" Work arounds are identical to options except that they should be used only when necessary. Their purpose is to try to hide problems with -various software (not just engines). The default value is always -correct for bug-free software. +various software (not just engines). .PP \&\s-1IMPORTANT:\s0 Any of these work arounds might be removed in future versions of PolyGlot. You are strongly recommended to contact the @@ -553,14 +552,13 @@ however do not send a new pv string just before sending the move. In that case the output of PolyGlot would be inconsistent. When RepeatPV is false PolyGlot does not repeat the last pv string. Due to the way kibitzing is implemented, KibitzMove is disabled in that case. -.IP "\fBWbWorkArounds\fR (default: false)" 4 -.IX Item "WbWorkArounds (default: false)" +.IP "\fBWbWorkArounds\fR (default: true)" 4 +.IX Item "WbWorkArounds (default: true)" The intention of this option is to provide work arounds for -xboard/winboard bugs should they arise. Currently it only prevents -\&\*(L"feature option=\*(R" commands which contain \*(L"Draw\*(R" in their name from -being sent to the \s-1GUI\s0. Some versions of xboard/winboard contain a bug -which causes such options to be interpreted as draw claims by the -engine. +xboard/winboard bugs should they arise. Currently it decapitalizes +the word Draw in options that contain this word. Some versions of +xboard/winboard contain a bug which causes such options to be +interpreted as draw claims by the engine. .Sp Engines that send options with \*(L"Draw\*(R" in their name are Rybka and \s-1HIARCS\s0. .Sh "[Engine] section" diff --git a/polyglot.pod b/polyglot.pod index 0465ce6..285e9b1 100644 --- a/polyglot.pod +++ b/polyglot.pod @@ -473,8 +473,7 @@ process is allowed to run on. This option works only on Windows. Work arounds are identical to options except that they should be used only when necessary. Their purpose is to try to hide problems with -various software (not just engines). The default value is always -correct for bug-free software. +various software (not just engines). IMPORTANT: Any of these work arounds might be removed in future versions of PolyGlot. You are strongly recommended to contact the @@ -519,14 +518,13 @@ In that case the output of PolyGlot would be inconsistent. When RepeatPV is false PolyGlot does not repeat the last pv string. Due to the way kibitzing is implemented, KibitzMove is disabled in that case. -=item B (default: false) +=item B (default: true) The intention of this option is to provide work arounds for -xboard/winboard bugs should they arise. Currently it only prevents -"feature option=" commands which contain "Draw" in their name from -being sent to the GUI. Some versions of xboard/winboard contain a bug -which causes such options to be interpreted as draw claims by the -engine. +xboard/winboard bugs should they arise. Currently it decapitalizes +the word Draw in options that contain this word. Some versions of +xboard/winboard contain a bug which causes such options to be +interpreted as draw claims by the engine. Engines that send options with "Draw" in their name are Rybka and HIARCS. diff --git a/polyglot.spec b/polyglot.spec index ea33c64..e3f1504 100644 --- a/polyglot.spec +++ b/polyglot.spec @@ -1,6 +1,6 @@ Summary: A Winboard protocol to UCI protocol adapter Name: polyglot -Version: 1.4.33b +Version: 1.4.34b Release: 1 License: GPL Group: Amusement/Games diff --git a/uci.c b/uci.c index 21c36e9..f8537e2 100644 --- a/uci.c +++ b/uci.c @@ -36,7 +36,7 @@ const char * thread_options[]={ "number of threads", // toga "number threads", // Deep Learning Toga "threads", // glaurung, zappa, cyclone, grapefruit, - // Deep Shredder, Deep Junior + // Deep Shredder, Deep Junior, bright "core threads", // HIARCS "max cpus", // rybka "cpus", // Deep Sjeng, Fruit2.3.5 @@ -61,33 +61,21 @@ static int mate_score (int dist); // uci_set_threads() void uci_set_threads(uci_t * uci, int n) { - const char **thread_options_copy = thread_options; - const char *thread_option; ASSERT(n>=1); - while((thread_option = *(thread_options_copy++))){ - uci_send_option(uci,thread_option,"%d",n); // checks also for existence + const char *thread_option=uci_thread_option(uci); + if(thread_option){ + uci_send_option(uci,thread_option,"%d",n); } } -// uci_thread_option_exists() - -bool uci_thread_option_exist(uci_t * uci) { - const char **thread_options_copy = thread_options; - const char *thread_option; - while((thread_option = *(thread_options_copy++))){ - if(uci_option_exist(uci,thread_option)) return TRUE; - } - return FALSE; -} const char * uci_thread_option(uci_t * uci){ - const char **thread_options_copy = thread_options; + const char **p = thread_options; const char *thread_option; - int i; - while((thread_option = *(thread_options_copy++))){ - i=uci_get_option(uci,thread_option); - if(i>=0){ - return Uci->option[i].name; + option_t *opt; + while((thread_option = *(p++))){ + if((opt=option_find(uci->option,thread_option))){ + return opt->name; break; } } @@ -100,8 +88,7 @@ static bool uci_is_ok(const uci_t * uci) { if (uci == NULL) return FALSE; if (uci->engine == NULL) return FALSE; - if (uci->option_nb < 0 || uci->option_nb >= OptionNb) return FALSE; - + if (!option_is_ok(uci->option)) return FALSE; return TRUE; } @@ -123,7 +110,7 @@ void uci_open(uci_t * uci, engine_t * engine) { my_string_set(&uci->name,""); uci->author = NULL; my_string_set(&uci->author,""); - uci->option_nb = 0; + option_init(uci->option); uci->ready_nb = 0; uci->searching = 0; @@ -146,22 +133,13 @@ void uci_open(uci_t * uci, engine_t * engine) { void uci_close(uci_t * uci) { - int i; - option_t * opt; - ASSERT(uci_is_ok(uci)); engine_close(uci->engine); uci->engine = NULL; my_string_clear(&uci->name); my_string_clear(&uci->author); - for (i = 0; i < uci->option_nb; i++) { - opt = &uci->option[i]; - my_string_clear(&opt->name); - my_string_clear(&opt->default_); - } - - uci->option_nb = 0; + option_clear(uci->option); } // uci_clear() @@ -267,39 +245,18 @@ void uci_send_ucinewgame(uci_t * uci) { ASSERT(uci!=NULL); - if (option_get_int("UCIVersion") >= 2) { + if (option_get_int(Option,"UCIVersion") >= 2) { engine_send(uci->engine,"ucinewgame"); } } -// uci_option_exist() - -bool uci_option_exist(uci_t * uci, const char option[]) { - - int i; - option_t * opt; - - ASSERT(uci_is_ok(uci)); - ASSERT(option!=NULL); - - // scan options - - for (i = 0; i < uci->option_nb; i++) { - opt = &uci->option[i]; - if (my_string_case_equal(opt->name,option)) return TRUE; - } - - return FALSE; -} - // uci_send_option() -void uci_send_option(uci_t * uci, const char option[], const char format[], ...) { +bool uci_send_option(uci_t * uci, const char option[], const char format[], ...) { - va_list arg_list; - char value[StringSize]; - int i; + char value[FormatBufferSize]; option_t * opt; + bool found=FALSE; ASSERT(uci_is_ok(uci)); ASSERT(option!=NULL); @@ -307,24 +264,27 @@ void uci_send_option(uci_t * uci, const char option[], const char format[], ...) // format - va_start(arg_list,format); - vsprintf(value,format,arg_list); - va_end(arg_list); + CONSTRUCT_ARG_STRING(format,value); if (UseDebug) my_log("POLYGLOT OPTION %s VALUE %s\n",option,value); - // scan options - - for (i = 0; i < uci->option_nb; i++) { - - opt = &uci->option[i]; - - if (my_string_case_equal(opt->name,option) && !my_string_equal(opt->default_,value)) { - engine_send(uci->engine,"setoption name %s value %s",opt->name,value); - my_string_set(&opt->default_,value); - break; - } + opt=option_find(uci->option,option); + if(opt){ + found=TRUE; + if(!my_string_case_equal(opt->type,"button")){ + if(!my_string_equal(opt->value,value)){ + engine_send(uci->engine,"setoption name %s value %s", + opt->name,value); + my_string_set(&opt->value,value); + }else{ + my_log("POLYGLOT Not sending option \"%s\" since it " + "already has the correct value.\n",opt->name); + } + }else{ + engine_send(uci->engine,"setoption name %s",opt->name); + } } + return found; } // uci_parse() @@ -387,9 +347,9 @@ int uci_parse(uci_t * uci, const char string[]) { // search information - if (uci->searching && uci->pending_nb == 1) { // current search - event = parse_info(uci,argument); - } + if (uci->searching && uci->pending_nb == 1) { // current search + event = parse_info(uci,argument); + } } else if (my_string_equal(command,"option")) { @@ -444,12 +404,19 @@ static int parse_bestmove(uci_t * uci, const char string[]) { // bestmove if (!parse_get_string(parse,argument,StringSize)) { - my_fatal("parse_bestmove(): missing argument\n"); + return EVENT_ILLEGAL_MOVE; +// my_fatal("parse_bestmove(): missing argument\n"); } uci->best_move = move_from_can(argument,uci->board); - if (uci->best_move == MoveNone) my_fatal("parse_bestmove(): not a move \"%s\"\n",argument); + if (uci->best_move == MoveNone) { + return EVENT_ILLEGAL_MOVE; +// my_fatal("parse_bestmove(): not a move \"%s\"\n",argument); + } + if(!move_is_legal(uci->best_move,uci->board)){ + return EVENT_ILLEGAL_MOVE; + } ASSERT(uci->best_move!=MoveNone); ASSERT(move_is_legal(uci->best_move,uci->board)); @@ -544,6 +511,8 @@ static int parse_info(uci_t * uci, const char string[]) { int multipvline=0; sint64 ln; + + ASSERT(uci_is_ok(uci)); ASSERT(string!=NULL); @@ -691,12 +660,15 @@ static int parse_info(uci_t * uci, const char string[]) { if (n >= 0) uci->sel_depth = n; - } else if (my_string_equal(option,"string")) { - if(!strncmp(argument,"DrawOffer",9)) + } else if (my_string_equal(option,"string")) { + if(my_string_case_equal(argument,"DrawOffer")){ event |= EVENT_DRAW; - if(!strncmp(argument,"Resign",6)) + }else if(my_string_case_equal(argument,"Resign")){ event |= EVENT_RESIGN; - + }else{ + strcpy(uci->info,argument); + event|=EVENT_INFO; + } // TODO: argument to EOS ASSERT(!my_string_empty(argument)); @@ -720,6 +692,12 @@ static int parse_info(uci_t * uci, const char string[]) { } else { my_log("POLYGLOT unknown option \"%s\" for command \"%s\"\n",option,command); + // this is for buggy engines; it should probably be protected + // by a "WorkAround" option. + strcpy(uci->info,option); + strcat(uci->info," "); + strcat(uci->info,argument); + event|=EVENT_INFO; } } @@ -738,55 +716,11 @@ static int parse_info(uci_t * uci, const char string[]) { return event; } -int uci_get_option(uci_t * uci, const char * name){ - int i; - for(i=0;ioption_nb;i++){ - if(my_string_case_equal(Uci->option[i].name,name)){ - return i; - } - } - return -1; -} - - - -// uci_set_option() - -void uci_set_option(uci_t * uci, - const char * name, - const char * default_, - const char * type, - const char * max, - const char * min, - int var_nb, - const char * var[]){ - int i,j; - for(i=0;ioption_nb;i++){ - if(my_string_equal(Uci->option[i].name,name)){ - break; - } - } - if(ioption[i].name),name); - my_string_set(&(Uci->option[i].default_),default_); - my_string_set(&(Uci->option[i].type),type); - my_string_set(&(Uci->option[i].min),min); - my_string_set(&(Uci->option[i].max),max); - Uci->option[i].var_nb=var_nb; - for(j=0;joption[i].var[j]),var[j]); - } - if(i==Uci->option_nb){ - Uci->option_nb++; - } - } -} - // parse_option() static void parse_option(uci_t * uci, const char string[]) { - option_t * opt; + option_t opt[1]; parse_t parse[1]; char command[StringSize]; char option[StringSize]; @@ -799,32 +733,16 @@ static void parse_option(uci_t * uci, const char string[]) { strcpy(command,"option"); - if (uci->option_nb >= OptionNb) return; - - opt = &uci->option[uci->option_nb]; - uci->option_nb++; - - opt->value=NULL; + memset(opt,0,sizeof(option_t)); + my_string_set(&opt->value,""); - opt->mode=0; - - opt->name = NULL; my_string_set(&opt->name,""); - - - opt->default_ = NULL; my_string_set(&opt->default_,""); - - opt->max = NULL; my_string_set(&opt->max,""); - - opt->min = NULL; my_string_set(&opt->min,""); - - opt->type = NULL; my_string_set(&opt->type,""); - opt->var_nb=0; + opt->mode=0; parse_open(parse,string); parse_add_keyword(parse,"default"); @@ -887,6 +805,8 @@ static void parse_option(uci_t * uci, const char string[]) { } parse_close(parse); + option_insert(uci->option,opt); + option_free(opt); if (UseDebug) my_log("POLYGLOT option name \"%s\" default \"%s\"\n",opt->name,opt->default_); } @@ -966,9 +886,9 @@ static int mate_score(int dist) { if (FALSE) { } else if (dist > 0) { - return +option_get_int("MateScore") - (+dist) * 2 + 1; + return +option_get_int(Option,"MateScore") - (+dist) * 2 + 1; } else if (dist < 0) { - return -option_get_int("MateScore") + (-dist) * 2; + return -option_get_int(Option,"MateScore") + (-dist) * 2; } return 0; diff --git a/uci.h b/uci.h index 0ac4f30..0a471fd 100644 --- a/uci.h +++ b/uci.h @@ -13,9 +13,11 @@ #include "option.h" #include "util.h" -// defines +// macros -#define OptionNb 256 +// I need to make a uniform string type. + +#define UciStringSize 4096 // types @@ -26,8 +28,7 @@ typedef struct { const char * name; const char * author; - int option_nb; - option_t option[OptionNb]; + option_list_t option[1]; bool ready; int ready_nb; @@ -61,18 +62,21 @@ typedef struct { int root_move_pos; int root_move_nb; bool multipv_mode; + char info[UciStringSize]; } uci_t; typedef enum { - EVENT_NONE = 0, - EVENT_UCI = 1 << 0, - EVENT_READY = 1 << 1, - EVENT_STOP = 1 << 2, - EVENT_MOVE = 1 << 3, - EVENT_PV = 1 << 4, - EVENT_DEPTH = 1 << 5, - EVENT_DRAW = 1 << 6, - EVENT_RESIGN= 1 << 7 + EVENT_NONE = 0, + EVENT_UCI = 1 << 0, + EVENT_READY = 1 << 1, + EVENT_STOP = 1 << 2, + EVENT_MOVE = 1 << 3, + EVENT_PV = 1 << 4, + EVENT_DEPTH = 1 << 5, + EVENT_DRAW = 1 << 6, + EVENT_RESIGN = 1 << 7, + EVENT_ILLEGAL_MOVE = 1 << 8, + EVENT_INFO = 1 << 9 } dummy_event_t; // variables @@ -88,27 +92,11 @@ extern void uci_send_stop (uci_t * uci); extern void uci_send_stop_sync (uci_t * uci); extern void uci_send_ucinewgame (uci_t * uci); extern void uci_set_threads (uci_t * uci, int n); -extern bool uci_thread_option_exist(uci_t * uci); extern const char * uci_thread_option(uci_t * uci); -extern int uci_get_option (uci_t * uci, const char * name); - -extern bool uci_option_exist (uci_t * uci, const char option[]); -extern void uci_send_option (uci_t * uci, const char option[], const char format[], ...); - -extern void uci_close (uci_t * uci); - -extern void uci_clear (uci_t * uci); - -extern int uci_parse (uci_t * uci, const char string[]); - -void uci_set_option(uci_t * uci, - const char * name, - const char * default_, - const char * type, - const char * max, - const char * min, - int var_nb, - const char * var[]); +extern bool uci_send_option (uci_t * uci, const char option[], const char format[], ...); +extern void uci_close (uci_t * uci); +extern void uci_clear (uci_t * uci); +extern int uci_parse (uci_t * uci, const char string[]); #endif // !defined UCI_H diff --git a/uci2uci.c b/uci2uci.c index 611697a..1c13d0f 100644 --- a/uci2uci.c +++ b/uci2uci.c @@ -121,6 +121,7 @@ static void format_uci_option_line(char * option_line,option_t *opt){ char option_string[StringSize]; int j; strcpy(option_line,""); + // buffer overflow alert strcat(option_line,"option name"); if(opt->mode&PG){ strcat(option_line," Polyglot"); @@ -150,21 +151,22 @@ static void format_uci_option_line(char * option_line,option_t *opt){ // send_uci_options() static void send_uci_options() { - int i; - option_t *p=Option; + + option_t * opt; char option_line[StringSize]=""; gui_send(GUI,"id name %s", Uci->name); gui_send(GUI,"id author %s", Uci->author); - for(i=0;ioption_nb;i++){ - format_uci_option_line(option_line,Uci->option+i); - gui_send(GUI,"%s",option_line); + option_start_iter(Uci->option); + while((opt=option_next(Uci->option))){ + format_uci_option_line(option_line,opt); + gui_send(GUI,"%s",option_line); } - while(p->name){ - if(p->mode &UCI){ - format_uci_option_line(option_line,p); + option_start_iter(Option); + while((opt=option_next(Option))){ + if(opt->mode &UCI){ + format_uci_option_line(option_line,opt); gui_send(GUI,"%s",option_line); } - p++; } gui_send(GUI,"uciok"); } @@ -216,7 +218,7 @@ void uci2uci_gui_step(char string[]) { } SavedMove=MoveNone; if(!strstr(string,"infinite")){ - move=book_move(UCIboard,option_get_bool("BookRandom")); + move=book_move(UCIboard,option_get_bool(Option,"BookRandom")); if (move != MoveNone && move_is_legal(move,UCIboard)) { if(strstr(string,"ponder")){ SavedMove=move; diff --git a/util.c b/util.c index 8551aca..0d75adf 100644 --- a/util.c +++ b/util.c @@ -29,7 +29,6 @@ static bool Error; FILE * LogFile=NULL; - // functions // util_init() @@ -158,45 +157,47 @@ void my_log_close() { // my_log() void my_log(const char format[], ...) { + + char string[FormatBufferSize]; + + ASSERT(format!=NULL); - va_list ap; - - ASSERT(format!=NULL); +// format - if (LogFile != NULL) { - fprintf(LogFile,"%.3f ",now_real()); - va_start(ap,format); + CONSTRUCT_ARG_STRING(format,string); + - vfprintf(LogFile,format,ap); - va_end(ap); + if (LogFile != NULL) { + fprintf(LogFile,"%.3f %s",now_real(),string); #ifdef _WIN32 - fflush(LogFile); + fflush(LogFile); #endif - } + } } // my_fatal() void my_fatal(const char format[], ...) { - va_list ap; + char string[FormatBufferSize]; - ASSERT(format!=NULL); + ASSERT(format!=NULL); - va_start(ap,format); +// format - vfprintf(stderr,format,ap); - if (LogFile != NULL) vfprintf(LogFile,format,ap); + CONSTRUCT_ARG_STRING(format,string); + + fprintf(stderr,format,string); + if (LogFile != NULL) fprintf(LogFile,format,&string); - va_end(ap); - if (Error) { // recursive error - my_log("POLYGLOT *** RECURSIVE ERROR ***\n"); - exit(EXIT_FAILURE); - // abort(); - } else { - Error = TRUE; - quit(); - } + if (Error) { // recursive error + my_log("POLYGLOT *** RECURSIVE ERROR ***\n"); + exit(EXIT_FAILURE); + // abort(); + } else { + Error = TRUE; + quit(); + } } // my_file_read_line() @@ -394,19 +395,4 @@ double my_timer_elapsed_real(const my_timer_t * timer) { } -char * my_getcwd(char *buf, size_t size){ -#ifdef _WIN32 - return _getcwd(buf,size); -#else - return getcwd(buf,size); -#endif -} -int my_chdir (const char *path){ - ASSERT(path!=NULL); -#ifdef _WIN32 - return _chdir(path); -#else - return chdir(path); -#endif -} diff --git a/util.h b/util.h index cf197fe..2b0886c 100644 --- a/util.h +++ b/util.h @@ -65,6 +65,25 @@ #define snprintf _snprintf #endif +#define FormatBufferSize 4096 + +#define CONSTRUCT_ARG_STRING(format,buf) \ + { \ + va_list arg_list; \ + int written; \ + va_start(arg_list,format); \ + written=vsnprintf(buf, \ + sizeof(buf), \ + format, \ + arg_list); \ + va_end(arg_list); \ + buf[sizeof(buf)]='\0'; \ + if(written>=sizeof(buf) || written<0){ \ + my_fatal("write_buffer overflow: file \"%s\", line %d\n", \ + __FILE__,__LINE__); \ + } \ + } \ + // types typedef signed char sint8; @@ -92,6 +111,7 @@ typedef struct { bool running; } my_timer_t; + // functions extern void util_init (); @@ -135,9 +155,6 @@ extern double my_timer_elapsed_real (const my_timer_t * timer); extern char * my_error(); -extern char * my_getcwd (char *buf, size_t size); -extern int my_chdir (const char *path); - #endif // !defined UTIL_H // end of util.h diff --git a/xboard2uci.c b/xboard2uci.c index d255d6f..97c7b73 100644 --- a/xboard2uci.c +++ b/xboard2uci.c @@ -108,6 +108,7 @@ static void stop_search (); static void send_board (int extra_move); static void send_pv (); +static void send_info (); static void send_xboard_options (); @@ -135,10 +136,10 @@ void xboard2uci_init() { my_timer_reset(State->timer); // yes there are engines that do not have the "Hash" option.... - XB->has_feature_memory= uci_option_exist(Uci,"Hash"); - XB->has_feature_smp = uci_thread_option_exist(Uci); + XB->has_feature_memory= (option_find(Uci->option,"Hash")!=NULL); + XB->has_feature_smp = (uci_thread_option(Uci)!=NULL); // TODO: support for other types of table bases - XB->has_feature_egt = uci_option_exist(Uci,"NalimovPath"); + XB->has_feature_egt = (option_find(Uci->option,"NalimovPath")!=NULL); XB->analyse = FALSE; XB->computer = FALSE; XB->name = NULL; @@ -193,7 +194,7 @@ void xboard2uci_gui_step(char string[]) { } else if (match(string,"bk")) { - if (option_get_bool("Book")) { + if (option_get_bool(Option,"Book")) { game_get_board(Game,board); book_disp(board); } @@ -216,7 +217,7 @@ void xboard2uci_gui_step(char string[]) { XB->computer = TRUE; } else if (match(string,"draw")) { - if(uci_option_exist(Uci,"UCI_DrawOffers")){ + if(option_find(Uci->option,"UCI_DrawOffers")){ my_log("POLYGLOT draw from XB received"); uci_send_option(Uci,"DrawOffer","%s","draw");} } else if (match(string,"easy")) { @@ -266,7 +267,7 @@ void xboard2uci_gui_step(char string[]) { } else if (match(string,"hint")) { - if (option_get_bool("Book")) { + if (option_get_bool(Option,"Book")) { game_get_board(Game,board); move = book_move(board,FALSE); @@ -302,7 +303,7 @@ void xboard2uci_gui_step(char string[]) { uci_send_isready(Uci); my_log("POLYGLOT NEW GAME\n"); - option_set("Chess960","false"); + option_set(Option,"Chess960","false"); game_clear(Game); @@ -371,7 +372,8 @@ void xboard2uci_gui_step(char string[]) { XB->post = TRUE; } else if (match(string,"protover *")) { - + XB->proto_ver = atoi(Star[0]); + ASSERT(XB->proto_ver>=2); send_xboard_options(); } else if (match(string,"quit")) { @@ -423,7 +425,8 @@ void xboard2uci_gui_step(char string[]) { // book learning - if (option_get_bool("Book") && option_get_bool("BookLearn")) { + if (option_get_bool(Option,"Book") && + option_get_bool(Option,"BookLearn")) { if (FALSE) { } else if (my_string_equal(Star[0],"1-0")) { @@ -440,7 +443,11 @@ void xboard2uci_gui_step(char string[]) { gui_send(GUI,"Error (unknown command): %s",string); - } else if (match(string,"option *=*")){ + } else if (match(string,"option *=*") || + match(string,"option * =*") || + match(string,"option *= *") || + match(string,"option * = *") + ){ char *name=Star[0]; char *value=Star[1]; if(match(name, "Polyglot *")){ @@ -448,13 +455,18 @@ void xboard2uci_gui_step(char string[]) { polyglot_set_option(pg_name,value); }else{ start_protected_command(); - engine_send(Engine,"setoption name %s value %s",name,value); + if(!uci_send_option(Uci, name, "%s", value)){ + gui_send(GUI,"Error (unknown option): %s",name); + } end_protected_command(); } } else if (match(string,"option *")){ char *name=Star[0]; start_protected_command(); - engine_send(Engine,"setoption name %s",name); + // value is ignored + if(!uci_send_option(Uci, name, "%s", "")){ + gui_send(GUI,"Error (unknown option): %s",name); + }; end_protected_command(); } else if (XB->has_feature_smp && match(string,"cores *")){ int cores=atoi(Star[0]); @@ -490,9 +502,10 @@ void xboard2uci_gui_step(char string[]) { int real_memory; if(memory>=1){ // updating the available memory + option_t *opt; my_log("POLYGLOT setting the amount of memory to %dMb\n",memory); - if(uci_get_option(Uci,"NalimovCache")>=0){ - nalimov_cache=atoi(Uci->option[uci_get_option(Uci,"NalimovCache")].value); + if((opt=option_find(Uci->option,"NalimovCache"))){ + nalimov_cache=atoi(opt->value); }else{ nalimov_cache=0; } @@ -574,9 +587,9 @@ void xboard2uci_gui_step(char string[]) { } else if (match(string,"variant *")) { if (my_string_equal(Star[0],"fischerandom")) { - option_set("Chess960","true"); + option_set(Option,"Chess960","true"); } else { - option_set("Chess960","false"); + option_set(Option,"Chess960","false"); } } else if (match(string,"white")) { @@ -658,6 +671,7 @@ void xboard2uci_gui_step(char string[]) { void xboard2uci_engine_step(char string[]) { int event; + board_t board[1]; event = uci_parse(Uci,string); // react to events @@ -702,15 +716,33 @@ void xboard2uci_engine_step(char string[]) { send_pv(); } + if ((event & EVENT_INFO) != 0) { + + // the engine has sent info + + send_info(); + } if((event & (EVENT_DRAW|EVENT_RESIGN))!=0){ my_log("POYGLOT draw offer/resign from engine\n"); - if(uci_option_exist(Uci,"UCI_DrawOffers")){ + if(option_find(Uci->option,"UCI_DrawOffers")){ if(event & EVENT_DRAW) gui_send(GUI,"offer draw"); else gui_send(GUI,"resign"); } } + if(((event & EVENT_ILLEGAL_MOVE)!=0) && (State->state == THINK)){ + game_get_board(Game,board); + if(board->turn==White){ + gui_send(GUI,"0-1 {polyglot: resign" + " (illegal engine move white)}"); + }else{ + gui_send(GUI,"1-0 {polyglot: resign" + " (illegal engine move black)}"); + } + XB->result = TRUE; + mess(); + } } // format_xboard_option_line @@ -718,7 +750,9 @@ void xboard2uci_engine_step(char string[]) { void format_xboard_option_line(char * option_line, option_t *opt){ int j; char option_string[StringSize]; + char *tmp; strcpy(option_line,""); + // buffer overflow alert strcat(option_line,"feature option=\""); if(opt->mode&PG){ strcat(option_line,"Polyglot "); @@ -756,17 +790,21 @@ void format_xboard_option_line(char * option_line, option_t *opt){ } } strcat(option_line,"\""); + if(option_get_bool(Option,"WbWorkArounds") && + (tmp=strstr(option_line,"Draw"))){ + *tmp='d'; + my_log("POLYGLOT Decapitalizing \"Draw\" in option \"%s\"\n", + opt->name); + } } -// send_xboard_options +// send_xboard_options() static void send_xboard_options(){ - int i; + char option_line[StringSize]=""; - option_t *p=Option; const char * name; - XB->proto_ver = atoi(Star[0]); - ASSERT(XB->proto_ver>=2); + option_t *opt; gui_send(GUI,"feature done=0"); @@ -774,7 +812,8 @@ static void send_xboard_options(){ gui_send(GUI,"feature colors=0"); gui_send(GUI,"feature draw=1"); gui_send(GUI,"feature ics=1"); - gui_send(GUI,"feature myname=\"%s\"",option_get_string("EngineName")); + gui_send(GUI,"feature myname=\"%s\"", + option_get_string(Option,"EngineName")); gui_send(GUI,"feature name=1"); gui_send(GUI,"feature pause=0"); gui_send(GUI,"feature ping=1"); @@ -803,34 +842,33 @@ static void send_xboard_options(){ gui_send(GUI,"feature egt=\"\""); } - if (uci_option_exist(Uci,"UCI_Chess960")) { + if (option_find(Uci->option,"UCI_Chess960")) { gui_send(GUI,"feature variants=\"normal,fischerandom\""); } else { gui_send(GUI,"feature variants=\"normal\""); } - - for(i=0;ioption_nb;i++){ - if(my_string_case_equal(Uci->option[i].name,"UCI_AnalyseMode")) continue; - if(my_string_case_equal(Uci->option[i].name,"Ponder")) continue; - if(my_string_case_equal(Uci->option[i].name,"Hash")) continue; - if(my_string_case_equal(Uci->option[i].name,"NalimovPath")) continue; - if((name=uci_thread_option(Uci))!=NULL && my_string_case_equal(Uci->option[i].name,name)) continue; - if(option_get_bool("WbWorkArounds") && - strstr(Uci->option[i].name,"Draw")){ - my_log("POLYGLOT Dropping option \"%s\" because it contains \"Draw\"\n",Uci->option[i].name); - continue; - } - format_xboard_option_line(option_line,Uci->option+i); + option_start_iter(Uci->option); + while((opt=option_next(Uci->option))){ + if(my_string_case_equal(opt->name,"UCI_AnalyseMode")) continue; + if(my_string_case_equal(opt->name,"Ponder")) continue; + if(my_string_case_equal(opt->name,"Hash")) continue; + if(my_string_case_equal(opt->name,"NalimovPath")) continue; + if((name=uci_thread_option(Uci))!=NULL && + my_string_case_equal(opt->name,name)) continue; + + format_xboard_option_line(option_line,opt); + gui_send(GUI,"%s",option_line); - } - while(p->name){ - if(p->mode &XBOARD){ - format_xboard_option_line(option_line,p); + + + option_start_iter(Option); + while((opt=option_next(Option))){ + if(opt->mode &XBOARD){ + format_xboard_option_line(option_line,opt); gui_send(GUI,"%s",option_line); } - p++; } gui_send(GUI,"feature done=1"); @@ -839,7 +877,8 @@ static void send_xboard_options(){ // report_best_score() static int report_best_score(){ - if(!option_get_bool("ScoreWhite") || colour_is_white(Uci->board->turn)){ + if(!option_get_bool(Option,"ScoreWhite") || + colour_is_white(Uci->board->turn)){ return Uci->best_score; }else{ return -Uci->best_score; @@ -858,14 +897,14 @@ static void comp_move(int move) { ASSERT(State->state==THINK); ASSERT(!XB->analyse); - if(option_get_bool("RepeatPV")) + if(option_get_bool(Option,"RepeatPV")) send_pv(); // to update time and nodes // send the move game_get_board(Game,board); - if (move_is_castle(move,board) && option_get_bool("Chess960")) { + if (move_is_castle(move,board) && option_get_bool(Option,"Chess960")) { if (!move_to_san(move,board,string,256)) my_fatal("comp_move(): move_to_san() failed\n"); // O-O/O-O-O } else { if (!move_to_can(move,board,string,256)) my_fatal("comp_move(): move_to_can() failed\n"); @@ -875,14 +914,14 @@ static void comp_move(int move) { // resign? - if (option_get_bool("Resign") && Uci->root_move_nb > 1) { + if (option_get_bool(Option,"Resign") && Uci->root_move_nb > 1) { - if (Uci->best_score <= -abs(option_get_int("ResignScore"))) { + if (Uci->best_score <= -abs(option_get_int(Option,"ResignScore"))) { State->resign_nb++; my_log("POLYGLOT %d move%s with resign score\n",State->resign_nb,(State->resign_nb>1)?"s":""); - if (State->resign_nb >= option_get_int("ResignMoves")) { + if (State->resign_nb >= option_get_int(Option,"ResignMoves")) { my_log("POLYGLOT *** RESIGN ***\n"); gui_send(GUI,"resign"); } @@ -1153,11 +1192,11 @@ static void search_update() { // opening book - if (State->state == THINK && option_get_bool("Book")) { + if (State->state == THINK && option_get_bool(Option,"Book")) { game_get_board(Game,Uci->board); - move = book_move(Uci->board,option_get_bool("BookRandom")); + move = book_move(Uci->board,option_get_bool(Option,"BookRandom")); if (move != MoveNone && move_is_legal(move,Uci->board)) { @@ -1186,9 +1225,10 @@ static void search_update() { // options - uci_send_option(Uci,"UCI_Chess960","%s",option_get_bool("Chess960")?"true":"false"); + uci_send_option(Uci,"UCI_Chess960","%s", + option_get_bool(Option,"Chess960")?"true":"false"); - if (option_get_int("UCIVersion") >= 2) { + if (option_get_int(Option,"UCIVersion") >= 2) { uci_send_option(Uci,"UCI_Opponent","none none %s %s",(XB->computer)?"computer":"human",XB->name); uci_send_option(Uci,"UCI_AnalyseMode","%s",(XB->analyse)?"true":"false"); } @@ -1291,7 +1331,8 @@ static bool active() { static bool ponder() { - return XB->ponder && (option_get_bool("CanPonder") || uci_option_exist(Uci,"Ponder")); + return XB->ponder && (option_get_bool(Option,"CanPonder") || + option_find(Uci->option,"Ponder")); } // ponder_ok() @@ -1319,7 +1360,7 @@ static bool ponder_ok(int move) { if (status != PLAYING) return FALSE; // game ended - if (option_get_bool("Book") && is_in_book(board)) { + if (option_get_bool(Option,"Book") && is_in_book(board)) { return FALSE; } @@ -1342,7 +1383,7 @@ static void stop_search() { Uci->searching = FALSE; */ - if (option_get_bool("SyncStop")) { + if (option_get_bool(Option,"SyncStop")) { uci_send_stop_sync(Uci); } else { uci_send_stop(Uci); @@ -1418,6 +1459,15 @@ static void send_board(int extra_move) { engine_send(Engine,""); // newline } +// send_info() + +static void send_info() { + if (XB->post) { + gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth>0?Uci->best_depth:1, + 0,0,0.0,0,Uci->info); + } +} + // send_pv() static void send_pv() { @@ -1444,7 +1494,8 @@ static void send_pv() { gui_send(GUI,"%d %+d %.0f "S64_FORMAT" %s",Uci->best_depth,report_best_score(),Uci->time*100.0,Uci->node_nb,pv_string); - } else if (State->state == PONDER && option_get_bool("ShowPonder")) { + } else if (State->state == PONDER && + option_get_bool(Option,"ShowPonder")) { game_get_board(Game,board); move = State->exp_move; @@ -1459,14 +1510,16 @@ static void send_pv() { // kibitz - if ((Uci->searching && option_get_bool("KibitzPV") && Uci->time >= option_get_double("KibitzDelay")) - || (!Uci->searching && option_get_bool("KibitzMove"))) { + if ((Uci->searching && + option_get_bool(Option,"KibitzPV") && + Uci->time >= option_get_double(Option,"KibitzDelay")) + || (!Uci->searching && option_get_bool(Option,"KibitzMove"))) { if (State->state == THINK || State->state == ANALYSE) { line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize); if(kibitz_throttle(Uci->searching)){ - 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); + gui_send(GUI,"%s depth=%d time=%.2f node="S64_FORMAT" speed=%.0f score=%+.2f pv=\"%s\"",option_get_string(Option,"KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,((double)report_best_score())/100.0,pv_string); } } else if (State->state == PONDER) { @@ -1477,7 +1530,7 @@ static void send_pv() { move_to_san(move,board,move_string,256); line_to_san(Uci->best_pv,Uci->board,pv_string,StringSize); if(kibitz_throttle(Uci->searching)){ - 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); + gui_send(GUI,"%s depth=%d time=%.2f node="S64_FORMAT" speed=%.0f score=%+.2f pv=\"(%s) %s\"",option_get_string(Option,"KibitzCommand"),Uci->best_depth,Uci->time,Uci->node_nb,Uci->speed,((double)report_best_score())/100.0,move_string,pv_string); } } } @@ -1492,12 +1545,14 @@ static bool kibitz_throttle(bool searching){ static time_t lastKibitzPV=0; curr_time = time(NULL); if(searching){ // KibitzPV - if(curr_time >= (option_get_int("KibitzInterval") + lastKibitzPV)){ + if(curr_time >= + (option_get_int(Option,"KibitzInterval") + lastKibitzPV)){ lastKibitzPV=curr_time; return TRUE; } }else{ // KibitzMove - if(curr_time >= (option_get_int("KibitzInterval") + lastKibitzMove)){ + if(curr_time >= + (option_get_int(Option,"KibitzInterval") + lastKibitzMove)){ lastKibitzPV=curr_time; lastKibitzMove=curr_time; return TRUE; @@ -1555,4 +1610,4 @@ static void learn(int result) { book_flush(); } -// end of adapter.cpp +// end of xboard2uci.c -- 1.7.0.4