From 0095302b884166eb067151c58cf766b2bd3f193b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Teuli=C3=A8re?= Date: Mon, 30 Apr 2012 21:21:38 +0200 Subject: [PATCH] Use dedicated getters for the Move type: this is simpler to use and more readable --- game/duplicate.cpp | 17 ++++++----------- game/freegame.cpp | 6 ++---- game/game_move_cmd.cpp | 4 ++-- game/history.cpp | 2 +- game/move.cpp | 6 +++--- game/move.h | 27 ++++++++++++++++----------- game/player_move_cmd.cpp | 2 +- game/xml_writer.cpp | 10 +++++----- qt/arbit_assignments.cpp | 34 +++++++++++++++++----------------- qt/arbitration_widget.cpp | 10 +++++----- qt/history_widget.cpp | 8 ++++---- qt/main_window.cpp | 8 ++++---- utils/eliottxt.cpp | 2 +- utils/game_io.cpp | 8 ++++---- utils/ncurses.cpp | 10 +++++----- 15 files changed, 76 insertions(+), 78 deletions(-) diff --git a/game/duplicate.cpp b/game/duplicate.cpp index ffd6f83..3b96ba7 100644 --- a/game/duplicate.cpp +++ b/game/duplicate.cpp @@ -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(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. diff --git a/game/freegame.cpp b/game/freegame.cpp index be09885..da2d04a 100644 --- a/game/freegame.cpp +++ b/game/freegame.cpp @@ -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 { diff --git a/game/game_move_cmd.cpp b/game/game_move_cmd.cpp index e490833..373707e 100644 --- a/game/game_move_cmd.cpp +++ b/game/game_move_cmd.cpp @@ -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(); } diff --git a/game/history.cpp b/game/history.cpp index 8f3ad26..ff34322 100644 --- a/game/history.cpp +++ b/game/history.cpp @@ -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; diff --git a/game/move.cpp b/game/move.cpp index a152660..d2f725c 100644 --- a/game/move.cpp +++ b/game/move.cpp @@ -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 diff --git a/game/move.h b/game/move.h index 86fecdf..ea41ee5 100644 --- a/game/move.h +++ b/game/move.h @@ -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; diff --git a/game/player_move_cmd.cpp b/game/player_move_cmd.cpp index a33fda2..185a882 100644 --- a/game/player_move_cmd.cpp +++ b/game/player_move_cmd.cpp @@ -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()); } diff --git a/game/xml_writer.cpp b/game/xml_writer.cpp index a702dc6..580b2ca 100644 --- a/game/xml_writer.cpp +++ b/game/xml_writer.cpp @@ -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())); diff --git a/qt/arbit_assignments.cpp b/qt/arbit_assignments.cpp index 12e2e27..a70c243 100644 --- a/qt/arbit_assignments.cpp +++ b/qt/arbit_assignments.cpp @@ -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("%1").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; diff --git a/qt/arbitration_widget.cpp b/qt/arbitration_widget.cpp index 5ac01ae..514c67d 100644 --- a/qt/arbitration_widget.cpp +++ b/qt/arbitration_widget.cpp @@ -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()); } diff --git a/qt/history_widget.cpp b/qt/history_widget.cpp index 11c9651..ff4b8e1 100644 --- a/qt/history_widget.cpp +++ b/qt/history_widget.cpp @@ -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; diff --git a/qt/main_window.cpp b/qt/main_window.cpp index ec3d3d0..c171b1f 100644 --- a/qt/main_window.cpp +++ b/qt/main_window.cpp @@ -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]; diff --git a/utils/eliottxt.cpp b/utils/eliottxt.cpp index 926ca7d..02a0274 100644 --- a/utils/eliottxt.cpp +++ b/utils/eliottxt.cpp @@ -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); } diff --git a/utils/game_io.cpp b/utils/game_io.cpp index 8ec7c7c..e002954 100644 --- a/utils/game_io.cpp +++ b/utils/game_io.cpp @@ -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) % " - "; } diff --git a/utils/ncurses.cpp b/utils/ncurses.cpp index 6e03d4a..81f3d34 100644 --- a/utils/ncurses.cpp +++ b/utils/ncurses.cpp @@ -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,