AI: 评估局面时考虑在移动阶段的棋子活动性

并且将招法表添加预定义的表, 但暂未启用.
This commit is contained in:
CalciteM Team 2019-09-01 11:02:51 +08:00
parent 6111be774d
commit 575f5396a5
4 changed files with 179 additions and 14 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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);

View File

@ -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: