void displayPV() { int i; char sanMove[12]; for (i = 0; i < board.triangularLength[0]; i++) { toSan(board.triangularArray[0][i], sanMove); std::cout << sanMove << " "; makeMove(board.triangularArray[0][i]); } for (i = board.triangularLength[0]-1; i >= 0; i--) { unmakeMove(board.triangularArray[0][i]); } if ((!XB_MODE) && (i < 3)) std::cout << " "; // make sure to overwrite any remaining output of mode 3 std::cout << std::endl; std::cout.flush(); }
void Board::displaySearchStats(int mode, int depth, int score) { // displays various search statistics // only to be used when ply = 0 // mode = 1 : display header // mode = 2 : display full stats, including score and latest PV // mode = 3 : display current root move that is being searched // depth = ply, score = loop counter in the search move list char sanMove[12]; U64 dt, hh, mm, ss; switch (mode) { case 1: std::cout << "depth score nodes time knps PV" << std::endl; break; case 2: dt = msStop - msStart; // depth printf("%5d ", depth); // score printf("%+6.2f ", float(score/100.0)); // nodes searched if (inodes > 100000000) printf("%6.0f%c ", float(inodes/1000000.0), 'M'); else if (inodes > 10000000) printf("%6.2f%c ", float(inodes/1000000.0), 'M'); else if (inodes > 1000000) printf("%6.0f%c ", float(inodes/1000.0), 'K'); else if (inodes > 100000) printf("%6.1f%c ", float(inodes/1000.0), 'K'); else if (inodes > 10000) printf("%6.2f%c ", float(inodes/1000.0), 'K'); else printf("%7d ", inodes); // search time if (dt > 3600000) { hh = dt/3600000; mm = (dt - 3600000*hh)/60000; ss = (dt - 3600000*hh - 60000*mm)/1000; printf("%02d%c", hh, ':'); printf("%02d%c", mm, ':'); printf("%02d ", ss); } else if (dt > 60000) { mm = dt/60000; ss = (dt - 60000*mm)/1000; printf(" %02d%c", mm, ':'); printf("%02d ", ss); } else if (dt > 10000) printf(" %6.1f%c ", float(dt/1000.0), 's'); else if (dt > 1000) printf(" %6.2f%c ", float(dt/1000.0), 's'); else if (dt > 0) printf(" %5dms ", dt); else printf(" 0ms "); // search speed if (dt > 0) std::cout << std::setw(5) << (inodes/dt) << " "; else std::cout << " - "; // store this PV: rememberPV(); // display the PV displayPV(); break; case 3: // Note that the numbers refer to pseudo-legal moves: printf("%12s (%2d/%2d)%16s", " ", score+1, moveBufLen[depth+1]-moveBufLen[depth], " "); unmakeMove(moveBuffer[score]); toSan(moveBuffer[score], sanMove); std::cout << sanMove; makeMove(moveBuffer[score]); // printf("... \n"); printf("... \r"); std::cout.flush(); break; default: break; } return; }
void commands() { // ================================================================ // commands is used to read console input and execute the commands // It also serves as winboard driver. // The code is based on H.G. Muller's model WinBoard protocol driver: // http://www.open-aurec.com/wbforum/viewtopic.php?f=24&t=51739 // ================================================================= int i, j, number; int fenhalfmoveclock; int fenfullmovenumber; char fen[100]; char fencolor[1]; char fencastling[4]; char fenenpassant[2]; char sanMove[12]; char command[80]; char userinput[80]; U64 msStart,msStop, perftcount; Timer timer; Move move, dummy; // ================================================================= // infinite loop: // ================================================================= while (1) { fflush(stdout); // ================================================================= // think & move // ================================================================= if (XB_MODE) { if (XB_COMPUTER_SIDE == board.nextMove) { #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : start think" << std::endl; #endif move = board.think(); #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : exit think" << std::endl; std::cout << "#<KENNY : move " << SQUARENAME[move.getFrom()] << SQUARENAME[move.getTosq()] << std::endl; #endif if (move.moveInt) { printf("move "); printf("%s",SQUARENAME[move.getFrom()]); printf("%s",SQUARENAME[move.getTosq()]); if (move.isPromotion()) printf("%s",PIECECHARS[move.getProm()]); printf("\n"); makeMove(move); board.endOfGame++; board.endOfSearch = board.endOfGame; } } fflush(stdout); // ================================================================= // ponder // ================================================================= if (XB_COMPUTER_SIDE != XB_NONE && XB_COMPUTER_SIDE != XB_ANALYZE && XB_PONDER && board.endOfGame) { XB_NO_TIME_LIMIT = true; #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : start ponder" << std::endl; #endif move = board.think(); #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : exit ponder" << std::endl; #endif XB_NO_TIME_LIMIT = false; } // ================================================================= // analyze // ================================================================= if (XB_COMPUTER_SIDE == XB_ANALYZE) { XB_NO_TIME_LIMIT = true; #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : start analyze" << std::endl; #endif move = board.think(); #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : exit analyze" << std::endl; #endif XB_NO_TIME_LIMIT = false; } } noPonder: // ================================================================= // display the command prompt // ================================================================= if (!XB_MODE) { if (board.nextMove == WHITE_MOVE) std::cout << "wt> "; else std::cout << "bl> "; fflush(stdout); } // ================================================================= // read input, but only after attending a pending command received during // search/ponder/analyze: // ================================================================= if (!XB_DO_PENDING) { #ifdef KENNY_DEBUG_WINBOARD if (XB_MODE) std::cout << "#-KENNY : COMPUTER_SIDE=" << (int)XB_COMPUTER_SIDE << " PONDER=" << XB_PONDER << " nextMove=" << (int)board.nextMove << std::endl; #endif for (CMD_BUFF_COUNT = 0; (CMD_BUFF[CMD_BUFF_COUNT] = getchar()) != '\n'; CMD_BUFF_COUNT++); CMD_BUFF[CMD_BUFF_COUNT+1] = '\0'; #ifdef KENNY_DEBUG_WINBOARD if (XB_MODE) std::cout << "#>KENNY : " << CMD_BUFF << std::endl; #endif } #ifdef KENNY_DEBUG_WINBOARD else { if (XB_MODE) std::cout << "#>KENNY : " << CMD_BUFF << " (from peek)" << std::endl; } #endif XB_DO_PENDING = false; // ================================================================= // ignore empty lines // ================================================================= if (!CMD_BUFF_COUNT) continue; // ================================================================= // extract the first word // ================================================================= sscanf(CMD_BUFF, "%s", command); // ================================================================= // help, h or ?: show this help - list of CONSOLE-ONLY COMMANDS // ================================================================= if ((!XB_MODE) && ((!strcmp(command, "help")) || (!strcmp(command, "h")) || (!strcmp(command, "?")))) { std::cout << std::endl << "help:" << std::endl; std::cout << "black : BLACK to move" << std::endl; std::cout << "cc : play computer-to-computer " << std::endl; std::cout << "d : display board " << std::endl; std::cout << "eval : show static evaluation of this position" << std::endl; std::cout << "exit : exit program " << std::endl; std::cout << "game : show game moves " << std::endl; std::cout << "go : computer next move " << std::endl; std::cout << "help, h, or ? : show this help " << std::endl; std::cout << "info : display variables (for testing purposes)" << std::endl; std::cout << "ini : read the initialization file" << std::endl; std::cout << "memory n : max memory to use (in MB)" << std::endl; std::cout << "move e2e4, or h7h8q : enter a move (use this format)" << std::endl; std::cout << "moves : show all legal moves" << std::endl; std::cout << "new : start new game" << std::endl; std::cout << "perft n : calculate raw number of nodes from here, depth n " << std::endl; #ifdef KENNY_VERBOSE_SEE std::cout << "qsearch : shows sorted capture movelist" << std::endl; #endif std::cout << "quit : exit program " << std::endl; std::cout << "r : rotate board " << std::endl; std::cout << "readfen filename n : reads #-th FEN position from filename" << std::endl; std::cout << "sd n : set the search depth to n" << std::endl; std::cout << "setup : setup board... " << std::endl; std::cout << "test filename : starts search on all FEN position in 'filename'" << std::endl; std::cout << " using current time & search depth parameters" << std::endl; std::cout << " output is written in test.log" << std::endl; std::cout << "time s : time per move in seconds" << std::endl; std::cout << "undo : take back last move" << std::endl; std::cout << "white : WHITE to move" << std::endl; std::cout << std::endl; continue; } // ================================================================= // accepted: in reply to the "feature" command // ================================================================= if (XB_MODE && !strcmp(command, "accepted")) continue; // ================================================================= // analyze: enter analyze mode // ================================================================= if (XB_MODE && !strcmp(command, "analyze")) { XB_COMPUTER_SIDE = XB_ANALYZE; continue; } // ================================================================= // black: BLACK to move // ================================================================= if (!XB_MODE && !strcmp(command, "black") && board.nextMove == WHITE_MOVE) { board.hashkey ^= KEY.side; board.endOfSearch = 0; board.endOfGame = 0; board.nextMove = BLACK_MOVE; continue; } // ================================================================= // bk: show book moves from this position, if any // ================================================================= if (XB_MODE && !strcmp(command, "bk")) continue; // ================================================================= // cc: play computer-to-computer // ================================================================= if (!XB_MODE && !strcmp(command, "cc")) { while (!_kbhit() && !board.isEndOfgame(i, dummy)) { move = board.think(); if (move.moveInt) { makeMove(move); board.endOfGame++; board.endOfSearch = board.endOfGame; board.display(); } } continue; } // ================================================================= // computer: the opponent is also a computer chess engine // ================================================================= if (XB_MODE && !strcmp(command, "computer")) continue; // ================================================================= // cores n: informs the engine on how many CPU cores it is allowed to use maximally // ================================================================= if (XB_MODE && !strcmp(command, "cores")) continue; // ================================================================= // d: display board // ================================================================= if (!XB_MODE && !strcmp(command, "d")) { board.display(); continue; } // ================================================================= // easy: turn off pondering // ================================================================= if (XB_MODE && !strcmp(command, "easy")) { XB_PONDER = false; continue; } // ================================================================= // egtpath type path: informs the engine in which directory it can find end-game tables // ================================================================= if (XB_MODE && !strcmp(command, "egtpath")) continue; // ================================================================= // eval: show static evaluation of this position // ================================================================= if (!XB_MODE && !strcmp(command, "eval")) { number = board.eval(); std::cout << "eval score = " << number << std::endl; #ifdef KENNY_DEBUG_EVAL board.mirror(); board.display(); i = board.eval(); std::cout << "eval score = " << i << std::endl; board.mirror(); if (number != i) std::cout << "evaluation is not symmetrical! " << number << std::endl; else std::cout << "evaluation is symmetrical" << std::endl; #endif continue; } // ================================================================= // exit: leave analyze mode / exit program (if not in WB) // ================================================================= if (!strcmp(command, "exit")) { if (XB_MODE) { XB_COMPUTER_SIDE = XB_NONE; continue; } else break; } // ================================================================= // force: Set the engine to play neither color // ================================================================= if (XB_MODE && !strcmp(command, "force")) { XB_COMPUTER_SIDE = XB_NONE; continue; } // ================================================================= // game: show game moves // ================================================================= if (!XB_MODE && !strcmp(command, "game")) { if (board.endOfGame) { // make a temporary copy of board.gameLine[]; number = board.endOfGame; GameLineRecord *tmp = new GameLineRecord[number]; memcpy(tmp, board.gameLine, number * sizeof(GameLineRecord)); // unmake all moves: for (i = number-1 ; i >= 0 ; i--) { unmakeMove(tmp[i].move); board.endOfSearch = --board.endOfGame; } // redo all moves: j = board.nextMove; for (i = 0 ; i < number; i++) { // move numbering: if (!((i+j+2)%2)) std::cout << (i+2*j+2)/2 << ". "; else if (!i) std::cout << "1. ... "; // construct the move string toSan(tmp[i].move, sanMove); std::cout << sanMove; // output CRLF, or space: if (!((i+j+1)%2)) std::cout << std::endl; else std::cout << " "; // make the move: makeMove(tmp[i].move); board.endOfSearch = ++board.endOfGame; } std::cout << std::endl; // delete the temporary copy: delete[] tmp; } else { std::cout << "there are no game moves" << std::endl; } continue; } // ================================================================= // go: leave force mode and set the engine to play the color that is on move // ================================================================= if (!strcmp(command, "go")) { if (XB_MODE) { XB_COMPUTER_SIDE = board.nextMove; continue; } else { if (!board.isEndOfgame(i, dummy)) { move = board.think(); if (move.moveInt) { makeMove(move); board.endOfGame++; board.endOfSearch = board.endOfGame; } board.display(); board.isEndOfgame(i, dummy); CMD_BUFF_COUNT = '\0'; } else { board.display(); CMD_BUFF_COUNT = '\0'; } } continue; } // ================================================================= // hard: turn on pondering // ================================================================= if (XB_MODE && !strcmp(command, "hard")) { XB_PONDER = true; continue; } // ================================================================= // hint: respond with "Hint: xxx", where xxx is a suggested move // ================================================================= if (XB_MODE && !strcmp(command, "hint")) { continue; } // ================================================================= // ics hostname: the engine is playing on an Internet Chess Server (ICS) with the given hostname // ================================================================= if (XB_MODE && !strcmp(command, "ics")) { continue; } // ================================================================= // info: display variables (for testing purposes) // ================================================================= if (!XB_MODE && !strcmp(command, "info")) { info(); continue; } // ================================================================= // ini: read the initialization file // ================================================================= if (!XB_MODE && !strcmp(command, "ini")) { readIniFile(); continue; } // ================================================================= // level mps base inc: set time controls // ================================================================= if (XB_MODE && !strcmp(command, "level")) { sscanf(CMD_BUFF, "level %d %d %d", &XB_MPS, &XB_MIN, &XB_INC) == 3 || sscanf(CMD_BUFF, "level %d %d:%d %d", &XB_MPS, &XB_MIN, &XB_SEC, &XB_INC); XB_INC *= 1000; continue; } // ================================================================= // memory n: informs the engine on how much memory it is allowed to use maximally, in MB // ================================================================= if (XB_MODE && !strcmp(command, "memory")) continue; // ================================================================= // moves: show all legal moves // ================================================================= if (!XB_MODE && !strcmp(command, "moves")) { board.moveBufLen[0] = 0; board.moveBufLen[1] = movegen(board.moveBufLen[0]); std::cout << std::endl << "moves from this position:" << std::endl; number = 0; for (i = board.moveBufLen[0]; i < board.moveBufLen[1]; i++) { makeMove(board.moveBuffer[i]); if (isOtherKingAttacked()) { unmakeMove(board.moveBuffer[i]); } else { unmakeMove(board.moveBuffer[i]); toSan(board.moveBuffer[i], sanMove); std::cout << ++number << ". " << sanMove << std::endl; } } continue; } // ================================================================= // move: enter a move (use this format: move e2e4, or h7h8q) // ================================================================= if (!XB_MODE && !strcmp(command, "")) { sscanf(CMD_BUFF,"%s",userinput); // generate the pseudo-legal move list board.moveBufLen[0] = 0; board.moveBufLen[1] = movegen(board.moveBufLen[0]); if (isValidTextMove(userinput, move)) // check to see if the user move is also found in the pseudo-legal move list { makeMove(move); if (isOtherKingAttacked()) // post-move check to see if we are leaving our king in check { unmakeMove(move); std::cout << " invalid move, leaving king in check: " << userinput << std::endl; } else { board.endOfGame++; board.endOfSearch = board.endOfGame; board.display(); } } else { std::cout << " move is invalid or not recognized: " << userinput << std::endl; } continue; } // ================================================================= // name <something>: informs the engine of its opponent's name // ================================================================= if (XB_MODE && !strcmp(command, "name")) continue; // ================================================================= // new: reset the board to the standard chess starting position // ================================================================= if (!strcmp(command, "new")) { board.init(); if (XB_MODE) { XB_COMPUTER_SIDE = BLACK_MOVE; board.searchDepth = MAX_PLY; } continue; } // ================================================================= // nopost: turn off thinking/pondering output // ================================================================= if (XB_MODE && !strcmp(command, "nopost")) { XB_POST = false; continue; } // ================================================================= // otim n: set a clock that belongs to the opponent, in centiseconds // ================================================================= if (XB_MODE && !strcmp(command, "otim")) { // do not start pondering after receiving time commands, as a move will follow immediately sscanf(CMD_BUFF, "otim %d", &XB_OTIM); XB_OTIM *= 10; // convert to miliseconds; goto noPonder; } // ================================================================= // option name[=value]: setting of an engine-define option // ================================================================= if (XB_MODE && !strcmp(command, "option")) continue; // ================================================================= // perft: calculate raw number of nodes from here, depth n // ================================================================= if (!XB_MODE && !strcmp(command, "perft")) { sscanf(CMD_BUFF,"perft %d", &number); std::cout << " starting perft " << number << "..." << std::endl; timer.init(); board.moveBufLen[0] = 0; #ifdef KENNY_DEBUG_PERFT ICAPT = 0; IEP = 0; IPROM = 0; ICASTLOO = 0; ICASTLOOO = 0; ICHECK = 0; #endif msStart = timer.getms(); perftcount = perft(0, number); msStop = timer.getms(); std::cout << "nodes = " << perftcount << ", " << msStop - msStart << " ms, "; if ((msStop - msStart) > 0) std::cout << (perftcount/(msStop - msStart)) << " knods/s"; std::cout << std::endl; CMD_BUFF_COUNT = '\0'; #ifdef KENNY_DEBUG_PERFT std::cout << "captures = " << ICAPT << std::endl; std::cout << "en-passant = " << IEP << std::endl; std::cout << "castlings = " << ICASTLOO + ICASTLOOO << std::endl; std::cout << "promotions = " << IPROM << std::endl; std::cout << "checks = " << ICHECK << std::endl; #endif continue; } // ================================================================= // ping n: reply by sending the string pong n // ================================================================= if (XB_MODE && !strcmp(command, "ping")) { sscanf(CMD_BUFF,"ping %d", &number); std::cout << "pong " << number << std::endl; continue; } // ================================================================= // post: turn on thinking/pondering output // ================================================================= if (XB_MODE && !strcmp(command, "post")) { XB_POST = true; continue; } // ================================================================= // protover n: protocol version // ================================================================= if (XB_MODE && !strcmp(command, "protover")) { std::cout << "feature ping=1" << std::endl; std::cout << "feature setboard=1" << std::endl; std::cout << "feature colors=0" << std::endl; std::cout << "feature usermove=1" << std::endl; std::cout << "feature memory=1" << std::endl; std::cout << "feature debug=1" << std::endl; std::cout << "feature done=1" << std::endl; continue; } #ifdef KENNY_VERBOSE_SEE // ================================================================= // qsearch: shows sorted capture movelist // ================================================================= if (!XB_MODE && !strcmp(command, "qsearch")) { board.moveBufLen[0] = 0; board.moveBufLen[1] = captgen(board.moveBufLen[0]); std::cout << std::endl << "sorted capturing moves from this position:" << std::endl; std::cout << std::endl << " score:" << std::endl; number = 0; for (i = board.moveBufLen[0]; i < board.moveBufLen[1]; i++) { makeMove(board.moveBuffer[i]); if (isOtherKingAttacked()) { unmakeMove(board.moveBuffer[i]); } else { unmakeMove(board.moveBuffer[i]); std::cout << ++number << ". "; displayMove(board.moveBuffer[i]); std::cout << " " << board.moveBuffer[i + OFFSET].moveInt << std::endl; } } continue; } #endif // ================================================================= // quit: exit program // ================================================================= if (!strcmp(command, "quit")) break; // ================================================================= // r: rotate board // ================================================================= if (!XB_MODE && !strcmp(command, "r")) { board.viewRotated = !board.viewRotated; continue; } // ================================================================= // random: ignored // ================================================================= if (XB_MODE && !strcmp(command, "random")) continue; // ================================================================= // rating: ICS opponent's rating // ================================================================= if (XB_MODE && !strcmp(command, "rating")) continue; // ================================================================= // readfen filename n: reads #-th FEN position from filename // ================================================================= if (!XB_MODE && !strcmp(command, "readfen")) { sscanf(CMD_BUFF,"readfen %s %d", userinput, &number); board.init(); readFen(userinput, number); board.display(); continue; } // ================================================================= // rejected: feature is rejected // ================================================================= if (XB_MODE && !strcmp(command, "rejected")) continue; // ================================================================= // remove: undo the last two moves (one for each player) and continue playing the same color. // ================================================================= if (XB_MODE && !strcmp(command, "remove")) { if (board.endOfGame) { unmakeMove(board.gameLine[--board.endOfGame].move); board.endOfSearch = board.endOfGame; } if (board.endOfGame) { unmakeMove(board.gameLine[--board.endOfGame].move); board.endOfSearch = board.endOfGame; } continue; } // ================================================================= // result string {comment}: end the each game, e.g.: result 1-0 {White mates} // ================================================================= if (XB_MODE && !strcmp(command, "result")) { XB_COMPUTER_SIDE = XB_NONE; continue; } // ================================================================= // sd n: set the search depth to n // ================================================================= if (!strcmp(command, "sd")) { sscanf(CMD_BUFF,"sd %d", &board.searchDepth); if (board.searchDepth < 1) board.searchDepth = 1; if (board.searchDepth > MAX_PLY) board.searchDepth = MAX_PLY; std::cout << "KENNY> search depth " << board.searchDepth << std::endl; continue; } // ================================================================= // setboard fen: set up the board/position // ================================================================= if (XB_MODE && !strcmp(command, "setboard")) { XB_COMPUTER_SIDE = XB_NONE; sscanf(CMD_BUFF, "setboard %s %s %s %s %d %d", fen, fencolor, fencastling, fenenpassant, &fenhalfmoveclock, &fenfullmovenumber); setupFen(fen, fencolor, fencastling, fenenpassant, fenhalfmoveclock, fenfullmovenumber); continue; } // ================================================================= // setup: setup board... // ================================================================= if (!XB_MODE && !strcmp(command, "setup")) { setup(); continue; } // ================================================================= // stopfrac (0-100%): undocumented command to interactively change this // parameter (e.g. for running testsuites), default value is 60 // Don't start a new iteration if STOPFRAC fraction of the max search time // has passed // ================================================================= if (!XB_MODE && !strcmp(command, "stopfrac")) { number = (int)(STOPFRAC * 100); sscanf(CMD_BUFF, "stopfrac %d", &number); if (number < 1) number = 1; if (number > 100) number = 100; STOPFRAC = (float)(number/100.0); std::cout << "KENNY> stopfrac " << 100*STOPFRAC << std::endl; continue; } // ================================================================= // st time: set time controls // ================================================================= if (XB_MODE && !strcmp(command, "st")) { sscanf(CMD_BUFF, "st %d", &board.maxTime); board.maxTime *= board.maxTime; // convert to ms continue; } // ================================================================= // test filename: starts search on all FEN position in 'filename // ================================================================= if (!XB_MODE && !strcmp(command, "test")) { sscanf(CMD_BUFF,"test %s", userinput); board.init(); test(userinput); continue; } // ================================================================= // time: set a clock that belongs to the engine // ================================================================= if (!strcmp(command, "time")) { number = (int)board.maxTime / 1000; sscanf(CMD_BUFF,"time %d", &number); if (number < 1) number = 1; if (!XB_MODE) std::cout << "KENNY> search time " << number << " seconds" << std::endl; if (XB_MODE) { XB_CTIM = number * 10; board.maxTime = number * 10; // conversion to ms } else { board.maxTime = number * 1000; // conversion to ms } goto noPonder; } // ================================================================= // undo: take back last move // ================================================================= if (!strcmp(command, "undo")) { if (board.endOfGame) { unmakeMove(board.gameLine[--board.endOfGame].move); board.endOfSearch = board.endOfGame; if (!XB_MODE) board.display(); } else if (!XB_MODE) std::cout << "already at start of game" << std::endl; continue; } // ================================================================= // usermove move: do a move // ================================================================= if (XB_MODE && !strcmp(command, "usermove")) { sscanf(CMD_BUFF,"usermove %s",userinput); // generate the pseudo-legal move list board.moveBufLen[0] = 0; board.moveBufLen[1] = movegen(board.moveBufLen[0]); if (isValidTextMove(userinput, move)) // check to see if the user move is also found in the pseudo-legal move list { makeMove(move); if (isOtherKingAttacked()) // post-move check to see if we are leaving our king in check { #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : usermove illegal" << std::endl; #endif unmakeMove(move); } else { #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : usermove " << userinput << " made" << std::endl; #endif board.endOfGame++; board.endOfSearch = board.endOfGame; } } else { #ifdef KENNY_DEBUG_WINBOARD std::cout << "#-KENNY : usermove illegal" << std::endl; #endif } continue; } // ================================================================= // variant: the game is not standard chess // ================================================================= if(XB_MODE && !strcmp(command, "variant")) continue; // ================================================================= // white: WHITE to move // ================================================================= if (!XB_MODE && !strcmp(command, "white") && board.nextMove == BLACK_MOVE) { board.hashkey ^= KEY.side; board.endOfSearch = 0; board.endOfGame = 0; board.nextMove = WHITE_MOVE; continue; } // ================================================================= // xboard: put the engine into "xboard mode", stop all unsolicited output // ================================================================= if (!XB_MODE && !strcmp(command, "xboard")) { #ifdef KENNY_DEBUG_WINBOARD if (XB_MODE) std::cout << "#>KENNY : xboard" << std::endl; #endif std::cout << std::endl; XB_COMPUTER_SIDE = XB_NONE; XB_MODE = true; XB_POST = false; board.init(); continue; } // ================================================================= // unknown command: // ================================================================= printf("Error: unknown command: %s\n", command); #ifdef KENNY_DEBUG_WINBOARD if (XB_MODE) std::cout << "#<KENNY : Error: unknown command: " << command << std::endl; #endif } }