出现三次重复局面判为和棋并添加和棋盘数显示
This commit is contained in:
parent
563c5bea05
commit
8b092ad2ca
|
@ -84,12 +84,16 @@ void AiThread::run()
|
|||
emit calcStarted();
|
||||
mutex.unlock();
|
||||
|
||||
ai_ab.alphaBetaPruning(aiDepth); // 顶层调用ab剪枝
|
||||
const char *str = ai_ab.bestMove();
|
||||
qDebug() << "Computer:" << str << "\n";
|
||||
|
||||
if (strcmp(str, "error!"))
|
||||
if (ai_ab.alphaBetaPruning(aiDepth) == 3) {
|
||||
qDebug() << "Draw\n";
|
||||
const char *str = "draw";
|
||||
emit command(str);
|
||||
} else {
|
||||
const char *str = ai_ab.bestMove();
|
||||
qDebug() << "Computer:" << str << "\n";
|
||||
if (strcmp(str, "error!"))
|
||||
emit command(str);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MODE
|
||||
qDebug() << "Thread" << id << "run" << ++iTemp << "times";
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
//#define BOOK_LEARNING
|
||||
|
||||
#define THREEFOLD_REPETITION
|
||||
|
||||
//#define DONOT_DELETE_TREE
|
||||
|
||||
#define MOVE_PRIORITY_TABLE_SUPPORT
|
||||
|
|
|
@ -870,8 +870,8 @@ bool GameController::command(const QString &cmd, bool update /*= true*/)
|
|||
ai2.stop();
|
||||
|
||||
// 弹框
|
||||
//message = QString::fromStdString(chess_.getTips());
|
||||
//QMessageBox::about(NULL, "游戏结果", message);
|
||||
message = QString::fromStdString(chess_.getTips());
|
||||
QMessageBox::about(NULL, "游戏结果", message);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -124,7 +124,7 @@ NineChess::NineChess()
|
|||
// 单独提出 board 等数据,免得每次都写 context.board;
|
||||
board_ = context.board;
|
||||
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
//hash_ = &context.hash;
|
||||
//zobrist_ = &context.zobrist;
|
||||
|
||||
|
@ -141,7 +141,7 @@ NineChess::NineChess()
|
|||
setContext(&RULES[1]);
|
||||
|
||||
// 比分归零
|
||||
score_1 = score_2 = 0;
|
||||
score_1 = score_2 = score_draw = 0;
|
||||
}
|
||||
|
||||
NineChess::NineChess(const NineChess &chess)
|
||||
|
@ -385,14 +385,11 @@ bool NineChess::setContext(const struct Rule *rule, int maxStepsLedToDraw, int m
|
|||
// 当前棋局(3×8)
|
||||
if (board == nullptr) {
|
||||
memset(context.board, 0, sizeof(context.board));
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
context.hash = 0ull;
|
||||
#endif
|
||||
} else {
|
||||
memcpy(context.board, board, sizeof(context.board));
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
//context.hash = hash;
|
||||
#endif
|
||||
}
|
||||
|
||||
// 计算盘面子数
|
||||
|
@ -498,9 +495,6 @@ void NineChess::getContext(struct Rule &rule, int &step, int &flags,
|
|||
nPiecesInHand_1 = context.nPiecesInHand_1;
|
||||
nPiecesInHand_2 = context.nPiecesInHand_2;
|
||||
num_NeedRemove = context.nPiecesNeedRemove;
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
//hash = context.hash;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NineChess::reset()
|
||||
|
@ -544,7 +538,7 @@ bool NineChess::reset()
|
|||
// 用时置零
|
||||
elapsedMS_1 = elapsedMS_2 = 0;
|
||||
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
// 哈希归零
|
||||
context.hash = 0;
|
||||
#endif
|
||||
|
@ -702,7 +696,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
|
|||
|
||||
board_[pos] = piece;
|
||||
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
updateHash(pos);
|
||||
#endif
|
||||
move_ = pos;
|
||||
|
@ -797,7 +791,7 @@ bool NineChess::place(int c, int p, long time_p /* = -1*/)
|
|||
updateHash(pos);
|
||||
#endif
|
||||
board_[currentPos] = '\x00';
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
revertHash(currentPos);
|
||||
#endif
|
||||
currentPos = pos;
|
||||
|
@ -873,11 +867,11 @@ bool NineChess::capture(int c, int p, long time_p /* = -1*/)
|
|||
revertHash(pos);
|
||||
#endif
|
||||
board_[pos] = '\x0f';
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
updateHash(pos);
|
||||
#endif
|
||||
} else { // 去子
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
revertHash(pos);
|
||||
#endif
|
||||
board_[pos] = '\x00';
|
||||
|
@ -1045,7 +1039,7 @@ bool NineChess::place(int pos)
|
|||
|
||||
board_[pos] = piece;
|
||||
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
updateHash(pos);
|
||||
#endif
|
||||
move_ = pos;
|
||||
|
@ -1123,11 +1117,11 @@ bool NineChess::place(int pos)
|
|||
// 移子
|
||||
move_ = (currentPos << 8) + pos;
|
||||
board_[pos] = board_[currentPos];
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
updateHash(pos);
|
||||
#endif
|
||||
board_[currentPos] = '\x00';
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
revertHash(currentPos);
|
||||
#endif
|
||||
currentPos = pos;
|
||||
|
@ -1193,15 +1187,15 @@ bool NineChess::capture(int pos)
|
|||
}
|
||||
|
||||
if (currentRule.hasForbiddenPoint && context.stage == GAME_PLACING) {
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
revertHash(pos);
|
||||
#endif
|
||||
board_[pos] = '\x0f';
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
updateHash(pos);
|
||||
#endif
|
||||
} else { // 去子
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
revertHash(pos);
|
||||
#endif
|
||||
board_[pos] = '\x00';
|
||||
|
@ -1215,7 +1209,7 @@ bool NineChess::capture(int pos)
|
|||
move_ = -pos;
|
||||
currentPos = 0;
|
||||
context.nPiecesNeedRemove--;
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
updateHash(pos);
|
||||
#endif
|
||||
//step++;
|
||||
|
@ -1328,14 +1322,14 @@ bool NineChess::giveup(Player loser)
|
|||
if (loser == PLAYER1) {
|
||||
context.stage = GAME_OVER;
|
||||
winner = PLAYER2;
|
||||
tips = "玩家1投子认负,玩家2获胜!";
|
||||
tips = "玩家1投子认负。";
|
||||
sprintf(cmdline, "Player1 give up!");
|
||||
cmdlist.push_back(string(cmdline));
|
||||
return true;
|
||||
} else if (loser == PLAYER2) {
|
||||
context.stage = GAME_OVER;
|
||||
winner = PLAYER1;
|
||||
tips = "玩家2投子认负,玩家1获胜!";
|
||||
tips = "玩家2投子认负。";
|
||||
sprintf(cmdline, "Player2 give up!");
|
||||
cmdlist.push_back(string(cmdline));
|
||||
return true;
|
||||
|
@ -1404,6 +1398,21 @@ bool NineChess::command(const char *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef THREEFOLD_REPETITION
|
||||
if (!strcmp(cmd, "Threefold Repetition. Draw!")) {
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(cmd, "draw")) {
|
||||
context.stage = GAME_OVER;
|
||||
winner = DRAW;
|
||||
score_draw++;
|
||||
tips = "三次重复局面判和。";
|
||||
sprintf(cmdline, "Threefold Repetition. Draw!");
|
||||
cmdlist.push_back(string(cmdline));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1468,6 +1477,12 @@ inline long NineChess::update(long time_p /*= -1*/)
|
|||
|
||||
// 是否分出胜负
|
||||
bool NineChess::win()
|
||||
{
|
||||
return win(false);
|
||||
}
|
||||
|
||||
// 是否分出胜负
|
||||
bool NineChess::win(bool forceDraw)
|
||||
{
|
||||
if (context.stage == GAME_OVER)
|
||||
return true;
|
||||
|
@ -1482,7 +1497,7 @@ bool NineChess::win()
|
|||
elapsedMS_1 = currentRule.maxTimeLedToLose * 60000;
|
||||
winner = PLAYER2;
|
||||
context.stage = GAME_OVER;
|
||||
tips = "玩家1超时,玩家2获胜!";
|
||||
tips = "玩家1超时判负。";
|
||||
sprintf(cmdline, "Time over. Player2 win!");
|
||||
cmdlist.push_back(string(cmdline));
|
||||
return true;
|
||||
|
@ -1492,7 +1507,7 @@ bool NineChess::win()
|
|||
elapsedMS_2 = currentRule.maxTimeLedToLose * 60000;
|
||||
winner = PLAYER1;
|
||||
context.stage = GAME_OVER;
|
||||
tips = "玩家2超时,玩家1获胜!";
|
||||
tips = "玩家2超时判负。";
|
||||
sprintf(cmdline, "Time over. Player1 win!");
|
||||
cmdlist.push_back(string(cmdline));
|
||||
return true;
|
||||
|
@ -1550,14 +1565,14 @@ bool NineChess::win()
|
|||
// 规则要求被“闷”判负,则对手获胜
|
||||
if (currentRule.isLoseWhenNoWay) {
|
||||
if (context.turn == PLAYER1) {
|
||||
tips = "玩家1无子可走,玩家2获胜!";
|
||||
tips = "玩家1无子可走被闷。";
|
||||
winner = PLAYER2;
|
||||
context.stage = GAME_OVER;
|
||||
sprintf(cmdline, "Player1 no way to go. Player2 win!");
|
||||
cmdlist.push_back(string(cmdline));
|
||||
return true;
|
||||
} else {
|
||||
tips = "玩家2无子可走,玩家1获胜!";
|
||||
tips = "玩家2无子可走被闷。";
|
||||
winner = PLAYER1;
|
||||
context.stage = GAME_OVER;
|
||||
sprintf(cmdline, "Player2 no way to go. Player1 win!");
|
||||
|
@ -1568,13 +1583,24 @@ bool NineChess::win()
|
|||
return true;
|
||||
}
|
||||
}
|
||||
// 否则让棋,由对手走
|
||||
else {
|
||||
else { // 否则让棋,由对手走
|
||||
changeTurn();
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef THREEFOLD_REPETITION
|
||||
if (forceDraw)
|
||||
{
|
||||
tips = "重复三次局面和棋!";
|
||||
winner = DRAW;
|
||||
context.stage = GAME_OVER;
|
||||
sprintf(cmdline, "Threefold Repetition. Draw!");
|
||||
cmdlist.push_back(string(cmdline));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1760,7 +1786,7 @@ void NineChess::cleanForbiddenPoints()
|
|||
for (int j = 0; j < N_SEATS; j++) {
|
||||
pos = i * N_SEATS + j;
|
||||
if (board_[pos] == '\x0f') {
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
revertHash(pos);
|
||||
#endif
|
||||
board_[pos] = '\x00';
|
||||
|
@ -1781,7 +1807,7 @@ void NineChess::setTips()
|
|||
switch (context.stage) {
|
||||
case NineChess::GAME_NOTSTARTED:
|
||||
tips = "轮到玩家1落子,剩余" + std::to_string(context.nPiecesInHand_1) + "子" +
|
||||
" 比分 " + to_string(score_1) + ":" + to_string(score_2);
|
||||
" 比分 " + to_string(score_1) + ":" + to_string(score_2) + ", 和棋 " + to_string(score_draw);
|
||||
break;
|
||||
|
||||
case NineChess::GAME_PLACING:
|
||||
|
@ -1817,20 +1843,22 @@ void NineChess::setTips()
|
|||
break;
|
||||
|
||||
case NineChess::GAME_OVER:
|
||||
if (winner == DRAW)
|
||||
tips = "超出限定步数,双方平局";
|
||||
if (winner == DRAW) {
|
||||
tips = "双方平局";
|
||||
score_draw++;
|
||||
}
|
||||
else if (winner == PLAYER1) {
|
||||
score_1++;
|
||||
if (tips.find("无子可走") != tips.npos)
|
||||
tips += "玩家1获胜!比分 " + to_string(score_1) + ":" + to_string(score_2);
|
||||
tips += "玩家1获胜!比分 " + to_string(score_1) + ":" + to_string(score_2) + ", 和棋 " + to_string(score_draw);
|
||||
else
|
||||
tips = "玩家1获胜!比分 " + to_string(score_1) + ":" + to_string(score_2);
|
||||
tips = "玩家1获胜!比分 " + to_string(score_1) + ":" + to_string(score_2) + ", 和棋 " + to_string(score_draw);
|
||||
} else if (winner == PLAYER2) {
|
||||
score_2++;
|
||||
if (tips.find("无子可走") != tips.npos)
|
||||
tips += "玩家2获胜!比分 " + to_string(score_1) + ":" + to_string(score_2);
|
||||
tips += "玩家2获胜!比分 " + to_string(score_1) + ":" + to_string(score_2) + ", 和棋 " + to_string(score_draw);
|
||||
else
|
||||
tips = "玩家2获胜!比分 " + to_string(score_1) + ":" + to_string(score_2);
|
||||
tips = "玩家2获胜!比分 " + to_string(score_1) + ":" + to_string(score_2) + ", 和棋 " + to_string(score_draw);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2312,7 +2340,7 @@ void NineChess::rotate(int degrees, bool cmdChange /*= true*/)
|
|||
}
|
||||
}
|
||||
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
|
||||
#if 0
|
||||
/*
|
||||
|
@ -2403,5 +2431,5 @@ uint64_t NineChess::updateHashMisc()
|
|||
|
||||
return context.hash;
|
||||
}
|
||||
#endif /* HASH_MAP_ENABLE */
|
||||
#endif /* HASH_MAP_ENABLE etc. */
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
// 赢盘数
|
||||
int score_1;
|
||||
int score_2;
|
||||
int score_draw;
|
||||
|
||||
// 嵌套的规则结构体
|
||||
struct Rule
|
||||
|
@ -188,7 +189,7 @@ public:
|
|||
*/
|
||||
int board[N_POINTS];
|
||||
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
// 局面的哈希值
|
||||
uint64_t hash;
|
||||
|
||||
|
@ -481,6 +482,7 @@ protected:
|
|||
|
||||
// 是否分出胜负
|
||||
bool win();
|
||||
bool win(bool forceDraw);
|
||||
|
||||
// 清除所有禁点
|
||||
void cleanForbiddenPoints();
|
||||
|
@ -497,7 +499,7 @@ protected:
|
|||
bool place(int pos);
|
||||
bool capture(int pos);
|
||||
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
// hash相关
|
||||
uint64_t getHash();
|
||||
uint64_t revertHash(int pos);
|
||||
|
|
|
@ -28,6 +28,10 @@ HashMap<uint64_t, NineChessAi_ab::HashValue> bookHashMap(bookHashsize);
|
|||
vector<uint64_t> openingBook;
|
||||
#endif // BOOK_LEARNING
|
||||
|
||||
#ifdef THREEFOLD_REPETITION
|
||||
vector<uint64_t> positions;
|
||||
#endif
|
||||
|
||||
NineChessAi_ab::NineChessAi_ab() :
|
||||
rootNode(nullptr),
|
||||
requiredQuit(false),
|
||||
|
@ -77,7 +81,7 @@ struct NineChessAi_ab::Node *NineChessAi_ab::addNode(
|
|||
|
||||
player = player; // Remove warning
|
||||
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
newNode->hash = 0;
|
||||
#endif
|
||||
|
||||
|
@ -359,6 +363,10 @@ void NineChessAi_ab::setChess(const NineChess &chess)
|
|||
//clearBookHashMap();
|
||||
//openingBook.clear();
|
||||
#endif // BOOK_LEARNING
|
||||
|
||||
#ifdef THREEFOLD_REPETITION
|
||||
positions.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
this->chess_ = chess;
|
||||
|
@ -583,6 +591,28 @@ int NineChessAi_ab::alphaBetaPruning(int depth)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef THREEFOLD_REPETITION
|
||||
static int nRepetition = 0;
|
||||
|
||||
if (chess_.getStage() == NineChess::GAME_MOVING) {
|
||||
uint64_t hash = chess_.getHash();
|
||||
|
||||
if (std::find(positions.begin(), positions.end(), hash) != positions.end()) {
|
||||
nRepetition++;
|
||||
if (nRepetition == 3) {
|
||||
nRepetition = 0;
|
||||
return 3;
|
||||
}
|
||||
} else {
|
||||
positions.push_back(hash);
|
||||
}
|
||||
}
|
||||
|
||||
if (chess_.getStage() == NineChess::GAME_PLACING) {
|
||||
positions.clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOVE_PRIORITY_TABLE_SUPPORT
|
||||
#ifdef RANDOM_MOVE
|
||||
shuffleMovePriorityTable();
|
||||
|
@ -611,7 +641,7 @@ int NineChessAi_ab::alphaBetaPruning(int depth)
|
|||
|
||||
// 生成了 Alpha-Beta 树
|
||||
|
||||
return value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NineChessAi_ab::alphaBetaPruning(int depth, int alpha, int beta, Node *node)
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
struct Node* parent; // 父节点
|
||||
size_t id; // 结点编号
|
||||
bool pruned; // 是否在此处剪枝
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING))
|
||||
#if ((defined HASH_MAP_ENABLE) || (defined BOOK_LEARNING) || (defined THREEFOLD_REPETITION))
|
||||
uint64_t hash; // 哈希值
|
||||
#endif
|
||||
#ifdef HASH_MAP_ENABLE
|
||||
|
|
Loading…
Reference in New Issue