+=========1.4w10UCIb20===========\r
+- More refactoring.\r
+- No more polling for GUI input\r
=========1.4w10UCIb18===========\r
- Two new utilities: info-book and dump-book.\r
=========1.4w10UCIb17===========\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
+be possible to close an engine and reopen another one (if that ever became useful) \r
=========1.4w10UCIb16===========\r
- xboard options commands\r
- correction of handling of combo boxes in UCI protocol\r
Unconditionally stop the seach after this amount of time.
-depth-delta (default: 3)
- Stop the search if the best move has been constant for this many
- depths, on condition that the mininal depth and minimal time have
- been reached.
+ Stop the search if the solution as been found and the best move has
+ been constant for this many depths, on condition that the mininal
+ depth and minimal time have been reached.
-min-depth (default: 8)
Minimal search depth when the search is stopped using
option = value
...
- Lines starting with "#" are ignored.
+ The characters "#" and ";" serve as comment characters.
NOTE: There can be spaces in option names or values. Do not use
quotes. Boolean values are written as "true" or "false".
polyglot make-book -pgn games.pgn -bin book.bin -max-ply 30
- Merge books "in1.bin" and "in2.bin" into a book "out.bin".
+ Merge books "w1.bin" and "w2.bin" into a book "w.bin".
polyglot merge-book -in1 w1.bin -in2 w2.bin -out w.bin
+ Inspect lines for white in "w.bin"
+
+ polyglot dump-book -bin w.bin -color white -out w_white.txt
+
+ Test epd file "test.epd" with a (maximum) search time of 7 minutes per
+ position
+
+ polyglot epd-test -epd test.epd -max-time 420
+
The command line for using the UCI engine "fruit" in a GUI which uses
the xboard protocol.
- 2009-01-15 POLYGLOT(6)
+ 2009-01-16 POLYGLOT(6)
uint64 key;\r
uint16 move;\r
uint16 count;\r
- union{ // unfortunately minggw32 seems to have a bug with anon unions.\r
- struct { \r
+// Unfortunately the minggw32 cross compiler [4.2.1-sjlj (mingw32-2)] \r
+// seems to have a bug with anon structs contained in unions when using -O2.\r
+// See the ASSERT below in "read_entry_file"...\r
+// To be fair this seems to be illegal in C++\r
+// although it is hard to understand why, and the compiler does not complain\r
+// even with -Wall.\r
+// union { \r
+// struct { \r
uint16 n;\r
uint16 sum;\r
- };\r
- struct{\r
+// };\r
+// struct {\r
uint8 height;\r
int line;\r
- };\r
- };\r
+// };\r
+ // };\r
uint8 colour;\r
};\r
\r
#define PACKAGE_NAME "polyglot"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "polyglot 1.4w10UCIb18"
+#define PACKAGE_STRING "polyglot 1.4w10UCIb20"
/* 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.4w10UCIb18"
+#define PACKAGE_VERSION "1.4w10UCIb20"
/* 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.4w10UCIb18"
+#define VERSION "1.4w10UCIb20"
/* Define like PROTOTYPES; this can be used by system headers. */
#define __PROTOTYPES 1
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for polyglot 1.4w10UCIb18.
+# Generated by GNU Autoconf 2.61 for polyglot 1.4w10UCIb20.
#
# Report bugs to <michel.vandenbergh@uhasselt.be>.
#
# Identity of this package.
PACKAGE_NAME='polyglot'
PACKAGE_TARNAME='polyglot'
-PACKAGE_VERSION='1.4w10UCIb18'
-PACKAGE_STRING='polyglot 1.4w10UCIb18'
+PACKAGE_VERSION='1.4w10UCIb20'
+PACKAGE_STRING='polyglot 1.4w10UCIb20'
PACKAGE_BUGREPORT='michel.vandenbergh@uhasselt.be'
ac_unique_file="mainloop.cpp"
# 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.4w10UCIb18 to adapt to many kinds of systems.
+\`configure' configures polyglot 1.4w10UCIb20 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of polyglot 1.4w10UCIb18:";;
+ short | recursive ) echo "Configuration of polyglot 1.4w10UCIb20:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-polyglot configure 1.4w10UCIb18
+polyglot configure 1.4w10UCIb20
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
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.4w10UCIb18, which was
+It was created by polyglot $as_me 1.4w10UCIb20, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE='polyglot'
- VERSION='1.4w10UCIb18'
+ VERSION='1.4w10UCIb20'
cat >>confdefs.h <<_ACEOF
# 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.4w10UCIb18, which was
+This file was extended by polyglot $as_me 1.4w10UCIb20, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-polyglot config.status 1.4w10UCIb18
+polyglot config.status 1.4w10UCIb20
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([polyglot], [1.4w10UCIb18], [michel.vandenbergh@uhasselt.be])
+AC_INIT([polyglot], [1.4w10UCIb20], [michel.vandenbergh@uhasselt.be])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([mainloop.cpp])
AC_CONFIG_HEADER([config.h])
\r
}\r
\r
+// engine_get_non_blocking()\r
+\r
+bool engine_get_non_blocking(engine_t * engine, char string[], int size){\r
+ if(io_line_ready(engine->io)){\r
+ engine_get(engine,string,StringSize);\r
+ return true;\r
+ }else{\r
+ string[0]='\0';\r
+ return false;\r
+ }\r
+}\r
+\r
// engine_get()\r
\r
void engine_get(engine_t * engine, char string[], int size) {\r
\r
void set_affinity(engine_t *engine, int affin){\r
if(affin==-1) return;\r
- SetProcessAffinityMask((engine->pipeEngine).hProcess,affin);\r
+ SetProcessAffinityMask((engine->io).hProcess,affin);\r
}\r
\r
// Eric Mullins!\r
\r
void engine_set_nice_value(engine_t *engine, int value){\r
- SetPriorityClass((engine->pipeEngine).hProcess,\r
+ SetPriorityClass((engine->io).hProcess,\r
GetWin32Priority(value));\r
}\r
\r
\r
void engine_send_queue(engine_t * engine,const char *szFormat, ...) {\r
- nQueuePtr += vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));\r
+ nQueuePtr += vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));\r
}\r
\r
void engine_send(engine_t * engine, const char *szFormat, ...) {\r
vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));\r
- (engine->pipeEngine).LineOutput(szQueueString);\r
+ (engine->io).LineOutput(szQueueString);\r
my_log("Adapter->Engine: %s\n",szQueueString);\r
nQueuePtr = 0;\r
}\r
\r
void engine_close(engine_t * engine){\r
char string[StringSize];\r
- (engine->pipeEngine).Close();\r
+ (engine->io).Close();\r
// TODO: Timeout\r
- while (!engine_eof(Engine)) {\r
- engine_get(Engine,string,StringSize); \r
- }\r
- (engine->pipeEngine).Kill();\r
+ while (!engine_eof(Engine)) { \r
+ engine_get_non_blocking(Engine,string,StringSize);\r
+ Idle();\r
+ }\r
+ (engine->io).Kill();\r
}\r
\r
\r
void engine_open(engine_t * engine){\r
- int affinity;\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
- if((engine->pipeEngine).Active()){\r
+ (engine->io).Open(option_get_string("EngineCommand"));\r
+ if((engine->io).Active()){\r
engine->state|=ENGINE_ACTIVE;\r
//play with affinity (bad idea)\r
affinity=option_get_int("Affinity");\r
\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
+ if ((engine->io).GetBuffer(szLineStr)) {\r
my_log("Engine->Adapter: %s\n",szLineStr);\r
return true;\r
} else {\r
szLineStr[0]='\0';\r
- if(engine->pipeEngine.EOF_()){\r
- my_log("POLYGLOT EOF received from engine\n");\r
+ if(engine->io.EOF_()){\r
engine->state|=ENGINE_EOF;\r
}\r
return false;\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 && !engine_eof(engine)){\r
- Idle();\r
- }else{\r
- break;\r
- }\r
+ (engine->io).LineInput(szLineStr);\r
+ if(engine->io.EOF_()){\r
+ engine->state|=ENGINE_EOF;\r
}\r
}\r
\r
\r
struct engine_t {\r
#ifndef _WIN32\r
- io_t io[1];\r
+ io_t io[1];\r
pid_t pid;\r
#else\r
- PipeStruct pipeEngine;\r
+ PipeStruct io;\r
#endif\r
uint32 state;\r
};\r
static uint64 LastNodeNb;\r
static move_t LastPV[LineSize];\r
\r
+static my_timer_t Timer[1];\r
+\r
// prototypes\r
\r
static void epd_test_file (const char file_name[]);\r
\r
// search\r
\r
+ my_timer_start(Timer); // also resets\r
+ \r
// which ones of the next two alternatives is best?\r
engine_send(Engine,"go movetime %.0f depth %d",MaxTime*1000.0,MaxDepth);\r
//engine_send(Engine,"go infinite");\r
\r
while (!engine_eof(Engine) && engine_step()) {\r
bool stop=false;\r
- // stop search?\r
\r
+ // stop search?\r
+// printf("Uci->time=%.2f time=%.2f\n",Uci->time,my_timer_elapsed_real(Timer));\r
if (Uci->depth > MaxDepth){\r
my_log("POLYGLOT Maximum depth %d reached\n",MaxDepth);\r
stop=true;\r
- }else if(Uci->time >= MaxTime){\r
+ }else if(my_timer_elapsed_real(Timer) >= MaxTime){\r
my_log("POLYGLOT Maximum search time %.2fs reached\n",MaxTime);\r
stop=true;\r
}else if(Uci->depth - FirstDepth >= DepthDelta){\r
- my_log("POLYGLOT DepthDelta (=%d) reached\n",DepthDelta);\r
if(Uci->depth > MinDepth){\r
- my_log("POLYGLOT Minimum depth %d reached\n",MinDepth);\r
if(Uci->time >= MinTime){\r
- my_log("POLYGLOT Minimum search time %.2fs reached\n",MinTime);\r
if(is_solution(FirstMove,board,bm,am)){\r
- my_log("POLYGLOT Solution is correct\n");\r
+ my_log("POLYGLOT Solution found\n",MaxTime);\r
stop=true;\r
- }else{\r
- my_log("POLYGLOT Solution is not correct\n");\r
}\r
}\r
}\r
printf("%2d: %-15s %s %4d",tot,id,correct?"OK":"--",hit);\r
\r
if (!line_to_san(LastPV,Uci->board,pv_string,StringSize)) ASSERT(false);\r
- printf(" [at: depth=%2d time=%6.2f nodes="S64_FORMAT"] score=%+6.2f pv=%s\n",FirstDepth,FirstTime,FirstNodeNb,double(LastScore)/100.0,pv_string);\r
+ printf(" score=%+6.2f pv [D=%2d, T=%7.2fs, N=%6dk] =%s\n",double(LastScore)/100.0,FirstDepth,FirstTime,(int)FirstNodeNb/1000,pv_string);\r
}\r
\r
printf("\nscore=%d/%d",hit,tot);\r
#endif
#ifdef _WIN32
- (gui->pipeStdin).Open();
+ (gui->io).Open();
#else
gui->io->in_fd = STDIN_FILENO;
// gui_get_non_blocking()
-// this is only non_blocking on windows!
-
bool gui_get_non_blocking(gui_t * gui, char string[], int size) {
ASSERT(gui!=NULL);
ASSERT(string!=NULL);
ASSERT(size>=256);
#ifndef _WIN32
- if (!io_get_line(gui->io,string,size)) { // EOF
- my_log("POLYGLOT *** EOF from GUI ***\n");
- quit();
+ if(io_line_ready(gui->io)){
+ gui_get(GUI,string,StringSize);
+ return true;
+ }else{
+ string[0]='\0';
+ return false;
}
- return true;
#else
- if ((gui->pipeStdin).LineInput(string)) {
+ if ((gui->io).GetBuffer(string)) {
my_log("GUI->Adapter: %s\n", string);
return true;
} else {
string[0]='\0';
return false;
}
-
#endif
}
void gui_get(gui_t * gui, char string[], int size) {
bool data_available;
- while(true){
- data_available=gui_get_non_blocking(gui, string, size);
- if(!data_available){
- Idle();
- }else{
- break;
- }
+#ifdef _WIN32
+ (gui->io).LineInput(string);
+ my_log("GUI->Adapter: %s\n", string);
+#else
+ if (!io_get_line(gui->io,string,size)) { // EOF
+ my_log("POLYGLOT *** EOF from GUI ***\n");
+ quit();
}
+#endif
}
#ifndef _WIN32
io_send(gui->io,"%s",string);
#else
- printf("%s\n",string);
- fflush(stdout);
+ gui->io.LineOutput(string);
my_log("Adapter->GUI: %s\n",string);
#endif
}
struct gui_t {
#ifndef _WIN32
- io_t io[1];
+ io_t io[1];
#else
- PipeStruct pipeStdin;
+ PipeStruct io;
#endif
};
// constants\r
\r
\r
-static const char * const Version = "1.4W10UCIb18";\r
+static const char * const Version = "1.4W10UCIb20";\r
static const char * const HelpMessage = "\\r
SYNTAX\n\\r
* polyglot [configfile]\n\\r
* polyglot merge-book -in1 inputfile1 -in2 inputfile2 [-out outputfile]\n\\r
* polyglot info-book [-bin inputfile] [-exact]\n\\r
* polyglot dumb-book [-bin inputfile] -color color [-out outputfile]\n\\r
-* polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-max-time time] [-depth-delta delta]\n\\r
+* polyglot [configfile] epd-test [-epd inputfile] [-min-depth depth] [-max-depth depth] [-min-time time] [-max-time time] [-depth-delta delta]\n\\r
* polyglot perft [-fen fen] [-max-depth depth]\\r
";\r
\r
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
+ my_fatal("Could not start \"%s\"\n",option_get("EngineCommand"));\r
}\r
\r
if (option_get_bool("UCI")) {\r
\r
stop_search();\r
engine_send(Engine,"quit");\r
+ my_log("POLYGLOT Closing engine\n");\r
engine_close(Engine);\r
\r
}\r
+ my_log("POLYGLOT Calling exit\n");\r
exit(EXIT_SUCCESS);\r
}\r
\r
\r
// prototypes\r
\r
-static void mainloop_step ();\r
-static void mainloop_init();\r
+static void mainloop_init ();\r
+static void mainloop_wait_for_event ();\r
static void mainloop_engine_step(char * string);\r
static void mainloop_gui_step(char * string);\r
\r
+// functions\r
+\r
// mainloop_init()\r
\r
static void mainloop_init(){\r
if(!option_get_bool("UCI")){\r
- xboard_init();\r
+ xboard2uci_init(); // the default\r
}\r
}\r
\r
\r
static void mainloop_engine_step(char * string){\r
if(option_get_bool("UCI")){\r
- uci_engine_step(string); \r
+ uci2uci_engine_step(string); \r
}else{\r
- engine_step(string);\r
+ xboard2uci_engine_step(string);\r
}\r
}\r
\r
\r
static void mainloop_gui_step(char * string){\r
if(option_get_bool("UCI")){\r
- uci_gui_step(string); \r
+ uci2uci_gui_step(string); \r
+ }else if(my_string_equal(string,"uci")){ // mode auto detection\r
+ my_log("POLYGLOT *** Switching to UCI mode ***\n");\r
+ option_set("UCI","true");\r
+ uci2uci_gui_step(string);\r
}else{\r
- xboard_step(string);\r
- } \r
+ xboard2uci_gui_step(string);\r
+ }\r
}\r
\r
-\r
-\r
// mainloop()\r
\r
void mainloop() {\r
+ char string[StringSize];\r
mainloop_init();\r
- while (!engine_eof(Engine)) mainloop_step();\r
- my_log("POLYGLOT *** EOF file received from engine ***");\r
+ while (!engine_eof(Engine)) {\r
+ // process buffered lines\r
+ while(TRUE){\r
+ if(gui_get_non_blocking(GUI,string,StringSize)){\r
+ mainloop_gui_step(string);\r
+ }else if(!engine_eof(Engine) &&\r
+ engine_get_non_blocking(Engine,string,StringSize) ){\r
+ mainloop_engine_step(string);\r
+ }else{\r
+ break;\r
+ }\r
+ }\r
+ mainloop_wait_for_event();\r
+ }\r
+ my_log("POLYGLOT *** EOF file received from engine ***\n");\r
}\r
\r
-// adapter_step()\r
\r
+\r
+\r
+// mainloop_wait_for_event()\r
+\r
+static void mainloop_wait_for_event(){\r
#ifdef _WIN32\r
-static void mainloop_step(){ // polling!\r
- bool xin,ein;\r
+ HANDLE hHandles[2];\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
+ hHandles[0]=(GUI->io).hEvent;\r
+ hHandles[1]=(Engine->io).hEvent;\r
+ WaitForMultipleObjects(2, // count\r
+ hHandles, //\r
+ FALSE, // return if one object is signaled\r
+ INFINITE // no timeout\r
+ );\r
#else\r
-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
+ // add gui input\r
\r
ASSERT(GUI->io->in_fd>=0);\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
+ } \r
#endif\r
+}\r
+\r
+\r
\r
#include "pipe.h"
#include "util.h"
+// functions
+
+DWORD WINAPI ThreadProc(LPVOID lpParam){
+ PipeStruct *p=(PipeStruct *) lpParam;
+ while(!p->EOF_()){
+ p->ReadInput();
+ }
+ return 0;
+}
+
+
+
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;
- sa.lpSecurityDescriptor = NULL;
- CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0);
- CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0);
- si.cb = sizeof(STARTUPINFO);
- si.lpReserved = si.lpDesktop = si.lpTitle = NULL;
- si.dwFlags = STARTF_USESTDHANDLES;
- si.cbReserved2 = 0;
- si.lpReserved2 = NULL;
- si.hStdInput = hStdinRead;
- si.hStdOutput = hStdoutWrite;
- si.hStdError = hStdoutWrite;
- if(CreateProcess(NULL, (LPSTR) szProcFile, NULL, NULL, TRUE, DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP, NULL, NULL, &si, &pi)){
- state|=PIPE_ACTIVE;
- hProcess=pi.hProcess;
- CloseHandle(pi.hThread);
- CloseHandle(hStdinRead);
- CloseHandle(hStdoutWrite);
- hInput = hStdoutRead;
- hOutput = hStdinWrite;
- bConsole = FALSE;
+ 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);
+ bPipe=FALSE;
+ } else {
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = TRUE;
+ sa.lpSecurityDescriptor = NULL;
+ CreatePipe(&hStdinRead, &hStdinWrite, &sa, 0);
+ CreatePipe(&hStdoutRead, &hStdoutWrite, &sa, 0);
+ si.cb = sizeof(STARTUPINFO);
+ si.lpReserved = si.lpDesktop = si.lpTitle = NULL;
+ si.dwFlags = STARTF_USESTDHANDLES;
+ si.cbReserved2 = 0;
+ si.lpReserved2 = NULL;
+ si.hStdInput = hStdinRead;
+ si.hStdOutput = hStdoutWrite;
+ si.hStdError = hStdoutWrite;
+ if(CreateProcess(NULL,
+ (LPSTR) szProcFile,
+ NULL,
+ NULL,
+ TRUE,
+ DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,
+ NULL,
+ NULL,
+ &si,
+ &pi)){
+ hProcess=pi.hProcess;
+ CloseHandle(pi.hThread);
+ CloseHandle(hStdinRead);
+ CloseHandle(hStdoutWrite);
+ hInput = hStdoutRead;
+ hOutput = hStdinWrite;
+ bConsole = FALSE;
+ bPipe=TRUE;
+ }else{
+ my_fatal("PipeStruct::Open(): %s",my_error());
+ }
}
- }
- if (bConsole) {
- SetConsoleMode(hInput, dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
- FlushConsoleInputBuffer(hInput);
- } else {
- nBytesLeft = 0;
- }
- nReadEnd = 0;
+ if (bConsole) {
+ SetConsoleMode(hInput,
+ dwMode & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT));
+ FlushConsoleInputBuffer(hInput);
+ }
+ nReadEnd = 0;
+ InitializeCriticalSection(&CriticalSection);
+ hEvent=CreateEvent(NULL, // default security
+ FALSE, // auto reset
+ FALSE, // not signaled
+ NULL // nameless
+ );
+ hThread=CreateThread(NULL, // default security
+ 0, // default stacksize
+ ThreadProc, // worker function
+ this, // tell worker about ourselves
+ 0, // run immediately
+ NULL // nameless
+ );
+
+ set_Active();
}
+
void PipeStruct::Close(void) const {
- CloseHandle(hOutput);
+ CloseHandle(hOutput);
}
void PipeStruct::Kill(void) const {
- CloseHandle(hInput);
- CloseHandle(hOutput);
- DWORD lpexit;
-
- if(GetExitCodeProcess(hProcess,&lpexit)){
- if(lpexit==STILL_ACTIVE)
- //must be java,hammer it down!
- TerminateProcess(hProcess,lpexit);
- }
+ CloseHandle(hInput);
+ CloseHandle(hOutput);
+ DWORD lpexit;
+
+ if(GetExitCodeProcess(hProcess,&lpexit)){
+ if(lpexit==STILL_ACTIVE)
+ //must be java,hammer it down!
+ TerminateProcess(hProcess,lpexit);
+ }
CloseHandle(hProcess);
}
bool PipeStruct::EOF_(void){ // EOF is defined
- return state&PIPE_EOF;
+ int ret;
+ EnterCriticalSection(&CriticalSection);
+ ret=state&PIPE_EOF;
+ LeaveCriticalSection(&CriticalSection);
+ return ret;
+}
+
+void PipeStruct::set_EOF_(void){
+ EnterCriticalSection(&CriticalSection);
+ state|=PIPE_EOF;
+ LeaveCriticalSection(&CriticalSection);
}
bool PipeStruct::Active(void){
- return state&PIPE_ACTIVE;
+ int ret;
+ EnterCriticalSection(&CriticalSection);
+ ret=state&PIPE_ACTIVE;
+ LeaveCriticalSection(&CriticalSection);
+ return ret;
}
-void PipeStruct::ReadInput(void) {
- DWORD 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!
- }
+void PipeStruct::set_Active(void){
+ EnterCriticalSection(&CriticalSection);
+ state|=PIPE_ACTIVE;
+ LeaveCriticalSection(&CriticalSection);
}
-bool PipeStruct::CheckInput(void) {
- DWORD dwEvents, dwBytes;
- if (bConsole) { // a tty, or an un-redirected handle
- GetNumberOfConsoleInputEvents(hInput, &dwEvents);
- if (dwEvents > 1) {
- return TRUE;
- } else {
- return FALSE;
+
+
+int PipeStruct::ReadLine(void){
+ DWORD dwBytes;
+ int ret;
+ int start=0;
+ int start1;
+
+ if(!bPipe){
+ fgets(lpReadBuffer,LINE_INPUT_MAX_CHAR,stdin);
+ start=strlen(lpReadBuffer);
+ if(!start){
+ set_EOF_();
+ lpReadBuffer[0]='\0';
+ }
+ return start;
+ }else{
+ while(TRUE){
+ // Unfortunately we need to use polling here.
+ // Otherwise Windows returns single bytes if
+ // the engine runs at low priority.
+ // This kills performance.
+ while(TRUE){
+ ret=PeekNamedPipe(hInput,
+ NULL, // don't read anything yet
+ 0, // no buffer
+ NULL, // no we don't read anything!
+ &dwBytes,// now we're talking
+ NULL); // nono we don't read anything
+ if(!ret){
+ set_EOF_();
+ lpReadBuffer[0]='\0';
+ return 0;
+ }
+ if(dwBytes>0){
+ break;
+ }else{
+ Idle();
+ }
+
+ }
+ ret=ReadFile(hInput,
+ lpReadBuffer+start,
+ LINE_INPUT_MAX_CHAR-start,
+ &dwBytes,
+ NULL);
+ if(!ret){
+ set_EOF_();
+ lpReadBuffer[0]='\0';
+ return 0;
+ }else{
+ start1=start;
+ start+=dwBytes;
+ if (memchr(lpReadBuffer+start1, '\n', dwBytes)){
+ lpReadBuffer[start]='\0';
+ return start;
+ }
+ }
+ }
}
- } else { // a handle redirected to a pipe or a file
- if (nBytesLeft > 0) {
- return TRUE;
- } else {
- if (PeekNamedPipe(hInput, NULL, 0, NULL, &dwBytes, NULL)) {
- nBytesLeft = dwBytes;
- return nBytesLeft > 0; // a pipe
- } else {
- return TRUE; // a file, always TRUE
+}
+
+void PipeStruct::ReadInput(void) {
+ DWORD dwBytes;
+ int ret;
+ ret=ReadLine();
+ EnterCriticalSection(&CriticalSection);
+ if(!EOF_()){
+ if(ret+nReadEnd>=LINE_INPUT_MAX_CHAR){
+ my_fatal("PipeStruct::ReadInput(): buffer overflow\n");
}
- }
+ memcpy(lpBuffer+nReadEnd,lpReadBuffer,ret);
+ nReadEnd += ret;
}
+ LeaveCriticalSection(&CriticalSection);
+ SetEvent(hEvent);
}
void PipeStruct::LineOutput(const char *szLineStr) const {
DWORD dwBytes;
int nStrLen;
char szWriteBuffer[LINE_INPUT_MAX_CHAR];
- nStrLen = strlen(szLineStr);
- memcpy(szWriteBuffer, szLineStr, nStrLen);
- szWriteBuffer[nStrLen] = '\r';
- szWriteBuffer[nStrLen + 1] = '\n';
- WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
+ if(bPipe){
+ nStrLen = strlen(szLineStr);
+ memcpy(szWriteBuffer, szLineStr, nStrLen);
+ szWriteBuffer[nStrLen] = '\r';
+ szWriteBuffer[nStrLen + 1] = '\n';
+ WriteFile(hOutput, szWriteBuffer, nStrLen + 2, &dwBytes, NULL);
+ }else{
+ printf("%s\n",szLineStr);
+ fflush(stdout);
+ }
}
-
-
bool PipeStruct::GetBuffer(char *szLineStr) {
char *lpFeedEnd;
int nFeedEnd;
- lpFeedEnd = (char *) memchr(szBuffer, '\n', nReadEnd);
+ int ret;
+ EnterCriticalSection(&CriticalSection);
+ lpFeedEnd = (char *) memchr(lpBuffer, '\n', nReadEnd);
if (lpFeedEnd == NULL) {
- return FALSE;
+ ret=FALSE;
} else {
- nFeedEnd = lpFeedEnd - szBuffer;
- memcpy(szLineStr, szBuffer, nFeedEnd);
+ nFeedEnd = lpFeedEnd - lpBuffer;
+ memcpy(szLineStr, lpBuffer, nFeedEnd);
if (szLineStr[nFeedEnd - 1] == '\r') {
szLineStr[nFeedEnd - 1] = '\0';
} else {
}
nFeedEnd ++;
nReadEnd -= nFeedEnd;
- memcpy(szBuffer, szBuffer + nFeedEnd, nReadEnd);
- return TRUE;
+ memcpy(lpBuffer, lpBuffer + nFeedEnd, nReadEnd);
+ ret=TRUE;
}
+ LeaveCriticalSection(&CriticalSection);
+ return ret;
}
-bool PipeStruct::LineInput(char *szLineStr) {
- if (GetBuffer(szLineStr)) {
- return TRUE;
- }
- if (CheckInput()) {
- ReadInput();
- if (GetBuffer(szLineStr)) {
- return TRUE;
- } else {
- if (nReadEnd == LINE_INPUT_MAX_CHAR) {
- memcpy(szLineStr, szBuffer, LINE_INPUT_MAX_CHAR - 1);
- szLineStr[LINE_INPUT_MAX_CHAR - 1] = '\0';
- szBuffer[0] = szBuffer[LINE_INPUT_MAX_CHAR - 1];
- nReadEnd = 1;
- return TRUE;
- } else {
- return FALSE;
- }
+void PipeStruct::LineInput(char *szLineStr) {
+ while(!EOF_()){
+ if (GetBuffer(szLineStr)) {
+ break;
+ }else{
+ WaitForSingleObject(hEvent,INFINITE);
+ }
}
- } else {
- return FALSE;
- }
}
#endif
// constants
-const int LINE_INPUT_MAX_CHAR = 4096;
+const int LINE_INPUT_MAX_CHAR = 10*4096;
// defines
HANDLE hInput, hOutput;
HANDLE hProcess;
- DWORD state;
+ HANDLE hThread;
+ HANDLE hEvent;
BOOL bConsole;
- int nBytesLeft;
- int nReadEnd;
- char szBuffer[LINE_INPUT_MAX_CHAR];
+ BOOL bPipe;
+
+ CRITICAL_SECTION CriticalSection;
+
+ volatile DWORD state;
+ volatile int nReadEnd;
+ char lpBuffer[LINE_INPUT_MAX_CHAR];
+ char lpReadBuffer[LINE_INPUT_MAX_CHAR];
void Open(const char *szExecFile = NULL);
void Close(void) const;
void Kill(void) const;
bool EOF_(void);
+ void set_EOF_(void);
bool Active(void);
+ void set_Active(void);
void ReadInput(void);
+ int ReadLine(void);
bool CheckInput(void);
bool GetBuffer(char *szLineStr);
- bool LineInput(char *szLineStr);
+ void LineInput(char *szLineStr);
void LineOutput(const char *szLineStr) const;
-}; // pipe
+
+};
+
+// pipe
#endif
#endif
.\" ========================================================================
.\"
.IX Title "POLYGLOT 6"
-.TH POLYGLOT 6 "2009-01-15" "" ""
+.TH POLYGLOT 6 "2009-01-16" "" ""
.SH "NAME"
PolyGlot \- Winboard protocol to UCI protocol adapter
\- book engine for Polyglot books
Unconditionally stop the seach after this amount of time.
.IP "\fB\-depth\-delta\fR (default: 3)" 4
.IX Item "-depth-delta (default: 3)"
-Stop the search if the best move has been constant for this many depths,
-on condition that the mininal depth and minimal time have been reached.
+Stop the search if the solution as been found and the best move has
+been constant for this many depths, on condition that the mininal
+depth and minimal time have been reached.
.IP "\fB\-min\-depth\fR (default: 8)" 4
.IX Item "-min-depth (default: 8)"
Minimal search depth when the search is stopped using \*(L"\-depth\-delta\*(R".
\& ...
.Ve
.PP
-Lines starting with \*(L"#\*(R" are ignored.
+The characters \*(L"#\*(R" and \*(L";\*(R" serve as comment characters.
.PP
\&\s-1NOTE:\s0 There can be spaces in option names or values. Do not use
quotes. Boolean values are written as \*(L"true\*(R" or \*(L"false\*(R".
\& polyglot make\-book \-pgn games.pgn \-bin book.bin \-max\-ply 30
.Ve
.PP
-Merge books \*(L"in1.bin\*(R" and \*(L"in2.bin\*(R" into a book \*(L"out.bin\*(R".
+Merge books \*(L"w1.bin\*(R" and \*(L"w2.bin\*(R" into a book \*(L"w.bin\*(R".
.PP
.Vb 1
\& polyglot merge\-book \-in1 w1.bin \-in2 w2.bin \-out w.bin
.Ve
.PP
+Inspect lines for white in \*(L"w.bin\*(R"
+.PP
+.Vb 1
+\& polyglot dump\-book \-bin w.bin \-color white \-out w_white.txt
+.Ve
+.PP
+Test epd file \*(L"test.epd\*(R" with a (maximum) search time of 7 minutes per position
+.PP
+.Vb 1
+\& polyglot epd\-test \-epd test.epd \-max\-time 420
+.Ve
+.PP
The command line for using the \s-1UCI\s0 engine \*(L"fruit\*(R" in a \s-1GUI\s0 which uses the
xboard protocol.
.PP
=item B<-depth-delta> (default: 3)
-Stop the search if the best move has been constant for this many depths,
-on condition that the mininal depth and minimal time have been reached.
+Stop the search if the solution as been found and the best move has
+been constant for this many depths, on condition that the mininal
+depth and minimal time have been reached.
=item B<-min-depth> (default: 8)
option = value
...
-Lines starting with "#" are ignored.
+The characters "#" and ";" serve as comment characters.
NOTE: There can be spaces in option names or values. Do not use
quotes. Boolean values are written as "true" or "false".
polyglot make-book -pgn games.pgn -bin book.bin -max-ply 30
-Merge books "in1.bin" and "in2.bin" into a book "out.bin".
+Merge books "w1.bin" and "w2.bin" into a book "w.bin".
polyglot merge-book -in1 w1.bin -in2 w2.bin -out w.bin
+Inspect lines for white in "w.bin"
+
+ polyglot dump-book -bin w.bin -color white -out w_white.txt
+
+Test epd file "test.epd" with a (maximum) search time of 7 minutes per position
+
+ polyglot epd-test -epd test.epd -max-time 420
+
The command line for using the UCI engine "fruit" in a GUI which uses the
xboard protocol.
Summary: A Winboard protocol to UCI protocol adapter
Name: polyglot
-Version: 1.4w10UCIb18
+Version: 1.4w10UCIb20
Release: 1
License: GPL
Group: Amusement/Games
// do_perft()\r
\r
void do_perft(int argc,char * argv[]){\r
- const char * fen=StartFen;\r
+ const char * fen=NULL;\r
int depth=1;\r
board_t board[1];\r
int i;\r
} else if (my_string_equal(argv[i],"-fen")) {\r
i++;\r
if (argv[i] == NULL) my_fatal("do_perft(): missing argument\n");\r
- fen=strdup(argv[i]);\r
+ my_string_set(&fen,argv[i]);\r
} else if (my_string_equal(argv[i],"-max-depth")){\r
i++;\r
if (argv[i] == NULL) my_fatal("do_perft(): missing argument\n");\r
my_fatal("do_perft(): unknown option \"%s\"\n",argv[i]);\r
}\r
}\r
+ if(fen==NULL){\r
+ my_string_set(&fen,StartFen);\r
+ }\r
board_from_fen(board,fen);\r
search_perft(board,depth);\r
}\r
static bool Init=true;
static int SavedMove=MoveNone;
+// prototypes
+
+static void send_uci_options();
+
// parse_position()
static void parse_position(const char string[]) {
// send_uci_options()
-void send_uci_options() {
+static void send_uci_options() {
int i;
option_t *p=Option;
char option_line[StringSize]="";
}
-// uci_gui_step()
+// uci2uci_gui_step()
-void uci_gui_step(char string[]) {
+void uci2uci_gui_step(char string[]) {
int move;
if(false){
}else if(match(string,"uci")){
engine_send(Engine,"%s",string);
}
-void uci_engine_step(char string[]) {
+void uci2uci_engine_step(char string[]) {
gui_send(GUI,string);
}
// functions
-extern void uci_gui_step(char string[]);
-extern void uci_engine_step(char string[]);
-extern void send_uci_options();
+extern void uci2uci_gui_step(char string[]);
+extern void uci2uci_engine_step(char string[]);
#endif // !defined UCI2UCI_H
#include "posix.h"\r
#include "util.h"\r
\r
+//\r
+\r
+const int ErrorBufferSize=4096;\r
+\r
// variables\r
\r
static bool Error;\r
+static char ErrorBuffer[ErrorBufferSize];\r
\r
FILE * LogFile=NULL;\r
\r
\r
return elapsed;\r
}\r
+\r
+// my_timer()\r
+\r
+char * my_error(){\r
+#ifdef _WIN32\r
+ FormatMessage(\r
+ FORMAT_MESSAGE_FROM_SYSTEM,\r
+ NULL,\r
+ GetLastError(),\r
+ LANG_USER_DEFAULT,\r
+ ErrorBuffer,\r
+ ErrorBufferSize,\r
+ NULL);\r
+ return ErrorBuffer;\r
+#else\r
+ return strerror(errno);\r
+#endif\r
+}\r
+\r
\r
extern double my_timer_elapsed_real (const my_timer_t * timer);\r
\r
+extern char * my_error();\r
\r
#endif // !defined UTIL_H\r
\r
\r
// functions\r
\r
-// xboard_init()\r
+// xboard2uci_init()\r
\r
-void xboard_init() {\r
+void xboard2uci_init() {\r
// init\r
\r
game_clear(Game);\r
XB->opp_time = 300.0;\r
}\r
\r
-void xboard_step(char string[]) {\r
+// xboard2uci_gui_step()\r
+\r
+void xboard2uci_gui_step(char string[]) {\r
\r
int move;\r
char move_string[256];\r
board_t board[1];\r
- 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
+\r
if (false) {\r
\r
} else if (match(string,"accepted *")) {\r
return;\r
}\r
\r
-// engine_step()\r
+// xboard2uci_engine_step()\r
\r
-void engine_step(char string[]) {\r
+void xboard2uci_engine_step(char string[]) {\r
\r
int event;\r
event = uci_parse(Uci,string);\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
+extern void xboard2uci_init ();\r
+extern void xboard2uci_gui_step (char string[]);\r
+extern void xboard2uci_engine_step (char string[]);\r
\r
#endif // !defined XBOARD2UCI_H\r
\r