diff --git a/NineChess/ninechess.pro b/NineChess/ninechess.pro index 79161391..a93553b2 100644 --- a/NineChess/ninechess.pro +++ b/NineChess/ninechess.pro @@ -18,7 +18,6 @@ CONFIG += C++11 \ INCLUDEPATH += src SOURCES += \ - src/hashmap.cpp \ src/main.cpp \ src/boarditem.cpp \ src/gamecontroller.cpp \ @@ -31,6 +30,7 @@ SOURCES += \ src/aithread.cpp HEADERS += \ + src/HashNode.h \ src/boarditem.h \ src/config.h \ src/gamecontroller.h \ diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index c3af4348..93592483 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -692,6 +692,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) } board_[pos] = piece; + #ifdef HASH_MAP_ENABLE updateHash(pos); #endif @@ -788,7 +789,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/) #endif board_[currentPos] = '\x00'; #ifdef HASH_MAP_ENABLE - updateHash(currentPos); + revertHash(currentPos); #endif currentPos = pos; currentStep++; @@ -858,10 +859,20 @@ bool NineChess::capture(int c, int p, long time_p /* = -1*/) } // 去子(设置禁点) - if (currentRule.hasForbiddenPoint && context.stage == GAME_PLACING) + if (currentRule.hasForbiddenPoint && context.stage == GAME_PLACING) { +#ifdef HASH_MAP_ENABLE + revertHash(pos); +#endif board_[pos] = '\x0f'; - else // 去子 +#ifdef HASH_MAP_ENABLE + updateHash(pos); +#endif + } else { // 去子 +#ifdef HASH_MAP_ENABLE + revertHash(pos); +#endif board_[pos] = '\x00'; + } if (context.turn == PLAYER1) context.nPiecesOnBoard_2--; @@ -875,9 +886,6 @@ bool NineChess::capture(int c, int p, long time_p /* = -1*/) currentPos = 0; context.nPiecesNeedRemove--; currentStep++; -#ifdef HASH_MAP_ENABLE - updateHash(pos); -#endif // 去子完成 // 如果决出胜负 @@ -1027,6 +1035,7 @@ bool NineChess::place(int pos) } board_[pos] = piece; + #ifdef HASH_MAP_ENABLE updateHash(pos); #endif @@ -1110,7 +1119,7 @@ bool NineChess::place(int pos) #endif board_[currentPos] = '\x00'; #ifdef HASH_MAP_ENABLE - updateHash(currentPos); + revertHash(currentPos); #endif currentPos = pos; //step++; @@ -1174,11 +1183,20 @@ bool NineChess::capture(int pos) return false; } - // 去子(设置禁点) - if (currentRule.hasForbiddenPoint && context.stage == GAME_PLACING) - board_[pos] = '\x0f'; - else // 去子 - board_[pos] = '\x00'; + if (currentRule.hasForbiddenPoint && context.stage == GAME_PLACING) { +#ifdef HASH_MAP_ENABLE + revertHash(pos); +#endif + board_[pos] = '\x0f'; +#ifdef HASH_MAP_ENABLE + updateHash(pos); +#endif + } else { // 去子 +#ifdef HASH_MAP_ENABLE + revertHash(pos); +#endif + board_[pos] = '\x00'; + } if (context.turn == PLAYER1) context.nPiecesOnBoard_2--; @@ -1727,10 +1745,10 @@ void NineChess::cleanForbiddenPoints() for (int j = 0; j < N_SEATS; j++) { pos = i * N_SEATS + j; if (board_[pos] == '\x0f') { - board_[pos] = '\x00'; #ifdef HASH_MAP_ENABLE - updateHash(pos); + revertHash(pos); #endif + board_[pos] = '\x00'; } } } @@ -2324,7 +2342,8 @@ uint64_t NineChess::getHash() return context.hash; } -// hash函数,对应可重复去子的规则 + + uint64_t NineChess::updateHash(int pos) { #if 0 @@ -2345,6 +2364,16 @@ uint64_t NineChess::updateHash(int pos) // 清除或者放置棋子 context.hash ^= context.zobrist[pos][pointType]; + return context.hash; +} + +uint64_t NineChess::revertHash(int pos) +{ + return updateHash(pos); +} + +uint64_t NineChess::updateHashMisc() +{ // 清除标记位 context.hash &= ~0xFF; diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index a0c6d0d5..c939b0f0 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -496,7 +496,9 @@ protected: #ifdef HASH_MAP_ENABLE // hash相关 uint64_t getHash(); - uint64_t NineChess::updateHash(int pos); + uint64_t revertHash(int pos); + uint64_t updateHash(int pos); + uint64_t updateHashMisc(); #endif /* HASH_MAP_ENABLE */ private: diff --git a/NineChess/src/ninechessai_ab.cpp b/NineChess/src/ninechessai_ab.cpp index df92e59b..1eea4b62 100644 --- a/NineChess/src/ninechessai_ab.cpp +++ b/NineChess/src/ninechessai_ab.cpp @@ -18,7 +18,7 @@ using namespace CTSL; #ifdef HASH_MAP_ENABLE -HashMap hashmap(65536); +HashMap hashmap(1024); #endif NineChessAi_ab::NineChessAi_ab() : @@ -26,16 +26,16 @@ NineChessAi_ab::NineChessAi_ab() : requiredQuit(false), nodeCount(0), #ifdef HASH_MAP_ENABLE + hashEntryCount(0), hashHitCount(0), - //hashmap(HashMap::getInstance()), + hashInsertNewCount(0), + hashAddrHitCount(0), + hashReplaceCozDepthCount(0), + hashReplaceCozHashCount(0), #endif evaluatedNodeCount(0) { buildRoot(); - -#ifdef HASH_MAP_ENABLE - //hashmap = HashMap::getInstance(); -#endif } NineChessAi_ab::~NineChessAi_ab() @@ -52,6 +52,7 @@ void NineChessAi_ab::buildRoot() struct NineChessAi_ab::Node *NineChessAi_ab::addNode(Node *parent, int value, int move, enum NineChess::Player player) { Node *newNode = new Node; // (10%) + newNode->parent = parent; newNode->value = value; newNode->move = move; @@ -59,10 +60,13 @@ struct NineChessAi_ab::Node *NineChessAi_ab::addNode(Node *parent, int value, in nodeCount++; newNode->id = nodeCount; - //newNode->rand = rand() % 24; // (1%) - newNode->pruned = false; +#ifdef HASH_MAP_ENABLE + newNode->hash = 0; + newNode->isHash = false; +#endif + #ifdef DEBUG_AB_TREE newNode->player = player; newNode->root = rootNode; @@ -75,9 +79,6 @@ struct NineChessAi_ab::Node *NineChessAi_ab::addNode(Node *parent, int value, in newNode->alpha = -INF_VALUE; newNode->beta = INF_VALUE; newNode->result = 0; -#ifdef HASH_MAP_ENABLE - newNode->isHash = false; -#endif newNode->visited = false; int c, p; @@ -97,7 +98,7 @@ struct NineChessAi_ab::Node *NineChessAi_ab::addNode(Node *parent, int value, in } newNode->cmd = cmd; -#endif +#endif // DEBUG_AB_TREE if (parent) { parent->children.push_back(newNode); // (7%) @@ -106,12 +107,6 @@ struct NineChessAi_ab::Node *NineChessAi_ab::addNode(Node *parent, int value, in return newNode; } -// 静态hashmap初始化 -//mutex NineChessAi_ab::hashMapMutex; -//HashMap NineChessAi_ab::hashmap; -//std::unique_ptr> HashMap::instance; - - #ifdef MOVE_PRIORITY_TABLE_SUPPORT #ifdef RANDOM_MOVE void NineChessAi_ab::shuffleMovePriorityTable() @@ -158,7 +153,7 @@ void NineChessAi_ab::generateLegalMoves(Node *node) const int MOVE_PRIORITY_TABLE_SIZE = NineChess::N_RINGS * NineChess::N_SEATS; int pos = 0; - node->children.reserve(48); + node->children.reserve(48); // 余量空间 (2%) #ifdef MOVE_PRIORITY_TABLE_SUPPORT #ifdef RANDOM_MOVE @@ -173,13 +168,13 @@ void NineChessAi_ab::generateLegalMoves(Node *node) 8, 10, 12, 14, // 中圈十字架 }; #endif // RANDOM_MOVE -#else +#else // MOVE_PRIORITY_TABLE_SUPPORT int movePriorityTable[MOVE_PRIORITY_TABLE_SIZE] = { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, }; -#endif +#endif // MOVE_PRIORITY_TABLE_SUPPORT // 如果有子节点,则返回,避免重复建立 if (node->children.size()) { diff --git a/NineChess/src/ninechessai_ab.h b/NineChess/src/ninechessai_ab.h index 67af8d05..d41a0c16 100644 --- a/NineChess/src/ninechessai_ab.h +++ b/NineChess/src/ninechessai_ab.h @@ -59,12 +59,11 @@ public: vector children; // 子节点列表 struct Node* parent; // 父节点 size_t id; // 结点编号 - int rand; // 随机数,对于 value 一致的结点随机排序用 + bool pruned; // 是否在此处剪枝 #ifdef HASH_MAP_ENABLE - uint64_t hash; + uint64_t hash; // 哈希值 bool isHash; // 是否从 Hash 读取 #endif /* HASH_MAP_ENABLE */ - bool pruned; // 是否在此处剪枝 #ifdef DEBUG_AB_TREE string cmd; enum NineChess::Player player; // 此招是谁下的 @@ -193,8 +192,15 @@ private: // 评估过的结点个数 size_t evaluatedNodeCount; - // Hash 命中次数 +#ifdef HASH_MAP_ENABLE + // Hash 统计数据 + size_t hashEntryCount; size_t hashHitCount; + size_t hashInsertNewCount; + size_t hashAddrHitCount; + size_t hashReplaceCozDepthCount; + size_t hashReplaceCozHashCount; +#endif // 局面数据栈 stack contextStack;