version 1.4w10UCIb17
authorH.G. Muller <h.g.muller@hccnet.nl>
Thu, 9 Jun 2011 07:44:50 +0000 (09:44 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Thu, 9 Jun 2011 07:45:50 +0000 (09:45 +0200)
26 files changed:
ChangeLog
Makefile.am
Makefile.in
README
config.h
configure
configure.ac
engine.cpp
engine.h
epd.cpp
gui.cpp
io.cpp
main.cpp
mainloop.cpp [new file with mode: 0644]
mainloop.h [new file with mode: 0644]
pipe.cpp
pipe.h
polyglot.man
polyglot.pod
polyglot.spec
search.cpp
uci.cpp
uci2uci.cpp
uci2uci.h
xboard2uci.cpp [new file with mode: 0644]
xboard2uci.h [new file with mode: 0644]

index 83ac8ec..ab9261c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+=========1.4w10UCIb17===========\r
+- More refactoring. main.cpp is now #ifdef _WIN32 free.\r
+- The main loop (previously in adapter.cpp) is now in its own file mainloop.cpp.\r
+- adapter.cpp has been renamed into xboard2uci.cpp. It is #ifdef _WIN32 free.\r
+- EOF from the engine no longer kills PG. It should now\r
+be possible to close an engine and reopen another one (if that ever were useful) \r
 =========1.4w10UCIb16===========\r
 - xboard options commands\r
 - correction of handling of combo boxes in UCI protocol\r
index 49e424b..85c63ce 100644 (file)
@@ -2,7 +2,7 @@
 #AM_CXXFLAGS=-g
 
 bin_PROGRAMS = polyglot
-polyglot_SOURCES = adapter.cpp attack.cpp board.cpp book.cpp book_make.cpp book_merge.cpp colour.cpp  engine.cpp epd.cpp fen.cpp gui.cpp game.cpp hash.cpp io.cpp line.cpp list.cpp main.cpp move.cpp move_do.cpp move_gen.cpp move_legal.cpp option.cpp parse.cpp pgn.cpp piece.cpp pipe.cpp posix.cpp random.cpp san.cpp search.cpp square.cpp uci.cpp uci2uci.cpp util.cpp adapter.h colour.h hash.h move_gen.h piece.h uci2uci.h attack.h config.h gui.h io.h move.h pipe.h posix.h uci.h board.h engine.h line.h move_legal.h random.h util.h book.h epd.h list.h option.h san.h book_make.h fen.h main.h parse.h search.h book_merge.h game.h move_do.h pgn.h square.h
+polyglot_SOURCES = mainloop.cpp attack.cpp board.cpp book.cpp book_make.cpp book_merge.cpp colour.cpp  engine.cpp epd.cpp fen.cpp gui.cpp game.cpp hash.cpp io.cpp line.cpp list.cpp main.cpp move.cpp move_do.cpp move_gen.cpp move_legal.cpp option.cpp parse.cpp pgn.cpp piece.cpp pipe.cpp posix.cpp random.cpp san.cpp search.cpp square.cpp uci.cpp uci2uci.cpp util.cpp xboard2uci.cpp mainloop.h colour.h hash.h move_gen.h piece.h uci2uci.h attack.h config.h gui.h io.h move.h pipe.h posix.h uci.h board.h engine.h line.h move_legal.h random.h util.h book.h epd.h list.h option.h san.h book_make.h fen.h main.h parse.h search.h book_merge.h game.h move_do.h pgn.h square.h xboard2uci.h
 
 dist_doc_DATA = README README1.3 README1.4 README1.4w README1.4w10UCI book_format.html
 
index 3dc2037..702e4d5 100644 (file)
@@ -54,7 +54,7 @@ am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man6dir)" \
        "$(DESTDIR)$(docdir)"
 binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
 PROGRAMS = $(bin_PROGRAMS)
-am_polyglot_OBJECTS = adapter.$(OBJEXT) attack.$(OBJEXT) \
+am_polyglot_OBJECTS = mainloop.$(OBJEXT) attack.$(OBJEXT) \
        board.$(OBJEXT) book.$(OBJEXT) book_make.$(OBJEXT) \
        book_merge.$(OBJEXT) colour.$(OBJEXT) engine.$(OBJEXT) \
        epd.$(OBJEXT) fen.$(OBJEXT) gui.$(OBJEXT) game.$(OBJEXT) \
@@ -64,7 +64,7 @@ am_polyglot_OBJECTS = adapter.$(OBJEXT) attack.$(OBJEXT) \
        parse.$(OBJEXT) pgn.$(OBJEXT) piece.$(OBJEXT) pipe.$(OBJEXT) \
        posix.$(OBJEXT) random.$(OBJEXT) san.$(OBJEXT) \
        search.$(OBJEXT) square.$(OBJEXT) uci.$(OBJEXT) \
-       uci2uci.$(OBJEXT) util.$(OBJEXT)
+       uci2uci.$(OBJEXT) util.$(OBJEXT) xboard2uci.$(OBJEXT)
 polyglot_OBJECTS = $(am_polyglot_OBJECTS)
 polyglot_LDADD = $(LDADD)
 DEFAULT_INCLUDES = -I.@am__isrc@
@@ -193,7 +193,7 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
-polyglot_SOURCES = adapter.cpp attack.cpp board.cpp book.cpp book_make.cpp book_merge.cpp colour.cpp  engine.cpp epd.cpp fen.cpp gui.cpp game.cpp hash.cpp io.cpp line.cpp list.cpp main.cpp move.cpp move_do.cpp move_gen.cpp move_legal.cpp option.cpp parse.cpp pgn.cpp piece.cpp pipe.cpp posix.cpp random.cpp san.cpp search.cpp square.cpp uci.cpp uci2uci.cpp util.cpp adapter.h colour.h hash.h move_gen.h piece.h uci2uci.h attack.h config.h gui.h io.h move.h pipe.h posix.h uci.h board.h engine.h line.h move_legal.h random.h util.h book.h epd.h list.h option.h san.h book_make.h fen.h main.h parse.h search.h book_merge.h game.h move_do.h pgn.h square.h
+polyglot_SOURCES = mainloop.cpp attack.cpp board.cpp book.cpp book_make.cpp book_merge.cpp colour.cpp  engine.cpp epd.cpp fen.cpp gui.cpp game.cpp hash.cpp io.cpp line.cpp list.cpp main.cpp move.cpp move_do.cpp move_gen.cpp move_legal.cpp option.cpp parse.cpp pgn.cpp piece.cpp pipe.cpp posix.cpp random.cpp san.cpp search.cpp square.cpp uci.cpp uci2uci.cpp util.cpp xboard2uci.cpp mainloop.h colour.h hash.h move_gen.h piece.h uci2uci.h attack.h config.h gui.h io.h move.h pipe.h posix.h uci.h board.h engine.h line.h move_legal.h random.h util.h book.h epd.h list.h option.h san.h book_make.h fen.h main.h parse.h search.h book_merge.h game.h move_do.h pgn.h square.h xboard2uci.h
 dist_doc_DATA = README README1.3 README1.4 README1.4w README1.4w10UCI book_format.html
 man6_MANS = polyglot.man
 EXTRA_DIST = makefile.gcc polyglot.man polyglot.pod polyglot.spec debian/changelog debian/control debian/docs debian/README debian/compat debian/copyright debian/files debian/polyglot.substvars debian/rules
@@ -285,7 +285,6 @@ mostlyclean-compile:
 distclean-compile:
        -rm -f *.tab.c
 
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/adapter.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/attack.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/board.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/book.Po@am__quote@
@@ -302,6 +301,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/line.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mainloop.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/move.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/move_do.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/move_gen.Po@am__quote@
@@ -319,6 +319,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci2uci.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xboard2uci.Po@am__quote@
 
 .cpp.o:
 @am__fastdepCXX_TRUE@  $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/README b/README
index 0b313e9..fa7080c 100644 (file)
--- a/README
+++ b/README
@@ -405,7 +405,12 @@ EXAMPLES
 
            polyglot merge-book -in1 w1.bin -in2 w2.bin -out w.bin
 
-       Here is a minimal config file
+       The command line for using the UCI engine "fruit" in a GUI which uses
+       the xboard protocol.
+
+           polyglot -ec fruit
+
+       The equivalent config file:
 
            [PolyGlot]
            EngineCommand = fruit
@@ -429,4 +434,4 @@ SEE ALSO
 
 
 
-                                  2009-01-13                       POLYGLOT(6)
+                                  2009-01-14                       POLYGLOT(6)
index b05211e..2de88c9 100644 (file)
--- a/config.h
+++ b/config.h
 #define PACKAGE_NAME "polyglot"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "polyglot 1.4w10UCIb16"
+#define PACKAGE_STRING "polyglot 1.4w10UCIb17"
 
 /* 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.4w10UCIb16"
+#define PACKAGE_VERSION "1.4w10UCIb17"
 
 /* Define to 1 if the C compiler supports function prototypes. */
 #define PROTOTYPES 1
 #define TIME_WITH_SYS_TIME 1
 
 /* Version number of package */
-#define VERSION "1.4w10UCIb16"
+#define VERSION "1.4w10UCIb17"
 
 /* Define like PROTOTYPES; this can be used by system headers. */
 #define __PROTOTYPES 1
index 1e4b0f7..77ab853 100755 (executable)
--- 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.4w10UCIb16.
+# Generated by GNU Autoconf 2.61 for polyglot 1.4w10UCIb17.
 #
 # Report bugs to <michel.vandenbergh@uhasselt.be>.
 #
@@ -574,11 +574,11 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='polyglot'
 PACKAGE_TARNAME='polyglot'
-PACKAGE_VERSION='1.4w10UCIb16'
-PACKAGE_STRING='polyglot 1.4w10UCIb16'
+PACKAGE_VERSION='1.4w10UCIb17'
+PACKAGE_STRING='polyglot 1.4w10UCIb17'
 PACKAGE_BUGREPORT='michel.vandenbergh@uhasselt.be'
 
-ac_unique_file="adapter.cpp"
+ac_unique_file="mainloop.cpp"
 # Factoring default headers for most tests.
 ac_includes_default="\
 #include <stdio.h>
@@ -1216,7 +1216,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.4w10UCIb16 to adapt to many kinds of systems.
+\`configure' configures polyglot 1.4w10UCIb17 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1282,7 +1282,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of polyglot 1.4w10UCIb16:";;
+     short | recursive ) echo "Configuration of polyglot 1.4w10UCIb17:";;
    esac
   cat <<\_ACEOF
 
@@ -1368,7 +1368,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-polyglot configure 1.4w10UCIb16
+polyglot configure 1.4w10UCIb17
 generated by GNU Autoconf 2.61
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1382,7 +1382,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.4w10UCIb16, which was
+It was created by polyglot $as_me 1.4w10UCIb17, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   $ $0 $@
@@ -2072,7 +2072,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='polyglot'
- VERSION='1.4w10UCIb16'
+ VERSION='1.4w10UCIb17'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -7344,7 +7344,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.4w10UCIb16, which was
+This file was extended by polyglot $as_me 1.4w10UCIb17, which was
 generated by GNU Autoconf 2.61.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -7397,7 +7397,7 @@ Report bugs to <bug-autoconf@gnu.org>."
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-polyglot config.status 1.4w10UCIb16
+polyglot config.status 1.4w10UCIb17
 configured by $0, generated by GNU Autoconf 2.61,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
index db02fca..1973b38 100644 (file)
@@ -2,9 +2,9 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT([polyglot], [1.4w10UCIb16], [michel.vandenbergh@uhasselt.be])
+AC_INIT([polyglot], [1.4w10UCIb17], [michel.vandenbergh@uhasselt.be])
 AM_INIT_AUTOMAKE
-AC_CONFIG_SRCDIR([adapter.cpp])
+AC_CONFIG_SRCDIR([mainloop.cpp])
 AC_CONFIG_HEADER([config.h])
 
 # Checks for programs.
index 921683c..a898049 100644 (file)
@@ -160,11 +160,24 @@ void engine_open(engine_t * engine) {
       engine->io->out_fd = to_engine[1];\r
       engine->io->name = "Engine";\r
       engine->pid=pid;\r
+      engine->state|=ENGINE_ACTIVE; // can we test if this really true?\r
 \r
       io_init(engine->io);\r
    }\r
 }\r
 \r
+// engine_active\r
+\r
+bool engine_active(engine_t *engine){\r
+    return (engine->state & ENGINE_ACTIVE)!=0;\r
+}\r
+\r
+// engine_eof\r
+\r
+bool engine_eof(engine_t *engine){\r
+    return (engine->state & ENGINE_EOF)!=0;\r
+}\r
+\r
 // engine_set_nice_value()\r
 \r
 void engine_set_nice_value(engine_t * engine, int value){\r
@@ -178,7 +191,13 @@ void engine_close(engine_t * engine) {
 \r
    ASSERT(engine_is_ok(engine));\r
 \r
+   char string[StringSize];\r
    io_close(engine->io);\r
+       // TODO: timeout\r
+   while (!engine_eof(engine)) {\r
+       engine_get(engine,string,StringSize); \r
+   }\r
+\r
 }\r
 \r
 // engine_get()\r
@@ -194,8 +213,7 @@ void engine_get(engine_t * engine, char string[], int size) {
    }\r
 \r
    if (!io_get_line(engine->io,string,size)) { // EOF\r
-       my_log("POLYGLOT *** EOF from Engine ***\n");\r
-      exit(EXIT_SUCCESS);\r
+       engine->state|=ENGINE_EOF;\r
    }\r
 }\r
 \r
@@ -335,45 +353,69 @@ void engine_send(engine_t * engine, const char *szFormat, ...) {
 }\r
 \r
 void engine_close(engine_t * engine){\r
+    char string[StringSize];\r
     (engine->pipeEngine).Close();\r
+        // TODO: Timeout\r
+    while (!engine_eof(Engine)) {\r
+            engine_get(Engine,string,StringSize); \r
+        }\r
+    (engine->pipeEngine).Kill();\r
 }\r
 \r
 \r
 void engine_open(engine_t * engine){\r
    int affinity;\r
     char *my_dir;\r
+    engine->state=0;\r
     if( (my_dir = _getcwd( NULL, 0 )) == NULL )\r
         my_fatal("Can't build path: %s\n",strerror(errno));\r
     SetCurrentDirectory(option_get_string("EngineDir"));\r
     (engine->pipeEngine).Open(option_get_string("EngineCommand"));\r
-        //play with affinity (bad idea) \r
-    affinity=option_get_int("Affinity");\r
-    if(affinity!=-1) set_affinity(engine,affinity); //AAA\r
-        //lets go back\r
-    SetCurrentDirectory(my_dir);\r
-        // set a low priority\r
-    if (option_get_bool("UseNice")){\r
-          my_log("POLYGLOT Adjust Engine Piority\n");\r
-          engine_set_nice_value(engine, option_get_int("NiceValue"));\r
+    if((engine->pipeEngine).Active()){\r
+        engine->state|=ENGINE_ACTIVE;\r
+            //play with affinity (bad idea)\r
+        affinity=option_get_int("Affinity");\r
+        if(affinity!=-1) set_affinity(engine,affinity); //AAA\r
+            //lets go back\r
+        SetCurrentDirectory(my_dir);\r
+            // set a low priority\r
+        if (option_get_bool("UseNice")){\r
+            my_log("POLYGLOT Adjust Engine Piority\n");\r
+            engine_set_nice_value(engine, option_get_int("NiceValue"));\r
+        }\r
     }\r
     \r
 }\r
 \r
+bool engine_active(engine_t *engine){\r
+    return (engine->state & ENGINE_ACTIVE)!=0;\r
+}\r
+\r
+bool engine_eof(engine_t *engine){\r
+    return (engine->state & ENGINE_EOF)!=0;\r
+}\r
+\r
 bool engine_get_non_blocking(engine_t * engine, char *szLineStr, int size){\r
+    if(engine_eof(engine)){ return false;}\r
        if ((engine->pipeEngine).LineInput(szLineStr)) {\r
         my_log("Engine->Adapter: %s\n",szLineStr);\r
         return true;\r
     } else {\r
         szLineStr[0]='\0';\r
+        if(engine->pipeEngine.EOF_()){\r
+            my_log("POLYGLOT EOF received from engine\n");\r
+            engine->state|=ENGINE_EOF;\r
+        }\r
         return false;\r
     }\r
 }\r
 \r
 void engine_get(engine_t * engine, char *szLineStr, int size){\r
     bool data_available;\r
+    if(engine_eof(engine))return;\r
     while(true){\r
         data_available=engine_get_non_blocking(engine,szLineStr,size);\r
-        if(!data_available){\r
+        if(!data_available && !engine_eof(engine)){\r
             Idle();\r
         }else{\r
             break;\r
index 5414d8a..ee703e9 100644 (file)
--- a/engine.h
+++ b/engine.h
@@ -3,6 +3,11 @@
 #ifndef ENGINE_H\r
 #define ENGINE_H\r
 \r
+// defines\r
+\r
+#define ENGINE_EOF 1\r
+#define ENGINE_ACTIVE 2\r
+\r
 // includes\r
 \r
 #include "io.h"\r
@@ -18,6 +23,7 @@ struct engine_t {
 #else\r
     PipeStruct pipeEngine;\r
 #endif\r
+    uint32 state;\r
 };\r
 \r
 \r
@@ -31,6 +37,8 @@ extern engine_t Engine[1];
 extern bool engine_is_ok      (const engine_t * engine);\r
 extern void engine_open       (engine_t * engine);\r
 extern void engine_close      (engine_t * engine);\r
+extern bool engine_active     (engine_t * engine);\r
+extern bool engine_eof        (engine_t * engine);\r
 extern void engine_send       (engine_t * engine, const char format[], ...);\r
 extern void engine_send_queue (engine_t * engine, const char format[], ...);\r
 extern bool engine_get_non_blocking(engine_t * engine, char string[], int size);\r
diff --git a/epd.cpp b/epd.cpp
index 18c5190..70537da 100644 (file)
--- a/epd.cpp
+++ b/epd.cpp
@@ -241,7 +241,7 @@ static void epd_test_file(const char file_name[]) {
 \r
       // parse engine output\r
 \r
-      while (engine_step()) {\r
+      while (!engine_eof(Engine) && engine_step()) {\r
           bool stop=false;\r
          // stop search?\r
 \r
diff --git a/gui.cpp b/gui.cpp
index 9905800..354d276 100644 (file)
--- a/gui.cpp
+++ b/gui.cpp
@@ -3,6 +3,7 @@
 // includes
 
 #include <cstdarg>
+#include <csignal>
 
 #include "gui.h"
 #include "main.h"
@@ -17,18 +18,35 @@ gui_t GUI[1];
 
 // functions
 
+// sig_quit()
+
+static void sig_quit(int dummy){
+    my_log("POLYGLOT *** SIGINT Received ***\n");
+    quit();
+}
+
 
 // gui_init()
 
 void gui_init(gui_t *gui){
-    #ifdef _WIN32
+
+// the following is nice if the "GUI" is a console!
+    signal(SIGINT,sig_quit);
+#ifdef _WIN32
+    signal(SIGTERM,SIG_IGN);
+#ifdef SIGPIPE
+    signal(SIGPIPE,SIG_IGN);
+#endif
+#endif
+    
+#ifdef _WIN32
    (gui->pipeStdin).Open();
 #else
    
    gui->io->in_fd = STDIN_FILENO;
    gui->io->out_fd = STDOUT_FILENO;
    gui->io->name = "GUI";
-
+   
    io_init(gui->io);
 #endif
 }
diff --git a/io.cpp b/io.cpp
index 0a9345d..7246e89 100644 (file)
--- a/io.cpp
+++ b/io.cpp
@@ -100,7 +100,6 @@ void io_get_update(io_t * io) {
    if (size <= 0) my_fatal("io_get_update(): buffer overflow\n");\r
 \r
    // read as many data as possible\r
-\r
    n = my_read(io->in_fd,&io->in_buffer[pos],size);\r
    if (UseDebug) my_log("POLYGLOT read %d byte%s from %s\n",n,(n>1)?"s":"",io->name);\r
 \r
index ce6c235..b46be4a 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -4,18 +4,10 @@
 // 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
@@ -28,6 +20,7 @@
 #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
@@ -49,13 +45,14 @@ polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth d
 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
@@ -78,82 +75,77 @@ int main(int argc, char * argv[]) {
     }\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
@@ -210,49 +202,51 @@ static void init_book(){
 \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
@@ -266,117 +260,102 @@ static void parse_option() {
        }\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
diff --git a/mainloop.cpp b/mainloop.cpp
new file mode 100644 (file)
index 0000000..0d5a8f0
--- /dev/null
@@ -0,0 +1,134 @@
+// mainloop.cpp\r
+\r
+// constants\r
+\r
+static const int StringSize = 4096;\r
+\r
+// includes\r
+\r
+#include <cerrno>\r
+#include <cstdio>\r
+#include <cstdlib>\r
+#include <cstring>\r
+\r
+#ifndef _WIN32\r
+#include <sys/select.h>\r
+#include <sys/types.h> // Mac OS X needs this one\r
+#include <unistd.h>\r
+#endif\r
+\r
+#include "main.h"\r
+#include "engine.h"\r
+#include "gui.h"\r
+#include "option.h"\r
+#include "xboard2uci.h"\r
+#include "uci2uci.h"\r
+\r
+// prototypes\r
+\r
+static void mainloop_step      ();\r
+static void mainloop_init();\r
+static void mainloop_engine_step(char * string);\r
+static void mainloop_gui_step(char * string);\r
+\r
+// mainloop_init()\r
+    \r
+static void mainloop_init(){\r
+    if(!option_get_bool("UCI")){\r
+        xboard_init();\r
+    }\r
+}\r
+\r
+// mainloop_engine_step()\r
+\r
+static void mainloop_engine_step(char * string){\r
+    if(option_get_bool("UCI")){\r
+       uci_engine_step(string); \r
+    }else{\r
+        engine_step(string);\r
+    }\r
+}\r
+\r
+// mainloop_gui_step()\r
+\r
+static void mainloop_gui_step(char * string){\r
+    if(option_get_bool("UCI")){\r
+        uci_gui_step(string); \r
+    }else{\r
+        xboard_step(string);\r
+    }  \r
+}\r
+\r
+\r
+\r
+// mainloop()\r
+\r
+void mainloop() {\r
+    mainloop_init();\r
+    while (!engine_eof(Engine)) mainloop_step();\r
+    my_log("POLYGLOT *** EOF file received from engine ***");\r
+}\r
+\r
+// adapter_step()\r
+\r
+#ifdef _WIN32\r
+static void mainloop_step(){  // polling!\r
+    bool xin,ein;\r
+    char string[StringSize];\r
+    xin=gui_get_non_blocking(GUI,string,StringSize);\r
+    if(xin) mainloop_gui_step(string);\r
+    ein=engine_get_non_blocking(Engine,string,StringSize);\r
+    if(ein) mainloop_engine_step(string);\r
+    if(xin==false && ein==false) Idle();//nobody wants me,lets have a beauty nap\r
+}\r
+#else\r
+static void mainloop_step() {\r
+\r
+   fd_set set[1];\r
+   int fd_max;\r
+   int val;\r
+   char string[StringSize];\r
+\r
+       // process buffered lines\r
+\r
+   while (io_line_ready(GUI->io)){\r
+       gui_get(GUI,string,StringSize);\r
+       mainloop_gui_step(string);\r
+   }\r
+   while (!engine_eof(Engine) && io_line_ready(Engine->io)){\r
+       engine_get(Engine,string,StringSize);\r
+       mainloop_engine_step(string);\r
+   }\r
+\r
+   // init\r
+\r
+   FD_ZERO(set);\r
+   fd_max = -1; // HACK\r
+\r
+   // add xboard input\r
+\r
+   ASSERT(GUI->io->in_fd>=0);\r
+\r
+   FD_SET(GUI->io->in_fd,set);\r
+   if (GUI->io->in_fd > fd_max) fd_max = GUI->io->in_fd;\r
+\r
+   // add engine input\r
+\r
+   ASSERT(Engine->io->in_fd>=0);\r
+\r
+   FD_SET(Engine->io->in_fd,set);\r
+   if (Engine->io->in_fd > fd_max) fd_max = Engine->io->in_fd;\r
+\r
+   // wait for something to read (no timeout)\r
+\r
+   ASSERT(fd_max>=0);\r
+   val = select(fd_max+1,set,NULL,NULL,NULL);\r
+   if (val == -1 && errno != EINTR) my_fatal("adapter_step(): select(): %s\n",strerror(errno));\r
+\r
+   if (val > 0) {\r
+      if (FD_ISSET(GUI->io->in_fd,set)) io_get_update(GUI->io); // read some xboard input\r
+      if (FD_ISSET(Engine->io->in_fd,set)) io_get_update(Engine->io); // read some engine input\r
+   }\r
+}\r
+#endif\r
+\r
diff --git a/mainloop.h b/mainloop.h
new file mode 100644 (file)
index 0000000..709b3c9
--- /dev/null
@@ -0,0 +1,26 @@
+\r
+// mainloop.h\r
+\r
+#ifndef MAINLOOP_H\r
+#define MAINLOOP_H\r
+\r
+// includes\r
+\r
+#include "util.h"\r
+#include "uci2uci.h"\r
+\r
+// types\r
+\r
+\r
+\r
+\r
+\r
+// functions\r
+\r
+extern void mainloop ();\r
+\r
+\r
+#endif // !defined MAINLOOP_H\r
+\r
+// end of mainloop.h\r
+\r
index 3f8da2e..f12a787 100644 (file)
--- a/pipe.cpp
+++ b/pipe.cpp
@@ -1,17 +1,20 @@
 #ifdef _WIN32
 #include "pipe.h"
 #include "util.h"
+
 void PipeStruct::Open(const char *szProcFile) {
   DWORD dwMode;
   HANDLE hStdinRead, hStdinWrite, hStdoutRead, hStdoutWrite;
   SECURITY_ATTRIBUTES sa;
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
-
+  state=0;
   if (szProcFile == NULL) {
     hInput = GetStdHandle(STD_INPUT_HANDLE);
     hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
     bConsole = GetConsoleMode(hInput, &dwMode);
+    state|=PIPE_ACTIVE;
+    
   } else {
     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
     sa.bInheritHandle = TRUE;
@@ -26,17 +29,16 @@ void PipeStruct::Open(const char *szProcFile) {
     si.hStdInput = hStdinRead;
     si.hStdOutput = hStdoutWrite;
     si.hStdError = hStdoutWrite;
-    if(!CreateProcess(NULL, (LPSTR) szProcFile, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)){
-        my_fatal("PipeStruct::Open(): Could not start \"%s\"\n",szProcFile);
+    if(CreateProcess(NULL, (LPSTR) szProcFile, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)){
+        state|=PIPE_ACTIVE;
+        hProcess=pi.hProcess;
+        CloseHandle(pi.hThread);
+        CloseHandle(hStdinRead);
+        CloseHandle(hStdoutWrite);
+        hInput = hStdoutRead;
+        hOutput = hStdinWrite;
+        bConsole = FALSE;
     }
-       hProcess=pi.hProcess;
-    //CloseHandle(pi.hProcess);//not here,baby,but in pipe.close 
-    CloseHandle(pi.hThread);
-    CloseHandle(hStdinRead);
-    CloseHandle(hStdoutWrite);
-    hInput = hStdoutRead;
-    hOutput = hStdinWrite;
-    bConsole = FALSE;
   }
   if (bConsole) {
     SetConsoleMode(hInput, dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
@@ -48,30 +50,39 @@ void PipeStruct::Open(const char *szProcFile) {
 }
 
 void PipeStruct::Close(void) const {
+  CloseHandle(hOutput);
+}
+
+void PipeStruct::Kill(void) const {
   CloseHandle(hInput);
   CloseHandle(hOutput);
   DWORD lpexit;
 
-  my_log("POLYGLOT Closing child\n");
   if(GetExitCodeProcess(hProcess,&lpexit)){
        if(lpexit==STILL_ACTIVE)
-         my_log("POLYGLOT Process still active after \"quit\" ");
        //must be java,hammer it down!
        TerminateProcess(hProcess,lpexit);
   }
        CloseHandle(hProcess);
 }
 
+bool PipeStruct::EOF_(void){   // EOF is defined
+    return state&PIPE_EOF;
+}
+
+bool PipeStruct::Active(void){
+    return state&PIPE_ACTIVE;
+}
+
 void PipeStruct::ReadInput(void) {
   DWORD dwBytes;
-  if(!ReadFile(hInput, szBuffer + nReadEnd, LINE_INPUT_MAX_CHAR - nReadEnd, &dwBytes, NULL)){
-          // TODO move this comment to a more suitable place
-      my_log("POLYGLOT *** EOF from Engine or GUI ***\n");
-      exit(EXIT_SUCCESS); // if we are here there should be data!
-  }
-  nReadEnd += dwBytes;
-  if (nBytesLeft > 0) {
-    nBytesLeft -= dwBytes;
+  if(ReadFile(hInput, szBuffer + nReadEnd, LINE_INPUT_MAX_CHAR - nReadEnd, &dwBytes, NULL)){
+      nReadEnd += dwBytes;
+      if (nBytesLeft > 0) {
+          nBytesLeft -= dwBytes;
+      }
+  }else{
+      state|=PIPE_EOF;   // if we are here there should be data!
   }
 }
 
diff --git a/pipe.h b/pipe.h
index b13f513..ced06d7 100644 (file)
--- a/pipe.h
+++ b/pipe.h
@@ -5,28 +5,37 @@
 
 #include <windows.h>
 
-
 // constants
 
 const int LINE_INPUT_MAX_CHAR = 4096;
 
+// defines
+
+#define PIPE_EOF 1
+#define PIPE_ACTIVE 2
+
 // types
 
 struct PipeStruct {
-  HANDLE hInput, hOutput;
+
+    HANDLE hInput, hOutput;
     HANDLE hProcess;
-  BOOL bConsole;
-  int nBytesLeft;
-  int nReadEnd;
-  char szBuffer[LINE_INPUT_MAX_CHAR];
-
-  void Open(const char *szExecFile = NULL);
-  void Close(void) const;
-  void ReadInput(void);
-  bool CheckInput(void);
-  bool GetBuffer(char *szLineStr);
-  bool LineInput(char *szLineStr);
-  void LineOutput(const char *szLineStr) const;
+    DWORD state;
+    BOOL bConsole;
+    int nBytesLeft;
+    int nReadEnd;
+    char szBuffer[LINE_INPUT_MAX_CHAR];
+
+    void Open(const char *szExecFile = NULL);
+    void Close(void) const;
+    void Kill(void) const;
+    bool EOF_(void);
+    bool Active(void);
+    void ReadInput(void);
+    bool CheckInput(void);
+    bool GetBuffer(char *szLineStr);
+    bool LineInput(char *szLineStr);
+    void LineOutput(const char *szLineStr) const;
 }; // pipe
 
 #endif
index de6739d..e6d0ca8 100644 (file)
 .\" ========================================================================
 .\"
 .IX Title "POLYGLOT 6"
-.TH POLYGLOT 6 "2009-01-13" "" ""
+.TH POLYGLOT 6 "2009-01-14" "" ""
 .SH "NAME"
 PolyGlot \-  Winboard protocol to UCI protocol adapter
          \-  book engine for Polyglot books 
@@ -527,7 +527,14 @@ Merge books \*(L"in1.bin\*(R" and \*(L"in2.bin\*(R" into a book \*(L"out.bin\*(R
 \&    polyglot merge\-book \-in1 w1.bin \-in2 w2.bin \-out w.bin
 .Ve
 .PP
-Here is a minimal config file
+The command line for using the \s-1UCI\s0 engine \*(L"fruit\*(R" in a \s-1GUI\s0 which uses the
+xboard protocol.
+.PP
+.Vb 1
+\&    polyglot \-ec fruit
+.Ve
+.PP
+The equivalent config file:
 .PP
 .Vb 3
 \&    [PolyGlot]
index cd4cb21..db61280 100644 (file)
@@ -476,8 +476,12 @@ Merge books "in1.bin" and "in2.bin" into a book "out.bin".
 
     polyglot merge-book -in1 w1.bin -in2 w2.bin -out w.bin
 
+The command line for using the UCI engine "fruit" in a GUI which uses the
+xboard protocol.
 
-Here is a minimal config file
+    polyglot -ec fruit
+
+The equivalent config file:
 
     [PolyGlot]
     EngineCommand = fruit
index f413891..67a4465 100644 (file)
@@ -1,6 +1,6 @@
 Summary: A Winboard protocol to UCI protocol adapter
 Name: polyglot
-Version: 1.4w10UCIb16
+Version: 1.4w10UCIb17
 Release: 1
 License: GPL
 Group: Amusement/Games
index a867d24..b231882 100644 (file)
@@ -105,7 +105,7 @@ void search(const board_t * board, int depth_max, double time_max) {
 \r
    // wait for feed-back\r
 \r
-   while (true) {\r
+   while (!engine_eof(Engine)) {\r
 \r
       engine_get(Engine,string,256);\r
 \r
diff --git a/uci.cpp b/uci.cpp
index a84628e..d7f63b4 100644 (file)
--- a/uci.cpp
+++ b/uci.cpp
@@ -139,7 +139,7 @@ void uci_open(uci_t * uci, engine_t * engine) {
    do {\r
       engine_get(uci->engine,string,StringSize);\r
       event = uci_parse(uci,string);\r
-   } while ((event & EVENT_UCI) == 0);\r
+   } while (!engine_eof(Engine) && (event & EVENT_UCI) == 0);\r
 }\r
 \r
 // uci_close()\r
@@ -223,7 +223,7 @@ void uci_send_isready_sync(uci_t * uci) {
    do {\r
       engine_get(uci->engine,string,StringSize);\r
       event = uci_parse(uci,string);\r
-   } while ((event & EVENT_READY) == 0);\r
+   } while (!engine_eof(Engine) && (event & EVENT_READY) == 0);\r
 }\r
 \r
 // uci_send_stop()\r
@@ -258,7 +258,7 @@ void uci_send_stop_sync(uci_t * uci) {
    do {\r
       engine_get(uci->engine,string,StringSize);\r
       event = uci_parse(uci,string);\r
-   } while ((event & EVENT_STOP) == 0);\r
+   } while (!engine_eof(Engine) && (event & EVENT_STOP) == 0);\r
 }\r
 \r
 // uci_send_ucinewgame()\r
index e28d815..5dab703 100644 (file)
@@ -6,7 +6,6 @@
 #include <cstdlib>
 
 #include "util.h"
-#include "adapter.h"
 #include "board.h"
 #include "engine.h"
 #include "fen.h"
@@ -30,12 +29,6 @@ static board_t UCIboard[1];
 static bool Init=true;
 static int SavedMove=MoveNone;
 
-// defines
-
-#ifdef _WIN32
-#define strcasecmp lstrcmpi
-#endif
-
 // parse_position()
 
 static void parse_position(const char string[]) {
index 2e9e0a6..8a7049d 100644 (file)
--- a/uci2uci.h
+++ b/uci2uci.h
@@ -4,10 +4,6 @@
 #ifndef UCI2UCI_H
 #define UCI2UCI_H
 
-// constants
-
-const char * const PolyglotBookFile="Polyglot BookFile";
-
 // functions
 
 extern void uci_gui_step(char string[]);
diff --git a/xboard2uci.cpp b/xboard2uci.cpp
new file mode 100644 (file)
index 0000000..ed241a0
--- /dev/null
@@ -0,0 +1,1528 @@
+\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
diff --git a/xboard2uci.h b/xboard2uci.h
new file mode 100644 (file)
index 0000000..bea161a
--- /dev/null
@@ -0,0 +1,28 @@
+\r
+// xboard2uci.h\r
+\r
+#ifndef XBOARD2UCI_H\r
+#define XBOARD2UCI_H\r
+\r
+// includes\r
+\r
+#include "util.h"\r
+#include "uci2uci.h"\r
+\r
+// types\r
+\r
+\r
+\r
+\r
+\r
+// functions\r
+\r
+extern void adapter_loop ();\r
+extern void xboard_init           ();\r
+extern void xboard_step           (char string[]);\r
+extern void engine_step           (char string[]);\r
+\r
+#endif // !defined XBOARD2UCI_H\r
+\r
+// end of xboard2uci.h\r
+\r