dummyPosition->dummyGame
This commit is contained in:
parent
cd800ec73a
commit
7b03758676
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "evaluate.h"
|
||||
|
||||
value_t Evaluation::getValue(Game &dummyPosition, PositionContext *positionContext, MillGameAi_ab::Node *node)
|
||||
value_t Evaluation::getValue(Game &dummyGame, PositionContext *positionContext, MillGameAi_ab::Node *node)
|
||||
{
|
||||
// 初始评估值为0,对先手有利则增大,对后手有利则减小
|
||||
value_t value = VALUE_ZERO;
|
||||
|
@ -83,7 +83,7 @@ value_t Evaluation::getValue(Game &dummyPosition, PositionContext *positionConte
|
|||
|
||||
#ifdef EVALUATE_MOBILITY
|
||||
// 按棋子活动能力计分
|
||||
value += dummyPosition.getMobilityDiff(positionContext->turn, dummyPosition.currentRule, positionContext->nPiecesInHand[1], positionContext->nPiecesInHand[2], false) * 10;
|
||||
value += dummyGame.getMobilityDiff(positionContext->turn, dummyGame.currentRule, positionContext->nPiecesInHand[1], positionContext->nPiecesInHand[2], false) * 10;
|
||||
#endif /* EVALUATE_MOBILITY */
|
||||
|
||||
switch (positionContext->action) {
|
||||
|
@ -112,7 +112,7 @@ value_t Evaluation::getValue(Game &dummyPosition, PositionContext *positionConte
|
|||
// 布局阶段闷棋判断
|
||||
if (positionContext->nPiecesOnBoard[1] + positionContext->nPiecesOnBoard[2] >=
|
||||
Board::N_SEATS * Board::N_RINGS) {
|
||||
if (dummyPosition.getRule()->isStartingPlayerLoseWhenBoardFull) {
|
||||
if (dummyGame.getRule()->isStartingPlayerLoseWhenBoardFull) {
|
||||
value -= VALUE_WIN;
|
||||
} else {
|
||||
value = VALUE_DRAW;
|
||||
|
@ -121,17 +121,17 @@ value_t Evaluation::getValue(Game &dummyPosition, PositionContext *positionConte
|
|||
|
||||
// 走棋阶段被闷判断
|
||||
if (positionContext->action == ACTION_CHOOSE &&
|
||||
dummyPosition.context.board.isAllSurrounded(positionContext->turn, dummyPosition.currentRule, positionContext->nPiecesOnBoard, positionContext->turn) &&
|
||||
dummyPosition.getRule()->isLoseWhenNoWay) {
|
||||
dummyGame.context.board.isAllSurrounded(positionContext->turn, dummyGame.currentRule, positionContext->nPiecesOnBoard, positionContext->turn) &&
|
||||
dummyGame.getRule()->isLoseWhenNoWay) {
|
||||
// 规则要求被“闷”判负,则对手获胜
|
||||
value_t delta = positionContext->turn == PLAYER_1 ? -VALUE_WIN : VALUE_WIN;
|
||||
value += delta;
|
||||
}
|
||||
|
||||
// 剩余棋子个数判断
|
||||
if (positionContext->nPiecesOnBoard[1] < dummyPosition.getRule()->nPiecesAtLeast) {
|
||||
if (positionContext->nPiecesOnBoard[1] < dummyGame.getRule()->nPiecesAtLeast) {
|
||||
value -= VALUE_WIN;
|
||||
} else if (positionContext->nPiecesOnBoard[2] < dummyPosition.getRule()->nPiecesAtLeast) {
|
||||
} else if (positionContext->nPiecesOnBoard[2] < dummyGame.getRule()->nPiecesAtLeast) {
|
||||
value += VALUE_WIN;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
|
||||
Evaluation &operator=(const Evaluation &) = delete;
|
||||
|
||||
static value_t getValue(Game &dummyPosition, PositionContext *positionContext, MillGameAi_ab::Node *node);
|
||||
static value_t getValue(Game &dummyGame, PositionContext *positionContext, MillGameAi_ab::Node *node);
|
||||
|
||||
// 评估子力
|
||||
#ifdef EVALUATE_ENABLE
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "player.h"
|
||||
#include "misc.h"
|
||||
|
||||
void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyPosition,
|
||||
void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyGame,
|
||||
MillGameAi_ab::Node *node, MillGameAi_ab::Node *rootNode,
|
||||
move_t bestMove)
|
||||
{
|
||||
|
@ -34,17 +34,17 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyPosition,
|
|||
size_t newCapacity = 24;
|
||||
|
||||
// 留足余量空间避免多次重新分配,此动作本身也占用 CPU/内存 开销
|
||||
switch (dummyPosition.getPhase()) {
|
||||
switch (dummyGame.getPhase()) {
|
||||
case PHASE_PLACING:
|
||||
if (dummyPosition.getAction() == ACTION_CAPTURE) {
|
||||
newCapacity = static_cast<size_t>(dummyPosition.getPiecesOnBoardCount(dummyPosition.context.opponentId));
|
||||
if (dummyGame.getAction() == ACTION_CAPTURE) {
|
||||
newCapacity = static_cast<size_t>(dummyGame.getPiecesOnBoardCount(dummyGame.context.opponentId));
|
||||
} else {
|
||||
newCapacity = static_cast<size_t>(dummyPosition.getPiecesInHandCount(1) + dummyPosition.getPiecesInHandCount(2));
|
||||
newCapacity = static_cast<size_t>(dummyGame.getPiecesInHandCount(1) + dummyGame.getPiecesInHandCount(2));
|
||||
}
|
||||
break;
|
||||
case PHASE_MOVING:
|
||||
if (dummyPosition.getAction() == ACTION_CAPTURE) {
|
||||
newCapacity = static_cast<size_t>(dummyPosition.getPiecesOnBoardCount(dummyPosition.context.opponentId));
|
||||
if (dummyGame.getAction() == ACTION_CAPTURE) {
|
||||
newCapacity = static_cast<size_t>(dummyGame.getPiecesOnBoardCount(dummyGame.context.opponentId));
|
||||
} else {
|
||||
newCapacity = 6;
|
||||
}
|
||||
|
@ -65,28 +65,28 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyPosition,
|
|||
}
|
||||
|
||||
// 对手
|
||||
player_t opponent = Player::getOpponent(dummyPosition.context.turn);
|
||||
player_t opponent = Player::getOpponent(dummyGame.context.turn);
|
||||
|
||||
// 列出所有合法的下一招
|
||||
switch (dummyPosition.context.action) {
|
||||
switch (dummyGame.context.action) {
|
||||
// 对于选子和落子动作
|
||||
case ACTION_CHOOSE:
|
||||
case ACTION_PLACE:
|
||||
// 对于摆子阶段
|
||||
if (dummyPosition.context.phase & (PHASE_PLACING | PHASE_NOTSTARTED)) {
|
||||
if (dummyGame.context.phase & (PHASE_PLACING | PHASE_NOTSTARTED)) {
|
||||
for (move_t i : movePriorityTable) {
|
||||
location = i;
|
||||
|
||||
if (dummyPosition.boardLocations[location]) {
|
||||
if (dummyGame.boardLocations[location]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dummyPosition.context.phase != PHASE_NOTSTARTED || node != rootNode) {
|
||||
ai_ab.addNode(node, VALUE_ZERO, (move_t)location, bestMove, dummyPosition.context.turn);
|
||||
if (dummyGame.context.phase != PHASE_NOTSTARTED || node != rootNode) {
|
||||
ai_ab.addNode(node, VALUE_ZERO, (move_t)location, bestMove, dummyGame.context.turn);
|
||||
} else {
|
||||
// 若为先手,则抢占星位
|
||||
if (Board::isStarLocation(location)) {
|
||||
ai_ab.addNode(node, VALUE_INFINITE, (move_t)location, bestMove, dummyPosition.context.turn);
|
||||
ai_ab.addNode(node, VALUE_INFINITE, (move_t)location, bestMove, dummyGame.context.turn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,34 +94,34 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyPosition,
|
|||
}
|
||||
|
||||
// 对于移子阶段
|
||||
if (dummyPosition.context.phase & PHASE_MOVING) {
|
||||
if (dummyGame.context.phase & PHASE_MOVING) {
|
||||
int newLocation, oldLocation;
|
||||
|
||||
// 尽量走理论上较差的位置的棋子
|
||||
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||
oldLocation = movePriorityTable[i];
|
||||
|
||||
if (!dummyPosition.choose(oldLocation)) {
|
||||
if (!dummyGame.choose(oldLocation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dummyPosition.context.nPiecesOnBoard[dummyPosition.context.turnId] > dummyPosition.currentRule.nPiecesAtLeast ||
|
||||
!dummyPosition.currentRule.allowFlyWhenRemainThreePieces) {
|
||||
if (dummyGame.context.nPiecesOnBoard[dummyGame.context.turnId] > dummyGame.currentRule.nPiecesAtLeast ||
|
||||
!dummyGame.currentRule.allowFlyWhenRemainThreePieces) {
|
||||
// 对于棋盘上还有3个子以上,或不允许飞子的情况,要求必须在着法表中
|
||||
for (int direction = DIRECTION_CLOCKWISE; direction <= DIRECTION_OUTWARD; direction++) {
|
||||
// 对于原有位置,遍历四个方向的着法,如果棋盘上为空位就加到结点列表中
|
||||
newLocation = moveTable[oldLocation][direction];
|
||||
if (newLocation && !dummyPosition.boardLocations[newLocation]) {
|
||||
if (newLocation && !dummyGame.boardLocations[newLocation]) {
|
||||
move_t move = move_t((oldLocation << 8) + newLocation);
|
||||
ai_ab.addNode(node, VALUE_ZERO, move, bestMove, dummyPosition.context.turn); // (12%)
|
||||
ai_ab.addNode(node, VALUE_ZERO, move, bestMove, dummyGame.context.turn); // (12%)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 对于棋盘上还有不到3个字,但允许飞子的情况,不要求在着法表中,是空位就行
|
||||
for (newLocation = Board::LOCATION_BEGIN; newLocation < Board::LOCATION_END; newLocation++) {
|
||||
if (!dummyPosition.boardLocations[newLocation]) {
|
||||
if (!dummyGame.boardLocations[newLocation]) {
|
||||
move_t move = move_t((oldLocation << 8) + newLocation);
|
||||
ai_ab.addNode(node, VALUE_ZERO, move, bestMove, dummyPosition.context.turn);
|
||||
ai_ab.addNode(node, VALUE_ZERO, move, bestMove, dummyGame.context.turn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,12 +131,12 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyPosition,
|
|||
|
||||
// 对于吃子动作
|
||||
case ACTION_CAPTURE:
|
||||
if (dummyPosition.context.board.isAllInMills(opponent)) {
|
||||
if (dummyGame.context.board.isAllInMills(opponent)) {
|
||||
// 全成三的情况
|
||||
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||
location = movePriorityTable[i];
|
||||
if (dummyPosition.boardLocations[location] & opponent) {
|
||||
ai_ab.addNode(node, VALUE_ZERO, (move_t)-location, bestMove, dummyPosition.context.turn);
|
||||
if (dummyGame.boardLocations[location] & opponent) {
|
||||
ai_ab.addNode(node, VALUE_ZERO, (move_t)-location, bestMove, dummyGame.context.turn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -145,9 +145,9 @@ void MoveList::generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyPosition,
|
|||
// 不是全成三的情况
|
||||
for (int i = MOVE_PRIORITY_TABLE_SIZE - 1; i >= 0; i--) {
|
||||
location = movePriorityTable[i];
|
||||
if (dummyPosition.boardLocations[location] & opponent) {
|
||||
if (dummyPosition.getRule()->allowRemoveMill || !dummyPosition.context.board.inHowManyMills(location)) {
|
||||
ai_ab.addNode(node, VALUE_ZERO, (move_t)-location, bestMove, dummyPosition.context.turn);
|
||||
if (dummyGame.boardLocations[location] & opponent) {
|
||||
if (dummyGame.getRule()->allowRemoveMill || !dummyGame.context.board.inHowManyMills(location)) {
|
||||
ai_ab.addNode(node, VALUE_ZERO, (move_t)-location, bestMove, dummyGame.context.turn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
MoveList &operator=(const MoveList &) = delete;
|
||||
|
||||
// 生成所有合法的着法并建立子节点
|
||||
static void generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyPosition,
|
||||
static void generateLegalMoves(MillGameAi_ab &ai_ab, Game &dummyGame,
|
||||
MillGameAi_ab::Node *node, MillGameAi_ab::Node *rootNode,
|
||||
move_t bestMove);
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ depth_t MillGameAi_ab::changeDepth(depth_t originalDepth)
|
|||
{
|
||||
depth_t newDepth = originalDepth;
|
||||
|
||||
if ((dummyPosition.context.phase) & (PHASE_PLACING)) {
|
||||
if ((dummyGame.context.phase) & (PHASE_PLACING)) {
|
||||
#ifdef GAME_PLACING_DYNAMIC_DEPTH
|
||||
#ifdef DEAL_WITH_HORIZON_EFFECT
|
||||
#ifdef TRANSPOSITION_TABLE_ENABLE
|
||||
|
@ -77,7 +77,7 @@ depth_t MillGameAi_ab::changeDepth(depth_t originalDepth)
|
|||
depth_t depthTable[] = { 2, 13, 13, 13, 12, 11, 10, 9, 9, 8, 8, 7, 1 };
|
||||
#endif
|
||||
#endif // DEAL_WITH_HORIZON_EFFECT
|
||||
newDepth = depthTable[dummyPosition.getPiecesInHandCount(1)];
|
||||
newDepth = depthTable[dummyGame.getPiecesInHandCount(1)];
|
||||
#elif defined GAME_PLACING_FIXED_DEPTH
|
||||
newDepth = GAME_PLACING_FIXED_DEPTH;
|
||||
#endif // GAME_PLACING_DYNAMIC_DEPTH
|
||||
|
@ -85,7 +85,7 @@ depth_t MillGameAi_ab::changeDepth(depth_t originalDepth)
|
|||
|
||||
#ifdef GAME_MOVING_FIXED_DEPTH
|
||||
// 走棋阶段将深度调整
|
||||
if ((dummyPosition.context.phase) & (PHASE_MOVING)) {
|
||||
if ((dummyGame.context.phase) & (PHASE_MOVING)) {
|
||||
newDepth = GAME_MOVING_FIXED_DEPTH;
|
||||
}
|
||||
#endif /* GAME_MOVING_FIXED_DEPTH */
|
||||
|
@ -141,8 +141,8 @@ struct MillGameAi_ab::Node *MillGameAi_ab::addNode(
|
|||
|
||||
#ifdef DEBUG_AB_TREE
|
||||
newNode->root = rootNode;
|
||||
newNode->phase = dummyPosition.context.phase;
|
||||
newNode->action = dummyPosition.context.action;
|
||||
newNode->phase = dummyGame.context.phase;
|
||||
newNode->action = dummyGame.context.action;
|
||||
newNode->evaluated = false;
|
||||
newNode->nPiecesInHandDiff = INT_MAX;
|
||||
newNode->nPiecesOnBoardDiff = INT_MAX;
|
||||
|
@ -155,15 +155,15 @@ struct MillGameAi_ab::Node *MillGameAi_ab::addNode(
|
|||
char cmd[32] = { 0 };
|
||||
|
||||
if (move < 0) {
|
||||
dummyPosition.context.board.locationToPolar(-move, r, s);
|
||||
dummyGame.context.board.locationToPolar(-move, r, s);
|
||||
sprintf(cmd, "-(%1u,%1u)", r, s);
|
||||
} else if (move & 0x7f00) {
|
||||
int r1, s1;
|
||||
dummyPosition.context.board.locationToPolar(move >> 8, r1, s1);
|
||||
dummyPosition.context.board.locationToPolar(move & 0x00ff, r, s);
|
||||
dummyGame.context.board.locationToPolar(move >> 8, r1, s1);
|
||||
dummyGame.context.board.locationToPolar(move & 0x00ff, r, s);
|
||||
sprintf(cmd, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s);
|
||||
} else {
|
||||
dummyPosition.context.board.locationToPolar(move & 0x007f, r, s);
|
||||
dummyGame.context.board.locationToPolar(move & 0x007f, r, s);
|
||||
sprintf(cmd, "(%1u,%1u)", r, s);
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ struct MillGameAi_ab::Node *MillGameAi_ab::addNode(
|
|||
if (bestMove == 0 || move != bestMove) {
|
||||
#ifdef MILL_FIRST
|
||||
// 优先成三
|
||||
if (dummyPosition.getPhase() == GAME_PLACING && move > 0 && dummyPosition.context.board.isInMills(move, true)) {
|
||||
if (dummyGame.getPhase() == GAME_PLACING && move > 0 && dummyGame.context.board.isInMills(move, true)) {
|
||||
parent->children.insert(parent->children.begin(), newNode);
|
||||
} else {
|
||||
parent->children.push_back(newNode);
|
||||
|
@ -232,7 +232,7 @@ void MillGameAi_ab::sortLegalMoves(Node *node)
|
|||
{
|
||||
// 这个函数对效率的影响很大,排序好的话,剪枝较早,节省时间,但不能在此函数耗费太多时间
|
||||
|
||||
auto cmp = dummyPosition.context.turn == PLAYER_1 ? nodeGreater : nodeLess;
|
||||
auto cmp = dummyGame.context.turn == PLAYER_1 ? nodeGreater : nodeLess;
|
||||
|
||||
std::stable_sort(node->children.begin(), node->children.end(), cmp);
|
||||
}
|
||||
|
@ -275,8 +275,8 @@ void MillGameAi_ab::setPosition(const Game &position)
|
|||
}
|
||||
|
||||
this->position_ = position;
|
||||
dummyPosition = position;
|
||||
positionContext = &(dummyPosition.context);
|
||||
dummyGame = position;
|
||||
positionContext = &(dummyGame.context);
|
||||
requiredQuit = false;
|
||||
deleteTree(rootNode);
|
||||
#ifdef MEMORY_POOL
|
||||
|
@ -397,7 +397,7 @@ value_t MillGameAi_ab::alphaBetaPruning(depth_t depth, value_t alpha, value_t be
|
|||
enum TranspositionTable::HashType hashf = TranspositionTable::hashfALPHA;
|
||||
|
||||
// 获取哈希值
|
||||
hash_t hash = dummyPosition.getHash();
|
||||
hash_t hash = dummyGame.getHash();
|
||||
#ifdef DEBUG_AB_TREE
|
||||
node->hash = hash;
|
||||
#endif
|
||||
|
@ -454,7 +454,7 @@ value_t MillGameAi_ab::alphaBetaPruning(depth_t depth, value_t alpha, value_t be
|
|||
// 搜索到叶子节点(决胜局面) // TODO: 对哈希进行特殊处理
|
||||
if (positionContext->phase == PHASE_GAMEOVER) {
|
||||
// 局面评估
|
||||
node->value = Evaluation::getValue(dummyPosition, positionContext, node);
|
||||
node->value = Evaluation::getValue(dummyGame, positionContext, node);
|
||||
evaluatedNodeCount++;
|
||||
|
||||
// 为争取速胜,value 值 +- 深度
|
||||
|
@ -479,7 +479,7 @@ value_t MillGameAi_ab::alphaBetaPruning(depth_t depth, value_t alpha, value_t be
|
|||
// 搜索到第0层或需要退出
|
||||
if (!depth || requiredQuit) {
|
||||
// 局面评估
|
||||
node->value = Evaluation::getValue(dummyPosition, positionContext, node);
|
||||
node->value = Evaluation::getValue(dummyGame, positionContext, node);
|
||||
evaluatedNodeCount++;
|
||||
|
||||
// 为争取速胜,value 值 +- 深度 (有必要?)
|
||||
|
@ -511,18 +511,18 @@ value_t MillGameAi_ab::alphaBetaPruning(depth_t depth, value_t alpha, value_t be
|
|||
}
|
||||
|
||||
// 生成子节点树,即生成每个合理的着法
|
||||
MoveList::generateLegalMoves(*this, dummyPosition, node, rootNode, bestMove);
|
||||
MoveList::generateLegalMoves(*this, dummyGame, node, rootNode, bestMove);
|
||||
|
||||
// 根据演算模型执行 MiniMax 检索,对先手,搜索 Max, 对后手,搜索 Min
|
||||
|
||||
minMax = dummyPosition.context.turn == PLAYER_1 ? -VALUE_INFINITE : VALUE_INFINITE;
|
||||
minMax = dummyGame.context.turn == PLAYER_1 ? -VALUE_INFINITE : VALUE_INFINITE;
|
||||
|
||||
for (auto child : node->children) {
|
||||
// 上下文入栈保存,以便后续撤销着法
|
||||
contextStack.push(dummyPosition.context);
|
||||
contextStack.push(dummyGame.context);
|
||||
|
||||
// 执行着法
|
||||
dummyPosition.command(child->move);
|
||||
dummyGame.command(child->move);
|
||||
|
||||
#ifdef DEAL_WITH_HORIZON_EFFECT
|
||||
// 克服“水平线效应”: 若遇到吃子,则搜索深度增加
|
||||
|
@ -543,10 +543,10 @@ value_t MillGameAi_ab::alphaBetaPruning(depth_t depth, value_t alpha, value_t be
|
|||
value = alphaBetaPruning(depth - 1 + epsilon, alpha, beta, child);
|
||||
|
||||
// 上下文弹出栈,撤销着法
|
||||
dummyPosition.context = contextStack.top();
|
||||
dummyGame.context = contextStack.top();
|
||||
contextStack.pop();
|
||||
|
||||
if (dummyPosition.context.turn == PLAYER_1) {
|
||||
if (dummyGame.context.turn == PLAYER_1) {
|
||||
// 为走棋一方的层, 局面对走棋的一方来说是以 α 为评价
|
||||
|
||||
// 取最大值
|
||||
|
@ -722,15 +722,15 @@ const char *MillGameAi_ab::move2string(move_t move)
|
|||
int r, s;
|
||||
|
||||
if (move < 0) {
|
||||
dummyPosition.context.board.locationToPolar(-move, r, s);
|
||||
dummyGame.context.board.locationToPolar(-move, r, s);
|
||||
sprintf(cmdline, "-(%1u,%1u)", r, s);
|
||||
} else if (move & 0x7f00) {
|
||||
int r1, s1;
|
||||
dummyPosition.context.board.locationToPolar(move >> 8, r1, s1);
|
||||
dummyPosition.context.board.locationToPolar(move & 0x00ff, r, s);
|
||||
dummyGame.context.board.locationToPolar(move >> 8, r1, s1);
|
||||
dummyGame.context.board.locationToPolar(move & 0x00ff, r, s);
|
||||
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)", r1, s1, r, s);
|
||||
} else {
|
||||
dummyPosition.context.board.locationToPolar(move & 0x007f, r, s);
|
||||
dummyGame.context.board.locationToPolar(move & 0x007f, r, s);
|
||||
sprintf(cmdline, "(%1u,%1u)", r, s);
|
||||
}
|
||||
|
||||
|
|
|
@ -185,12 +185,12 @@ private:
|
|||
Game position_;
|
||||
|
||||
// 演算用的模型
|
||||
Game dummyPosition;
|
||||
Game dummyGame;
|
||||
|
||||
PositionContext *positionContext {};
|
||||
|
||||
// hash 计算时,各种转换用的模型
|
||||
Game dummyPositionShift;
|
||||
Game dummyGameShift;
|
||||
|
||||
// 根节点
|
||||
Node *rootNode {nullptr};
|
||||
|
|
|
@ -49,17 +49,17 @@ bool TranspositionTable::findHash(hash_t hash, TranspositionTable::HashValue &ha
|
|||
return iter;
|
||||
|
||||
// 变换局面,查找 hash (废弃)
|
||||
dummyPositionShift = dummyPosition;
|
||||
dummyGameShift = dummyGame;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (i)
|
||||
dummyPositionShift.mirror(false);
|
||||
dummyGameShift.mirror(false);
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (j)
|
||||
dummyPositionShift.turn(false);
|
||||
dummyGameShift.turn(false);
|
||||
for (int k = 0; k < 4; k++) {
|
||||
dummyPositionShift.rotate(k * 90, false);
|
||||
iter = hashmap.find(dummyPositionShift.getHash());
|
||||
dummyGameShift.rotate(k * 90, false);
|
||||
iter = hashmap.find(dummyGameShift.getHash());
|
||||
if (iter != hashmap.end())
|
||||
return iter;
|
||||
}
|
||||
|
|
|
@ -72,8 +72,8 @@ public:
|
|||
};
|
||||
|
||||
// 棋类(在数据模型内,玩家只分先后手,不分黑白)
|
||||
// 注意:Position 类不是线程安全的!
|
||||
// 所以不能跨线程修改 Position 类的静态成员变量,切记!
|
||||
// 注意:Game 类不是线程安全的!
|
||||
// 所以不能跨线程修改 Game 类的静态成员变量,切记!
|
||||
class Game
|
||||
{
|
||||
// AI友元类
|
||||
|
|
|
@ -124,7 +124,7 @@ void GameController::gameStart()
|
|||
{
|
||||
position_.configure(giveUpIfMostLose_, randomMove_);
|
||||
position_.start();
|
||||
dummyPosition = position_;
|
||||
dummyGame = position_;
|
||||
|
||||
// 每隔100毫秒调用一次定时器处理函数
|
||||
if (timeID == 0) {
|
||||
|
@ -150,7 +150,7 @@ void GameController::gameReset()
|
|||
// 重置游戏
|
||||
position_.configure(giveUpIfMostLose_, randomMove_);
|
||||
position_.reset();
|
||||
dummyPosition = position_;
|
||||
dummyGame = position_;
|
||||
|
||||
// 停掉线程
|
||||
if (!isAutoRestart) {
|
||||
|
@ -281,7 +281,7 @@ void GameController::setRule(int ruleNo, step_t stepLimited /*= -1*/, int timeLi
|
|||
|
||||
// 设置模型规则,重置游戏
|
||||
position_.setContext(&RULES[ruleNo], stepsLimit, timeLimit);
|
||||
dummyPosition = position_;
|
||||
dummyGame = position_;
|
||||
|
||||
// 重置游戏
|
||||
gameReset();
|
||||
|
@ -400,7 +400,7 @@ void GameController::flip()
|
|||
|
||||
position_.context.board.mirror(position_.cmdlist, position_.cmdline, position_.move_, position_.currentRule, position_.currentLocation);
|
||||
position_.context.board.rotate(180, position_.cmdlist, position_.cmdline, position_.move_, position_.currentRule, position_.currentLocation);
|
||||
dummyPosition = position_;
|
||||
dummyGame = position_;
|
||||
|
||||
// 更新棋谱
|
||||
int row = 0;
|
||||
|
@ -439,7 +439,7 @@ void GameController::mirror()
|
|||
}
|
||||
|
||||
position_.context.board.mirror(position_.cmdlist, position_.cmdline, position_.move_, position_.currentRule, position_.currentLocation);
|
||||
dummyPosition = position_;
|
||||
dummyGame = position_;
|
||||
|
||||
// 更新棋谱
|
||||
int row = 0;
|
||||
|
@ -481,7 +481,7 @@ void GameController::turnRight()
|
|||
}
|
||||
|
||||
position_.context.board.rotate(-90, position_.cmdlist, position_.cmdline, position_.move_, position_.currentRule, position_.currentLocation);
|
||||
dummyPosition = position_;
|
||||
dummyGame = position_;
|
||||
|
||||
// 更新棋谱
|
||||
int row = 0;
|
||||
|
@ -521,7 +521,7 @@ void GameController::turnLeft()
|
|||
}
|
||||
|
||||
position_.context.board.rotate(90, position_.cmdlist, position_.cmdline, position_.move_, position_.currentRule, position_.currentLocation);
|
||||
dummyPosition = position_;
|
||||
dummyGame = position_;
|
||||
|
||||
// 更新棋谱
|
||||
int row = 0;
|
||||
|
@ -642,7 +642,7 @@ bool GameController::actionPiece(QPointF pos)
|
|||
|
||||
if (QMessageBox::Ok == msgBox.exec()) {
|
||||
#endif /* !MOBILE_APP_UI */
|
||||
position_ = dummyPosition;
|
||||
position_ = dummyGame;
|
||||
manualListModel.removeRows(currentRow + 1, manualListModel.rowCount() - currentRow - 1);
|
||||
|
||||
// 如果再决出胜负后悔棋,则重新启动计时
|
||||
|
@ -953,14 +953,14 @@ bool GameController::phaseChange(int row, bool forceUpdate)
|
|||
|
||||
for (int i = 0; i <= row; i++) {
|
||||
loggerDebug("%s\n", mlist.at(i).toStdString().c_str());
|
||||
dummyPosition.command(mlist.at(i).toStdString().c_str());
|
||||
dummyGame.command(mlist.at(i).toStdString().c_str());
|
||||
}
|
||||
|
||||
// 下面这步关键,会让悔棋者承担时间损失
|
||||
dummyPosition.setStartTime(position_.getStartTimeb());
|
||||
dummyGame.setStartTime(position_.getStartTimeb());
|
||||
|
||||
// 刷新棋局场景
|
||||
updateScence(dummyPosition);
|
||||
updateScence(dummyGame);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -206,7 +206,7 @@ private:
|
|||
Game position_;
|
||||
|
||||
// 棋对象的数据模型(临时)
|
||||
Game dummyPosition;
|
||||
Game dummyGame;
|
||||
|
||||
// 2个AI的线程
|
||||
AiThread *ai[3];
|
||||
|
|
Loading…
Reference in New Issue