dummyPosition->dummyGame

This commit is contained in:
CalciteM Team 2019-09-15 17:47:49 +08:00
parent cd800ec73a
commit 7b03758676
10 changed files with 84 additions and 84 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -185,12 +185,12 @@ private:
Game position_;
// 演算用的模型
Game dummyPosition;
Game dummyGame;
PositionContext *positionContext {};
// hash 计算时,各种转换用的模型
Game dummyPositionShift;
Game dummyGameShift;
// 根节点
Node *rootNode {nullptr};

View File

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

View File

@ -72,8 +72,8 @@ public:
};
// 棋类(在数据模型内,玩家只分先后手,不分黑白)
// 注意:Position 类不是线程安全的!
// 所以不能跨线程修改 Position 类的静态成员变量,切记!
// 注意:Game 类不是线程安全的!
// 所以不能跨线程修改 Game 类的静态成员变量,切记!
class Game
{
// AI友元类

View File

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

View File

@ -206,7 +206,7 @@ private:
Game position_;
// 棋对象的数据模型(临时)
Game dummyPosition;
Game dummyGame;
// 2个AI的线程
AiThread *ai[3];