From 7e9dab2e9bebbb10459f038c72b97b868749e080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Teuli=C3=A8re?= Date: Fri, 11 Jan 2013 20:24:47 +0100 Subject: [PATCH] Topping: keep track of the player score --- game/cmd/player_event_cmd.cpp | 9 +++--- game/public_game.cpp | 12 +++++++ game/public_game.h | 4 +++ game/topping.cpp | 61 +++++++++++++++++++++++++++++------ game/topping.h | 15 ++++++++- qt/topping_widget.cpp | 23 +++++++++---- 6 files changed, 104 insertions(+), 20 deletions(-) diff --git a/game/cmd/player_event_cmd.cpp b/game/cmd/player_event_cmd.cpp index 764a979..772a28f 100644 --- a/game/cmd/player_event_cmd.cpp +++ b/game/cmd/player_event_cmd.cpp @@ -31,10 +31,11 @@ INIT_LOGGER(game, PlayerEventCmd); PlayerEventCmd::PlayerEventCmd(Player &ioPlayer, EventType iEvent, int iPoints) : m_player(ioPlayer), m_eventType(iEvent), m_points(iPoints) { - ASSERT(iEvent == PENALTY || iEvent == END_GAME || iPoints >= 0, - "Negative points not allowed"); - ASSERT(iEvent != PENALTY || iPoints <= 0, - "Positive points not allowed"); + // Solos and warnings are always positive + ASSERT(iEvent != SOLO || iPoints >= 0, "Negative points not allowed"); + ASSERT(iEvent != WARNING || iPoints >= 0, "Negative points not allowed"); + // Penalties are negative in arbitration mode, but positive in topping mode + // End game points are positive for one player and negative for all the other players } diff --git a/game/public_game.cpp b/game/public_game.cpp index 86b29d4..a514585 100644 --- a/game/public_game.cpp +++ b/game/public_game.cpp @@ -262,6 +262,18 @@ void PublicGame::toppingPlay(const wstring &iWord, const wstring &iCoord, int iE } +void PublicGame::toppingTimeOut() +{ + getTypedGame(m_game).turnTimeOut(); +} + + +void PublicGame::toppingAddPenalty(int iPenalty) +{ + getTypedGame(m_game).addPenalty(iPenalty); +} + + vector PublicGame::toppingGetTriedMoves() const { return getTypedGame(m_game).getTriedMoves(); diff --git a/game/public_game.h b/game/public_game.h index 1e34805..18de318 100644 --- a/game/public_game.h +++ b/game/public_game.h @@ -226,6 +226,10 @@ public: void toppingPlay(const wstring &iWord, const wstring &iCoord, int iElapsed); + void toppingTimeOut(); + + void toppingAddPenalty(int iPenalty); + vector toppingGetTriedMoves() const; Move toppingGetTopMove() const; diff --git a/game/topping.cpp b/game/topping.cpp index 236bf55..1054b7b 100644 --- a/game/topping.cpp +++ b/game/topping.cpp @@ -38,7 +38,9 @@ #include "player.h" #include "turn.h" #include "cmd/topping_move_cmd.h" +#include "cmd/player_rack_cmd.h" #include "cmd/player_move_cmd.h" +#include "cmd/player_event_cmd.h" #include "cmd/game_move_cmd.h" #include "encoding.h" @@ -105,8 +107,7 @@ void Topping::tryWord(const wstring &iWord, const wstring &iCoord, int iElapsed) else { // End the turn - // FIXME - recordPlayerMove(move, *m_players[m_currPlayer]); + recordPlayerMove(move, *m_players[m_currPlayer], iElapsed); // Next turn endTurn(); @@ -114,6 +115,38 @@ void Topping::tryWord(const wstring &iWord, const wstring &iCoord, int iElapsed) } +void Topping::turnTimeOut() +{ + LOG_INFO("Timeout reached, finishing turn automatically"); + + m_board.removeTestRound(); + + // Commented out, because the player already has + // an empty move by default +#if 0 + // The player didn't find the move + Command *pCmd = new PlayerMoveCmd(*m_players[m_currPlayer], Move()); + accessNavigation().addAndExecute(pCmd); +#endif + + // Give a penalty to the player + // XXX: should we give the penalty directly in the NO_MOVE move? + // TODO: get the value from the preferences instead of hard-coding + addPenalty(180); + + // Next turn + endTurn(); +} + + +void Topping::addPenalty(int iPenalty) +{ + Command *pCmd = new PlayerEventCmd(*m_players[m_currPlayer], + PlayerEventCmd::PENALTY, iPenalty); + accessNavigation().addAndExecute(pCmd); +} + + int Topping::play(const wstring &, const wstring &) { ASSERT(false, "The play() method should not be called in topping mode"); @@ -123,15 +156,19 @@ int Topping::play(const wstring &, const wstring &) } -void Topping::recordPlayerMove(const Move &iMove, Player &ioPlayer) +void Topping::recordPlayerMove(const Move &iMove, Player &ioPlayer, int iElapsed) { - // FIXME: the score of the player should not be the score of the move in topping mode - LOG_INFO("Player " << ioPlayer.getId() << " plays: " << lfw(iMove.toString())); + ASSERT(iMove.isValid(), "Only valid rounds should be played"); + // Modify the score of the given move, to be the elapsed time + Round copyRound = iMove.getRound(); + copyRound.setPoints(iElapsed); + Move newMove(copyRound); + // Update the rack and the score of the current player // PlayerMoveCmd::execute() must be called before Game::helperPlayMove() // (called in this class in endTurn()). // See the big comment in game.cpp, line 96 - Command *pCmd = new PlayerMoveCmd(ioPlayer, iMove); + Command *pCmd = new PlayerMoveCmd(ioPlayer, newMove); accessNavigation().addAndExecute(pCmd); } @@ -144,12 +181,18 @@ bool Topping::isFinished() const void Topping::endTurn() { - // Play the word on the board - const Move &move = m_players[m_currPlayer]->getLastMove(); + // Play the top move on the board + const Move &move = getTopMove(); Command *pCmd = new GameMoveCmd(*this, move, m_currPlayer); accessNavigation().addAndExecute(pCmd); accessNavigation().newTurn(); + // Make sure that the player has the correct rack + // (in case he didn't find the top, or not the same one) + Command *pCmd2 = new PlayerRackCmd(*m_players[m_currPlayer], + getHistory().getCurrentRack()); + accessNavigation().addAndExecute(pCmd2); + // Start next turn... start(); } @@ -174,7 +217,7 @@ void Topping::addPlayer(Player *iPlayer) Move Topping::getTopMove() const { BestResults results; - results.search(getDic(), getBoard(), m_players[0]->getCurrentRack().getRack(), + results.search(getDic(), getBoard(), getHistory().getCurrentRack().getRack(), getHistory().beforeFirstRound()); ASSERT(results.size() != 0, "No top move found"); return Move(results.get(0)); diff --git a/game/topping.h b/game/topping.h index d1cd06b..1c6d66f 100644 --- a/game/topping.h +++ b/game/topping.h @@ -77,12 +77,25 @@ public: */ Move getTopMove() const; + /** + * Indicate that the player didn't find the top in the allocated time. + * This will play the top on the board, give a points penalty to the player + * and start the next turn. + */ + void turnTimeOut(); + + /** + * Give an additional penalty to the player (probably because + * he used a hint) + */ + void addPenalty(int iPenalty); + private: /// Private constructor and destructor to force using the GameFactory class Topping(const GameParams &iParams, const Game *iMasterGame); /// Record a player move - void recordPlayerMove(const Move &iMove, Player &ioPlayer); + void recordPlayerMove(const Move &iMove, Player &ioPlayer, int iElapsed); void endTurn(); diff --git a/qt/topping_widget.cpp b/qt/topping_widget.cpp index 891c9ce..d8d563d 100644 --- a/qt/topping_widget.cpp +++ b/qt/topping_widget.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include "topping_widget.h" @@ -60,7 +60,7 @@ ToppingWidget::ToppingWidget(QWidget *parent, PlayModel &iPlayModel, TimerWidget *timerWidget = new TimerWidget(this, iTimerModel); timerWidget->setEnabled(false); - iTimerModel.setChronoMode(true); + //iTimerModel.setChronoMode(true); QObject::connect(&iTimerModel, SIGNAL(expired()), this, SLOT(timeoutPenalty())); layout->addWidget(timerWidget); @@ -228,15 +228,26 @@ void ToppingWidget::playWord(const wstring &iWord, const wstring &iCoord) void ToppingWidget::hintUsed(const AbstractHint &iHint) { - // TODO - LOG_INFO("Hint " << iHint.getName() << " used for a cost of " << iHint.getCost()); + LOG_INFO("Hint '" << iHint.getName() << "' used for a cost of " << iHint.getCost()); + m_game->toppingAddPenalty(iHint.getCost()); + emit gameUpdated(); } void ToppingWidget::timeoutPenalty() { - // TODO - LOG_INFO("Timeout penalty given"); + // Show the solution to the player in a dialog box + const Move &move = m_game->toppingGetTopMove(); + QMessageBox::information(this, "Eliot - " + _q("End of turn"), + _q("The allocated time for the turn has expired.\n" + "The top is %1 at %2 for %3 points.") + .arg(qfw(move.getRound().getWord())) + .arg(qfw(move.getRound().getCoord().toString())) + .arg(move.getScore())); + + // End the turn + m_game->toppingTimeOut(); + emit gameUpdated(); }