Btw, I write a Max2WB adapter to be able to play the stand-alone versions of uMax and Toledo_Nanochess under WinBoard! This is possible, because they essentially use the same protocol now (producing a move when you enter an empty line, and relaying it by printing a new board.)
The only catch is that to make it work, the engine should not buffer its output. So in the Toledo sprogram I had to replace the
putchar(l[...]); by
write(1,l+(...),1); to achieve that. (That is 3 extra characters.) In uMax 1.6 I added an fflush(stdout); for now.
This makes them play automatically under Windows+Cygwin (and I guess also under Linux), but the adapter is dependent on the cygwin1.dll. To use the adapter, start WB with
-fcp "./Max2WB ./uMax1_6" -scp "./Max2WB ./Toledo"
This works, but, as I said, after some 15 moves Toledo crashes my system. (Of course they ignore the WinBoard TC settings; be sure to play without
auto flag.)
Code: Select all
/**************************************************/
/* Minimal Max2QH adapter by H.G. Muller */
/**************************************************/
#include <stdio.h>
#include <signal.h>
char before[80], after[80];
FILE *f;
void ReadBoard(int inp, char *board)
{ // read 64 non-blank characters
int i;
char c, *oldBoard = board;
for(i=0; i<64; i++) {
do{ read(inp, &c, 1);
} while(c == '\n' || c == ' ' || c == '\t' || c == '\r');
*board++ = c;
}
fprintf(f, "E< '%s'\n", oldBoard); fflush(f);
}
void ProduceMove(int from, int to)
{
int ifrom=-1, ito=-1, i;
write(to, "\n", 1); // send thinking command (empty line)
ReadBoard(from, after); // should respond with board;
for(i=0; i<64; i++) {
if(before[i] == after[i]) continue;
if(after[i] == '.') {
// from-square
if(ifrom <= 0 || ifrom == 7 || ifrom == 070 || ifrom == 077)
ifrom = i; // first one, or overwrite corner Rook
else if(ifrom != 4 && ifrom != 074)
ifrom = 65; // must be e.p.
} else {
// if not empty after move, must be to-square
if(ito < 0 || ito != 4 && ito != 074)
ito = i; // first one, or write King over Rook
}
if(ifrom == 65) ifrom = ito ^ 010;
}
printf("move %c%c%c%c\n", 'a'+(ifrom&7), '8'-(ifrom>>3),
'a'+(ito&7), '8'-(ito>>3));
fflush(stdout);
}
main(int argc, char **argv)
{
int toPipe[2], fromPipe[2], from_prog, to_prog, pid, pid2, i, j;
char c, buf[256], command[256], *name;
if(argc < 2)
exit(0); // first arg must be engine
name = argv[1]; while(*name) name++;
while(name-argv[1] > 0 && name[-1] != '\\' && name[-1] != '/') name--;
/* OK, so we now send through to_prog, receive through from_prog */
f = fopen("log", "w");
{ /* cmain loop ommunicates to WinBoard */
int ponderStateWB = 0;
int ponderStateQH = 2;
int forceMode = 0;
setbuf(stdin, NULL);
i = 0;
while((c=getchar()) != EOF) {
if(c == '\r') continue;
if(c != '\n') { buf[i++] = c; continue; }
buf[i] = 0;
fprintf(f, "WB> %s\n", buf); fflush(f);
sscanf(buf, "%s", command);
if(!strcmp(command, "quit")) // pass on & kill
close(to_prog),
close(from_prog),
kill(pid, SIGKILL),
fclose(f),
exit(0);
else if(!strcmp(command, "result")) // pass on & kill
close(to_prog),
close(from_prog),
kill(pid, SIGKILL);
else if(!strcmp(command, "protover"))
printf("feature myname=\"%s\" done=1\n", name),
fflush(stdout);
else if(!strcmp(command, "go")) // end force mode & think
forceMode=0,
ProduceMove(from_prog, to_prog);
else if(!strcmp(command, "hard"))
ponderStateWB = 1;
else if(!strcmp(command, "easy"))
ponderStateWB = 0;
else if(!strcmp(command, "force")) // remember
forceMode = 1;
else if(!strcmp(command, "new")) { // start new engine proc
/* close old pipes */
if(from_prog)close(from_prog);
if(to_prog)close(to_prog);
/* set up pipes */
pipe(toPipe);
pipe(fromPipe);
/* create engine */
if((pid = fork()) == 0)
{ /* child */
fclose(stderr);
close(toPipe[1]);
close(fromPipe[0]);
dup2(toPipe[0], 0);
dup2(fromPipe[1], 1);
if(toPipe[0] >= 2) close(toPipe[0]);
close(fromPipe[1]);
execv(argv[1], argv+1);
perror(argv[1]);
exit(1);
}
/* parent */
close(toPipe[0]);
close(fromPipe[1]);
from_prog = fromPipe[0];
to_prog = toPipe[1];
forceMode = 0;
ReadBoard(from_prog, before);
} else if((buf[4] == 0 || buf[5] == 0) &&
command[0] >= 'a' && command[0] <= 'h' &&
command[2] >= 'a' && command[2] <= 'h' &&
command[1] >= '1' && command[1] <= '8' &&
command[3] >= '1' && command[3] <= '8' ) // pass on
{ /* move */
sprintf(command, "%c%c%c%c\n",
buf[0], buf[1], buf[2], buf[3]);
write(to_prog, command, 5);
ReadBoard(from_prog, before); // read board after forced move
if(!forceMode) // go thinking if not in force mode
ProduceMove(from_prog, to_prog);
}
i = 0;
}
}
}