pikafish协议
/* Pikafish Proxy - a Chinese Chess Engine Wrapper for XQWizard to run Pikafish Designed by Morning Yellow, Version: 2023-03-05, Last Modified: Jun. 2023 Copyright (C) 2023 www.xqbase.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <stdio.h> #include <string.h> #include "version.h" #include "../base/pipe.h" #include "../base/base.h" #include "../base/base2.h" #include "../base/rc4prng.h" #include "../eleeye/pregen.h" #include "../eleeye/position.h" #include "../eleeye/book.h" int main(void) { bool bUseBook; int i, nLen, mv, vl; uint32_t dwMoveStr; char *lp, *lpTime, *lp2; char sz[LINE_INPUT_MAX_CHAR], sz2[LINE_INPUT_MAX_CHAR]; char szTime[LINE_INPUT_MAX_CHAR], szInc[LINE_INPUT_MAX_CHAR], szBookFile[LINE_INPUT_MAX_CHAR]; BookStruct mvsBook[MAX_GEN_MOVES]; RC4Struct rc4; PipeStruct pipeConsole, pipeEngine; PositionStruct pos; bUseBook = true; LocatePath(sz, "pikafish-modern.exe"); LocatePath(szBookFile, "BOOK.DAT"); pipeConsole.Open(); pipeEngine.Open(sz); PreGenInit(); rc4.InitRand(); pos.FromFen(cszStartFen); while (pipeEngine.nEof == 0) { // Read Pikafish's Response while (pipeEngine.LineInput(sz)) { // printf("info string ENG->GUI: [%s]\n", sz); if (false) { // "Pikafish ...": Ignore } else if (strncmp(sz, "Pikafish ", 9) == 0) { // "id ...", "option ...", "uciok": Ignore } else if (strncmp(sz, "id ", 3) == 0) { } else if (strncmp(sz, "option ", 7) == 0) { } else if (strcmp(sz, "uciok") == 0) { // "bestmove (none)" -> "nobestmove" } else if (strcmp(sz, "bestmove (none)") == 0) { printf("nobestmove\n"); // "info depth ... score cp ..." -> "info depth ... score ..." } else if (strncmp(sz, "info depth ", 11) == 0) { lp = strstr(sz, " score cp "); if (lp != NULL) { strcpy(sz2, lp + 10); strcpy(lp + 7, sz2); } printf("%s\n", sz); // else: unchanged } else { printf("%s\n", sz); } fflush(stdout); } // Read XQWizard's Request while (pipeConsole.LineInput(sz)) { if (false) { // "ucci" -> "uci", show version and options } else if (strcmp(sz, "ucci") == 0) { printf("id name Pikafish\n"); printf("id version " PIKAFISH_VERSION "\n"); printf("option usemillisec type check default true\n"); printf("option usebook type check default true\n"); printf("option bookfiles type string default %s\n", szBookFile); printf("option hashsize type spin default 16 min 1 max 33554432\n"); printf("option threads type spin default 1 min 1 max 1024\n"); printf("ucciok\n"); strcpy(sz, "uci"); // "setoption ...": only accepts "usebook", "bookfiles", "hashsize" and "threads" } else if (strncmp(sz, "setoption ", 10) == 0) { if (false) { // "setoption usebook true/false" } else if (strncmp(sz, "setoption usebook ", 18) == 0) { lp = sz + 18; bUseBook = (strcmp(lp, "true") == 0 || strcmp(lp, "on") == 0); continue; // "setoption bookfiles ..." } else if (strncmp(sz, "setoption bookfiles ", 20) == 0) { lp = sz + 20; if (AbsolutePath(lp)) { strcpy(szBookFile, lp); } else { LocatePath(szBookFile, lp); } continue; // "setoption hashsize ..." -> "setoption name Hash value ..." } else if (strncmp(sz, "setoption hashsize ", 19) == 0) { strcpy(sz2, "setoption name Hash value "); strcat(sz2, sz + 19); strcpy(sz, sz2); // "setoption threads ..." -> "setoption name Threads value ..." } else if (strncmp(sz, "setoption threads ", 18) == 0) { sscanf(sz + 18, "%d", &i); sprintf(sz, "setoption name Threads value %d", i < 1 ? 1 : i); } else { // else: unchanged continue; } // "position ...": parse position for book search } else if (strncmp(sz, "position ", 9) == 0) { lp = strstr(sz, " fen "); if (lp == NULL) { pos.FromFen(cszStartFen); } else { pos.FromFen(lp + 5); } lp = strstr(sz, " moves "); if (lp != NULL) { lp += 7; nLen = (strlen(lp) + 1) / 5; for (i = 0; i < nLen; i ++) { mv = COORD_MOVE(*(uint32_t *) lp); lp += 5; if (mv == 0) { break; } if (pos.ucpcSquares[SRC(mv)] == 0) { break; } pos.MakeMove(mv); if (pos.LastMove().CptDrw > 0) { pos.SetIrrev(); } } } // "go ...": search book first, then call engine } else if (strncmp(sz, "go ", 3) == 0) { // search book if (bUseBook) { // a. get all moves for this position nLen = GetBookMoves(pos, szBookFile, mvsBook); if (nLen > 0) { vl = 0; for (i = 0; i < nLen; i ++) { vl += mvsBook[i].wvl; dwMoveStr = MOVE_COORD(mvsBook[i].wmv); printf("info depth 0 score %d pv %.4s\n", mvsBook[i].wvl, (const char *) &dwMoveStr); fflush(stdout); } // b. pick a random move by move weight vl = rc4.NextLong() % (uint32_t) vl; for (i = 0; i < nLen; i ++) { vl -= mvsBook[i].wvl; if (vl < 0) { break; } } // c. skip the move that causes repetition pos.MakeMove(mvsBook[i].wmv); if (pos.RepStatus(3) == 0) { dwMoveStr = MOVE_COORD(mvsBook[i].wmv); printf("bestmove %.4s", (const char *) &dwMoveStr); // d. get ponder move (next move with max weight) nLen = GetBookMoves(pos, szBookFile, mvsBook); pos.UndoMakeMove(); if (nLen > 0) { dwMoveStr = MOVE_COORD(mvsBook[0].wmv); printf(" ponder %.4s", (const char *) &dwMoveStr); } printf("\n"); fflush(stdout); continue; } pos.UndoMakeMove(); } } // "go time ..." -> "go wtime ... btime ..." lp = strstr(sz, " time "); if (lp != NULL) { lpTime = lp + 6; // copy text after "time" lp2 = strchr(lpTime, ' '); if (lp2 == NULL) { strcpy(szTime, lpTime + 6); } else { nLen = lp2 - lpTime; strncpy(szTime, lpTime, nLen); szTime[nLen] = '\0'; } // copy text after "increment" lp2 = strstr(sz, " increment "); if (lp2 == NULL) { // copy text after "movestogo" lp2 = strstr(sz, " movestogo "); if (lp2 == NULL) { sprintf(lp, " wtime %s btime %s", szTime, szTime); } else { lpTime = lp2 + 11; lp2 = strchr(lpTime, ' '); if (lp2 == NULL) { strcpy(szInc, lpTime); } else { nLen = lp2 - lpTime; strncpy(szInc, lpTime, nLen); szInc[nLen] = '\0'; } sprintf(lp, " wtime %s btime %s movestogo %s", szTime, szTime, szInc); } } else { lpTime = lp2 + 11; lp2 = strchr(lpTime, ' '); if (lp2 == NULL) { strcpy(szInc, lpTime); } else { nLen = lp2 - lpTime; strncpy(szInc, lpTime, nLen); szInc[nLen] = '\0'; } sprintf(lp, " wtime %s btime %s winc %s binc %s", szTime, szTime, szInc, szInc); } } // other options such as "go depth ...": unchanged } pipeEngine.LineOutput(sz); // printf("info string GUI->ENG: [%s]\n", sz); fflush(stdout); } Idle(); } pipeConsole.Close(); pipeEngine.Close(); return 0; }