Declarartion of j (near line 74) needs to be before first exectuted statement of a block unless you have a C99 compiler.
Code: Select all
/*********************** USI2WB 0.2 by H.G.Muller **************************/
#include <stdio.h>
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#ifdef _MSC_VER
#define SLEEP() Sleep(1)
#else
#define SLEEP() usleep(10)
#endif
#define WHITE 0
#define BLACK 1
#define NONE 2
char pause,
pondering,
ponder,
post;
int mps,
tc,
inc,
stime,
depth,
myTime,
hisTime,
stm,
computer = NONE,
memory,
oldMem = 0;
char move[2000][10];
int moveNr;
FILE *toE,
*fromE;
HANDLE process;
int pid;
DWORD thread_id;
void Engine2GUI()
{
char line[256],
command[256];
printf("# engine thread started\n");
while (1) {
int i = 0,
x;
char *p;
fflush(stdout);
while ((line[i] = x = fgetc(fromE)) != EOF && line[i] != '\n')
i++;
line[++i] = 0;
if (x == EOF)
exit(0);
printf("# engine said: %s", line);
sscanf(line, "%s", command);
if (!strcmp(command, "bestmove")) {
if (pondering) {
pondering = 0; // bestmove was reply to ponder miss; ignore.
continue;
}
// move was a move to be played
if (strstr(line + 9, "resign")) {
printf("resign\n");
computer = NONE;
}
sscanf(line, "bestmove %s", move[moveNr++]);
// first start a new ponder search, if pondering is on and we
// have a move to ponder on
if (computer != NONE && ponder && (p = strstr(line + 9, "ponder"))) {
int j;
sscanf(p + 7, "%s", move[moveNr]);
// load position
fprintf(toE, "position startpos");
printf("# position startpos");
for (j = 0; j <= moveNr; j++)
fprintf(toE, " %s", move[j]), printf(" %s", move[j]);
// and set engine pondering
pondering = 1;
fprintf(toE, "\ngo ponder\n");
printf("\n# go ponder\n");
}
// convert USI move to WB format
line[11] = 'a' + '9' - line[11];
line[12] = 'a' + '9' - line[12];
if (line[10] == '*') { // drop
line[10] = '@';
} else {
line[9] = 'a' + '9' - line[9];
line[10] = 'a' + '9' - line[10];
if ((stm == WHITE ? (line[10] > '6' || line[12] > '6') : (line[10] < '4' || line[12] < '4')) && line[13] != '+')
line[13] = '=', line[14] = 0;
}
printf("move %s\n", line + 9); // send move to GUI
stm = WHITE + BLACK - stm;
} else if (!strcmp(command, "info")) {
int d = 0,
s = 0,
t = 0,
n = 0;
char *pv;
if (!post)
continue;
if (pv = strstr(line + 4, " pv ")) { // convert PV info to WB
// thinking output
if (p = strstr(line + 4, " depth "))
sscanf(p + 7, "%d", &d);
if (p = strstr(line + 4, " score cp "))
sscanf(p + 10, "%d", &s);
if (p = strstr(line + 4, " nodes "))
sscanf(p + 7, "%d", &n);
if (p = strstr(line + 4, " time "))
sscanf(p + 6, "%d", &t);
printf("%3d %6d %6d %10d %s", d, s, t, n, pv + 4);
}
} else if (!strcmp(command, "option")) { // pass option on as WB
// feature
char name[80],
buf[80];
// printf("feature option=\"%s -%s\"", name, );
} else if (!strcmp(command, "id")) {
char name[256];
if (sscanf(line, "id name %s", name) == 1)
printf("feature myname=\"%s (USI2WB)\"\n", name);
continue;
} else if (!strcmp(command, "readyok"))
pause = 0;
else if (!strcmp(command, "usiok"))
printf("feature done=1\n"); // done with options
}
}
void GUI2Engine()
{
char line[256],
command[256];
while (1) {
int i = 0;
if (computer == stm) {
int j;
printf("# start search\n");
// load position
fprintf(toE, "position startpos moves");
printf("# position startpos moves");
for (j = 0; j < moveNr; j++)
fprintf(toE, " %s", move[j]), printf(" %s", move[j]);
// and set engine thinking
fprintf(toE, "\ngo btime %d wtime %d", stm == WHITE ? 10 * myTime : 10 * hisTime, stm == BLACK ? 10 * myTime : 10 * hisTime);
printf("\n# go btime %d wtime %d", stm == WHITE ? 10 * myTime : 10 * hisTime, stm == BLACK ? 10 * myTime : 10 * hisTime);
if (stime > 0)
fprintf(toE, " movetime %d", stime), printf(" movetime %d", stime);
else if (mps)
fprintf(toE, " movestogo %d", mps * (moveNr / (2 * mps) + 1) - moveNr / 2), printf(" movestogo %d", mps * (moveNr / (2 * mps) + 1) - moveNr / 2);
if (inc)
fprintf(toE, " winc %d binc %d", 10 * inc, 10 * inc), printf(" winc %d binc %d", 10 * inc, 10 * inc);
if (depth > 0)
fprintf(toE, " depth %d", depth), printf(" depth %d", depth);
fprintf(toE, "\n");
printf("\n");
}
nomove:
fflush(toE);
while ((line[i] = getchar()) != EOF && line[i] != '\n')
i++;
line[++i] = 0;
sscanf(line, "%s", command);
while (pause)
SLEEP(); // wait for readyok
if (!strcmp(command, "protover")) {
printf("feature colors=0, variants=\"shogi\" setboard=1 ping=0 memory=1 smp=1 usermove=1 debug=1 reuse=0 done=0\n");
fprintf(toE, "usi\n"); // this prompts USI engine for
// options
} else if (!strcmp(command, "new")) {
computer = BLACK;
stm = WHITE;
moveNr = 0;
depth = -1;
if (memory != oldMem)
fprintf(toE, "setoption name USI_Hash value %d\n", memory);
oldMem = memory;
// we can set other options here
pause = 1; // wait for option settings to take effect
fprintf(toE, "isready\n");
fprintf(toE, "usinewgame\n");
} else if (!strcmp(command, "usermove")) {
// convert input move to USI format
if (line[10] == '@') { // drop
line[10] = '*';
} else {
line[9] = 'a' + '9' - line[9];
line[10] = 'a' + '9' - line[10];
}
line[11] = 'a' + '9' - line[11];
line[12] = 'a' + '9' - line[12];
if (line[13] == '=')
line[13] = 0; // no '=' in USI format!
else if (line[13] != '\n')
line[13] = '+'; // cater to WB 4.4 bug :-(
sscanf(line, "usermove %s", command); // strips off linefeed
stm = WHITE + BLACK - stm;
// when pondering we either continue the ponder search as normal
// search, or abort it
if (pondering) {
if (!strcmp(command, move[moveNr])) { // ponder hit
pondering = 0;
moveNr++;
fprintf(toE, "ponderhit\n");
goto nomove;
}
fprintf(toE, "stop\n"); // note: 'pondering' remains set
// until engine acknowledges 'stop'
// with 'bestmove'
}
sscanf(line, "usermove %s", move[moveNr++]); // possibly overwrites
// ponder move
} else if (!strcmp(command, "level")) {
int sec = 0;
sscanf(line, "level %d %d:%d %d", &mps, &tc, &sec, &inc) == 4 ||
sscanf(line, "level %d %d %d", &mps, &tc, &inc);
tc = (60 * tc + sec) * 100;
inc *= 100;
stime = 0;
} else if (!strcmp(command, "xboard"));
else if (!strcmp(command, "force"))
computer = NONE;
else if (!strcmp(command, "go"))
computer = stm;
else if (!strcmp(command, "time"))
sscanf(line + 4, "%d", &myTime);
else if (!strcmp(command, "otim"))
sscanf(line + 4, "%d", &hisTime);
else if (!strcmp(command, "post"))
post = 1;
else if (!strcmp(command, "nopost"))
post = 0;
else if (!strcmp(command, "easy"))
ponder = 0;
else if (!strcmp(command, "hard"))
ponder = 1;
else if (!strcmp(command, "memory"))
sscanf(line, "memory %d", &memory);
else if (!strcmp(command, "sd"))
sscanf(line, "sd %d", &depth);
else if (!strcmp(command, "st"))
sscanf(line, "st %d", &stime), stime *= 100, inc = 0;
else if (!strcmp(command, "quit"))
fprintf(toE, "quit\n"), fflush(toE), exit(0);
}
}
int StartEngine(char *cmdLine, char *dir)
{
HANDLE hChildStdinRd,
hChildStdinWr,
hChildStdoutRd,
hChildStdoutWr;
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
DWORD err;
/* Set the bInheritHandle flag so pipe handles are inherited. */
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
/* Create a pipe for the child's STDOUT. */
if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
return GetLastError();
/* Create a pipe for the child's STDIN. */
if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
return GetLastError();
SetCurrentDirectory(dir); // go to engine directory
/* Now create the child process. */
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.lpReserved = NULL;
siStartInfo.lpDesktop = NULL;
siStartInfo.lpTitle = NULL;
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.cbReserved2 = 0;
siStartInfo.lpReserved2 = NULL;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdError = hChildStdoutWr;
fSuccess = CreateProcess(NULL,
cmdLine, /* command line */
NULL, /* process security attributes */
NULL, /* primary thread security attrs */
TRUE, /* handles are inherited */
DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP,
NULL, /* use parent's environment */
NULL,
&siStartInfo, /* STARTUPINFO pointer */
&piProcInfo); /* receives
* PROCESS_INFORMATION */
if (!fSuccess)
return GetLastError();
// if (0) { // in the future we could trigger this by an argument
// SetPriorityClass(piProcInfo.hProcess, GetWin32Priority(appData.niceEngines));
// }
/* Close the handles we don't need in the parent */
CloseHandle(piProcInfo.hThread);
CloseHandle(hChildStdinRd);
CloseHandle(hChildStdoutWr);
process = piProcInfo.hProcess;
pid = piProcInfo.dwProcessId;
fromE = (FILE *) _fdopen(_open_osfhandle((long) hChildStdoutRd, _O_TEXT | _O_RDONLY), "r");
toE = (FILE *) _fdopen(_open_osfhandle((long) hChildStdinWr, _O_WRONLY), "w");
return NO_ERROR;
}
int main(int argc, char **argv)
{
char *dir = NULL;
if (argc < 2) {
printf("usage is: USI2WB <engine.exe> [<engine directory>]");
exit(-1);
}
if (argc > 2)
dir = argv[2];
// spawn engine proc
StartEngine(argv[1], dir);
// create separate thread to handle engine->GUI traffic
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Engine2GUI,
(LPVOID) NULL, 0, &thread_id);
// handle GUI->engine traffic in original thread
GUI2Engine();
return 0;
}