From f720014bf0f4fe88b5dd8f4d3c83ff5ddd18c5c1 Mon Sep 17 00:00:00 2001 From: CalciteM Date: Sun, 23 Jun 2019 09:19:36 +0800 Subject: [PATCH] ai: refactor --- NineChess/src/ninechess.cpp | 24 +++++++++++++---------- NineChess/src/ninechess.h | 2 +- NineChess/src/ninechessai_ab.cpp | 33 ++++++++++++++++++++++++-------- NineChess/src/ninechessai_ab.h | 2 +- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index 6492d529..f2a51969 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -103,12 +103,12 @@ const struct NineChess::Rule NineChess::RULES[N_RULES] = { }; // 名义上是个数组,实际上相当于一个判断是否在棋盘上的函数 -const char NineChess::onBoard[(N_RINGS + 2) * N_SEATS] = { - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', - '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', - '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', - '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00' +const int NineChess::onBoard[(N_RINGS + 2) * N_SEATS] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 招法表 @@ -1449,14 +1449,15 @@ int NineChess::isInMills(int pos) int NineChess::addMills(int pos) { - //成三用一个64位整数了,规则如下 - //0x 00 00 00 00 00 00 00 00 - // unused unused piece1 pos1 piece2 pos2 piece3 pos3 - //piece1、piece2、piece3按照序号从小到大顺序排放 + // 成三用一个64位整数了,规则如下 + // 0x 00 00 00 00 00 00 00 00 + // unused unused piece1 pos1 piece2 pos2 piece3 pos3 + // piece1、piece2、piece3按照序号从小到大顺序排放 uint64_t mill = 0; int n = 0; int p[3], min, temp; char m = board_[pos] & '\x30'; + for (int i = 0; i < 3; i++) { p[0] = pos; p[1] = millTable[pos][i][0]; @@ -1464,6 +1465,7 @@ int NineChess::addMills(int pos) // 如果成三 if (m & board_[p[1]] & board_[p[2]]) { + // 排序 for (int j = 0; j < 2; j++) { min = j; @@ -1477,6 +1479,7 @@ int NineChess::addMills(int pos) p[j] = temp; } } + // 成三 mill = (((uint64_t)board_[p[0]]) << 40) + (((uint64_t)p[0]) << 32) @@ -1489,6 +1492,7 @@ int NineChess::addMills(int pos) if (currentRule.allowRemovePiecesRepeatedly) { n++; } + // 如果不允许相同三连反复去子 else { // 迭代器 diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index 33926c66..8445b9d3 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -171,7 +171,7 @@ public: private: // 空棋盘点位,用于判断一个棋子位置是否在棋盘上 - static const char onBoard[(N_RINGS + 2) * N_SEATS]; + static const int onBoard[(N_RINGS + 2) * N_SEATS]; // 招法表,每个位置有最多4种走法:顺时针、逆时针、向内、向外 // 这个表跟规则有关,一旦规则改变需要重新修改 diff --git a/NineChess/src/ninechessai_ab.cpp b/NineChess/src/ninechessai_ab.cpp index 3158f494..ca5c5f86 100644 --- a/NineChess/src/ninechessai_ab.cpp +++ b/NineChess/src/ninechessai_ab.cpp @@ -37,6 +37,7 @@ void NineChessAi_ab::buildChildren(Node *node) // 临时变量 char opponent = chessTemp.context.turn == NineChess::PLAYER1 ? 0x20 : 0x10; + // 列出所有合法的下一招 switch (chessTemp.context.action) { case NineChess::ACTION_CHOOSE: @@ -59,8 +60,10 @@ void NineChessAi_ab::buildChildren(Node *node) for (int i = NineChess::N_SEATS; i < (NineChess::N_RINGS + 1) * NineChess::N_SEATS; i++) { if (!chessTemp.choose(i)) continue; - if ((chessTemp.context.turn == NineChess::PLAYER1 && (chessTemp.context.nPiecesOnBoard_1 > chessTemp.currentRule.nPiecesAtLeast || !chessTemp.currentRule.allowFlyWhenRemainThreePieces)) || - (chessTemp.context.turn == NineChess::PLAYER2 && (chessTemp.context.nPiecesOnBoard_2 > chessTemp.currentRule.nPiecesAtLeast || !chessTemp.currentRule.allowFlyWhenRemainThreePieces))) { + if ((chessTemp.context.turn == NineChess::PLAYER1 && + (chessTemp.context.nPiecesOnBoard_1 > chessTemp.currentRule.nPiecesAtLeast || !chessTemp.currentRule.allowFlyWhenRemainThreePieces)) || + (chessTemp.context.turn == NineChess::PLAYER2 && + (chessTemp.context.nPiecesOnBoard_2 > chessTemp.currentRule.nPiecesAtLeast || !chessTemp.currentRule.allowFlyWhenRemainThreePieces))) { for (int j = 0; j < 4; j++) { newPos = chessTemp.moveTable[i][j]; if (newPos && !chessTemp.board_[newPos]) { @@ -247,6 +250,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) { // 评价值 int value; + // 当前节点的MinMax值,最终赋值给节点value,与alpha和Beta不同 int minMax; @@ -270,8 +274,9 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) return node->value; } +#if 0 // 检索hashmap -/* uint64_t hash = chessTemp.chessHash(); + uint64_t hash = chessTemp.chessHash(); mtx.lock(); auto itor = findHash(hash); if (node != rootNode) { @@ -287,14 +292,16 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) } } } - mtx.unlock();*/ + mtx.unlock(); +#endif // 生成子节点树 buildChildren(node); + // 排序子节点树 sortChildren(node); - // 根据演算模型执行MiniMax检索,对先手,搜索Max + // 根据演算模型执行 MiniMax 检索,对先手,搜索 Max if (chessTemp.whosTurn() == NineChess::PLAYER1) { minMax = -infinity; for (auto child : node->children) { @@ -303,15 +310,19 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) value = alphaBetaPruning(depth - 1, alpha, beta, child); chessTemp.context = dataStack.top(); dataStack.pop(); + // 取最大值 if (value > minMax) minMax = value; + if (value > alpha) alpha = value; + // 剪枝返回 if (alpha >= beta) break; } + // 取最大值 node->value = minMax; } @@ -324,15 +335,19 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) value = alphaBetaPruning(depth - 1, alpha, beta, child); chessTemp.context = dataStack.top(); dataStack.pop(); + // 取最小值 if (value < minMax) minMax = value; + if (value < beta) beta = value; + // 剪枝返回 if (alpha >= beta) break; } + // 取最小值 node->value = minMax; } @@ -344,7 +359,8 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) child->children.clear(); } - /* // 添加到hashmap +#if 0 + // 添加到hashmap mtx.lock(); if (itor == hashmap.end()) { HashValue hashValue; @@ -360,9 +376,10 @@ int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node) itor->second.depth = depth; } } - mtx.unlock();*/ + mtx.unlock(); +#endif - // 返回 + // 返回 return node->value; } diff --git a/NineChess/src/ninechessai_ab.h b/NineChess/src/ninechessai_ab.h index 10362b93..ab804644 100644 --- a/NineChess/src/ninechessai_ab.h +++ b/NineChess/src/ninechessai_ab.h @@ -109,7 +109,7 @@ private: static const size_t maxHashCount = 1024 * 1024; // 定义极大值,等于16位有符号整形数字的最大值 - static const int infinity = INT16_MAX; + static const int infinity = INT32_MAX; private: // 命令行