static QString evalString(const MoveEvaluation& eval) { if (eval.isBookEval()) return "book"; if (eval.isEmpty()) return QString(); QString str; if (eval.depth() > 0) { int score = eval.score(); int absScore = qAbs(score); if (score > 0) str += "+"; // Detect mate-in-n scores if (absScore > 9900 && (absScore = 1000 - (absScore % 1000)) < 100) { if (score < 0) str += "-"; str += "M" + QString::number(absScore); } else str += QString::number(double(score) / 100.0, 'f', 2); str += "/" + QString::number(eval.depth()) + " "; } int t = eval.time(); if (t == 0) return str + "0s"; int precision = 0; if (t < 100) precision = 3; else if (t < 1000) precision = 2; else if (t < 10000) precision = 1; str += QString::number(double(t / 1000.0), 'f', precision) + 's'; return str; }
void GameAdjudicator::addEval(const Chess::Board* board, const MoveEvaluation& eval) { Chess::Side side = board->sideToMove().opposite(); // Tablebase adjudication if (m_tbEnabled) { m_result = board->tablebaseResult(); if (!m_result.isNone()) return; } // Moves forced by the user (eg. from opening book or played by user) if (eval.depth() <= 0) { m_drawScoreCount = 0; m_resignScoreCount[side] = 0; return; } // Draw adjudication if (m_drawMoveNum > 0) { if (qAbs(eval.score()) <= m_drawScore) m_drawScoreCount++; else m_drawScoreCount = 0; if (board->plyCount() / 2 >= m_drawMoveNum && m_drawScoreCount >= m_drawMoveCount * 2) { m_result = Chess::Result(Chess::Result::Adjudication, Chess::Side::NoSide); return; } } // Resign adjudication if (m_resignMoveCount > 0) { int& count = m_resignScoreCount[side]; if (eval.score() <= m_resignScore) count++; else count = 0; if (count >= m_resignMoveCount) m_result = Chess::Result(Chess::Result::Adjudication, side.opposite()); } }
void EvalWidget::onEval(const MoveEvaluation& eval) { auto nps = eval.nps(); if (nps) { QString npsStr = nps < 10000 ? QString("%1").arg(nps) : QString("%1k").arg(nps / 1000); auto item = m_statsTable->itemPrototype()->clone(); item->setText(npsStr); m_statsTable->setItem(0, NpsHeader, item); } if (eval.tbHits()) { auto item = m_statsTable->itemPrototype()->clone(); item->setText(QString::number(eval.tbHits())); m_statsTable->setItem(0, TbHeader, item); } if (eval.hashUsage()) { double usage = double(eval.hashUsage()) / 10.0; auto item = m_statsTable->itemPrototype()->clone(); item->setText(QString("%1%").arg(usage, 0, 'f', 1)); m_statsTable->setItem(0, HashHeader, item); } auto ponderMove = eval.ponderMove(); if (!ponderMove.isEmpty()) { auto item = m_statsTable->itemPrototype()->clone(); item->setText(ponderMove); m_statsTable->setItem(0, PonderMoveHeader, item); } if (eval.ponderhitRate()) { double rate = double(eval.ponderhitRate() / 10.0); auto item = m_statsTable->itemPrototype()->clone(); item->setText(QString("%1%").arg(rate, 0, 'f', 1)); m_statsTable->setItem(0, PonderHitHeader, item); } QString depth; if (eval.depth()) { depth = QString::number(eval.depth()); if (eval.selectiveDepth()) depth += "/" + QString::number(eval.selectiveDepth()); } QString time; int ms = eval.time(); if (!ms) time = ""; else if (ms < 1000) time = QString("%1 ms").arg(ms); else if (ms < 1000 * 60 * 60) time = QTime(0, 0).addMSecs(eval.time()).toString("mm:ss"); else time = QTime(0, 0).addMSecs(eval.time()).toString("hh:mm:ss"); QString nodeCount; if (eval.nodeCount()) nodeCount = QString::number(eval.nodeCount()); QString score = eval.scoreText(); QVector<QTableWidgetItem*> items; items << new QTableWidgetItem(depth) << new QTableWidgetItem(time) << new QTableWidgetItem(nodeCount) << new QTableWidgetItem(score) << new QTableWidgetItem(eval.pv()); for (int i = 0; i < 4; i++) items[i]->setTextAlignment(Qt::AlignVCenter | Qt::AlignRight); if (eval.depth() != m_depth || (eval.pv() != m_pv && !m_pv.isEmpty())) m_pvTable->insertRow(0); m_depth = eval.depth(); m_pv = eval.pv(); for (int i = 0; i < items.size(); i++) m_pvTable->setItem(0, i, items.at(i)); }