Use dedicated getters for the Move type: this is simpler to use and more readable

This commit is contained in:
Olivier Teulière 2012-04-30 21:21:38 +02:00
parent 6ba32f4835
commit 0095302b88
15 changed files with 76 additions and 78 deletions

View file

@ -110,8 +110,7 @@ void Duplicate::playAI(unsigned int p)
player->compute(getDic(), getBoard(), getHistory().beforeFirstRound());
const Move &move = player->getMove();
if (move.getType() == Move::CHANGE_LETTERS ||
move.getType() == Move::PASS)
if (move.isChangeLetters() || move.isPass())
{
// The AI player must be buggy...
ASSERT(false, "AI tried to cheat!");
@ -249,8 +248,7 @@ Player * Duplicate::findBestPlayer() const
BOOST_FOREACH(Player *player, m_players)
{
const Move &move = player->getLastMove();
if (move.getType() == Move::VALID_ROUND &&
move.getScore() > bestScore)
if (move.isValid() && move.getScore() > bestScore)
{
bestScore = move.getScore();
bestPlayer = player;
@ -265,7 +263,7 @@ void Duplicate::endTurn()
static const unsigned int REF_PLAYER_ID = 0;
// Define the master move if it is not already defined
if (m_masterMove.getType() != Move::VALID_ROUND)
if (!m_masterMove.isValid())
{
// The chosen implementation is to find the best move among the players' moves.
// It is more user-friendly than forcing the best move when nobody found it.
@ -311,7 +309,7 @@ void Duplicate::endTurn()
{
if (player != bestPlayer &&
player->getLastMove().getScore() >= bestScore &&
player->getLastMove().getType() == Move::VALID_ROUND)
player->getLastMove().isValid())
{
otherWithSameScore = true;
break;
@ -385,8 +383,7 @@ bool Duplicate::hasPlayed(unsigned iPlayerId) const
MatchingPlayer predicate(iPlayerId);
const PlayerMoveCmd *cmd =
getNavigation().getCurrentTurn().findMatchingCmd<PlayerMoveCmd>(predicate);
return cmd != 0 && cmd->isExecuted() &&
cmd->getMove().getType() != Move::NO_MOVE;
return cmd != 0 && cmd->isExecuted() && !cmd->getMove().isNull();
}
@ -398,9 +395,7 @@ void Duplicate::innerSetMasterMove(const Move &iMove)
void Duplicate::setMasterMove(const Move &iMove)
{
ASSERT(iMove.getType() == Move::VALID_ROUND ||
iMove.getType() == Move::NO_MOVE,
"Invalid move type");
ASSERT(iMove.isValid() || iMove.isNull(), "Invalid move type");
// If this method is called several times for the same turn, it will
// result in many MasterMoveCmd commands in the command stack.

View file

@ -100,8 +100,7 @@ void FreeGame::playAI(unsigned int p)
player->compute(getDic(), getBoard(), getHistory().beforeFirstRound());
const Move &move = player->getMove();
if (move.getType() == Move::CHANGE_LETTERS ||
move.getType() == Move::PASS)
if (move.isChangeLetters() || move.isPass())
{
ASSERT(checkPass(*player, move.getChangedLetters()) == 0,
"AI tried to cheat!");
@ -177,8 +176,7 @@ int FreeGame::endTurn()
accessNavigation().addAndExecute(pCmd);
// Complete the rack for the player that just played
if (move.getType() == Move::VALID_ROUND ||
move.getType() == Move::CHANGE_LETTERS)
if (move.isValid() || move.isChangeLetters())
{
try
{

View file

@ -55,7 +55,7 @@ void GameMoveCmd::doExecute()
// For moves corresponding to a valid round, we have much more
// work to do...
if (m_move.getType() == Move::VALID_ROUND)
if (m_move.isValid())
{
playRound();
}
@ -65,7 +65,7 @@ void GameMoveCmd::doExecute()
void GameMoveCmd::doUndo()
{
// Undo playing the round on the board
if (m_move.getType() == Move::VALID_ROUND)
if (m_move.isValid())
{
unplayRound();
}

View file

@ -89,7 +89,7 @@ bool History::beforeFirstRound() const
{
for (unsigned int i = 0; i < m_history.size() - 1; i++)
{
if (m_history[i]->getMove().getType() == Move::VALID_ROUND)
if (m_history[i]->getMove().isValid())
return false;
}
return true;

View file

@ -105,7 +105,7 @@ PlayedRack Move::ComputeRackForMove(const PlayedRack &iOldRack, const Move &iMov
// Using a Rack object will indirectly do it for us
Rack newRack = iOldRack.getRack();
if (iMove.getType() == Move::VALID_ROUND)
if (iMove.isValid())
{
// Remove the played tiles from the rack
const Round &round = iMove.getRound();
@ -120,7 +120,7 @@ PlayedRack Move::ComputeRackForMove(const PlayedRack &iOldRack, const Move &iMov
}
}
}
else if (iMove.getType() == Move::CHANGE_LETTERS)
else if (iMove.isChangeLetters())
{
// Remove the changed tiles from the rack
const wstring & changed = iMove.getChangedLetters();
@ -129,7 +129,7 @@ PlayedRack Move::ComputeRackForMove(const PlayedRack &iOldRack, const Move &iMov
newRack.remove(Tile(ch));
}
}
else if (iMove.getType() == Move::NO_MOVE)
else if (iMove.isNull())
{
// Special case: when the player didn't play, we keep the
// original played rack, to avoid the implicit reordering

View file

@ -73,17 +73,12 @@ class Move
*/
Move(const wstring &iLetters);
enum Type
{
VALID_ROUND,
INVALID_WORD,
PASS,
CHANGE_LETTERS,
NO_MOVE,
};
/// Return the type of move
Type getType() const { return m_type; }
// Return the type of move
bool isValid() const { return m_type == VALID_ROUND; }
bool isInvalid() const { return m_type == INVALID_WORD; }
bool isPass() const { return m_type == PASS; }
bool isChangeLetters() const { return m_type == CHANGE_LETTERS; }
bool isNull() const { return m_type == NO_MOVE; }
/// Get the score of this move (0 unless the round is valid)
int getScore() const { return m_score; }
@ -127,6 +122,16 @@ class Move
wstring toString() const;
private:
enum Type
{
VALID_ROUND,
INVALID_WORD,
PASS,
CHANGE_LETTERS,
NO_MOVE,
};
/// Type of move
Type m_type;

View file

@ -30,7 +30,7 @@ INIT_LOGGER(game, PlayerMoveCmd);
PlayerMoveCmd::PlayerMoveCmd(Player &ioPlayer, const Move &iMove, bool iAutoExec)
: m_player(ioPlayer), m_move(iMove)
{
setAutoExecutable(iAutoExec || iMove.getType() == Move::NO_MOVE);
setAutoExecutable(iAutoExec || iMove.isNull());
}

View file

@ -72,22 +72,22 @@ static void writeMove(ostream &out, const Move &iMove,
if (iPlayerId != -1)
out << " playerid=\"" << iPlayerId << "\"";
out << " points=\"" << iMove.getScore() << "\" type=\"";
if (iMove.getType() == Move::VALID_ROUND)
if (iMove.isValid())
{
const Round &round = iMove.getRound();
out << "valid\" word=\"" << toUtf8(round.getWord())
<< "\" coord=\"" << toUtf8(round.getCoord().toString()) << "\" />";
}
else if (iMove.getType() == Move::INVALID_WORD)
else if (iMove.isInvalid())
{
out << "invalid\" word=\"" << toUtf8(iMove.getBadWord())
<< "\" coord=\"" << toUtf8(iMove.getBadCoord()) << "\" />";
}
else if (iMove.getType() == Move::CHANGE_LETTERS)
else if (iMove.isChangeLetters())
out << "change\" letters=\"" << toUtf8(iMove.getChangedLetters()) << "\" />";
else if (iMove.getType() == Move::PASS)
else if (iMove.isPass())
out << "pass\" />";
else if (iMove.getType() == Move::NO_MOVE)
else if (iMove.isNull())
out << "none\" />";
else
throw SaveGameException("Unsupported move: " + lfw(iMove.toString()));

View file

@ -126,7 +126,7 @@ void ArbitAssignments::refresh()
// Update the master move
const Move &masterMove = m_game->duplicateGetMasterMove();
if (masterMove.getType() == Move::NO_MOVE)
if (masterMove.isNull())
{
labelMasterMove->setText(QString("<i>%1</i>").arg(_q("Not selected yet")));
}
@ -161,7 +161,7 @@ void ArbitAssignments::updatePlayersModel()
continue;
// Hide players with an assigned move other than "No move"
if (hideAssignedPlayers && m_game->hasPlayed(player.getId()) &&
player.getLastMove().getType() != Move::NO_MOVE)
!player.getLastMove().isNull())
{
continue;
}
@ -181,13 +181,13 @@ void ArbitAssignments::updatePlayersModel()
QPalette palette = treeViewPlayers->palette();
QColor color = palette.color(QPalette::Normal, QPalette::WindowText);
if (move.getType() == Move::VALID_ROUND)
if (move.isValid())
{
const Round &round = move.getRound();
m_playersModel->setData(m_playersModel->index(rowNum, 2), qfw(round.getWord()));
m_playersModel->setData(m_playersModel->index(rowNum, 3), qfw(round.getCoord().toString()));
}
else if (move.getType() == Move::INVALID_WORD)
else if (move.isInvalid())
{
m_playersModel->setData(m_playersModel->index(rowNum, 2), "<" + qfw(move.getBadWord()) + ">");
m_playersModel->setData(m_playersModel->index(rowNum, 3), qfw(move.getBadCoord()));
@ -214,7 +214,7 @@ void ArbitAssignments::updatePlayersModel()
void ArbitAssignments::enableAssignmentButtons()
{
bool hasSelResult = m_game->isLastTurn() &&
m_selectedMove.getType() != Move::NO_MOVE;
!m_selectedMove.isNull();
bool hasSelPlayer = m_game->isLastTurn() &&
treeViewPlayers->selectionModel()->hasSelection();
// Enable the "Assign move" button iff a move is selected
@ -238,7 +238,7 @@ void ArbitAssignments::populatePlayersMenu(QMenu &iMenu, const QPoint &iPoint)
return;
// Action to assign the selected move
if (m_selectedMove.getType() != Move::NO_MOVE)
if (!m_selectedMove.isNull())
{
const Move &move = m_selectedMove;
QAction *assignSelMoveAction =
@ -350,7 +350,7 @@ bool ArbitAssignments::selectPlayerByTable(unsigned tabNb, QString *oName)
void ArbitAssignments::showMasterPreview()
{
const Move &move = m_game->duplicateGetMasterMove();
if (move.getType() == Move::VALID_ROUND)
if (move.isValid())
{
// TODO: deselect move in the Results?
m_game->setTestRound(move.getRound());
@ -373,7 +373,7 @@ void ArbitAssignments::assignMasterMove()
const Move &masterMove = m_game->duplicateGetMasterMove();
// Make sure the user knows what she's doing
if (masterMove.getType() != Move::NO_MOVE)
if (!masterMove.isNull())
{
QString msg = _q("There is already a master move for this turn.");
QString question = _q("Do you want to replace it?");
@ -385,7 +385,7 @@ void ArbitAssignments::assignMasterMove()
}
const Move &move = m_selectedMove;
if (move.getType() != Move::VALID_ROUND)
if (!move.isValid())
{
notifyProblem(_q("The master move must be a valid move."));
return;
@ -445,7 +445,7 @@ void ArbitAssignments::assignDefaultMasterMove()
{
const Move &currMove = m_game->duplicateGetMasterMove();
// Do not overwrite an existing move
if (currMove.getType() != Move::NO_MOVE)
if (!currMove.isNull())
return;
// Search the best moves
@ -480,7 +480,7 @@ void ArbitAssignments::assignDefaultMasterMove()
void ArbitAssignments::assignSelectedMove()
{
if (m_selectedMove.getType() == Move::NO_MOVE ||
if (m_selectedMove.isNull() ||
!treeViewPlayers->selectionModel()->hasSelection())
{
return;
@ -516,7 +516,7 @@ void ArbitAssignments::helperAssignMove(const Move &iMove)
BOOST_FOREACH(unsigned int id, playersIdSet)
{
if (m_game->hasPlayed(id) &&
m_game->getPlayer(id).getLastMove().getType() != Move::NO_MOVE)
!m_game->getPlayer(id).getLastMove().isNull())
{
assignedIdSet.insert(id);
}
@ -529,7 +529,7 @@ void ArbitAssignments::helperAssignMove(const Move &iMove)
players = QString("\t%1\n").arg(qfw(m_game->getPlayer(id).getName()));
}
// The warning is different depending on the type of move
if (iMove.getType() == Move::NO_MOVE)
if (iMove.isNull())
{
QString msg = _q("You are going to suppress the assigned move for the following players:\n");
if (!QtCommon::requestConfirmation(PrefsDialog::kCONFO_ARBIT_SUPPR_MOVE,
@ -594,7 +594,7 @@ void ArbitAssignments::addPenalty()
QString ArbitAssignments::formatMove(const Move &iMove) const
{
if (iMove.getType() == Move::VALID_ROUND)
if (iMove.isValid())
{
return QString("%1 - %2 - %3")
.arg(qfw(iMove.getRound().getWord()))
@ -603,7 +603,7 @@ QString ArbitAssignments::formatMove(const Move &iMove) const
}
else
{
ASSERT(iMove.getType() == Move::INVALID_WORD, "Unexpected move type");
ASSERT(iMove.isInvalid(), "Unexpected move type");
return QString("%1 - %2 - %3")
.arg(qfw(iMove.getBadWord()))
.arg(qfw(iMove.getBadCoord()))
@ -614,7 +614,7 @@ QString ArbitAssignments::formatMove(const Move &iMove) const
void ArbitAssignments::endTurn()
{
if (m_game->duplicateGetMasterMove().getType() != Move::VALID_ROUND)
if (!m_game->duplicateGetMasterMove().isValid())
{
notifyProblem(_q("You must select a master move before ending the turn."));
return;
@ -624,7 +624,7 @@ void ArbitAssignments::endTurn()
for (unsigned int i = 0; i < m_game->getNbPlayers(); ++i)
{
if (m_game->getPlayer(i).isHuman() &&
(!m_game->hasPlayed(i) || m_game->getPlayer(i).getLastMove().getType() == Move::NO_MOVE))
(!m_game->hasPlayed(i) || m_game->getPlayer(i).getLastMove().isNull()))
{
allPlayed = false;
break;

View file

@ -299,7 +299,7 @@ int ArbitrationWidget::addSingleMove(const Move &iMove, int moveType,
int rowNum = m_resultsModel->rowCount();
m_resultsModel->insertRow(rowNum);
if (iMove.getType() == Move::VALID_ROUND)
if (iMove.isValid())
{
const Round &r = iMove.getRound();
m_resultsModel->setData(m_resultsModel->index(rowNum, 0), qfw(r.getWord()));
@ -308,7 +308,7 @@ int ArbitrationWidget::addSingleMove(const Move &iMove, int moveType,
}
else
{
ASSERT(iMove.getType() == Move::INVALID_WORD, "Unexpected move type");
ASSERT(iMove.isInvalid(), "Unexpected move type");
m_resultsModel->setData(m_resultsModel->index(rowNum, 0), qfw(iMove.getBadWord()));
m_resultsModel->setData(m_resultsModel->index(rowNum, 1), qfw(iMove.getBadCoord()));
m_resultsModel->setData(m_resultsModel->index(rowNum, 3), _q("Invalid"));
@ -493,7 +493,7 @@ void ArbitrationWidget::populateResultsMenu(QMenu &iMenu, const QPoint &iPoint)
QString selectedWord = m_resultsModel->data(wordIndex).toString();
QAction *showDefAction = m_resultsPopup->getShowDefinitionEntry(selectedWord);
iMenu.addAction(showDefAction);
if (move.getType() != Move::VALID_ROUND)
if (!move.isValid())
showDefAction->setEnabled(false);
// Action to select as master move
@ -505,7 +505,7 @@ void ArbitrationWidget::populateResultsMenu(QMenu &iMenu, const QPoint &iPoint)
QObject::connect(setAsMasterAction, SIGNAL(triggered()),
m_assignmentsWidget, SLOT(assignMasterMove()));
iMenu.addAction(setAsMasterAction);
if (move.getType() != Move::VALID_ROUND)
if (!move.isValid())
setAsMasterAction->setEnabled(false);
// Action to select all the players
@ -680,7 +680,7 @@ void ArbitrationWidget::showPreview(const QItemSelection &iSelected)
if (!iSelected.indexes().empty())
{
const Move &move = getSelectedMove();
if (move.getType() == Move::VALID_ROUND)
if (move.isValid())
{
m_game->setTestRound(move.getRound());
}

View file

@ -192,7 +192,7 @@ void HistoryWidget::updateModel()
}
// Set the rest
if (m.getType() == Move::VALID_ROUND)
if (m.isValid())
{
const Round &r = m.getRound();
wstring coord = r.getCoord().toString();
@ -200,18 +200,18 @@ void HistoryWidget::updateModel()
setCellData(rowNum, m_colRef, qfw(coord));
color = Qt::black;
}
else if (m.getType() == Move::INVALID_WORD)
else if (m.isInvalid())
{
setCellData(rowNum, m_colWord, "<" + qfw(m.getBadWord()) + ">");
setCellData(rowNum, m_colRef, qfw(m.getBadCoord()));
color = Qt::red;
}
else if (m.getType() == Move::NO_MOVE)
else if (m.isNull())
{
setCellData(rowNum, m_colWord, _q("(NO MOVE)"));
color = Qt::blue;
}
else if (m.getType() == Move::PASS)
else if (m.isPass())
{
setCellData(rowNum, m_colWord, _q("(PASS)"));
color = Qt::blue;

View file

@ -940,7 +940,7 @@ void MainWindow::onGamePrint()
curWidth += colWidths[1];
// Word and coordinates
if (m.getType() == Move::VALID_ROUND)
if (m.isValid())
{
const Round &r = m.getRound();
painter.drawText(curWidth, nextHeight, qfw(r.getWord()));
@ -949,7 +949,7 @@ void MainWindow::onGamePrint()
qfw(r.getCoord().toString()));
curWidth += colWidths[3];
}
else if (m.getType() == Move::INVALID_WORD)
else if (m.isInvalid())
{
painter.drawText(curWidth, nextHeight,
"<" + qfw(m.getBadWord()) + ">");
@ -957,13 +957,13 @@ void MainWindow::onGamePrint()
painter.drawText(curWidth, nextHeight, qfw(m.getBadCoord()));
curWidth += colWidths[3];
}
else if (m.getType() == Move::NO_MOVE)
else if (m.isNull())
{
painter.drawText(curWidth, nextHeight, _q("(NO MOVE)"));
curWidth += colWidths[2];
curWidth += colWidths[3];
}
else if (m.getType() == Move::PASS)
else if (m.isPass())
{
painter.drawText(curWidth, nextHeight, _q("(PASS)"));
curWidth += colWidths[2];

View file

@ -764,7 +764,7 @@ void loopArbitration(PublicGame &iGame)
const wstring &word = parseLetters(tokens, 1, iGame.getDic());
const wstring &coord = parseAlphaNum(tokens, 2);
const Move &move = iGame.arbitrationCheckWord(word, coord);
if (move.getType() != Move::VALID_ROUND)
if (!move.isValid())
throw GameException("Incorrect master move: " + lfw(move.toString()));
iGame.duplicateSetMasterMove(move);
}

View file

@ -239,7 +239,7 @@ void GameIO::printGameDebug(ostream &out, const PublicGame &iGame)
fmter % padAndConvert(str(wformat(L"%1%") % (i + 1)), 5);
fmter % padAndConvert(str(wformat(L"%1%") % turn.getPlayer()), 1);
fmter % padAndConvert(turn.getPlayedRack().toString(), 8);
if (move.getType() == Move::VALID_ROUND)
if (move.isValid())
{
const Round &round = move.getRound();
fmter % padAndConvert(round.getWord(), 14, false);
@ -249,16 +249,16 @@ void GameIO::printGameDebug(ostream &out, const PublicGame &iGame)
}
else
{
if (move.getType() == Move::INVALID_WORD)
if (move.isInvalid())
{
fmter % padAndConvert(L"#" + move.getBadWord() + L"#", 14, false);
fmter % padAndConvert(move.getBadCoord(), 3);
}
else if (move.getType() == Move::CHANGE_LETTERS)
else if (move.isChangeLetters())
{
fmter % padAndConvert(L"[" + move.getChangedLetters() + L"]", 14, false) % " - ";
}
else if (move.getType() == Move::PASS)
else if (move.isPass())
{
fmter % padAndConvert(L"(PASS)", 14, false) % " - ";
}

View file

@ -397,7 +397,7 @@ void CursesIntf::drawHistory(Box &ioBox) const
{
const Turn& t = m_game->getHistory().getTurn(i);
const Move& m = t.getMove();
if (m.getType() == Move::VALID_ROUND)
if (m.isValid())
{
// The move corresponds to a played round: display it
const Round &r = m.getRound();
@ -409,7 +409,7 @@ void CursesIntf::drawHistory(Box &ioBox) const
padAndConvert(coord, 3).c_str(), r.getPoints(),
t.getPlayer(), r.getBonus() ? '*' : ' ');
}
else if (m.getType() == Move::INVALID_WORD)
else if (m.isInvalid())
{
// The move corresponds to an invalid word: display it
wstring invWord = L"<" + m.getBadWord() + L">";
@ -424,11 +424,11 @@ void CursesIntf::drawHistory(Box &ioBox) const
{
// The move corresponds to a passed turn or changed letters
wstring action;
if (m.getType() == Move::NO_MOVE)
if (m.isNull())
action = wfl(_("(NO MOVE)"));
else if (m.getType() == Move::PASS)
else if (m.isPass())
action = wfl(_("(PASS)"));
else if (m.getType() == Move::CHANGE_LETTERS)
else if (m.isChangeLetters())
action = L"(-" + m.getChangedLetters() + L")";
ioBox.printDataLine(i, x,