diff --git a/gamewindow.ui b/gamewindow.ui
index e247efef..cb6169aa 100644
--- a/gamewindow.ui
+++ b/gamewindow.ui
@@ -291,6 +291,7 @@
+
@@ -1113,6 +1114,17 @@
电脑着法随机(&R)
+
+
+ true
+
+
+ true
+
+
+ 必败时认输(&G)
+
+
diff --git a/src/ai/search.cpp b/src/ai/search.cpp
index 3c4c256c..e80690f2 100644
--- a/src/ai/search.cpp
+++ b/src/ai/search.cpp
@@ -831,6 +831,7 @@ const char* MillGameAi_ab::bestMove()
{
vector bestMoves;
size_t bestMovesSize = 0;
+ bool isMostLose = true; // 是否必败
if ((rootNode->children).empty()) {
return "error!";
@@ -867,6 +868,30 @@ const char* MillGameAi_ab::bestMove()
i++;
}
+ // 检查是否必败
+
+ MillGame::Player whosTurn = chess_.whosTurn();
+
+ for (auto child : rootNode->children) {
+ // TODO: 使用常量代替
+ if (whosTurn == MillGame::PLAYER1 && child->value > -10000 ||
+ whosTurn == MillGame::PLAYER2 && child->value < 10000) {
+ isMostLose = false;
+ break;
+ }
+ }
+
+ // 自动认输
+ if (isMostLose) {
+ if (whosTurn == MillGame::PLAYER1) {
+ sprintf(cmdline, "Player1 give up!");
+ } else if (whosTurn == MillGame::PLAYER2) {
+ sprintf(cmdline, "Player2 give up!");
+ }
+
+ return cmdline;
+ }
+
for (auto child : rootNode->children) {
if (child->value == rootNode->value) {
bestMoves.push_back(child);
diff --git a/src/game/millgame.cpp b/src/game/millgame.cpp
index 5b67e97d..7c822214 100644
--- a/src/game/millgame.cpp
+++ b/src/game/millgame.cpp
@@ -168,6 +168,7 @@ MillGame &MillGame::operator = (const MillGame &chess)
currentStep = chess.currentStep;
moveStep = chess.moveStep;
randomMove_ = chess.randomMove_;
+ giveUpIfMostLose_ = chess.giveUpIfMostLose_;
board_ = context.board;
currentPos = chess.currentPos;
winner = chess.winner;
@@ -663,8 +664,11 @@ void MillGame::createMillTable()
}
// 设置配置
-bool MillGame::configure(bool randomMove)
+bool MillGame::configure(bool giveUpIfMostLose, bool randomMove)
{
+ // 设置是否必败时认输
+ this->giveUpIfMostLose_ = giveUpIfMostLose;
+
// 设置是否随机走子
this->randomMove_ = randomMove;
@@ -1398,10 +1402,12 @@ bool MillGame::giveup(Player loser)
winner = PLAYER2;
tips = "玩家1投子认负。";
sprintf(cmdline, "Player1 give up!");
+ score_2++;
} else if (loser == PLAYER2) {
winner = PLAYER1;
tips = "玩家2投子认负。";
sprintf(cmdline, "Player2 give up!");
+ score_1++;
}
cmdlist.emplace_back(string(cmdline));
@@ -1465,7 +1471,7 @@ bool MillGame::command(const char *cmd)
}
// 认输
- args = sscanf(cmd, "Players%1u give up!", &t);
+ args = sscanf(cmd, "Player%1u give up!", &t);
if (args == 1) {
if (t == 1) {
diff --git a/src/game/millgame.h b/src/game/millgame.h
index 80854146..f0fe6239 100644
--- a/src/game/millgame.h
+++ b/src/game/millgame.h
@@ -304,7 +304,7 @@ public:
MillGame &operator=(const MillGame &);
// 设置配置
- bool configure(bool randomMove);
+ bool configure(bool giveUpIfMostLose, bool randomMove);
// 设置棋局状态和棋盘上下文,用于初始化
bool setContext(const struct Rule *rule,
@@ -362,6 +362,12 @@ public:
int getMoveStep() const
{
return moveStep;
+ }
+
+ // 获取是否必败时认输
+ bool getGiveUpIfMostLose() const
+ {
+ return giveUpIfMostLose_;
}
// 获取 AI 是否随机走子
@@ -575,6 +581,9 @@ private:
// 从走子阶段开始或上次吃子起的步数
int moveStep {};
+ // 是否必败时认输
+ bool giveUpIfMostLose_ {true};
+
// AI 是否随机走子
bool randomMove_ {true};
diff --git a/src/ui/qt/gamecontroller.cpp b/src/ui/qt/gamecontroller.cpp
index 7508b2a4..183eabd6 100644
--- a/src/ui/qt/gamecontroller.cpp
+++ b/src/ui/qt/gamecontroller.cpp
@@ -54,6 +54,7 @@ GameController::GameController(GameScene & scene, QObject * parent) :
ruleNo_(-1),
timeLimit(0),
stepsLimit(50),
+ giveUpIfMostLose_(true),
randomMove_(true)
{
// 已在view的样式表中添加背景,scene中不用添加背景
@@ -116,7 +117,7 @@ const QMap GameController::getActions()
void GameController::gameStart()
{
- chess_.configure(randomMove_);
+ chess_.configure(giveUpIfMostLose_, randomMove_);
chess_.start();
chessTemp = chess_;
@@ -142,7 +143,7 @@ void GameController::gameReset()
}
// 重置游戏
- chess_.configure(randomMove_);
+ chess_.configure(giveUpIfMostLose_, randomMove_);
chess_.reset();
chessTemp = chess_;
@@ -283,7 +284,7 @@ void GameController::setRule(int ruleNo, MillGame::step_t stepLimited /*= -1*/,
void GameController::setEngine1(bool arg)
{
- chess_.configure(randomMove_);
+ chess_.configure(giveUpIfMostLose_, randomMove_);
isAiPlayer1 = arg;
if (arg) {
@@ -299,7 +300,7 @@ void GameController::setEngine1(bool arg)
void GameController::setEngine2(bool arg)
{
- chess_.configure(randomMove_);
+ chess_.configure(giveUpIfMostLose_, randomMove_);
isAiPlayer2 = arg;
if (arg) {
@@ -370,6 +371,11 @@ void GameController::playSound(const QString &soundPath)
#endif /* ! DONOT_PLAY_SOUND */
}
+void GameController::setGiveUpIfMostLose(bool arg)
+{
+ giveUpIfMostLose_ = arg;
+}
+
void GameController::setAutoRestart(bool arg)
{
isAutoRestart = arg;
@@ -778,11 +784,9 @@ bool GameController::giveUp()
if (chess_.whosTurn() == MillGame::PLAYER1) {
result = chess_.giveup(MillGame::PLAYER1);
- chess_.score_2++;
}
else if (chess_.whosTurn() == MillGame::PLAYER2) {
result = chess_.giveup(MillGame::PLAYER2);
- chess_.score_1++;
}
if (result) {
diff --git a/src/ui/qt/gamecontroller.h b/src/ui/qt/gamecontroller.h
index 0787cd50..06b055ea 100644
--- a/src/ui/qt/gamecontroller.h
+++ b/src/ui/qt/gamecontroller.h
@@ -70,6 +70,11 @@ public:
return stepsLimit;
}
+ bool getGiveUpIfMostLose()
+ {
+ return giveUpIfMostLose_;
+ }
+
bool getRandomMove()
{
return randomMove_;
@@ -150,6 +155,9 @@ public slots:
// 播放声音
void playSound(const QString &soundPath);
+ // 是否必败时认输
+ void setGiveUpIfMostLose(bool arg);
+
// 是否自动开局
void setAutoRestart(bool arg = false);
@@ -240,6 +248,9 @@ private:
// 是否有落子音效
bool hasSound;
+ // 是否必败时认输
+ bool giveUpIfMostLose_;
+
// 是否棋局结束后自动重新开局
bool isAutoRestart;
diff --git a/src/ui/qt/gamewindow.cpp b/src/ui/qt/gamewindow.cpp
index 384e9e67..5ab7a4df 100644
--- a/src/ui/qt/gamewindow.cpp
+++ b/src/ui/qt/gamewindow.cpp
@@ -204,6 +204,9 @@ void MillGameWindow::initialize()
connect(ui.actionAnimation_A, SIGNAL(toggled(bool)),
game, SLOT(setAnimation(bool)));
+ connect(ui.actionGiveUpIfMostLose_G, SIGNAL(toggled(bool)),
+ game, SLOT(setGiveUpIfMostLose(bool)));
+
connect(ui.actionAutoRestart_A, SIGNAL(toggled(bool)),
game, SLOT(setAutoRestart(bool)));