From 575f5396a5dd56ead8b48a18339d083f9d262f88 Mon Sep 17 00:00:00 2001 From: CalciteM Team Date: Sun, 1 Sep 2019 11:02:51 +0800 Subject: [PATCH] =?UTF-8?q?AI:=20=E8=AF=84=E4=BC=B0=E5=B1=80=E9=9D=A2?= =?UTF-8?q?=E6=97=B6=E8=80=83=E8=99=91=E5=9C=A8=E7=A7=BB=E5=8A=A8=E9=98=B6?= =?UTF-8?q?=E6=AE=B5=E7=9A=84=E6=A3=8B=E5=AD=90=E6=B4=BB=E5=8A=A8=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 并且将招法表添加预定义的表, 但暂未启用. --- NineChess/include/config.h | 16 ++-- NineChess/src/ninechess.cpp | 152 +++++++++++++++++++++++++++++++ NineChess/src/ninechess.h | 6 ++ NineChess/src/ninechessai_ab.cpp | 19 ++-- 4 files changed, 179 insertions(+), 14 deletions(-) diff --git a/NineChess/include/config.h b/NineChess/include/config.h index 90d74b4d..34c90685 100644 --- a/NineChess/include/config.h +++ b/NineChess/include/config.h @@ -42,20 +42,22 @@ //#define MIN_MAX_ONLY -//#define EVALUATE_ENABLE +#define EVALUATE_ENABLE #ifdef EVALUATE_ENABLE -#define EVALUATE_MATERIAL -#define EVALUATE_SPACE +//#define EVALUATE_MATERIAL +//#define EVALUATE_SPACE #define EVALUATE_MOBILITY -#define EVALUATE_TEMPO -#define EVALUATE_THREAT -#define EVALUATE_SHAPE -#define EVALUATE_MOTIF +//#define EVALUATE_TEMPO +//#define EVALUATE_THREAT +//#define EVALUATE_SHAPE +//#define EVALUATE_MOTIF #endif /* EVALUATE_ENABLE */ //#define MILL_FIRST +//#define CONST_MOVE_TABLE + //#define DEAL_WITH_HORIZON_EFFECT #define IDS_SUPPORT diff --git a/NineChess/src/ninechess.cpp b/NineChess/src/ninechess.cpp index e0dca4e0..da0ba455 100644 --- a/NineChess/src/ninechess.cpp +++ b/NineChess/src/ninechess.cpp @@ -210,6 +210,109 @@ NineChess::Player NineChess::getOpponent(NineChess::Player player) void NineChess::createMoveTable() { +#ifdef CONST_MOVE_TABLE + const int moveTable_noObliqueLine[NineChess::N_POINTS][NineChess::N_POINTS] = { + /* 0 */ {0, 0, 0, 0}, + /* 1 */ {0, 0, 0, 0}, + /* 2 */ {0, 0, 0, 0}, + /* 3 */ {0, 0, 0, 0}, + /* 4 */ {0, 0, 0, 0}, + /* 5 */ {0, 0, 0, 0}, + /* 6 */ {0, 0, 0, 0}, + /* 7 */ {0, 0, 0, 0}, + + /* 8 */ {9, 15, 16, 0}, + /* 9 */ {8, 10, 0, 0}, + /* 10 */ {9, 11, 18, 0}, + /* 11 */ {10, 12, 0, 0}, + /* 12 */ {11, 13, 20, 0}, + /* 13 */ {12, 14, 0, 0}, + /* 14 */ {13, 15, 22, 0}, + /* 15 */ {8, 14, 0, 0}, + + /* 16 */ {8, 17, 23, 24}, + /* 17 */ {16, 18, 0, 0}, + /* 18 */ {10, 17, 19, 26}, + /* 19 */ {18, 20, 0, 0}, + /* 20 */ {12, 19, 21, 28}, + /* 21 */ {20, 22, 0, 0}, + /* 22 */ {14, 21, 23, 30}, + /* 23 */ {16, 22, 0, 0}, + + /* 24 */ {16, 25, 31, 0}, + /* 25 */ {24, 26, 0, 0}, + /* 26 */ {18, 25, 27, 0}, + /* 27 */ {26, 28, 0, 0}, + /* 28 */ {20, 27, 29, 0}, + /* 29 */ {28, 30, 0, 0}, + /* 30 */ {22, 29, 31, 0}, + /* 31 */ {24, 30, 0, 0}, + + /* 32 */ {0, 0, 0, 0}, + /* 33 */ {0, 0, 0, 0}, + /* 34 */ {0, 0, 0, 0}, + /* 35 */ {0, 0, 0, 0}, + /* 36 */ {0, 0, 0, 0}, + /* 37 */ {0, 0, 0, 0}, + /* 38 */ {0, 0, 0, 0}, + /* 39 */ {0, 0, 0, 0}, + }; + + const int moveTable_obliqueLine[NineChess::N_POINTS][NineChess::N_POINTS] = { + /* 0 */ {0, 0, 0, 0}, + /* 1 */ {0, 0, 0, 0}, + /* 2 */ {0, 0, 0, 0}, + /* 3 */ {0, 0, 0, 0}, + /* 4 */ {0, 0, 0, 0}, + /* 5 */ {0, 0, 0, 0}, + /* 6 */ {0, 0, 0, 0}, + /* 7 */ {0, 0, 0, 0}, + + /* 8 */ {9, 15, 16, 0}, + /* 9 */ {8, 10, 17, 0}, + /* 10 */ {9, 11, 18, 0}, + /* 11 */ {10, 12, 19, 0}, + /* 12 */ {11, 13, 20, 0}, + /* 13 */ {12, 14, 21, 0}, + /* 14 */ {13, 15, 22, 0}, + /* 15 */ {8, 14, 23, 0}, + + /* 16 */ {8, 17, 23, 24}, + /* 17 */ {9, 16, 18, 25}, + /* 18 */ {10, 17, 19, 26}, + /* 19 */ {11, 18, 20, 27}, + /* 20 */ {12, 19, 21, 28}, + /* 21 */ {13, 20, 22, 29}, + /* 22 */ {14, 21, 23, 30}, + /* 23 */ {15, 16, 22, 31}, + + /* 24 */ {16, 25, 31, 0}, + /* 25 */ {17, 24, 26, 0}, + /* 26 */ {18, 25, 27, 0}, + /* 27 */ {19, 26, 28, 0}, + /* 28 */ {20, 27, 29, 0}, + /* 29 */ {21, 28, 30, 0}, + /* 30 */ {22, 29, 31, 0}, + /* 31 */ {23, 24, 30, 0}, + + /* 32 */ {0, 0, 0, 0}, + /* 33 */ {0, 0, 0, 0}, + /* 34 */ {0, 0, 0, 0}, + /* 35 */ {0, 0, 0, 0}, + /* 36 */ {0, 0, 0, 0}, + /* 37 */ {0, 0, 0, 0}, + /* 38 */ {0, 0, 0, 0}, + /* 39 */ {0, 0, 0, 0}, + }; + + if (currentRule.hasObliqueLines) { + memcpy(moveTable, moveTable_obliqueLine, sizeof(moveTable)); + } else { + memcpy(moveTable, moveTable_obliqueLine, sizeof(moveTable)); + } + +#else /* CONST_MOVE_TABLE */ + for (int r = 1; r <= N_RINGS; r++) { for (int s = 0; s < N_SEATS; s++) { int p = r * N_SEATS + s; @@ -243,6 +346,7 @@ void NineChess::createMoveTable() #endif } } +#endif /* CONST_MOVE_TABLE */ } void NineChess::createMillTable() @@ -1444,6 +1548,54 @@ bool NineChess::isAllInMills(enum Player player) return isAllInMills(ch); } +// 判断玩家的棋子周围有几个空位 +int NineChess::getSurroundedEmptyPosCount(int pos, bool includeFobidden) +{ + int count = 0; + + if ((context.turn == PLAYER1 && + (context.nPiecesOnBoard_1 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces)) || + (context.turn == PLAYER2 && + (context.nPiecesOnBoard_2 > currentRule.nPiecesAtLeast || !currentRule.allowFlyWhenRemainThreePieces))) { + int d, movePos; + for (d = 0; d < N_MOVE_DIRECTIONS; d++) { + movePos = moveTable[pos][d]; + if (movePos) { + if (board_[movePos] == 0x00 || + (includeFobidden && board_[movePos] == 0x0F)) { + count++; + } + } + } + } + + return count; +} + +// 计算玩家1和玩家2的棋子活动能力之差 +int NineChess::getMobilityDiff(bool includeFobidden) +{ + int *board = context.board; + int mobility1 = 0; + int mobility2 = 0; + int diff = 0; + int n = 0; + + for (int i = POS_BEGIN; i < POS_END; i++) { + n = getSurroundedEmptyPosCount(i, includeFobidden); + + if (board[i] & 0x10) { + mobility1 += n; + } else if (board[i] & 0x20) { + mobility2 += n; + } + } + + diff = mobility1 - mobility2; + + return diff; +} + // 判断玩家的棋子是否被围 bool NineChess::isSurrounded(int pos) { diff --git a/NineChess/src/ninechess.h b/NineChess/src/ninechess.h index f3b8492c..c318d3c0 100644 --- a/NineChess/src/ninechess.h +++ b/NineChess/src/ninechess.h @@ -451,6 +451,9 @@ public: return context.nPiecesNeedRemove; } + // 计算玩家1和玩家2的棋子活动能力之差 + int getMobilityDiff(bool includeFobidden); + // 游戏重置 bool reset(); @@ -489,6 +492,9 @@ protected: bool isAllInMills(char ch); bool isAllInMills(enum Player); + // 判断玩家的棋子周围有几个空位 + int getSurroundedEmptyPosCount(int pos, bool includeFobidden); + // 判断玩家的棋子是否被围 bool isSurrounded(int pos); diff --git a/NineChess/src/ninechessai_ab.cpp b/NineChess/src/ninechessai_ab.cpp index 9f86c505..4f2047e5 100644 --- a/NineChess/src/ninechessai_ab.cpp +++ b/NineChess/src/ninechessai_ab.cpp @@ -511,49 +511,49 @@ void NineChessAi_ab::setChess(const NineChess &chess) #ifdef EVALUATE_ENABLE #ifdef EVALUATE_MATERIAL -int NineChessAi_ab::evaluateMaterial(Node *node) +NineChessAi_ab::value_t NineChessAi_ab::evaluateMaterial(Node *node) { return 0; } #endif #ifdef EVALUATE_SPACE -int NineChessAi_ab::evaluateSpace(Node *node) +NineChessAi_ab::value_t NineChessAi_ab::evaluateSpace(Node *node) { return 0; } #endif #ifdef EVALUATE_MOBILITY -int NineChessAi_ab::evaluateMobility(Node *node) +NineChessAi_ab::value_t NineChessAi_ab::evaluateMobility(Node *node) { return 0; } #endif #ifdef EVALUATE_TEMPO -int NineChessAi_ab::evaluateTempo(Node *node) +NineChessAi_ab::value_t NineChessAi_ab::evaluateTempo(Node *node) { return 0; } #endif #ifdef EVALUATE_THREAT -int NineChessAi_ab::evaluateThreat(Node *node) +NineChessAi_ab::value_t NineChessAi_ab::evaluateThreat(Node *node) { return 0; } #endif #ifdef EVALUATE_SHAPE -int NineChessAi_ab::evaluateShape(Node *node) +NineChessAi_ab::value_t NineChessAi_ab::evaluateShape(Node *node) { return 0; } #endif #ifdef EVALUATE_MOTIF -int NineChessAi_ab::evaluateMotif(Node *node) +NineChessAi_ab::value_t NineChessAi_ab::evaluateMotif(Node *node) { return 0; } @@ -621,6 +621,11 @@ NineChessAi_ab::value_t NineChessAi_ab::evaluate(Node *node) // 按场上棋子计分 value += chessContext->nPiecesOnBoard_1 * 100 - chessContext->nPiecesOnBoard_2 * 100; +#ifdef EVALUATE_MOBILITY + // 按棋子活动能力计分 + value += chessTemp.getMobilityDiff(false) * 10; +#endif /* EVALUATE_MOBILITY */ + switch (chessContext->action) { // 选子和落子使用相同的评价方法 case NineChess::ACTION_CHOOSE: