diff --git a/ChineseChess.pro.user b/ChineseChess.pro.user index 129305a..184d04c 100644 --- a/ChineseChess.pro.user +++ b/ChineseChess.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId @@ -60,6 +60,7 @@ *.md, *.MD, Makefile false true + true @@ -100,16 +101,16 @@ ProjectExplorer.Project.Target.0 Desktop - Desktop Qt 6.3.1 MinGW 64-bit - Desktop Qt 6.3.1 MinGW 64-bit - qt.qt6.631.win64_mingw_kit + Desktop Qt 6.4.2 MinGW 64-bit + Desktop Qt 6.4.2 MinGW 64-bit + qt.qt6.642.win64_mingw_kit 1 0 0 0 - D:\Qt\QtProjects\build-ChineseChess-Desktop_Qt_6_3_1_MinGW_64_bit-Debug - D:/Qt/QtProjects/build-ChineseChess-Desktop_Qt_6_3_1_MinGW_64_bit-Debug + D:\Qt\QtProjects\ChineseChess\..\build-ChineseChess-Desktop_Qt_6_4_2_MinGW_64_bit-Debug + D:/Qt/QtProjects/build-ChineseChess-Desktop_Qt_6_4_2_MinGW_64_bit-Debug true @@ -122,8 +123,8 @@ Qt4ProjectManager.MakeStep 2 - Build - Build + 构建 + 构建 ProjectExplorer.BuildSteps.Build @@ -147,8 +148,8 @@ 2 - D:\Qt\QtProjects\build-ChineseChess-Desktop_Qt_6_3_1_MinGW_64_bit-Release - D:/Qt/QtProjects/build-ChineseChess-Desktop_Qt_6_3_1_MinGW_64_bit-Release + D:\Qt\QtProjects\ChineseChess\..\build-ChineseChess-Desktop_Qt_6_4_2_MinGW_64_bit-Release + D:/Qt/QtProjects/build-ChineseChess-Desktop_Qt_6_4_2_MinGW_64_bit-Release true @@ -161,8 +162,8 @@ Qt4ProjectManager.MakeStep 2 - Build - Build + 构建 + 构建 ProjectExplorer.BuildSteps.Build @@ -188,8 +189,8 @@ 0 - D:\Qt\QtProjects\build-ChineseChess-Desktop_Qt_6_3_1_MinGW_64_bit-Profile - D:/Qt/QtProjects/build-ChineseChess-Desktop_Qt_6_3_1_MinGW_64_bit-Profile + D:\Qt\QtProjects\ChineseChess\..\build-ChineseChess-Desktop_Qt_6_4_2_MinGW_64_bit-Profile + D:/Qt/QtProjects/build-ChineseChess-Desktop_Qt_6_4_2_MinGW_64_bit-Profile true @@ -202,8 +203,8 @@ Qt4ProjectManager.MakeStep 2 - Build - Build + 构建 + 构建 ProjectExplorer.BuildSteps.Build @@ -232,8 +233,8 @@ 0 - Deploy - Deploy + 部署 + 部署 ProjectExplorer.BuildSteps.Deploy 1 @@ -256,7 +257,7 @@ true false true - D:/Qt/QtProjects/build-ChineseChess-Desktop_Qt_6_3_1_MinGW_64_bit-Release + D:/Qt/QtProjects/build-ChineseChess-Desktop_Qt_6_4_2_MinGW_64_bit-Release 1 diff --git a/src/GUI/dialog.cpp b/src/GUI/dialog.cpp index a00ada3..fd93936 100644 --- a/src/GUI/dialog.cpp +++ b/src/GUI/dialog.cpp @@ -439,17 +439,8 @@ void Dialog::on_PlayerSide_currentIndexChanged(int index) { // 电脑难度选择 void Dialog::on_ComputerHard_currentIndexChanged(int index) { - // 电脑每一步至少搜索多长时间(单位:毫秒) - switch (index) { - case 0: - this->m_chessEngine->setSearchTime(3000); - break; - case 1: - this->m_chessEngine->setSearchTime(6000); - break; - default: - this->m_chessEngine->setSearchTime(9000); - } + // 电脑每一步至少搜索多长时间(单位:毫秒) + this->m_chessEngine->setSearchTime(1000 * (index + 1)); } // 翻转按钮点击槽函数 @@ -764,6 +755,7 @@ inline void Dialog::setMoving(const bool isMoving) { // 查找云开局库 inline std::tuple Dialog::searchBook() { QNetworkAccessManager cloudBook; + cloudBook.setTransferTimeout(500); // 搜索开局库 QNetworkReply *cloudReply = cloudBook.get( QNetworkRequest{"http://www.chessdb.cn/chessdb.php?action=queryall&board=" + diff --git a/src/GUI/dialog.ui b/src/GUI/dialog.ui index 142ced2..3a07e4c 100644 --- a/src/GUI/dialog.ui +++ b/src/GUI/dialog.ui @@ -995,16 +995,49 @@ color:transparent; font:40px + + 2 + + + + 1 秒 + + + + + 2 秒 + + 3 秒 + + + 4 秒 + + + + + 5 秒 + + 6 秒 + + + 7 秒 + + + + + 8 秒 + + 9 秒 diff --git a/src/search/chessengine.cpp b/src/search/chessengine.cpp index d0fb641..e6ae0e0 100644 --- a/src/search/chessengine.cpp +++ b/src/search/chessengine.cpp @@ -33,6 +33,15 @@ void ChessEngine::search() { // 时间控制 auto startTimeStamp = clock(); + auto timeMan = QtConcurrent::run([&] { + while (not searchInstances.front().isStopped() and + clock() - startTimeStamp < this->m_searchTime) { + std::this_thread::yield(); + } + for (auto &searchInstance : searchInstances) { + searchInstance.stopSearch(); + } + }); forever { // 多线程搜索 @@ -41,15 +50,10 @@ void ChessEngine::search() { searchInstance.searchRoot(this->m_currentDepth); } - // 随便取出一个最好的分数查看一下 - this->m_bestScore = searchInstances.front().bestScore(); - this->m_bestMove = searchInstances.front().bestMove(); - - // 如果只有一个合法走法或者赢了或者输了或者产生了长将局面或者超过时间就停止搜索就不用再往下搜索了 - if (searchInstances.front().legalMove() == 1 or - this->m_bestScore < LOST_SCORE or this->m_bestScore > WIN_SCORE or - clock() - startTimeStamp > this->m_searchTime) { - // 从所有的线程中选出分数最高的那一个走法来走 + // 记录所有的线程中最高分数与对应的走法 + if (not searchInstances.front().isStopped()) { + this->m_bestScore = searchInstances.front().bestScore(); + this->m_bestMove = searchInstances.front().bestMove(); for (const auto &searchInstance : searchInstances) { qint16 threadScore { searchInstance.bestScore() }; if (this->m_bestScore < threadScore) { @@ -57,10 +61,24 @@ void ChessEngine::search() { this->m_bestMove = searchInstance.bestMove(); } } + } else { + // 如果被迫停止,那么这一层没有搜索完成 + --this->m_currentDepth; + } + + // 如果只有一个合法走法或者超过了最大层数或者超过时间就停止搜索就不用再往下搜索了 + if (searchInstances.front().isStopped() or + searchInstances.front().legalMove() == 1 or + this->m_currentDepth >= 99 or + clock() - startTimeStamp > this->m_searchTime) { + // 停止时间管理 + searchInstances.front().stopSearch(); + timeMan.waitForFinished(); // 走棋 this->m_chessboard.makeMove(this->m_bestMove); break; } + // 增加层数 ++this->m_currentDepth; } diff --git a/src/search/searchinstance.cpp b/src/search/searchinstance.cpp index 48ef141..e17ebaf 100644 --- a/src/search/searchinstance.cpp +++ b/src/search/searchinstance.cpp @@ -2,10 +2,10 @@ namespace PikaChess { /** 搜索的衰减层数 [第几层][第几个走法] */ -quint16 REDUCTIONS[64][128]; +quint16 REDUCTIONS[100][128]; /** 延迟走法裁剪的裁剪层数 [第几层] */ -quint16 LMP_MOVE_COUNT[64]; +quint16 LMP_MOVE_COUNT[100]; SearchInstance::SearchInstance(const Chessboard &chessboard, HashTable &hashTable) : m_chessboard { chessboard }, m_hashTable { hashTable } { } @@ -74,7 +74,7 @@ qint16 SearchInstance::searchFull(qint16 alpha, const qint16 beta, this->m_iidMove = INVALID_MOVE; // 达到深度就返回静态评价,由于空着裁剪,深度可能小于-1 - if (depth <= 0) return searchQuiescence(alpha, beta); + if (depth <= 0 or this->m_stop) return searchQuiescence(alpha, beta); // 杀棋步数裁剪 qint16 tryScore = LOSS_SCORE + this->m_distance; @@ -278,6 +278,10 @@ Move SearchInstance::bestMove() const { return this->m_bestMove; } quint8 SearchInstance::legalMove() const { return this->m_legalMove; } +void SearchInstance::stopSearch() { this->m_stop = true; } + +bool SearchInstance::isStopped() const { return this->m_stop; } + bool SearchInstance::makeMove(Move &move) { bool result { this->m_chessboard.makeMove(move) }; if (result) ++this->m_distance; diff --git a/src/search/searchinstance.h b/src/search/searchinstance.h index 20304eb..e280e59 100644 --- a/src/search/searchinstance.h +++ b/src/search/searchinstance.h @@ -28,6 +28,12 @@ class SearchInstance { /** 当前局面有效的走法数 */ quint8 legalMove() const; + /** 让线程停止搜索 */ + void stopSearch(); + + /** 查看当前线程是否已经停止搜索 */ + bool isStopped() const; + protected: /** 走一步 */ bool makeMove(Move &move); @@ -51,6 +57,9 @@ class SearchInstance { void setBestMove(const Move &move, qint8 depth); private: + /** 停止标志 */ + volatile bool m_stop { false }; + /** 距离根节点的距离 */ quint8 m_distance { 0 }; diff --git a/src/table/pregen.cpp b/src/table/pregen.cpp index 47e56a3..680496b 100644 --- a/src/table/pregen.cpp +++ b/src/table/pregen.cpp @@ -9,10 +9,10 @@ extern __m128i BITBOARD_MASK[90]; extern __m128i BITBOARD_NOT_MASK[90]; /** 延迟走法衰减的衰减层数 */ -extern quint16 REDUCTIONS[64][128]; +extern quint16 REDUCTIONS[100][128]; /** 延迟走法裁剪的裁剪层数 [第几层] */ -extern quint16 LMP_MOVE_COUNT[64]; +extern quint16 LMP_MOVE_COUNT[100]; PreGen::PreGen() { // 位棋盘掩码初始化 @@ -92,7 +92,7 @@ PreGen::PreGen() { quint16 reduce[128]; for (quint8 i { 1 }; i < 128; ++i) reduce[i] = int(21.9 * std::log(i)); - for (quint8 depth = 1; depth < 64; ++depth) { + for (quint8 depth = 1; depth < 100; ++depth) { LMP_MOVE_COUNT[depth] = 3 + depth * depth; for (quint8 moveCount = 1; moveCount < 128; ++moveCount) { int r = reduce[depth] * reduce[moveCount];