Chess::Move ChessGame::bookMove(Chess::Side side) { Q_ASSERT(!side.isNull()); if (m_book[side] == nullptr || m_moves.size() >= m_bookDepth[side] * 2) return Chess::Move(); Chess::GenericMove bookMove = m_book[side]->move(m_board->key()); Chess::Move move = m_board->moveFromGenericMove(bookMove); if (move.isNull()) return Chess::Move(); if (!m_board->isLegalMove(move)) { qWarning("Illegal opening book move for %s: %s", qPrintable(side.toString()), qPrintable(m_board->moveString(move, Chess::Board::LongAlgebraic))); return Chess::Move(); } if (m_board->isRepetition(move)) return Chess::Move(); return move; }
void XboardEngine::makeMove(const Chess::Move& move) { Q_ASSERT(!move.isNull()); QString moveString; if (move == m_nextMove) moveString = m_nextMoveString; else moveString = this->moveString(move); // If we're not in force mode, we'll have to wait for the // 'go' command until the move can be sent to the engine. if (!m_forceMode) { if (m_nextMove.isNull()) { m_nextMove = move; m_nextMoveString = moveString; return; } else if (move != m_nextMove) setForceMode(true); } if (m_ftUsermove) write("usermove " + moveString); else write(moveString); m_nextMove = Chess::Move(); }
QString XboardEngine::moveString(const Chess::Move& move) { Q_ASSERT(!move.isNull()); // Xboard always uses SAN for castling moves in random variants if (m_notation == Chess::Board::LongAlgebraic && board()->isRandomVariant()) { QString str(board()->moveString(move, Chess::Board::StandardAlgebraic)); if (str.startsWith("O-O")) return str; } return board()->moveString(move, m_notation); }
void UciEngine::parseLine(const QString& line) { const QStringRef command(firstToken(line)); if (command == "info") { parseInfo(command); } else if (command == "bestmove") { if (state() != Thinking) { if (state() == FinishingGame) pong(); else qDebug() << "Unexpected move from" << name(); return; } QString moveString(nextToken(command).toString()); m_moveStrings += " " + moveString; Chess::Move move = board()->moveFromString(moveString); if (!move.isNull()) emitMove(move); else forfeit(Chess::Result::IllegalMove, moveString); } else if (command == "readyok") { pong(); } else if (command == "uciok") { if (state() == Starting) { onProtocolStart(); ping(); } } else if (command == "id") { QStringRef tag(nextToken(command)); if (tag == "name" && name() == "UciEngine") setName(nextToken(tag, true).toString()); } else if (command == "registration") { if (nextToken(command) == "error") { qDebug("Failed to register UCI engine %s", qPrintable(name())); write("register later"); } } else if (command == "option") { EngineOption* option = parseOption(command); QString variant; if (option == 0 || !option->isValid()) qDebug("Invalid UCI option from %s: %s", qPrintable(name()), qPrintable(line)); else if (!(variant = variantFromUci(option->name())).isEmpty()) addVariant(variant); else if (option->name() == "UCI_Opponent") m_sendOpponentsName = true; else if (option->name() == "Ponder" || (option->name().startsWith("UCI_") && option->name() != "UCI_LimitStrength" && option->name() != "UCI_Elo")) { // TODO: Deal with UCI features } else { addOption(option); return; } delete option; } }