void UciEngine::startThinking() { if (m_ponderState == PonderHit) { m_ponderState = NotPondering; write("ponderhit"); return; } const TimeControl* whiteTc = 0; const TimeControl* blackTc = 0; const TimeControl* myTc = timeControl(); if (side() == Chess::Side::White) { whiteTc = myTc; blackTc = opponent()->timeControl(); } else if (side() == Chess::Side::Black) { whiteTc = opponent()->timeControl(); blackTc = myTc; } else qFatal("Player %s doesn't have a side", qPrintable(name())); QString command = "go"; if (!m_ponderMove.isNull()) { command += " ponder"; m_ponderState = Pondering; } else m_ponderState = NotPondering; if (myTc->isInfinite()) { if (myTc->plyLimit() == 0 && myTc->nodeLimit() == 0) command += " infinite"; } else if (myTc->timePerMove() > 0) command += QString(" movetime %1").arg(myTc->timeLeft()); else { command += QString(" wtime %1").arg(whiteTc->timeLeft()); command += QString(" btime %1").arg(blackTc->timeLeft()); if (whiteTc->timeIncrement() > 0) command += QString(" winc %1").arg(whiteTc->timeIncrement()); if (blackTc->timeIncrement() > 0) command += QString(" binc %1").arg(blackTc->timeIncrement()); if (myTc->movesLeft() > 0) command += QString(" movestogo %1").arg(myTc->movesLeft()); } if (myTc->plyLimit() > 0) command += QString(" depth %1").arg(myTc->plyLimit()); if (myTc->nodeLimit() > 0) command += QString(" nodes %1").arg(myTc->nodeLimit()); write(command); }
void XboardEngine::sendTimeLeft() { if (!m_ftTime) return; if (timeControl()->isInfinite()) { write(QString("time %1").arg(s_infiniteSec)); return; } int csLeft = timeControl()->timeLeft() / 10; int ocsLeft = opponent()->timeControl()->timeLeft() / 10; if (csLeft < 0) csLeft = 0; if (ocsLeft < 0) ocsLeft = 0; write(QString("time %1\notim %2").arg(csLeft).arg(ocsLeft)); }
void XboardEngine::startGame() { m_drawOnNextMove = false; m_gotResult = false; m_forceMode = false; m_nextMove = Chess::Move(); write("new"); if (board()->variant() != "standard") write("variant " + variantToXboard(board()->variant())); if (board()->isRandomVariant() || board()->fenString() != board()->defaultFenString()) { if (m_ftSetboard) write("setboard " + board()->fenString()); else qDebug("%s doesn't support the setboard command", qPrintable(name())); } // Send the time controls const TimeControl* myTc = timeControl(); if (myTc->isInfinite()) { if (myTc->plyLimit() == 0 && myTc->nodeLimit() == 0) write(QString("st %1").arg(s_infiniteSec)); } else if (myTc->timePerMove() > 0) write(QString("st %1").arg(myTc->timePerMove() / 1000)); else write(QString("level %1 %2 %3") .arg(myTc->movesPerTc()) .arg(msToXboardTime(myTc->timePerTc())) .arg(double(myTc->timeIncrement()) / 1000)); if (myTc->plyLimit() > 0) write(QString("sd %1").arg(myTc->plyLimit())); if (myTc->nodeLimit() > 0) { if (m_ftNps) write(QString("st 1\nnps %1").arg(myTc->nodeLimit())); else qDebug("%s doesn't support the nps command", qPrintable(name())); } // Show thinking write("post"); // Pondering if (pondering()) write("hard"); else write("easy"); setForceMode(true); // Tell the opponent's type and name to the engine if (m_ftName) { if (!opponent()->isHuman()) write("computer"); write("name " + opponent()->name()); } }
Move Board::think() { // =========================================================================== // This is the entry point for search, it is intended to drive iterative deepening // The search stops if (whatever comes first): // - there is no legal move (checkmate or stalemate) // - there is only one legal move (in this case we don't need to search) // - time is up // - the search is interrupted by the user, or by winboard // - the search depth is reached // =========================================================================== int score, legalmoves, currentdepth; Move singlemove; lastScore = 0; // =========================================================================== // Check if the game has ended, or if there is only one legal move, // because then we don't need to search: // =========================================================================== if (isEndOfgame(legalmoves, singlemove)) return NOMOVE; if (legalmoves == 1) { //LC std::cout << "forced move: "; displayMove(singlemove); std::cout << std::endl; /*if (XB_MODE && XB_POST) { printf("0 0 0 0 "); displayMove(singlemove); std::cout << std::endl; }*/ return singlemove; } // =========================================================================== // There is more than legal 1 move, so prepare to search: // =========================================================================== if (XB_MODE) timeControl(); lastPVLength = 0; memset(lastPV, 0 , sizeof(lastPV)); memset(whiteHeuristics, 0, sizeof(whiteHeuristics)); memset(blackHeuristics, 0, sizeof(blackHeuristics)); inodes = 0; countdown = UPDATEINTERVAL; timedout = false; // display console header displaySearchStats(1, 0, 0); timer.init(); msStart = timer.getms(); // iterative deepening: for (currentdepth = 1; currentdepth <= searchDepth; currentdepth++) { // clear the buffers: memset(moveBufLen, 0, sizeof(moveBufLen)); memset(moveBuffer, 0, sizeof(moveBuffer)); memset(triangularLength, 0, sizeof(triangularLength)); memset(triangularArray, 0, sizeof(triangularArray)); followpv = true; allownull = true; score = alphabetapvs(0, currentdepth, -LARGE_NUMBER, LARGE_NUMBER); lastScore = score; // now check if time is up // if not decide if it makes sense to start another iteration: if (timedout) { //LC std::cout << std::endl; return (lastPV[0]); } else { if (!XB_NO_TIME_LIMIT) { msStop = timer.getms(); if ((msStop - msStart) > (STOPFRAC * maxTime)) { //if (!XB_MODE) std::cout << " ok" << std::endl; return (lastPV[0]); } } } displaySearchStats(2, currentdepth, score); // stop searching if the current depth leads to a forced mate: if ((score > (CHECKMATESCORE-currentdepth)) || (score < -(CHECKMATESCORE-currentdepth))) currentdepth = searchDepth; } return (lastPV[0]); }