diff --git a/game/command.cpp b/game/command.cpp index cb8cb6f..88901f3 100644 --- a/game/command.cpp +++ b/game/command.cpp @@ -23,7 +23,7 @@ Command::Command() - : m_executed(false) + : m_executed(false), m_autoExecution(true) { } diff --git a/game/command.h b/game/command.h index 2e53b33..59091dd 100644 --- a/game/command.h +++ b/game/command.h @@ -58,6 +58,17 @@ class Command */ bool isExecuted() const { return m_executed; } + /** + * Mark the command as auto-executable, which means that it will + * be automatically executed if the commands history is cleared + * just before this command. + * Auto-executable commands correspond to commands for AI players, + * for which the user cannot change the behaviour. + */ + void setAutoExecution(bool autoExec) { m_autoExecution = autoExec; } + /// Return true if the command is auto-executable + virtual bool isAutoExecution() const { return m_autoExecution; } + /** * Description of the command, for debugging purposes */ @@ -69,6 +80,7 @@ class Command private: bool m_executed; + bool m_autoExecution; }; #endif diff --git a/game/duplicate.cpp b/game/duplicate.cpp index 34bd556..2f46c1b 100644 --- a/game/duplicate.cpp +++ b/game/duplicate.cpp @@ -61,12 +61,12 @@ int Duplicate::play(const wstring &iCoord, const wstring &iWord) if (res == 0) { // Everything is OK, we can play the word - recordPlayerMove(Move(round), currPlayer); + recordPlayerMove(Move(round), currPlayer, true); } else { // Record the invalid move of the player - recordPlayerMove(Move(iWord, iCoord), currPlayer); + recordPlayerMove(Move(iWord, iCoord), currPlayer, true); } // Little hack to handle duplicate games with only AI players. @@ -93,7 +93,7 @@ void Duplicate::playAI(unsigned int p) ASSERT(false, "AI tried to cheat!"); } - recordPlayerMove(move, *player); + recordPlayerMove(move, *player, false); } @@ -164,12 +164,14 @@ void Duplicate::tryEndTurn() } -void Duplicate::recordPlayerMove(const Move &iMove, Player &ioPlayer) +void Duplicate::recordPlayerMove(const Move &iMove, Player &ioPlayer, bool isForHuman) { Command *pCmd = new PlayerMoveCmd(ioPlayer, iMove); + pCmd->setAutoExecution(!isForHuman); accessNavigation().addAndExecute(pCmd); Command *pCmd2 = new MarkPlayedCmd(*this, ioPlayer.getId(), true); + pCmd2->setAutoExecution(!isForHuman); accessNavigation().addAndExecute(pCmd2); } diff --git a/game/duplicate.h b/game/duplicate.h index 2bea63e..5e6a75a 100644 --- a/game/duplicate.h +++ b/game/duplicate.h @@ -95,7 +95,7 @@ private: Duplicate(const Dictionary &iDic); /// Record a player move - void recordPlayerMove(const Move &iMove, Player &ioPlayer); + void recordPlayerMove(const Move &iMove, Player &ioPlayer, bool isForHuman); /// Make the AI player whose ID is p play its turn void playAI(unsigned int p); diff --git a/game/freegame.cpp b/game/freegame.cpp index 037bde5..d03ac5e 100644 --- a/game/freegame.cpp +++ b/game/freegame.cpp @@ -66,14 +66,14 @@ int FreeGame::play(const wstring &iCoord, const wstring &iWord) Move move(round); // Update the rack and the score of the current player - recordPlayerMove(move, *m_players[m_currPlayer]); + recordPlayerMove(move, *m_players[m_currPlayer], true); } else { Move move(iWord, iCoord); // Record the invalid move of the player - recordPlayerMove(move, *m_players[m_currPlayer]); + recordPlayerMove(move, *m_players[m_currPlayer], true); } // Next turn @@ -100,15 +100,17 @@ void FreeGame::playAI(unsigned int p) } // Update the rack and the score of the current player - recordPlayerMove(move, *player); + recordPlayerMove(move, *player, false); endTurn(); } -void FreeGame::recordPlayerMove(const Move &iMove, Player &ioPlayer) +void FreeGame::recordPlayerMove(const Move &iMove, Player &ioPlayer, + bool isForHuman) { Command *pCmd = new PlayerMoveCmd(ioPlayer, iMove); + pCmd->setAutoExecution(!isForHuman); accessNavigation().addAndExecute(pCmd); } @@ -275,7 +277,7 @@ int FreeGame::pass(const wstring &iToChange) Move move(iToChange); // End the player's turn - recordPlayerMove(move, player); + recordPlayerMove(move, player, true); // Next game turn endTurn(); diff --git a/game/freegame.h b/game/freegame.h index bd1fe9f..7f12431 100644 --- a/game/freegame.h +++ b/game/freegame.h @@ -86,7 +86,7 @@ private: void playAI(unsigned int p); /// Record a player move - void recordPlayerMove(const Move &iMove, Player &ioPlayer); + void recordPlayerMove(const Move &iMove, Player &ioPlayer, bool isForHuman); /// Finish the current turn int endTurn(); diff --git a/game/navigation.cpp b/game/navigation.cpp index c487d37..8db2839 100644 --- a/game/navigation.cpp +++ b/game/navigation.cpp @@ -145,6 +145,11 @@ void Navigation::lastTurn() void Navigation::clearFuture() { + // Replay the auto-execution turns + // (i.e. turns where only the AI was involved) + while (!isLastTurn() && m_turnCommands[m_currTurn]->isAutoExecution()) + nextTurn(); + // When there is no future, don't do anything if (isLastTurn()) return; diff --git a/game/training.cpp b/game/training.cpp index 17faa00..16b5a79 100644 --- a/game/training.cpp +++ b/game/training.cpp @@ -59,6 +59,7 @@ void Training::setRackRandom(bool iCheck, set_rack_mode mode) const PlayedRack &newRack = helperSetRackRandom(getCurrentPlayer().getCurrentRack(), iCheck, mode); Command *pCmd = new PlayerRackCmd(*m_players[m_currPlayer], newRack); + pCmd->setAutoExecution(false); accessNavigation().addAndExecute(pCmd); } @@ -130,6 +131,7 @@ void Training::recordPlayerMove(const Move &iMove, Player &ioPlayer) // (called in this class in endTurn()). // See the big comment in game.cpp, line 96 Command *pCmd = new PlayerMoveCmd(ioPlayer, iMove); + pCmd->setAutoExecution(false); accessNavigation().addAndExecute(pCmd); } diff --git a/game/turn_cmd.cpp b/game/turn_cmd.cpp index 46960c1..28c56a4 100644 --- a/game/turn_cmd.cpp +++ b/game/turn_cmd.cpp @@ -69,6 +69,17 @@ void TurnCmd::doUndo() } +bool TurnCmd::isAutoExecution() const +{ + BOOST_FOREACH(Command *cmd, m_commands) + { + if (!cmd->isAutoExecution()) + return false; + } + return true; +} + + wstring TurnCmd::toString() const { wostringstream oss; diff --git a/game/turn_cmd.h b/game/turn_cmd.h index bf40963..e8876ee 100644 --- a/game/turn_cmd.h +++ b/game/turn_cmd.h @@ -46,6 +46,8 @@ class TurnCmd: public Command bool isEmpty() const { return m_commands.empty(); } + virtual bool isAutoExecution() const; + virtual wstring toString() const; protected: