refactor: 简化部分函数和参数变量命名
This commit is contained in:
parent
4a6b8963f7
commit
0d931e4877
|
@ -63,7 +63,7 @@ value_t Evaluation::getValue(Game &tempGame, Position *position, AIAlgorithm::No
|
||||||
|
|
||||||
// 如果形成去子状态,每有一个可去的子,算100分
|
// 如果形成去子状态,每有一个可去的子,算100分
|
||||||
case ACTION_CAPTURE:
|
case ACTION_CAPTURE:
|
||||||
nPiecesNeedRemove = (position->turn == PLAYER_1) ?
|
nPiecesNeedRemove = (position->sideToMove == PLAYER_1) ?
|
||||||
position->nPiecesNeedRemove : -(position->nPiecesNeedRemove);
|
position->nPiecesNeedRemove : -(position->nPiecesNeedRemove);
|
||||||
value += nPiecesNeedRemove * VALUE_EACH_PIECE_NEEDREMOVE;
|
value += nPiecesNeedRemove * VALUE_EACH_PIECE_NEEDREMOVE;
|
||||||
#ifdef DEBUG_AB_TREE
|
#ifdef DEBUG_AB_TREE
|
||||||
|
@ -94,7 +94,7 @@ value_t Evaluation::getValue(Game &tempGame, Position *position, AIAlgorithm::No
|
||||||
|
|
||||||
// 如果形成去子状态,每有一个可去的子,算128分
|
// 如果形成去子状态,每有一个可去的子,算128分
|
||||||
case ACTION_CAPTURE:
|
case ACTION_CAPTURE:
|
||||||
nPiecesNeedRemove = (position->turn == PLAYER_1) ?
|
nPiecesNeedRemove = (position->sideToMove == PLAYER_1) ?
|
||||||
position->nPiecesNeedRemove : -(position->nPiecesNeedRemove);
|
position->nPiecesNeedRemove : -(position->nPiecesNeedRemove);
|
||||||
value += nPiecesNeedRemove * VALUE_EACH_PIECE_NEEDREMOVE_2;
|
value += nPiecesNeedRemove * VALUE_EACH_PIECE_NEEDREMOVE_2;
|
||||||
#ifdef DEBUG_AB_TREE
|
#ifdef DEBUG_AB_TREE
|
||||||
|
@ -121,10 +121,10 @@ value_t Evaluation::getValue(Game &tempGame, Position *position, AIAlgorithm::No
|
||||||
|
|
||||||
// 走棋阶段被闷判断
|
// 走棋阶段被闷判断
|
||||||
if (position->action == ACTION_CHOOSE &&
|
if (position->action == ACTION_CHOOSE &&
|
||||||
tempGame.position.board.isAllSurrounded(position->turn, tempGame.currentRule, position->nPiecesOnBoard, position->turn) &&
|
tempGame.position.board.isAllSurrounded(position->sideToMove, tempGame.currentRule, position->nPiecesOnBoard, position->sideToMove) &&
|
||||||
tempGame.getRule()->isLoseWhenNoWay) {
|
tempGame.getRule()->isLoseWhenNoWay) {
|
||||||
// 规则要求被“闷”判负,则对手获胜
|
// 规则要求被“闷”判负,则对手获胜
|
||||||
value_t delta = position->turn == PLAYER_1 ? -VALUE_WIN : VALUE_WIN;
|
value_t delta = position->sideToMove == PLAYER_1 ? -VALUE_WIN : VALUE_WIN;
|
||||||
value += delta;
|
value += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
void MoveList::generate(AIAlgorithm &ai, Game &tempGame,
|
||||||
AIAlgorithm::Node *node, AIAlgorithm::Node *root,
|
AIAlgorithm::Node *node, AIAlgorithm::Node *root,
|
||||||
move_t bestMove)
|
move_t bestMove)
|
||||||
{
|
{
|
||||||
|
@ -65,7 +65,7 @@ void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对手
|
// 对手
|
||||||
player_t opponent = Player::getOpponent(tempGame.position.turn);
|
player_t opponent = Player::getOpponent(tempGame.position.sideToMove);
|
||||||
|
|
||||||
// 列出所有合法的下一招
|
// 列出所有合法的下一招
|
||||||
switch (tempGame.position.action) {
|
switch (tempGame.position.action) {
|
||||||
|
@ -82,11 +82,11 @@ void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempGame.position.phase != PHASE_NOTSTARTED || node != root) {
|
if (tempGame.position.phase != PHASE_NOTSTARTED || node != root) {
|
||||||
ai.addNode(node, VALUE_ZERO, (move_t)location, bestMove, tempGame.position.turn);
|
ai.addNode(node, VALUE_ZERO, (move_t)location, bestMove, tempGame.position.sideToMove);
|
||||||
} else {
|
} else {
|
||||||
// 若为先手,则抢占星位
|
// 若为先手,则抢占星位
|
||||||
if (Board::isStarLocation(location)) {
|
if (Board::isStarLocation(location)) {
|
||||||
ai.addNode(node, VALUE_INFINITE, (move_t)location, bestMove, tempGame.position.turn);
|
ai.addNode(node, VALUE_INFINITE, (move_t)location, bestMove, tempGame.position.sideToMove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempGame.position.nPiecesOnBoard[tempGame.position.turnId] > tempGame.currentRule.nPiecesAtLeast ||
|
if (tempGame.position.nPiecesOnBoard[tempGame.position.sideId] > tempGame.currentRule.nPiecesAtLeast ||
|
||||||
!tempGame.currentRule.allowFlyWhenRemainThreePieces) {
|
!tempGame.currentRule.allowFlyWhenRemainThreePieces) {
|
||||||
// 对于棋盘上还有3个子以上,或不允许飞子的情况,要求必须在着法表中
|
// 对于棋盘上还有3个子以上,或不允许飞子的情况,要求必须在着法表中
|
||||||
for (int direction = DIRECTION_CLOCKWISE; direction <= DIRECTION_OUTWARD; direction++) {
|
for (int direction = DIRECTION_CLOCKWISE; direction <= DIRECTION_OUTWARD; direction++) {
|
||||||
|
@ -113,7 +113,7 @@ void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
||||||
newLocation = moveTable[oldLocation][direction];
|
newLocation = moveTable[oldLocation][direction];
|
||||||
if (newLocation && !tempGame.boardLocations[newLocation]) {
|
if (newLocation && !tempGame.boardLocations[newLocation]) {
|
||||||
move_t move = move_t((oldLocation << 8) + newLocation);
|
move_t move = move_t((oldLocation << 8) + newLocation);
|
||||||
ai.addNode(node, VALUE_ZERO, move, bestMove, tempGame.position.turn); // (12%)
|
ai.addNode(node, VALUE_ZERO, move, bestMove, tempGame.position.sideToMove); // (12%)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -121,7 +121,7 @@ void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
||||||
for (newLocation = Board::LOCATION_BEGIN; newLocation < Board::LOCATION_END; newLocation++) {
|
for (newLocation = Board::LOCATION_BEGIN; newLocation < Board::LOCATION_END; newLocation++) {
|
||||||
if (!tempGame.boardLocations[newLocation]) {
|
if (!tempGame.boardLocations[newLocation]) {
|
||||||
move_t move = move_t((oldLocation << 8) + newLocation);
|
move_t move = move_t((oldLocation << 8) + newLocation);
|
||||||
ai.addNode(node, VALUE_ZERO, move, bestMove, tempGame.position.turn);
|
ai.addNode(node, VALUE_ZERO, move, bestMove, tempGame.position.sideToMove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
||||||
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||||
location = movePriorityTable[i];
|
location = movePriorityTable[i];
|
||||||
if (tempGame.boardLocations[location] & opponent) {
|
if (tempGame.boardLocations[location] & opponent) {
|
||||||
ai.addNode(node, VALUE_ZERO, (move_t)-location, bestMove, tempGame.position.turn);
|
ai.addNode(node, VALUE_ZERO, (move_t)-location, bestMove, tempGame.position.sideToMove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -147,7 +147,7 @@ void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
||||||
location = movePriorityTable[i];
|
location = movePriorityTable[i];
|
||||||
if (tempGame.boardLocations[location] & opponent) {
|
if (tempGame.boardLocations[location] & opponent) {
|
||||||
if (tempGame.getRule()->allowRemoveMill || !tempGame.position.board.inHowManyMills(location)) {
|
if (tempGame.getRule()->allowRemoveMill || !tempGame.position.board.inHowManyMills(location)) {
|
||||||
ai.addNode(node, VALUE_ZERO, (move_t)-location, bestMove, tempGame.position.turn);
|
ai.addNode(node, VALUE_ZERO, (move_t)-location, bestMove, tempGame.position.sideToMove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ void MoveList::generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveList::createMoveTable(Game &game)
|
void MoveList::create(Game &game)
|
||||||
{
|
{
|
||||||
// Note: 未严格按 direction_t 中枚举的顺序从左到右排列
|
// Note: 未严格按 direction_t 中枚举的顺序从左到右排列
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -374,7 +374,7 @@ void MoveList::createMoveTable(Game &game)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveList::shuffleMovePriorityTable(Game &game)
|
void MoveList::shuffle(Game &game)
|
||||||
{
|
{
|
||||||
array<move_t, 4> movePriorityTable0 = { (move_t)17, (move_t)19, (move_t)21, (move_t)23 }; // 中圈四个顶点 (星位)
|
array<move_t, 4> movePriorityTable0 = { (move_t)17, (move_t)19, (move_t)21, (move_t)23 }; // 中圈四个顶点 (星位)
|
||||||
array<move_t, 8> movePriorityTable1 = { (move_t)25, (move_t)27, (move_t)29, (move_t)31, (move_t)9, (move_t)11, (move_t)13, (move_t)15 }; // 外圈和内圈四个顶点
|
array<move_t, 8> movePriorityTable1 = { (move_t)25, (move_t)27, (move_t)29, (move_t)31, (move_t)9, (move_t)11, (move_t)13, (move_t)15 }; // 外圈和内圈四个顶点
|
||||||
|
|
|
@ -34,15 +34,15 @@ public:
|
||||||
MoveList &operator=(const MoveList &) = delete;
|
MoveList &operator=(const MoveList &) = delete;
|
||||||
|
|
||||||
// 生成所有合法的着法并建立子节点
|
// 生成所有合法的着法并建立子节点
|
||||||
static void generateLegalMoves(AIAlgorithm &ai, Game &tempGame,
|
static void generate(AIAlgorithm &ai, Game &tempGame,
|
||||||
AIAlgorithm::Node *node, AIAlgorithm::Node *root,
|
AIAlgorithm::Node *node, AIAlgorithm::Node *root,
|
||||||
move_t bestMove);
|
move_t bestMove);
|
||||||
|
|
||||||
// 生成着法表
|
// 生成着法表
|
||||||
static void createMoveTable(Game &game);
|
static void create(Game &game);
|
||||||
|
|
||||||
// 随机打乱着法搜索顺序
|
// 随机打乱着法搜索顺序
|
||||||
static void shuffleMovePriorityTable(Game &game);
|
static void shuffle(Game &game);
|
||||||
|
|
||||||
// 着法表 // TODO: Move to private
|
// 着法表 // TODO: Move to private
|
||||||
inline static move_t moveTable[Board::N_LOCATIONS][DIRECTIONS_COUNT] = { {MOVE_NONE} };
|
inline static move_t moveTable[Board::N_LOCATIONS][DIRECTIONS_COUNT] = { {MOVE_NONE} };
|
||||||
|
|
|
@ -53,9 +53,9 @@ AIAlgorithm::~AIAlgorithm()
|
||||||
root = nullptr;
|
root = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
depth_t AIAlgorithm::changeDepth(depth_t originalDepth)
|
depth_t AIAlgorithm::changeDepth(depth_t origDepth)
|
||||||
{
|
{
|
||||||
depth_t newDepth = originalDepth;
|
depth_t newDepth = origDepth;
|
||||||
|
|
||||||
if ((tempGame.position.phase) & (PHASE_PLACING)) {
|
if ((tempGame.position.phase) & (PHASE_PLACING)) {
|
||||||
#ifdef GAME_PLACING_DYNAMIC_DEPTH
|
#ifdef GAME_PLACING_DYNAMIC_DEPTH
|
||||||
|
@ -105,7 +105,7 @@ struct AIAlgorithm::Node *AIAlgorithm::addNode(
|
||||||
value_t value,
|
value_t value,
|
||||||
move_t move,
|
move_t move,
|
||||||
move_t bestMove,
|
move_t bestMove,
|
||||||
enum player_t player
|
player_t side
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
#ifdef MEMORY_POOL
|
#ifdef MEMORY_POOL
|
||||||
|
@ -137,7 +137,7 @@ struct AIAlgorithm::Node *AIAlgorithm::addNode(
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
newNode->player = player;
|
newNode->sideToMove = side;
|
||||||
|
|
||||||
#ifdef DEBUG_AB_TREE
|
#ifdef DEBUG_AB_TREE
|
||||||
newNode->root = root;
|
newNode->root = root;
|
||||||
|
@ -228,11 +228,11 @@ bool AIAlgorithm::nodeGreater(const Node *first, const Node *second)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void AIAlgorithm::sortLegalMoves(Node *node)
|
void AIAlgorithm::sortMoves(Node *node)
|
||||||
{
|
{
|
||||||
// 这个函数对效率的影响很大,排序好的话,剪枝较早,节省时间,但不能在此函数耗费太多时间
|
// 这个函数对效率的影响很大,排序好的话,剪枝较早,节省时间,但不能在此函数耗费太多时间
|
||||||
|
|
||||||
auto cmp = tempGame.position.turn == PLAYER_1 ? nodeGreater : nodeLess;
|
auto cmp = tempGame.position.sideToMove == PLAYER_1 ? nodeGreater : nodeLess;
|
||||||
|
|
||||||
std::stable_sort(node->children.begin(), node->children.end(), cmp);
|
std::stable_sort(node->children.begin(), node->children.end(), cmp);
|
||||||
}
|
}
|
||||||
|
@ -262,7 +262,7 @@ void AIAlgorithm::setGame(const Game &game)
|
||||||
// 如果规则改变,重建hashmap
|
// 如果规则改变,重建hashmap
|
||||||
if (strcmp(this->game_.currentRule.name, game.currentRule.name) != 0) {
|
if (strcmp(this->game_.currentRule.name, game.currentRule.name) != 0) {
|
||||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
TranspositionTable::clearTranspositionTable();
|
TranspositionTable::clear();
|
||||||
#endif // TRANSPOSITION_TABLE_ENABLE
|
#endif // TRANSPOSITION_TABLE_ENABLE
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef BOOK_LEARNING
|
||||||
|
@ -297,7 +297,7 @@ void AIAlgorithm::setGame(const Game &game)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int AIAlgorithm::alphaBetaPruning(depth_t depth)
|
int AIAlgorithm::search(depth_t depth)
|
||||||
{
|
{
|
||||||
value_t value = VALUE_ZERO;
|
value_t value = VALUE_ZERO;
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ int AIAlgorithm::alphaBetaPruning(depth_t depth)
|
||||||
time_t time0 = time(nullptr);
|
time_t time0 = time(nullptr);
|
||||||
srand(static_cast<unsigned int>(time0));
|
srand(static_cast<unsigned int>(time0));
|
||||||
|
|
||||||
chrono::steady_clock::time_point timeStart = chrono::steady_clock::now();
|
auto timeStart = chrono::steady_clock::now();
|
||||||
chrono::steady_clock::time_point timeEnd;
|
chrono::steady_clock::time_point timeEnd;
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef BOOK_LEARNING
|
||||||
|
@ -345,17 +345,17 @@ int AIAlgorithm::alphaBetaPruning(depth_t depth)
|
||||||
#endif // THREEFOLD_REPETITION
|
#endif // THREEFOLD_REPETITION
|
||||||
|
|
||||||
// 随机打乱着法顺序
|
// 随机打乱着法顺序
|
||||||
MoveList::shuffleMovePriorityTable(game_);
|
MoveList::shuffle(game_);
|
||||||
|
|
||||||
#ifdef IDS_SUPPORT
|
#ifdef IDS_SUPPORT
|
||||||
// 深化迭代
|
// 深化迭代
|
||||||
for (depth_t i = 2; i < d; i += 1) {
|
for (depth_t i = 2; i < d; i += 1) {
|
||||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
#ifdef CLEAR_TRANSPOSITION_TABLE
|
#ifdef CLEAR_TRANSPOSITION_TABLE
|
||||||
TranspositionTable::clearTranspositionTable(); // 每次走子前清空哈希表
|
TranspositionTable::clear(); // 每次走子前清空哈希表
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
alphaBetaPruning(i, -VALUE_INFINITE, VALUE_INFINITE, root);
|
search(i, -VALUE_INFINITE, VALUE_INFINITE, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
timeEnd = chrono::steady_clock::now();
|
timeEnd = chrono::steady_clock::now();
|
||||||
|
@ -364,11 +364,11 @@ int AIAlgorithm::alphaBetaPruning(depth_t depth)
|
||||||
|
|
||||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
#ifdef CLEAR_TRANSPOSITION_TABLE
|
#ifdef CLEAR_TRANSPOSITION_TABLE
|
||||||
TranspositionTable::clearTranspositionTable(); // 每次走子前清空哈希表
|
TranspositionTable::clear(); // 每次走子前清空哈希表
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
value = alphaBetaPruning(d, value_t(-VALUE_INFINITE) /* alpha */, VALUE_INFINITE /* beta */, root);
|
value = search(d, value_t(-VALUE_INFINITE) /* alpha */, VALUE_INFINITE /* beta */, root);
|
||||||
|
|
||||||
timeEnd = chrono::steady_clock::now();
|
timeEnd = chrono::steady_clock::now();
|
||||||
loggerDebug("Total Time: %llus\n", chrono::duration_cast<chrono::seconds>(timeEnd - timeStart).count());
|
loggerDebug("Total Time: %llus\n", chrono::duration_cast<chrono::seconds>(timeEnd - timeStart).count());
|
||||||
|
@ -378,7 +378,7 @@ int AIAlgorithm::alphaBetaPruning(depth_t depth)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_t AIAlgorithm::alphaBetaPruning(depth_t depth, value_t alpha, value_t beta, Node *node)
|
value_t AIAlgorithm::search(depth_t depth, value_t alpha, value_t beta, Node *node)
|
||||||
{
|
{
|
||||||
// 评价值
|
// 评价值
|
||||||
value_t value;
|
value_t value;
|
||||||
|
@ -483,7 +483,7 @@ value_t AIAlgorithm::alphaBetaPruning(depth_t depth, value_t alpha, value_t beta
|
||||||
evaluatedNodeCount++;
|
evaluatedNodeCount++;
|
||||||
|
|
||||||
// 为争取速胜,value 值 +- 深度 (有必要?)
|
// 为争取速胜,value 值 +- 深度 (有必要?)
|
||||||
value_t delta = value_t(position->turn == PLAYER_1 ? depth : -depth);
|
value_t delta = value_t(position->sideToMove == PLAYER_1 ? depth : -depth);
|
||||||
node->value += delta;
|
node->value += delta;
|
||||||
|
|
||||||
#ifdef DEBUG_AB_TREE
|
#ifdef DEBUG_AB_TREE
|
||||||
|
@ -511,11 +511,11 @@ value_t AIAlgorithm::alphaBetaPruning(depth_t depth, value_t alpha, value_t beta
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成子节点树,即生成每个合理的着法
|
// 生成子节点树,即生成每个合理的着法
|
||||||
MoveList::generateLegalMoves(*this, tempGame, node, root, bestMove);
|
MoveList::generate(*this, tempGame, node, root, bestMove);
|
||||||
|
|
||||||
// 根据演算模型执行 MiniMax 检索,对先手,搜索 Max, 对后手,搜索 Min
|
// 根据演算模型执行 MiniMax 检索,对先手,搜索 Max, 对后手,搜索 Min
|
||||||
|
|
||||||
minMax = tempGame.position.turn == PLAYER_1 ? -VALUE_INFINITE : VALUE_INFINITE;
|
minMax = tempGame.position.sideToMove == PLAYER_1 ? -VALUE_INFINITE : VALUE_INFINITE;
|
||||||
|
|
||||||
for (auto child : node->children) {
|
for (auto child : node->children) {
|
||||||
// 棋局入栈保存,以便后续撤销着法
|
// 棋局入栈保存,以便后续撤销着法
|
||||||
|
@ -540,13 +540,13 @@ value_t AIAlgorithm::alphaBetaPruning(depth_t depth, value_t alpha, value_t beta
|
||||||
#endif /* DEEPER_IF_ONLY_ONE_LEGAL_MOVE */
|
#endif /* DEEPER_IF_ONLY_ONE_LEGAL_MOVE */
|
||||||
|
|
||||||
// 递归 Alpha-Beta 剪枝
|
// 递归 Alpha-Beta 剪枝
|
||||||
value = alphaBetaPruning(depth - 1 + epsilon, alpha, beta, child);
|
value = search(depth - 1 + epsilon, alpha, beta, child);
|
||||||
|
|
||||||
// 棋局弹出栈,撤销着法
|
// 棋局弹出栈,撤销着法
|
||||||
tempGame.position = positionStack.top();
|
tempGame.position = positionStack.top();
|
||||||
positionStack.pop();
|
positionStack.pop();
|
||||||
|
|
||||||
if (tempGame.position.turn == PLAYER_1) {
|
if (tempGame.position.sideToMove == PLAYER_1) {
|
||||||
// 为走棋一方的层, 局面对走棋的一方来说是以 α 为评价
|
// 为走棋一方的层, 局面对走棋的一方来说是以 α 为评价
|
||||||
|
|
||||||
// 取最大值
|
// 取最大值
|
||||||
|
@ -622,7 +622,7 @@ value_t AIAlgorithm::alphaBetaPruning(depth_t depth, value_t alpha, value_t beta
|
||||||
|
|
||||||
#ifdef IDS_SUPPORT
|
#ifdef IDS_SUPPORT
|
||||||
// 排序子节点树
|
// 排序子节点树
|
||||||
sortLegalMoves(node);
|
sortMoves(node);
|
||||||
#endif // IDS_SUPPORT
|
#endif // IDS_SUPPORT
|
||||||
|
|
||||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
|
@ -654,9 +654,9 @@ const char* AIAlgorithm::bestMove()
|
||||||
&& !child->pruned
|
&& !child->pruned
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
loggerDebug("[%.2d] %d\t%s\t%d *\n", i, child->move, move2string(child->move), child->value);
|
loggerDebug("[%.2d] %d\t%s\t%d *\n", i, child->move, moveToCommand(child->move), child->value);
|
||||||
} else {
|
} else {
|
||||||
loggerDebug("[%.2d] %d\t%s\t%d\n", i, child->move, move2string(child->move), child->value);
|
loggerDebug("[%.2d] %d\t%s\t%d\n", i, child->move, moveToCommand(child->move), child->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
@ -667,7 +667,7 @@ const char* AIAlgorithm::bestMove()
|
||||||
if (game_.getGiveUpIfMostLose() == true) {
|
if (game_.getGiveUpIfMostLose() == true) {
|
||||||
bool isMostLose = true; // 是否必败
|
bool isMostLose = true; // 是否必败
|
||||||
|
|
||||||
player_t whosTurn = game_.position.turn;
|
player_t whosTurn = game_.position.sideToMove;
|
||||||
|
|
||||||
for (auto child : root->children) {
|
for (auto child : root->children) {
|
||||||
if ((whosTurn == PLAYER_1 && child->value > -VALUE_WIN) ||
|
if ((whosTurn == PLAYER_1 && child->value > -VALUE_WIN) ||
|
||||||
|
@ -679,7 +679,7 @@ const char* AIAlgorithm::bestMove()
|
||||||
|
|
||||||
// 自动认输
|
// 自动认输
|
||||||
if (isMostLose) {
|
if (isMostLose) {
|
||||||
sprintf(cmdline, "Player%d give up!", game_.position.turnId);
|
sprintf(cmdline, "Player%d give up!", game_.position.sideId);
|
||||||
return cmdline;
|
return cmdline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -714,23 +714,23 @@ const char* AIAlgorithm::bestMove()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return move2string(bestMoves[0]->move);
|
return moveToCommand(bestMoves[0]->move);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *AIAlgorithm::move2string(move_t move)
|
const char *AIAlgorithm::moveToCommand(move_t move)
|
||||||
{
|
{
|
||||||
int r, s;
|
int r, s;
|
||||||
|
|
||||||
if (move < 0) {
|
if (move < 0) {
|
||||||
tempGame.position.board.locationToPolar(-move, r, s);
|
Board::locationToPolar(-move, r, s);
|
||||||
sprintf(cmdline, "-(%1u,%1u)", r, s);
|
sprintf(cmdline, "-(%1u,%1u)", r, s);
|
||||||
} else if (move & 0x7f00) {
|
} else if (move & 0x7f00) {
|
||||||
int r1, s1;
|
int r1, s1;
|
||||||
tempGame.position.board.locationToPolar(move >> 8, r1, s1);
|
Board::locationToPolar(move >> 8, r1, s1);
|
||||||
tempGame.position.board.locationToPolar(move & 0x00ff, r, s);
|
Board::locationToPolar(move & 0x00ff, r, s);
|
||||||
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s);
|
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s);
|
||||||
} else {
|
} else {
|
||||||
tempGame.position.board.locationToPolar(move & 0x007f, r, s);
|
Board::locationToPolar(move & 0x007f, r, s);
|
||||||
sprintf(cmdline, "(%1u,%1u)", r, s);
|
sprintf(cmdline, "(%1u,%1u)", r, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,12 +739,12 @@ const char *AIAlgorithm::move2string(move_t move)
|
||||||
|
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef BOOK_LEARNING
|
||||||
|
|
||||||
bool MillGameAi_ab::findBookHash(hash_t hash, HashValue &hashValue)
|
bool AIAlgorithm::findBookHash(hash_t hash, HashValue &hashValue)
|
||||||
{
|
{
|
||||||
return bookHashMap.find(hash, hashValue);
|
return bookHashMap.find(hash, hashValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MillGameAi_ab::recordBookHash(hash_t hash, const HashValue &hashValue)
|
int AIAlgorithm::recordBookHash(hash_t hash, const HashValue &hashValue)
|
||||||
{
|
{
|
||||||
//hashMapMutex.lock();
|
//hashMapMutex.lock();
|
||||||
bookHashMap.insert(hash, hashValue);
|
bookHashMap.insert(hash, hashValue);
|
||||||
|
@ -753,14 +753,14 @@ int MillGameAi_ab::recordBookHash(hash_t hash, const HashValue &hashValue)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MillGameAi_ab::clearBookHashMap()
|
void AIAlgorithm::clearBookHashMap()
|
||||||
{
|
{
|
||||||
//hashMapMutex.lock();
|
//hashMapMutex.lock();
|
||||||
bookHashMap.clear();
|
bookHashMap.clear();
|
||||||
//hashMapMutex.unlock();
|
//hashMapMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MillGameAi_ab::recordOpeningBookToHashMap()
|
void AIAlgorithm::recordOpeningBookToHashMap()
|
||||||
{
|
{
|
||||||
HashValue hashValue;
|
HashValue hashValue;
|
||||||
hash_t hash = 0;
|
hash_t hash = 0;
|
||||||
|
@ -780,13 +780,13 @@ void MillGameAi_ab::recordOpeningBookToHashMap()
|
||||||
openingBook.clear();
|
openingBook.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MillGameAi_ab::recordOpeningBookHashMapToFile()
|
void AIAlgorithm::recordOpeningBookHashMapToFile()
|
||||||
{
|
{
|
||||||
const QString bookFileName = "opening-book.txt";
|
const QString bookFileName = "opening-book.txt";
|
||||||
bookHashMap.dump(bookFileName);
|
bookHashMap.dump(bookFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MillGameAi_ab::loadOpeningBookFileToHashMap()
|
void AIAlgorithm::loadOpeningBookFileToHashMap()
|
||||||
{
|
{
|
||||||
const QString bookFileName = "opening-book.txt";
|
const QString bookFileName = "opening-book.txt";
|
||||||
bookHashMap.load(bookFileName);
|
bookHashMap.load(bookFileName);
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#ifndef MILLGAMEAI_AB
|
#ifndef SEARCH_H
|
||||||
#define MILLGAMEAI_AB
|
#define SEARCH_H
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public:
|
||||||
struct Node* parent {}; // 父节点
|
struct Node* parent {}; // 父节点
|
||||||
move_t move {}; // 着法的命令行指令,图上标示为节点前的连线
|
move_t move {}; // 着法的命令行指令,图上标示为节点前的连线
|
||||||
value_t value {}; // 节点的值
|
value_t value {}; // 节点的值
|
||||||
enum player_t player; // 此着是谁下的 (目前仅调试用)
|
player_t sideToMove; // 此着是谁下的 (目前仅调试用)
|
||||||
#ifdef SORT_CONSIDER_PRUNED
|
#ifdef SORT_CONSIDER_PRUNED
|
||||||
bool pruned {}; // 是否在此处剪枝
|
bool pruned {}; // 是否在此处剪枝
|
||||||
#endif
|
#endif
|
||||||
|
@ -106,7 +106,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alpha-Beta剪枝算法
|
// Alpha-Beta剪枝算法
|
||||||
int alphaBetaPruning(depth_t depth);
|
int search(depth_t depth);
|
||||||
|
|
||||||
// 返回最佳走法的命令行
|
// 返回最佳走法的命令行
|
||||||
const char *bestMove();
|
const char *bestMove();
|
||||||
|
@ -133,11 +133,11 @@ public: /* TODO: Move to private or protected */
|
||||||
// 增加新节点
|
// 增加新节点
|
||||||
struct Node *addNode(Node *parent, value_t value,
|
struct Node *addNode(Node *parent, value_t value,
|
||||||
move_t move, move_t bestMove,
|
move_t move, move_t bestMove,
|
||||||
enum player_t player);
|
player_t side);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// 对合法的着法降序排序
|
// 对合法的着法降序排序
|
||||||
void sortLegalMoves(Node *node);
|
void sortMoves(Node *node);
|
||||||
|
|
||||||
// 清空节点树
|
// 清空节点树
|
||||||
void deleteTree(Node *node);
|
void deleteTree(Node *node);
|
||||||
|
@ -172,13 +172,13 @@ protected:
|
||||||
#endif /* EVALUATE_ENABLE */
|
#endif /* EVALUATE_ENABLE */
|
||||||
|
|
||||||
// Alpha-Beta剪枝算法
|
// Alpha-Beta剪枝算法
|
||||||
value_t alphaBetaPruning(depth_t depth, value_t alpha, value_t beta, Node *node);
|
value_t search(depth_t depth, value_t alpha, value_t beta, Node *node);
|
||||||
|
|
||||||
// 返回着法的命令行
|
// 返回着法的命令行
|
||||||
const char *move2string(move_t move);
|
const char *moveToCommand(move_t move);
|
||||||
|
|
||||||
// 篡改深度
|
// 篡改深度
|
||||||
depth_t changeDepth(depth_t originalDepth);
|
depth_t changeDepth(depth_t origDepth);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 原始模型
|
// 原始模型
|
||||||
|
@ -234,4 +234,4 @@ private:
|
||||||
extern vector<hash_t> history;
|
extern vector<hash_t> history;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif /* SEARCH_H */
|
||||||
|
|
|
@ -94,7 +94,7 @@ int TranspositionTable::recordHash(value_t value, depth_t depth, TranspositionTa
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TranspositionTable::clearTranspositionTable()
|
void TranspositionTable::clear()
|
||||||
{
|
{
|
||||||
transpositionTable.clear();
|
transpositionTable.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public:
|
||||||
static int recordHash(value_t value, depth_t depth, HashType type, hash_t hash, move_t bestMove);
|
static int recordHash(value_t value, depth_t depth, HashType type, hash_t hash, move_t bestMove);
|
||||||
|
|
||||||
// 清空置换表
|
// 清空置换表
|
||||||
static void clearTranspositionTable();
|
static void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern HashMap<hash_t, TranspositionTable::HashValue> transpositionTable;
|
extern HashMap<hash_t, TranspositionTable::HashValue> transpositionTable;
|
||||||
|
@ -50,4 +50,3 @@ extern HashMap<hash_t, TranspositionTable::HashValue> transpositionTable;
|
||||||
#endif // TRANSPOSITION_TABLE_ENABLE
|
#endif // TRANSPOSITION_TABLE_ENABLE
|
||||||
|
|
||||||
#endif /* TT_H */
|
#endif /* TT_H */
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ void AiThread::setAi(const Game &game)
|
||||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||||
// 新下一盘前清除哈希表 (注意可能同时存在每步之前清除)
|
// 新下一盘前清除哈希表 (注意可能同时存在每步之前清除)
|
||||||
#ifdef CLEAR_TRANSPOSITION_TABLE
|
#ifdef CLEAR_TRANSPOSITION_TABLE
|
||||||
TranspositionTable::clearTranspositionTable();
|
TranspositionTable::clear();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ void AiThread::run()
|
||||||
while (!isInterruptionRequested()) {
|
while (!isInterruptionRequested()) {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
|
|
||||||
i = Player::toId(game_->position.turn);
|
i = Player::toId(game_->position.sideToMove);
|
||||||
|
|
||||||
if (i != id || waiting_) {
|
if (i != id || waiting_) {
|
||||||
pauseCondition.wait(&mutex);
|
pauseCondition.wait(&mutex);
|
||||||
|
@ -120,7 +120,7 @@ void AiThread::run()
|
||||||
emit calcStarted();
|
emit calcStarted();
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
||||||
if (ai.alphaBetaPruning(aiDepth) == 3) {
|
if (ai.search(aiDepth) == 3) {
|
||||||
// 三次重复局面和
|
// 三次重复局面和
|
||||||
loggerDebug("Draw\n\n");
|
loggerDebug("Draw\n\n");
|
||||||
strCommand = "draw";
|
strCommand = "draw";
|
||||||
|
|
|
@ -65,7 +65,7 @@ Board &Board::operator= (const Board &other)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::createMillTable(const Rule ¤tRule)
|
void Board::createMillTable(const Rule &rule)
|
||||||
{
|
{
|
||||||
const int millTable_noObliqueLine[Board::N_LOCATIONS][LINE_TYPES_COUNT][2] = {
|
const int millTable_noObliqueLine[Board::N_LOCATIONS][LINE_TYPES_COUNT][2] = {
|
||||||
/* 0 */ {{0, 0}, {0, 0}, {0, 0}},
|
/* 0 */ {{0, 0}, {0, 0}, {0, 0}},
|
||||||
|
@ -161,7 +161,7 @@ void Board::createMillTable(const Rule ¤tRule)
|
||||||
/* 39 */ {{0, 0}, {0, 0}, {0, 0}}
|
/* 39 */ {{0, 0}, {0, 0}, {0, 0}}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (currentRule.hasObliqueLines) {
|
if (rule.hasObliqueLines) {
|
||||||
memcpy(millTable, millTable_hasObliqueLines, sizeof(millTable));
|
memcpy(millTable, millTable_hasObliqueLines, sizeof(millTable));
|
||||||
} else {
|
} else {
|
||||||
memcpy(millTable, millTable_noObliqueLine, sizeof(millTable));
|
memcpy(millTable, millTable_noObliqueLine, sizeof(millTable));
|
||||||
|
@ -209,7 +209,6 @@ int Board::polarToLocation(int r, int s)
|
||||||
return r * N_SEATS + s - 1;
|
return r * N_SEATS + s - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Board::inHowManyMills(int location)
|
int Board::inHowManyMills(int location)
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
@ -226,7 +225,7 @@ int Board::inHowManyMills(int location)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Board::addMills(const Rule ¤tRule, int location)
|
int Board::addMills(const Rule &rule, int location)
|
||||||
{
|
{
|
||||||
// 成三用一个64位整数了,规则如下
|
// 成三用一个64位整数了,规则如下
|
||||||
// 0x 00 00 00 00 00 00 00 00
|
// 0x 00 00 00 00 00 00 00 00
|
||||||
|
@ -276,7 +275,7 @@ int Board::addMills(const Rule ¤tRule, int location)
|
||||||
+ static_cast<uint64_t>(p[2]);
|
+ static_cast<uint64_t>(p[2]);
|
||||||
|
|
||||||
// 如果允许相同三连反复去子
|
// 如果允许相同三连反复去子
|
||||||
if (currentRule.allowRemovePiecesRepeatedly) {
|
if (rule.allowRemovePiecesRepeatedly) {
|
||||||
n++;
|
n++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -302,7 +301,7 @@ int Board::addMills(const Rule ¤tRule, int location)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::isAllInMills(enum player_t player)
|
bool Board::isAllInMills(player_t player)
|
||||||
{
|
{
|
||||||
for (int i = LOCATION_BEGIN; i < LOCATION_END; i++) {
|
for (int i = LOCATION_BEGIN; i < LOCATION_END; i++) {
|
||||||
if (locations[i] & (uint8_t)player) {
|
if (locations[i] & (uint8_t)player) {
|
||||||
|
@ -316,13 +315,13 @@ bool Board::isAllInMills(enum player_t player)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断玩家的棋子周围有几个空位
|
// 判断玩家的棋子周围有几个空位
|
||||||
int Board::getSurroundedEmptyLocationCount(int turnId, const Rule ¤tRule, int nPiecesOnBoard[],
|
int Board::getSurroundedEmptyLocationCount(int sideId, const Rule &rule, int nPiecesOnBoard[],
|
||||||
int location, bool includeFobidden)
|
int location, bool includeFobidden)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
if (nPiecesOnBoard[turnId] > currentRule.nPiecesAtLeast ||
|
if (nPiecesOnBoard[sideId] > rule.nPiecesAtLeast ||
|
||||||
!currentRule.allowFlyWhenRemainThreePieces) {
|
!rule.allowFlyWhenRemainThreePieces) {
|
||||||
int moveLocation;
|
int moveLocation;
|
||||||
for (direction_t d = DIRECTION_BEGIN; d < DIRECTIONS_COUNT; d = (direction_t)(d + 1)) {
|
for (direction_t d = DIRECTION_BEGIN; d < DIRECTIONS_COUNT; d = (direction_t)(d + 1)) {
|
||||||
moveLocation = MoveList::moveTable[location][d];
|
moveLocation = MoveList::moveTable[location][d];
|
||||||
|
@ -339,11 +338,11 @@ int Board::getSurroundedEmptyLocationCount(int turnId, const Rule ¤tRule,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断玩家的棋子是否被围
|
// 判断玩家的棋子是否被围
|
||||||
bool Board::isSurrounded(int turnId, const Rule ¤tRule, int nPiecesOnBoard[], int location)
|
bool Board::isSurrounded(int sideId, const Rule &rule, int nPiecesOnBoard[], int location)
|
||||||
{
|
{
|
||||||
// 判断location处的棋子是否被“闷”
|
// 判断location处的棋子是否被“闷”
|
||||||
if (nPiecesOnBoard[turnId] > currentRule.nPiecesAtLeast ||
|
if (nPiecesOnBoard[sideId] > rule.nPiecesAtLeast ||
|
||||||
!currentRule.allowFlyWhenRemainThreePieces) {
|
!rule.allowFlyWhenRemainThreePieces) {
|
||||||
int i, moveLocation;
|
int i, moveLocation;
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
moveLocation = MoveList::moveTable[location][i];
|
moveLocation = MoveList::moveTable[location][i];
|
||||||
|
@ -358,15 +357,15 @@ bool Board::isSurrounded(int turnId, const Rule ¤tRule, int nPiecesOnBoard
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::isAllSurrounded(int turnId, const Rule ¤tRule, int nPiecesOnBoard[], char ch)
|
bool Board::isAllSurrounded(int sideId, const Rule &rule, int nPiecesOnBoard[], char ch)
|
||||||
{
|
{
|
||||||
// 如果摆满
|
// 如果摆满
|
||||||
if (nPiecesOnBoard[1] + nPiecesOnBoard[2] >= N_SEATS * N_RINGS)
|
if (nPiecesOnBoard[1] + nPiecesOnBoard[2] >= N_SEATS * N_RINGS)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// 判断是否可以飞子
|
// 判断是否可以飞子
|
||||||
if (nPiecesOnBoard[turnId] <= currentRule.nPiecesAtLeast &&
|
if (nPiecesOnBoard[sideId] <= rule.nPiecesAtLeast &&
|
||||||
currentRule.allowFlyWhenRemainThreePieces) {
|
rule.allowFlyWhenRemainThreePieces) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,15 +387,15 @@ bool Board::isAllSurrounded(int turnId, const Rule ¤tRule, int nPiecesOnBo
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断玩家的棋子是否全部被围
|
// 判断玩家的棋子是否全部被围
|
||||||
bool Board::isAllSurrounded(int turnId, const Rule ¤tRule, int nPiecesOnBoard[], enum player_t ply)
|
bool Board::isAllSurrounded(int sideId, const Rule &rule, int nPiecesOnBoard[], player_t player)
|
||||||
{
|
{
|
||||||
char t = 0x30 & ply;
|
char t = 0x30 & player;
|
||||||
|
|
||||||
return isAllSurrounded(turnId, currentRule, nPiecesOnBoard, t);
|
return isAllSurrounded(sideId, rule, nPiecesOnBoard, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
enum player_t Board::getWhosPiece(int r, int s)
|
player_t Board::getWhosPiece(int r, int s)
|
||||||
{
|
{
|
||||||
int location = polarToLocation(r, s);
|
int location = polarToLocation(r, s);
|
||||||
|
|
||||||
|
@ -409,7 +408,7 @@ enum player_t Board::getWhosPiece(int r, int s)
|
||||||
return PLAYER_NOBODY;
|
return PLAYER_NOBODY;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Board::getPieceRS(const player_t &player, const int &number, int &r, int &s, struct Rule ¤tRule)
|
bool Board::getPieceRS(const player_t &player, const int &number, int &r, int &s, struct Rule &rule)
|
||||||
{
|
{
|
||||||
int piece;
|
int piece;
|
||||||
|
|
||||||
|
@ -421,7 +420,7 @@ bool Board::getPieceRS(const player_t &player, const int &number, int &r, int &s
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (number > 0 && number <= currentRule.nTotalPiecesEachSide)
|
if (number > 0 && number <= rule.nTotalPiecesEachSide)
|
||||||
piece &= number;
|
piece &= number;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
@ -466,7 +465,7 @@ bool Board::isStarLocation(int location)
|
||||||
location == 23);
|
location == 23);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct Rule ¤tRule, int location, bool cmdChange /*= true*/)
|
void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct Rule &rule, int location, bool cmdChange /*= true*/)
|
||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
int r, s;
|
int r, s;
|
||||||
|
@ -510,7 +509,7 @@ void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct
|
||||||
location = r * N_SEATS + s;
|
location = r * N_SEATS + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentRule.allowRemovePiecesRepeatedly) {
|
if (rule.allowRemovePiecesRepeatedly) {
|
||||||
for (auto &mill : millList) {
|
for (auto &mill : millList) {
|
||||||
llp[0] = (mill & 0x000000ff00000000) >> 32;
|
llp[0] = (mill & 0x000000ff00000000) >> 32;
|
||||||
llp[1] = (mill & 0x0000000000ff0000) >> 16;
|
llp[1] = (mill & 0x0000000000ff0000) >> 16;
|
||||||
|
@ -578,7 +577,7 @@ void Board::mirror(list <string> &cmdlist, char* cmdline, int32_t move_, struct
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int location, bool cmdChange /*= true*/)
|
void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rule &rule, int location, bool cmdChange /*= true*/)
|
||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
int r, s;
|
int r, s;
|
||||||
|
@ -635,7 +634,7 @@ void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rul
|
||||||
location = r * N_SEATS + s;
|
location = r * N_SEATS + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentRule.allowRemovePiecesRepeatedly) {
|
if (rule.allowRemovePiecesRepeatedly) {
|
||||||
for (auto &mill : millList) {
|
for (auto &mill : millList) {
|
||||||
llp[0] = (mill & 0x000000ff00000000) >> 32;
|
llp[0] = (mill & 0x000000ff00000000) >> 32;
|
||||||
llp[1] = (mill & 0x0000000000ff0000) >> 16;
|
llp[1] = (mill & 0x0000000000ff0000) >> 16;
|
||||||
|
@ -743,7 +742,7 @@ void Board::turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int location, bool cmdChange /*= true*/)
|
void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule &rule, int location, bool cmdChange /*= true*/)
|
||||||
{
|
{
|
||||||
// 将degrees转化为0~359之间的数
|
// 将degrees转化为0~359之间的数
|
||||||
degrees = degrees % 360;
|
degrees = degrees % 360;
|
||||||
|
@ -831,7 +830,7 @@ void Board::rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t m
|
||||||
location = r * N_SEATS + s;
|
location = r * N_SEATS + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentRule.allowRemovePiecesRepeatedly) {
|
if (rule.allowRemovePiecesRepeatedly) {
|
||||||
for (auto &mill : millList) {
|
for (auto &mill : millList) {
|
||||||
llp[0] = (mill & 0x000000ff00000000) >> 32;
|
llp[0] = (mill & 0x000000ff00000000) >> 32;
|
||||||
llp[1] = (mill & 0x0000000000ff0000) >> 16;
|
llp[1] = (mill & 0x0000000000ff0000) >> 16;
|
||||||
|
|
|
@ -63,40 +63,40 @@ public:
|
||||||
static int millTable[N_LOCATIONS][LINE_TYPES_COUNT][N_RINGS - 1];
|
static int millTable[N_LOCATIONS][LINE_TYPES_COUNT][N_RINGS - 1];
|
||||||
|
|
||||||
// 生成成三表
|
// 生成成三表
|
||||||
void createMillTable(const Rule ¤tRule);
|
void createMillTable(const Rule &rule);
|
||||||
|
|
||||||
// 局面左右镜像
|
// 局面左右镜像
|
||||||
void mirror(list <string> &cmdlist, char *cmdline, int32_t move_, struct Rule ¤tRule, int currentPos, bool cmdChange = true);
|
void mirror(list <string> &cmdlist, char *cmdline, int32_t move_, struct Rule &rule, int currentPos, bool cmdChange = true);
|
||||||
|
|
||||||
// 局面内外翻转
|
// 局面内外翻转
|
||||||
void turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int currentPos, bool cmdChange = true);
|
void turn(list <string> &cmdlist, char *cmdline, int32_t move_, const Rule &rule, int currentPos, bool cmdChange = true);
|
||||||
|
|
||||||
// 局面逆时针旋转
|
// 局面逆时针旋转
|
||||||
void rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule ¤tRule, int currentPos, bool cmdChange = true);
|
void rotate(int degrees, list <string> &cmdlist, char *cmdline, int32_t move_, const Rule &rule, int currentPos, bool cmdChange = true);
|
||||||
|
|
||||||
// 判断棋盘location处的棋子处于几个“三连”中
|
// 判断棋盘location处的棋子处于几个“三连”中
|
||||||
int inHowManyMills(int location);
|
int inHowManyMills(int location);
|
||||||
|
|
||||||
// 判断玩家的所有棋子是否都处于“三连”状态
|
// 判断玩家的所有棋子是否都处于“三连”状态
|
||||||
bool isAllInMills(enum player_t);
|
bool isAllInMills(player_t);
|
||||||
|
|
||||||
// 判断玩家的棋子周围有几个空位
|
// 判断玩家的棋子周围有几个空位
|
||||||
int getSurroundedEmptyLocationCount(int turnId, const Rule ¤tRule, int nPiecesOnBoard[], int location, bool includeFobidden);
|
int getSurroundedEmptyLocationCount(int sideId, const Rule &rule, int nPiecesOnBoard[], int location, bool includeFobidden);
|
||||||
|
|
||||||
// 判断玩家的棋子是否被围
|
// 判断玩家的棋子是否被围
|
||||||
bool isSurrounded(int turnId, const Rule ¤tRule, int nPiecesOnBoard[], int location);
|
bool isSurrounded(int sideId, const Rule &rule, int nPiecesOnBoard[], int location);
|
||||||
|
|
||||||
// 判断玩家的棋子是否全部被围
|
// 判断玩家的棋子是否全部被围
|
||||||
bool isAllSurrounded(int turnId, const Rule ¤tRule, int nPiecesOnBoard[], char ch);
|
bool isAllSurrounded(int sideId, const Rule &rule, int nPiecesOnBoard[], char ch);
|
||||||
|
|
||||||
bool isAllSurrounded(int turnId, const Rule ¤tRule, int nPiecesOnBoard[], enum player_t ply);
|
bool isAllSurrounded(int sideId, const Rule &rule, int nPiecesOnBoard[], player_t ply);
|
||||||
|
|
||||||
// 三连加入列表
|
// 三连加入列表
|
||||||
int addMills(const Rule ¤tRule, int location);
|
int addMills(const Rule &rule, int location);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// 获取位置点棋子的归属人
|
// 获取位置点棋子的归属人
|
||||||
enum player_t getWhosPiece(int r, int s);
|
player_t getWhosPiece(int r, int s);
|
||||||
|
|
||||||
bool getPieceRS(const player_t &player, const int &number, int &r, int &s, struct Rule ¤tRule);
|
bool getPieceRS(const player_t &player, const int &number, int &r, int &s, struct Rule ¤tRule);
|
||||||
#endif
|
#endif
|
||||||
|
@ -105,10 +105,10 @@ public:
|
||||||
bool getCurrentPiece(player_t &player, int &number, int currentPos);
|
bool getCurrentPiece(player_t &player, int &number, int currentPos);
|
||||||
|
|
||||||
// 将棋盘下标形式转化为第r圈,第s位,r和s下标都从1开始
|
// 将棋盘下标形式转化为第r圈,第s位,r和s下标都从1开始
|
||||||
void locationToPolar(int location, int &r, int &s);
|
static void locationToPolar(int location, int &r, int &s);
|
||||||
|
|
||||||
// 将第c圈,第p位转化为棋盘下标形式,r和s下标都从1开始
|
// 将第c圈,第p位转化为棋盘下标形式,r和s下标都从1开始
|
||||||
int polarToLocation(int r, int s);
|
static int polarToLocation(int r, int s);
|
||||||
|
|
||||||
static void printBoard();
|
static void printBoard();
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,9 @@ public:
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int toId(player_t who)
|
inline static int toId(player_t player)
|
||||||
{
|
{
|
||||||
return who == PLAYER_1 ? 1 : 2;
|
return player == PLAYER_1 ? 1 : 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static player_t idToPlayer(int id)
|
inline static player_t idToPlayer(int id)
|
||||||
|
|
|
@ -94,7 +94,7 @@ bool Game::configure(bool giveUpIfMostLose, bool randomMove)
|
||||||
// 设置棋局状态和棋盘数据,用于初始化
|
// 设置棋局状态和棋盘数据,用于初始化
|
||||||
bool Game::setPosition(const struct Rule *rule, step_t maxStepsLedToDraw, int maxTimeLedToLose,
|
bool Game::setPosition(const struct Rule *rule, step_t maxStepsLedToDraw, int maxTimeLedToLose,
|
||||||
step_t initialStep,
|
step_t initialStep,
|
||||||
phase_t phase, player_t turn, action_t action,
|
phase_t phase, player_t side, action_t action,
|
||||||
const char *locations,
|
const char *locations,
|
||||||
int nPiecesInHand_1, int nPiecesInHand_2, int nPiecesNeedRemove)
|
int nPiecesInHand_1, int nPiecesInHand_2, int nPiecesNeedRemove)
|
||||||
{
|
{
|
||||||
|
@ -118,7 +118,7 @@ bool Game::setPosition(const struct Rule *rule, step_t maxStepsLedToDraw, int ma
|
||||||
position.phase = phase;
|
position.phase = phase;
|
||||||
|
|
||||||
// 轮流状态标识
|
// 轮流状态标识
|
||||||
setTurn(turn);
|
setSideToMove(side);
|
||||||
|
|
||||||
// 动作状态标识
|
// 动作状态标识
|
||||||
position.action = action;
|
position.action = action;
|
||||||
|
@ -189,7 +189,7 @@ bool Game::setPosition(const struct Rule *rule, step_t maxStepsLedToDraw, int ma
|
||||||
winner = PLAYER_NOBODY;
|
winner = PLAYER_NOBODY;
|
||||||
|
|
||||||
// 生成着法表
|
// 生成着法表
|
||||||
MoveList::createMoveTable(*this);
|
MoveList::create(*this);
|
||||||
|
|
||||||
// 生成成三表
|
// 生成成三表
|
||||||
position.board.createMillTable(currentRule);
|
position.board.createMillTable(currentRule);
|
||||||
|
@ -236,7 +236,7 @@ bool Game::reset()
|
||||||
position.phase = PHASE_NOTSTARTED;
|
position.phase = PHASE_NOTSTARTED;
|
||||||
|
|
||||||
// 设置轮流状态
|
// 设置轮流状态
|
||||||
setTurn(PLAYER_1);
|
setSideToMove(PLAYER_1);
|
||||||
|
|
||||||
// 动作状态标识
|
// 动作状态标识
|
||||||
position.action = ACTION_PLACE;
|
position.action = ACTION_PLACE;
|
||||||
|
@ -317,7 +317,7 @@ bool Game::start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Game::place(int location, int time_p, int8_t rs)
|
bool Game::place(int location, int time_p, int8_t updateCmdlist)
|
||||||
{
|
{
|
||||||
// 如果局面为“结局”,返回false
|
// 如果局面为“结局”,返回false
|
||||||
if (position.phase == PHASE_GAMEOVER)
|
if (position.phase == PHASE_GAMEOVER)
|
||||||
|
@ -338,7 +338,7 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
// 格式转换
|
// 格式转换
|
||||||
int r = 0;
|
int r = 0;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
position.board.locationToPolar(location, r, s);
|
Board::locationToPolar(location, r, s);
|
||||||
|
|
||||||
// 时间的临时变量
|
// 时间的临时变量
|
||||||
int player_ms = -1;
|
int player_ms = -1;
|
||||||
|
@ -348,8 +348,8 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
if (position.phase == PHASE_PLACING) {
|
if (position.phase == PHASE_PLACING) {
|
||||||
int playerId = Player::toId(position.turn);
|
int playerId = Player::toId(position.sideToMove);
|
||||||
piece = (0x01 | position.turn) + currentRule.nTotalPiecesEachSide - position.nPiecesInHand[playerId];
|
piece = (0x01 | position.sideToMove) + currentRule.nTotalPiecesEachSide - position.nPiecesInHand[playerId];
|
||||||
position.nPiecesInHand[playerId]--;
|
position.nPiecesInHand[playerId]--;
|
||||||
position.nPiecesOnBoard[playerId]++;
|
position.nPiecesOnBoard[playerId]++;
|
||||||
|
|
||||||
|
@ -359,7 +359,7 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
|
|
||||||
move_ = static_cast<move_t>(location);
|
move_ = static_cast<move_t>(location);
|
||||||
|
|
||||||
if (rs) {
|
if (updateCmdlist) {
|
||||||
player_ms = update(time_p);
|
player_ms = update(time_p);
|
||||||
sprintf(cmdline, "(%1u,%1u) %02u:%02u",
|
sprintf(cmdline, "(%1u,%1u) %02u:%02u",
|
||||||
r, s, player_ms / 60, player_ms % 60);
|
r, s, player_ms / 60, player_ms % 60);
|
||||||
|
@ -386,9 +386,9 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
|
|
||||||
// 设置轮到谁走
|
// 设置轮到谁走
|
||||||
if (currentRule.isDefenderMoveFirst) {
|
if (currentRule.isDefenderMoveFirst) {
|
||||||
setTurn(PLAYER_2);
|
setSideToMove(PLAYER_2);
|
||||||
} else {
|
} else {
|
||||||
setTurn(PLAYER_1);
|
setSideToMove(PLAYER_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 再决胜负
|
// 再决胜负
|
||||||
|
@ -399,7 +399,7 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
// 如果双方还有子
|
// 如果双方还有子
|
||||||
else {
|
else {
|
||||||
// 设置轮到谁走
|
// 设置轮到谁走
|
||||||
changeTurn();
|
changeSideToMove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 如果成三
|
// 如果成三
|
||||||
|
@ -422,7 +422,7 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
// 对于中局落子 (ontext.phase == GAME_MOVING)
|
// 对于中局落子 (ontext.phase == GAME_MOVING)
|
||||||
|
|
||||||
// 如果落子不合法
|
// 如果落子不合法
|
||||||
if (position.nPiecesOnBoard[position.turnId] > currentRule.nPiecesAtLeast ||
|
if (position.nPiecesOnBoard[position.sideId] > currentRule.nPiecesAtLeast ||
|
||||||
!currentRule.allowFlyWhenRemainThreePieces) {
|
!currentRule.allowFlyWhenRemainThreePieces) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
|
@ -439,7 +439,7 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
// 移子
|
// 移子
|
||||||
move_ = static_cast<move_t>((currentLocation << 8) + location);
|
move_ = static_cast<move_t>((currentLocation << 8) + location);
|
||||||
|
|
||||||
if (rs) {
|
if (updateCmdlist) {
|
||||||
player_ms = update(time_p);
|
player_ms = update(time_p);
|
||||||
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u", currentLocation / Board::N_SEATS, currentLocation % Board::N_SEATS + 1,
|
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u) %02u:%02u", currentLocation / Board::N_SEATS, currentLocation % Board::N_SEATS + 1,
|
||||||
r, s, player_ms / 60, player_ms % 60);
|
r, s, player_ms / 60, player_ms % 60);
|
||||||
|
@ -465,7 +465,7 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
position.action = ACTION_CHOOSE;
|
position.action = ACTION_CHOOSE;
|
||||||
|
|
||||||
// 设置轮到谁走
|
// 设置轮到谁走
|
||||||
changeTurn();
|
changeSideToMove();
|
||||||
|
|
||||||
// 如果决出胜负
|
// 如果决出胜负
|
||||||
if (win()) {
|
if (win()) {
|
||||||
|
@ -482,7 +482,7 @@ bool Game::place(int location, int time_p, int8_t rs)
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (rs) {
|
if (updateCmdlist) {
|
||||||
setTips();
|
setTips();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -492,7 +492,7 @@ out:
|
||||||
bool Game::_place(int r, int s, int time_p)
|
bool Game::_place(int r, int s, int time_p)
|
||||||
{
|
{
|
||||||
// 转换为 location
|
// 转换为 location
|
||||||
int location = position.board.polarToLocation(r, s);
|
int location = Board::polarToLocation(r, s);
|
||||||
|
|
||||||
return place(location, time_p, true);
|
return place(location, time_p, true);
|
||||||
}
|
}
|
||||||
|
@ -500,12 +500,12 @@ bool Game::_place(int r, int s, int time_p)
|
||||||
bool Game::_capture(int r, int s, int time_p)
|
bool Game::_capture(int r, int s, int time_p)
|
||||||
{
|
{
|
||||||
// 转换为 location
|
// 转换为 location
|
||||||
int location = position.board.polarToLocation(r, s);
|
int location = Board::polarToLocation(r, s);
|
||||||
|
|
||||||
return capture(location, time_p, 1);
|
return capture(location, time_p, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Game::capture(int location, int time_p, int8_t cp)
|
bool Game::capture(int location, int time_p, int8_t updateCmdlist)
|
||||||
{
|
{
|
||||||
// 如果局面为"未开局"或“结局”,返回false
|
// 如果局面为"未开局"或“结局”,返回false
|
||||||
if (position.phase == PHASE_NOTSTARTED || position.phase == PHASE_GAMEOVER)
|
if (position.phase == PHASE_NOTSTARTED || position.phase == PHASE_GAMEOVER)
|
||||||
|
@ -522,12 +522,12 @@ bool Game::capture(int location, int time_p, int8_t cp)
|
||||||
// 格式转换
|
// 格式转换
|
||||||
int r = 0;
|
int r = 0;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
position.board.locationToPolar(location, r, s);
|
Board::locationToPolar(location, r, s);
|
||||||
|
|
||||||
// 时间的临时变量
|
// 时间的临时变量
|
||||||
int player_ms = -1;
|
int player_ms = -1;
|
||||||
|
|
||||||
player_t opponent = Player::getOpponent(position.turn);
|
player_t opponent = Player::getOpponent(position.sideToMove);
|
||||||
|
|
||||||
// 判断去子是不是对手棋
|
// 判断去子是不是对手棋
|
||||||
if (!(opponent & boardLocations[location]))
|
if (!(opponent & boardLocations[location]))
|
||||||
|
@ -554,7 +554,7 @@ bool Game::capture(int location, int time_p, int8_t cp)
|
||||||
|
|
||||||
move_ = static_cast<move_t>(-location);
|
move_ = static_cast<move_t>(-location);
|
||||||
|
|
||||||
if (cp) {
|
if (updateCmdlist) {
|
||||||
player_ms = update(time_p);
|
player_ms = update(time_p);
|
||||||
sprintf(cmdline, "-(%1u,%1u) %02u:%02u", r, s, player_ms / 60, player_ms % 60);
|
sprintf(cmdline, "-(%1u,%1u) %02u:%02u", r, s, player_ms / 60, player_ms % 60);
|
||||||
cmdlist.emplace_back(string(cmdline));
|
cmdlist.emplace_back(string(cmdline));
|
||||||
|
@ -597,9 +597,9 @@ bool Game::capture(int location, int time_p, int8_t cp)
|
||||||
|
|
||||||
// 设置轮到谁走
|
// 设置轮到谁走
|
||||||
if (currentRule.isDefenderMoveFirst) {
|
if (currentRule.isDefenderMoveFirst) {
|
||||||
setTurn(PLAYER_2);
|
setSideToMove(PLAYER_2);
|
||||||
} else {
|
} else {
|
||||||
setTurn(PLAYER_1);
|
setSideToMove(PLAYER_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 再决胜负
|
// 再决胜负
|
||||||
|
@ -613,7 +613,7 @@ bool Game::capture(int location, int time_p, int8_t cp)
|
||||||
position.action = ACTION_PLACE;
|
position.action = ACTION_PLACE;
|
||||||
|
|
||||||
// 设置轮到谁走
|
// 设置轮到谁走
|
||||||
changeTurn();
|
changeSideToMove();
|
||||||
|
|
||||||
// 如果决出胜负
|
// 如果决出胜负
|
||||||
if (win()) {
|
if (win()) {
|
||||||
|
@ -627,7 +627,7 @@ bool Game::capture(int location, int time_p, int8_t cp)
|
||||||
position.action = ACTION_CHOOSE;
|
position.action = ACTION_CHOOSE;
|
||||||
|
|
||||||
// 设置轮到谁走
|
// 设置轮到谁走
|
||||||
changeTurn();
|
changeSideToMove();
|
||||||
|
|
||||||
// 如果决出胜负
|
// 如果决出胜负
|
||||||
if (win()) {
|
if (win()) {
|
||||||
|
@ -636,7 +636,7 @@ bool Game::capture(int location, int time_p, int8_t cp)
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (cp) {
|
if (updateCmdlist) {
|
||||||
setTips();
|
setTips();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,9 +654,9 @@ bool Game::choose(int location)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 判断选子是否可选
|
// 判断选子是否可选
|
||||||
if (boardLocations[location] & position.turn) {
|
if (boardLocations[location] & position.sideToMove) {
|
||||||
// 判断location处的棋子是否被“闷”
|
// 判断location处的棋子是否被“闷”
|
||||||
if (position.board.isSurrounded(position.turnId, currentRule, position.nPiecesOnBoard, location)) {
|
if (position.board.isSurrounded(position.sideId, currentRule, position.nPiecesOnBoard, location)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,7 +674,7 @@ bool Game::choose(int location)
|
||||||
|
|
||||||
bool Game::choose(int r, int s)
|
bool Game::choose(int r, int s)
|
||||||
{
|
{
|
||||||
return choose(position.board.polarToLocation(r, s));
|
return choose(Board::polarToLocation(r, s));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Game::giveup(player_t loser)
|
bool Game::giveup(player_t loser)
|
||||||
|
@ -803,7 +803,7 @@ bool Game::command(int move)
|
||||||
inline int Game::update(int time_p /*= -1*/)
|
inline int Game::update(int time_p /*= -1*/)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
time_t *player_ms = &elapsedSeconds[position.turnId];
|
time_t *player_ms = &elapsedSeconds[position.sideId];
|
||||||
time_t playerNext_ms = elapsedSeconds[position.opponentId];
|
time_t playerNext_ms = elapsedSeconds[position.opponentId];
|
||||||
|
|
||||||
// 根据局面调整计时器
|
// 根据局面调整计时器
|
||||||
|
@ -912,15 +912,15 @@ bool Game::win(bool forceDraw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果中局被“闷”
|
// 如果中局被“闷”
|
||||||
if (position.phase == PHASE_MOVING && position.action == ACTION_CHOOSE && position.board.isAllSurrounded(position.turn, currentRule, position.nPiecesOnBoard, position.turn)) {
|
if (position.phase == PHASE_MOVING && position.action == ACTION_CHOOSE && position.board.isAllSurrounded(position.sideToMove, currentRule, position.nPiecesOnBoard, position.sideToMove)) {
|
||||||
// 规则要求被“闷”判负,则对手获胜
|
// 规则要求被“闷”判负,则对手获胜
|
||||||
position.phase = PHASE_GAMEOVER;
|
position.phase = PHASE_GAMEOVER;
|
||||||
|
|
||||||
if (currentRule.isLoseWhenNoWay) {
|
if (currentRule.isLoseWhenNoWay) {
|
||||||
tips = "玩家" + Player::chToStr(position.turnChar) + "无子可走被闷";
|
tips = "玩家" + Player::chToStr(position.chSide) + "无子可走被闷";
|
||||||
winner = Player::getOpponent(position.turn);
|
winner = Player::getOpponent(position.sideToMove);
|
||||||
int winnerId = Player::toId(winner);
|
int winnerId = Player::toId(winner);
|
||||||
sprintf(cmdline, "Player%d no way to go. Player%d win!", position.turnId, winnerId);
|
sprintf(cmdline, "Player%d no way to go. Player%d win!", position.sideId, winnerId);
|
||||||
cmdlist.emplace_back(string(cmdline));
|
cmdlist.emplace_back(string(cmdline));
|
||||||
#ifdef BOOK_LEARNING
|
#ifdef BOOK_LEARNING
|
||||||
MillGameAi_ab::recordOpeningBookToHashMap(); // TODO: 目前是对所有的失败记录到开局库
|
MillGameAi_ab::recordOpeningBookToHashMap(); // TODO: 目前是对所有的失败记录到开局库
|
||||||
|
@ -930,7 +930,7 @@ bool Game::win(bool forceDraw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 否则让棋,由对手走
|
// 否则让棋,由对手走
|
||||||
changeTurn();
|
changeSideToMove();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -951,7 +951,7 @@ bool Game::win(bool forceDraw)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算玩家1和玩家2的棋子活动能力之差
|
// 计算玩家1和玩家2的棋子活动能力之差
|
||||||
int Game::getMobilityDiff(enum player_t turn, const Rule &rule, int nPiecesOnBoard[], bool includeFobidden)
|
int Game::getMobilityDiff(player_t turn, const Rule &rule, int nPiecesOnBoard[], bool includeFobidden)
|
||||||
{
|
{
|
||||||
int *locations = boardLocations;
|
int *locations = boardLocations;
|
||||||
int mobility1 = 0;
|
int mobility1 = 0;
|
||||||
|
@ -990,30 +990,30 @@ void Game::cleanForbiddenLocations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::setTurn(player_t player)
|
void Game::setSideToMove(player_t player)
|
||||||
{
|
{
|
||||||
// 设置轮到谁走
|
// 设置轮到谁走
|
||||||
position.turn = player;
|
position.sideToMove = player;
|
||||||
|
|
||||||
position.turnId = Player::toId(position.turn);
|
position.sideId = Player::toId(position.sideToMove);
|
||||||
position.turnChar = Player::idToCh(position.turnId);
|
position.chSide = Player::idToCh(position.sideId);
|
||||||
|
|
||||||
position.opponent = Player::getOpponent(player);
|
position.opponent = Player::getOpponent(player);
|
||||||
|
|
||||||
position.opponentId = Player::toId(position.opponent);
|
position.opponentId = Player::toId(position.opponent);
|
||||||
position.opponentChar = Player::idToCh(position.opponentId);
|
position.chOpponent = Player::idToCh(position.opponentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::changeTurn()
|
void Game::changeSideToMove()
|
||||||
{
|
{
|
||||||
setTurn(Player::getOpponent(position.turn));
|
setSideToMove(Player::getOpponent(position.sideToMove));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::setTips()
|
void Game::setTips()
|
||||||
{
|
{
|
||||||
string winnerStr, t;
|
string winnerStr, t;
|
||||||
int winnerId;
|
int winnerId;
|
||||||
string turnStr = Player::chToStr(position.turnChar);
|
string turnStr = Player::chToStr(position.chSide);
|
||||||
|
|
||||||
switch (position.phase) {
|
switch (position.phase) {
|
||||||
case PHASE_NOTSTARTED:
|
case PHASE_NOTSTARTED:
|
||||||
|
@ -1023,7 +1023,7 @@ void Game::setTips()
|
||||||
|
|
||||||
case PHASE_PLACING:
|
case PHASE_PLACING:
|
||||||
if (position.action == ACTION_PLACE) {
|
if (position.action == ACTION_PLACE) {
|
||||||
tips = "轮到玩家" + turnStr + "落子,剩余" + std::to_string(position.nPiecesInHand[position.turnId]) + "子";
|
tips = "轮到玩家" + turnStr + "落子,剩余" + std::to_string(position.nPiecesInHand[position.sideId]) + "子";
|
||||||
} else if (position.action == ACTION_CAPTURE) {
|
} else if (position.action == ACTION_CAPTURE) {
|
||||||
tips = "成三!轮到玩家" + turnStr + "去子,需去" + std::to_string(position.nPiecesNeedRemove) + "子";
|
tips = "成三!轮到玩家" + turnStr + "去子,需去" + std::to_string(position.nPiecesNeedRemove) + "子";
|
||||||
}
|
}
|
||||||
|
@ -1120,7 +1120,7 @@ hash_t Game::updateHashMisc()
|
||||||
|
|
||||||
// 置位
|
// 置位
|
||||||
|
|
||||||
if (position.turn == PLAYER_2) {
|
if (position.sideToMove == PLAYER_2) {
|
||||||
position.hash |= 1U;
|
position.hash |= 1U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,13 +47,13 @@ public:
|
||||||
enum phase_t phase;
|
enum phase_t phase;
|
||||||
|
|
||||||
// 轮流状态标识
|
// 轮流状态标识
|
||||||
enum player_t turn;
|
player_t sideToMove;
|
||||||
int turnId;
|
int sideId;
|
||||||
char turnChar;
|
char chSide;
|
||||||
//string turnStr;
|
//string turnStr;
|
||||||
enum player_t opponent;
|
player_t opponent;
|
||||||
int opponentId;
|
int opponentId;
|
||||||
char opponentChar;
|
char chOpponent;
|
||||||
//string opponentStr;
|
//string opponentStr;
|
||||||
|
|
||||||
// 动作状态标识
|
// 动作状态标识
|
||||||
|
@ -169,7 +169,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断胜负
|
// 判断胜负
|
||||||
enum player_t whoWin() const
|
player_t whoWin() const
|
||||||
{
|
{
|
||||||
return winner;
|
return winner;
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算玩家1和玩家2的棋子活动能力之差
|
// 计算玩家1和玩家2的棋子活动能力之差
|
||||||
int getMobilityDiff(enum player_t turn, const Rule &rule, int nPiecesOnBoard[], bool includeFobidden);
|
int getMobilityDiff(player_t turn, const Rule &rule, int nPiecesOnBoard[], bool includeFobidden);
|
||||||
|
|
||||||
// 游戏重置
|
// 游戏重置
|
||||||
bool reset();
|
bool reset();
|
||||||
|
@ -260,10 +260,10 @@ public:
|
||||||
void cleanForbiddenLocations();
|
void cleanForbiddenLocations();
|
||||||
|
|
||||||
// 设置轮流
|
// 设置轮流
|
||||||
void setTurn(player_t player);
|
void setSideToMove(player_t player);
|
||||||
|
|
||||||
// 改变轮流
|
// 改变轮流
|
||||||
void changeTurn();
|
void changeSideToMove();
|
||||||
|
|
||||||
// 设置提示
|
// 设置提示
|
||||||
void setTips();
|
void setTips();
|
||||||
|
@ -328,7 +328,7 @@ private:
|
||||||
// uint64_t hash;
|
// uint64_t hash;
|
||||||
|
|
||||||
// 胜负标识
|
// 胜负标识
|
||||||
enum player_t winner;
|
player_t winner;
|
||||||
|
|
||||||
// 当前步数
|
// 当前步数
|
||||||
step_t currentStep {};
|
step_t currentStep {};
|
||||||
|
|
|
@ -609,7 +609,7 @@ void GameController::timerEvent(QTimerEvent *event)
|
||||||
|
|
||||||
bool GameController::isAIsTurn()
|
bool GameController::isAIsTurn()
|
||||||
{
|
{
|
||||||
return isAiPlayer[game_.position.turnId];
|
return isAiPlayer[game_.position.sideId];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关键槽函数,根据QGraphicsScene的信号和状态来执行选子、落子或去子
|
// 关键槽函数,根据QGraphicsScene的信号和状态来执行选子、落子或去子
|
||||||
|
@ -747,7 +747,7 @@ bool GameController::actionPiece(QPointF pos)
|
||||||
if (&game_ == &(this->game_)) {
|
if (&game_ == &(this->game_)) {
|
||||||
// 如果还未决出胜负
|
// 如果还未决出胜负
|
||||||
if (game_.whoWin() == PLAYER_NOBODY) {
|
if (game_.whoWin() == PLAYER_NOBODY) {
|
||||||
if (game_.position.turn == PLAYER_1) {
|
if (game_.position.sideToMove == PLAYER_1) {
|
||||||
if (isAiPlayer[1]) {
|
if (isAiPlayer[1]) {
|
||||||
ai[1]->resume();
|
ai[1]->resume();
|
||||||
}
|
}
|
||||||
|
@ -779,7 +779,7 @@ bool GameController::actionPiece(QPointF pos)
|
||||||
|
|
||||||
bool GameController::giveUp()
|
bool GameController::giveUp()
|
||||||
{
|
{
|
||||||
bool result = game_.giveup(game_.position.turn);
|
bool result = game_.giveup(game_.position.sideToMove);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -887,7 +887,7 @@ bool GameController::command(const QString &cmd, bool update /* = true */)
|
||||||
if (&game_ == &(this->game_)) {
|
if (&game_ == &(this->game_)) {
|
||||||
// 如果还未决出胜负
|
// 如果还未决出胜负
|
||||||
if (game_.whoWin() == PLAYER_NOBODY) {
|
if (game_.whoWin() == PLAYER_NOBODY) {
|
||||||
if (game_.position.turn == PLAYER_1) {
|
if (game_.position.sideToMove == PLAYER_1) {
|
||||||
if (isAiPlayer[1]) {
|
if (isAiPlayer[1]) {
|
||||||
ai[1]->resume();
|
ai[1]->resume();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue