tips: 将 setTips 转移到 GameController

已知问题:
人类走棋后未刷新 Tips,AI走后才刷新。
This commit is contained in:
Calcitem 2020-09-05 22:09:35 +08:00
parent 03c9f72ab0
commit 926fe1ad86
5 changed files with 144 additions and 102 deletions

View File

@ -34,8 +34,6 @@
#include "option.h"
string tips;
namespace Zobrist
{
Key psq[PIECE_TYPE_NB][SQUARE_NB];
@ -507,7 +505,7 @@ bool Position::set_position(const struct Rule *newRule)
create_mill_table();
currentSquare = SQ_0;
elapsedSeconds[BLACK] = elapsedSeconds[WHITE] = 0;
set_tips();
update_score();
cmdlist.clear();
int r;
@ -540,6 +538,7 @@ bool Position::reset()
action = ACTION_PLACE;
winner = NOBODY;
gameoverReason = NO_REASON;
memset(board, 0, sizeof(board));
st->key = 0;
@ -551,7 +550,7 @@ bool Position::reset()
millListSize = 0;
currentSquare = SQ_0;
elapsedSeconds[BLACK] = elapsedSeconds[WHITE] = 0;
set_tips();
update_score();
cmdlist.clear();
#ifdef ENDGAME_LEARNING
@ -580,6 +579,8 @@ bool Position::reset()
bool Position::start()
{
gameoverReason = NO_REASON;
switch (phase) {
case PHASE_PLACING:
case PHASE_MOVING:
@ -742,7 +743,7 @@ bool Position::put_piece(Square s, bool updateCmdlist)
out:
if (updateCmdlist) {
set_tips();
update_score();
}
return true;
@ -852,7 +853,7 @@ bool Position::remove_piece(Square s, bool updateCmdlist)
out:
if (updateCmdlist) {
set_tips();
update_score();
}
return true;
@ -885,13 +886,9 @@ bool Position::giveup(Color loser)
phase = PHASE_GAMEOVER;
Color loserColor = loser;
char loserCh = color_to_char(loserColor);
string loserStr = char_to_string(loserCh);
winner = ~loser;
tips = "玩家" + loserStr + "投子认负";
sprintf(cmdline, "Player%d give up!", loserColor);
gameoverReason = LOSE_REASON_GIVE_UP;
sprintf(cmdline, "Player%d give up!", loser);
score[winner]++;
cmdlist.emplace_back(string(cmdline));
@ -965,7 +962,7 @@ bool Position::command(const char *cmd)
phase = PHASE_GAMEOVER;
winner = DRAW;
score_draw++;
tips = "三次重复局面判和。";
gameoverReason = DRAW_REASON_THREEFOLD_REPETITION;
sprintf(cmdline, "Threefold Repetition. Draw!");
cmdlist.emplace_back(string(cmdline));
return true;
@ -1007,6 +1004,18 @@ int Position::update()
return ret;
}
void Position::update_score()
{
if (phase == PHASE_GAMEOVER) {
if (winner == DRAW) {
score_draw++;
return;
}
score[winner]++;
}
}
bool Position::check_gameover_condition(int8_t updateCmdlist)
{
if (phase & PHASE_NOTPLAYING) {
@ -1021,7 +1030,7 @@ bool Position::check_gameover_condition(int8_t updateCmdlist)
if (elapsedSeconds[i] > rule.maxTimeLedToLose * 60) {
elapsedSeconds[i] = rule.maxTimeLedToLose * 60;
winner = ~Color(i);
tips = "玩家" + char_to_string(color_to_char(Color(i))) + "超时判负。";
gameoverReason = LOST_REASON_TIME_OVER;
sprintf(cmdline, "Time over. Player%d win!", ~Color(i));
}
}
@ -1110,7 +1119,7 @@ bool Position::check_gameover_condition(int8_t updateCmdlist)
if (rule.isLoseButNotChangeTurnWhenNoWay) {
if (updateCmdlist) {
tips = "玩家" + char_to_string(color_to_char(sideToMove)) + "无子可走被闷";
gameoverReason = LOSE_REASON_NO_WAY;
winner = ~sideToMove;
sprintf(cmdline, "Player%d no way to go. Player%d win!", sideToMove, winner);
cmdlist.emplace_back(string(cmdline)); // TODO: memleak
@ -1192,59 +1201,6 @@ void Position::undo_null_move()
change_side_to_move();
}
void Position::set_tips()
{
string winnerStr, t;
string turnStr = char_to_string(color_to_char(sideToMove));
switch (phase) {
case PHASE_READY:
tips = "轮到玩家1落子剩余" + std::to_string(pieceCountInHand[BLACK]) + "" +
" 比分 " + to_string(score[BLACK]) + ":" + to_string(score[WHITE]) + ", 和棋 " + to_string(score_draw);
break;
case PHASE_PLACING:
if (action == ACTION_PLACE) {
tips = "轮到玩家" + turnStr + "落子,剩余" + std::to_string(pieceCountInHand[sideToMove]) + "";
} else if (action == ACTION_REMOVE) {
tips = "成三!轮到玩家" + turnStr + "去子,需去" + std::to_string(pieceCountNeedRemove) + "";
}
break;
case PHASE_MOVING:
if (action == ACTION_PLACE || action == ACTION_SELECT) {
tips = "轮到玩家" + turnStr + "选子移动";
} else if (action == ACTION_REMOVE) {
tips = "成三!轮到玩家" + turnStr + "去子,需去" + std::to_string(pieceCountNeedRemove) + "";
}
break;
case PHASE_GAMEOVER:
if (winner == DRAW) {
score_draw++;
tips = "双方平局!比分 " + to_string(score[BLACK]) + ":" + to_string(score[WHITE]) + ", 和棋 " + to_string(score_draw);
break;
}
winnerStr = char_to_string(color_to_char(winner));
score[winner]++;
t = "玩家" + winnerStr + "获胜!比分 " + to_string(score[BLACK]) + ":" + to_string(score[WHITE]) + ", 和棋 " + to_string(score_draw);
if (tips.find("无子可走") != string::npos) {
tips += t;
} else {
tips = t;
}
break;
default:
break;
}
}
time_t Position::get_elapsed_time(int us)
{
return elapsedSeconds[us];

View File

@ -29,8 +29,6 @@
#include "rule.h"
#include "search.h"
extern std::string tips;
/// StateInfo struct stores information needed to restore a Position object to
/// its previous state when we retract a move. Whenever a move is made on the
/// board (by calling Position::do_move), a StateInfo object must be passed.
@ -128,7 +126,6 @@ public:
int get_step() const;
enum Phase get_phase() const;
enum Action get_action() const;
const std::string get_tips() const;
const char *cmd_line() const;
const std::vector<std::string> *cmd_list() const;
@ -139,12 +136,12 @@ public:
bool giveup(Color loser);
bool command(const char *cmd);
int update();
void update_score();
bool check_gameover_condition(int8_t cp = 0);
void clean_banned();
void set_side_to_move(Color c);
void change_side_to_move();
void set_tips();
Color get_winner() const;
void mirror(bool cmdChange = true);
@ -168,9 +165,6 @@ public:
int pieces_on_board_count();
int pieces_in_hand_count();
static char color_to_char(Color color);
static std::string char_to_string(char ch);
static bool is_star_square(Square s);
// private:
@ -202,6 +196,7 @@ public:
/// Mill Game
Color them { NOCOLOR };
Color winner;
GameOverReason gameoverReason { NO_REASON };
enum Phase phase {PHASE_NONE};
enum Action action;
@ -342,20 +337,6 @@ inline bool Position::move_piece(Square from, Square to)
/// Mill Game
inline char Position::color_to_char(Color color)
{
return static_cast<char>('0' + color);
}
inline std::string Position::char_to_string(char ch)
{
if (ch == '1') {
return "1";
} else {
return "2";
}
}
inline Piece *Position::get_board() const
{
return (Piece *)board;
@ -381,11 +362,6 @@ inline enum Action Position::get_action() const
return action;
}
inline const std::string Position::get_tips() const
{
return tips;
}
inline const char *Position::cmd_line() const
{
return cmdline;

View File

@ -158,6 +158,16 @@ enum Action : uint16_t
ACTION_REMOVE = 0x0400
};
enum GameOverReason
{
NO_REASON,
LOSE_EASON_LESS_THAN_THREE,
LOSE_REASON_NO_WAY,
LOSE_REASON_GIVE_UP,
LOST_REASON_TIME_OVER,
DRAW_REASON_THREEFOLD_REPETITION,
};
enum Bound : uint8_t
{
BOUND_NONE,

View File

@ -254,7 +254,7 @@ void GameController::gameReset()
emit time2Changed(qtime.toString("hh:mm:ss"));
// 发信号更新状态栏
message = QString::fromStdString(position.get_tips());
message = QString::fromStdString(getTips());
emit statusBarChanged(message);
// 更新比分 LCD 显示
@ -679,7 +679,7 @@ void GameController::timerEvent(QTimerEvent *event)
#ifndef TRAINING_MODE
// 发信号更新状态栏
message = QString::fromStdString(position.get_tips());
message = QString::fromStdString(getTips());
emit statusBarChanged(message);
// 弹框
@ -762,7 +762,7 @@ bool GameController::actionPiece(QPointF pos)
timeID = startTimer(100);
// 发信号更新状态栏
message = QString::fromStdString(position.get_tips());
message = QString::fromStdString(getTips());
emit statusBarChanged(message);
#ifndef MOBILE_APP_UI
}
@ -830,7 +830,7 @@ bool GameController::actionPiece(QPointF pos)
if (result) {
// 发信号更新状态栏
message = QString::fromStdString(position.get_tips());
message = QString::fromStdString(getTips());
emit statusBarChanged(message);
// 将新增的棋谱行插入到ListModel
@ -896,9 +896,9 @@ bool GameController::giveUp()
manualListModel.setData(manualListModel.index(currentRow), i.c_str());
}
if (position.get_winner() != NOBODY)
if (position.get_winner() != NOBODY) {
playSound(GAME_SOUND_GIVE_UP, position.side_to_move());
}
#endif // TRAINING_MODE
return result;
@ -957,7 +957,7 @@ bool GameController::command(const QString &cmd, bool update /* = true */)
}
// 发信号更新状态栏
message = QString::fromStdString(position.get_tips());
message = QString::fromStdString(getTips());
emit statusBarChanged(message);
// 对于新开局
@ -1281,7 +1281,9 @@ bool GameController::updateScence(Position *p)
emit winningRate2Changed(QString::number(winningRate_2, 10));
emit winningRateDrawChanged(QString::number(winningRate_draw, 10));
#endif // TRAINING_MODE
setTips();
#endif // !TRAINING_MODE
return true;
}
@ -1366,3 +1368,89 @@ out:
file.flush();
file.close();
}
inline char GameController::color_to_char(Color color)
{
return static_cast<char>('0' + color);
}
inline std::string GameController::char_to_string(char ch)
{
if (ch == '1') {
return "黑方";
} else {
return "白方";
}
}
void GameController::setTips()
{
Position *p = &position;
string winnerStr, reasonStr, resultStr, scoreStr;
string turnStr = char_to_string(color_to_char(p->sideToMove));
switch (p->phase) {
case PHASE_READY:
tips = "轮到" + turnStr + "落子,剩余" + std::to_string(p->pieceCountInHand[BLACK]) + "" +
" 比分 " + to_string(p->score[BLACK]) + ":" + to_string(p->score[WHITE]) + ", 和棋 " + to_string(p->score_draw);
break;
case PHASE_PLACING:
if (p->action == ACTION_PLACE) {
tips = "轮到" + turnStr + "落子,剩余" + std::to_string(p->pieceCountInHand[p->sideToMove]) + "";
} else if (p->action == ACTION_REMOVE) {
tips = "成三!轮到" + turnStr + "去子,需去" + std::to_string(p->pieceCountNeedRemove) + "";
}
break;
case PHASE_MOVING:
if (p->action == ACTION_PLACE || p->action == ACTION_SELECT) {
tips = "轮到" + turnStr + "选子移动";
} else if (p->action == ACTION_REMOVE) {
tips = "成三!轮到" + turnStr + "去子,需去" + std::to_string(p->pieceCountNeedRemove) + "";
}
break;
case PHASE_GAMEOVER:
scoreStr = "比分 " + to_string(p->score[BLACK]) + " : " + to_string(p->score[WHITE]) + ", 和棋 " + to_string(p->score_draw);
switch (p->winner) {
case BLACK:
case WHITE:
winnerStr = char_to_string(color_to_char(p->winner));
resultStr = winnerStr + "获胜!";
break;
case DRAW:
resultStr = "双方平局!";
break;
default:
break;
}
switch (p->gameoverReason) {
case LOSE_EASON_LESS_THAN_THREE:
break;
case LOSE_REASON_NO_WAY:
reasonStr = turnStr + "无子可走被闷。";
break;
case LOSE_REASON_GIVE_UP:
reasonStr = turnStr + "投子认负。";
break;
case LOST_REASON_TIME_OVER:
reasonStr = turnStr + "超时判负。";
break;
case DRAW_REASON_THREEFOLD_REPETITION:
tips = "三次重复局面判和。";
break;
default:
break;
}
tips = reasonStr + resultStr + scoreStr;
break;
default:
break;
}
}

View File

@ -136,6 +136,10 @@ public:
return &position;
}
char color_to_char(Color color);
std::string char_to_string(char ch);
void setTips();
signals:
// 总盘数改变的信号
@ -378,6 +382,11 @@ public:
// 电脑执先手时为 true
bool isAiPlayer[COLOR_NB];
string getTips()
{
return tips;
}
private:
// 是否有落子动画
bool hasAnimation;
@ -435,6 +444,9 @@ private:
// 棋谱字符串列表模型
QStringListModel manualListModel;
// 提示语
string tips;
};
#endif // GAMECONTROLLER_H