Duplicate: get rid of the MarkPlayedCmd class

This commit is contained in:
Olivier Teulière 2012-04-08 01:07:59 +02:00
parent 1db5ccea8b
commit 196e02f9ad
7 changed files with 45 additions and 205 deletions

View file

@ -54,7 +54,6 @@ libgame_a_SOURCES= \
turn_cmd.cpp turn_cmd.h \
duplicate.cpp duplicate.h \
arbitration.cpp arbitration.h \
mark_played_cmd.h mark_played_cmd.cpp \
master_move_cmd.h master_move_cmd.cpp \
freegame.cpp freegame.h \
training.cpp training.h \

View file

@ -219,33 +219,12 @@ int Arbitration::getPenalty(unsigned iPlayerId) const
void Arbitration::assignMove(unsigned int iPlayerId, const Move &iMove)
{
ASSERT(iPlayerId < getNPlayers(), "Wrong player number");
Player &player = *m_players[iPlayerId];
if (hasPlayed(iPlayerId))
{
LOG_INFO("Re-assigning move for player " << iPlayerId);
replacePlayerMove(player, iMove);
}
else
{
recordPlayerMove(player, iMove);
}
recordPlayerMove(*m_players[iPlayerId], iMove);
}
void Arbitration::finalizeTurn()
{
// Assign a default empty move to the human players which have
// not played yet, to be able to end the turn.
BOOST_FOREACH(Player *player, m_players)
{
if (player->isHuman() && !hasPlayed(player->getId()))
{
LOG_INFO("Assigning a default move to player " << player->getId());
recordPlayerMove(*player, Move());
}
}
tryEndTurn();
}

View file

@ -44,7 +44,6 @@
#include "player_event_cmd.h"
#include "game_move_cmd.h"
#include "game_rack_cmd.h"
#include "mark_played_cmd.h"
#include "master_move_cmd.h"
#include "ai_player.h"
#include "navigation.h"
@ -145,9 +144,13 @@ void Duplicate::start()
return;
}
// Little hack to handle duplicate games with only AI players.
// This will have no effect when there is at least one human player
tryEndTurn();
bool isArbitration = getParams().getMode() == GameParams::kARBITRATION;
if (!isArbitration)
{
// Little hack to handle duplicate games with only AI players.
// This will have no effect when there is at least one human player
tryEndTurn();
}
}
@ -159,14 +162,18 @@ bool Duplicate::isFinished() const
void Duplicate::tryEndTurn()
{
for (unsigned int i = 0; i < getNPlayers(); i++)
bool isArbitration = getParams().getMode() == GameParams::kARBITRATION;
if (!isArbitration)
{
if (m_players[i]->isHuman() && !hasPlayed(i))
for (unsigned int i = 0; i < getNPlayers(); i++)
{
// A human player has not played...
m_currPlayer = i;
// So we don't finish the turn
return;
if (m_players[i]->isHuman() && !hasPlayed(i))
{
// A human player has not played...
m_currPlayer = i;
// So we don't finish the turn
return;
}
}
}
@ -187,22 +194,6 @@ void Duplicate::tryEndTurn()
}
void Duplicate::recordPlayerMove(Player &ioPlayer, const Move &iMove)
{
ASSERT(!hasPlayed(ioPlayer.getId()), "Player has already played");
LOG_INFO("Player " << ioPlayer.getId() << " plays: " << lfw(iMove.toString()));
bool isArbitration = getParams().getMode() == GameParams::kARBITRATION;
Command *pCmd = new PlayerMoveCmd(ioPlayer, iMove, isArbitration);
pCmd->setHumanIndependent(!ioPlayer.isHuman());
accessNavigation().addAndExecute(pCmd);
Command *pCmd2 = new MarkPlayedCmd(*this, ioPlayer.getId(), true);
pCmd2->setHumanIndependent(!ioPlayer.isHuman());
accessNavigation().addAndExecute(pCmd2);
}
struct MatchingPlayer : public unary_function<PlayerMoveCmd, bool>
{
MatchingPlayer(unsigned iPlayerId) : m_playerId(iPlayerId) {}
@ -216,21 +207,32 @@ struct MatchingPlayer : public unary_function<PlayerMoveCmd, bool>
};
void Duplicate::replacePlayerMove(Player &ioPlayer, const Move &iMove)
void Duplicate::recordPlayerMove(Player &ioPlayer, const Move &iMove)
{
ASSERT(hasPlayed(ioPlayer.getId()), "The player has no assigned move yet!");
LOG_INFO("Player " << ioPlayer.getId() << " plays: " << lfw(iMove.toString()));
// Find the PlayerMoveCmd we want to undo
bool isArbitration = getParams().getMode() == GameParams::kARBITRATION;
// Search a PlayerMoveCmd for the given player
MatchingPlayer predicate(ioPlayer.getId());
const PlayerMoveCmd *cmd =
getNavigation().getCurrentTurn().findMatchingCmd<PlayerMoveCmd>(predicate);
ASSERT(cmd != 0, "No matching PlayerMoveCmd found");
// Replace the player move
bool isArbitration = getParams().getMode() == GameParams::kARBITRATION;
Command *pCmd = new PlayerMoveCmd(ioPlayer, iMove, isArbitration);
pCmd->setHumanIndependent(!ioPlayer.isHuman());
accessNavigation().replaceCommand(*cmd, pCmd);
if (cmd == 0)
{
Command *pCmd = new PlayerMoveCmd(ioPlayer, iMove, isArbitration);
pCmd->setHumanIndependent(!ioPlayer.isHuman());
accessNavigation().addAndExecute(pCmd);
}
else
{
// Replace the player move
LOG_DEBUG("Replacing move for player " << ioPlayer.getId());
if (!getNavigation().isLastTurn())
throw GameException("Cannot add a command to an old turn");
Command *pCmd = new PlayerMoveCmd(ioPlayer, iMove, isArbitration);
pCmd->setHumanIndependent(!ioPlayer.isHuman());
accessNavigation().replaceCommand(*cmd, pCmd);
}
}
@ -369,20 +371,15 @@ void Duplicate::setPlayer(unsigned int p)
}
bool Duplicate::hasPlayed(unsigned int p) const
{
ASSERT(p < getNPlayers(), "Wrong player number");
map<unsigned int, bool>::const_iterator it = m_hasPlayed.find(p);
return it != m_hasPlayed.end() && it->second;
}
void Duplicate::setPlayedFlag(unsigned int iPlayerId, bool iNewFlag)
bool Duplicate::hasPlayed(unsigned iPlayerId) const
{
ASSERT(iPlayerId < getNPlayers(), "Wrong player number");
m_hasPlayed[iPlayerId] = iNewFlag;
// Search a PlayerMoveCmd for the given player
MatchingPlayer predicate(iPlayerId);
const PlayerMoveCmd *cmd =
getNavigation().getCurrentTurn().findMatchingCmd<PlayerMoveCmd>(predicate);
return cmd != 0 && cmd->isExecuted();
}
@ -418,9 +415,6 @@ void Duplicate::setGameAndPlayersRack(const PlayedRack &iRack)
{
Command *pCmd = new PlayerRackCmd(*player, iRack);
accessNavigation().addAndExecute(pCmd);
// Nobody has played yet in this round
Command *pCmd2 = new MarkPlayedCmd(*this, player->getId(), false);
accessNavigation().addAndExecute(pCmd2);
}
}

View file

@ -112,9 +112,6 @@ protected:
/// Record a player move
void recordPlayerMove(Player &ioPlayer, const Move &iMove);
/// Cancel the last move of a player (in the current turn)
void replacePlayerMove(Player &ioPlayer, const Move &iMove);
/// Helper function to set the game rack and the players rack at the same time
void setGameAndPlayersRack(const PlayedRack &iRack);
@ -136,10 +133,6 @@ protected:
void endGame();
private: // Used by friend classes
/// Change the "has played" status of the given player to the given status
// Note: only used by friend classes
void setPlayedFlag(unsigned int iPlayerId, bool iNewFlag);
void innerSetMasterMove(const Move &iMove);
private:
@ -163,9 +156,6 @@ private:
*/
void endTurn();
/// m_hasPlayed[p] is true iff player p has played for this turn
map<unsigned int, bool> m_hasPlayed;
/**
* Master move, i.e. the move that will be played on the board
* at this turn (even if no player actually played it).

View file

@ -1,60 +0,0 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2009 Olivier Teulière
* Authors: Olivier Teulière <ipkiss @@ gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
#include <sstream>
#include "mark_played_cmd.h"
#include "duplicate.h"
using namespace std;
INIT_LOGGER(game, MarkPlayedCmd);
MarkPlayedCmd::MarkPlayedCmd(Duplicate &ioDuplicate,
unsigned int iPlayerId,
bool iPlayedFlag)
: m_duplicateGame(ioDuplicate), m_playerId(iPlayerId),
m_newPlayedFlag(iPlayedFlag)
{
}
void MarkPlayedCmd::doExecute()
{
m_oldPlayedFlag = m_duplicateGame.hasPlayed(m_playerId);
m_duplicateGame.setPlayedFlag(m_playerId, m_newPlayedFlag);
}
void MarkPlayedCmd::doUndo()
{
m_duplicateGame.setPlayedFlag(m_playerId, m_oldPlayedFlag);
}
wstring MarkPlayedCmd::toString() const
{
wostringstream oss;
oss << L"MarkPlayedCmd (player " << m_playerId
<< L" marked " << m_newPlayedFlag << L")";
return oss.str();
}

View file

@ -1,57 +0,0 @@
/*****************************************************************************
* Eliot
* Copyright (C) 2009 Olivier Teulière
* Authors: Olivier Teulière <ipkiss @@ gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
#ifndef MARK_PLAYED_CMD_H_
#define MARK_PLAYED_CMD_H_
#include "command.h"
#include "logging.h"
class Duplicate;
/**
* Command used internally to change the "has played" flag of a player
* in a duplicate game.
*/
class MarkPlayedCmd: public Command
{
DEFINE_LOGGER();
public:
MarkPlayedCmd(Duplicate &ioDuplicate,
unsigned int iPlayerId,
bool iPlayedFlag);
virtual wstring toString() const;
protected:
virtual void doExecute();
virtual void doUndo();
private:
Duplicate &m_duplicateGame;
unsigned int m_playerId;
bool m_newPlayedFlag;
bool m_oldPlayedFlag;
};
#endif

View file

@ -38,7 +38,6 @@
#include "player_move_cmd.h"
#include "player_points_cmd.h"
#include "master_move_cmd.h"
#include "mark_played_cmd.h"
#include "dic.h"
#include "header.h"
@ -251,10 +250,6 @@ void XmlWriter::write(const Game &iGame, const string &iFileName)
out << endl;
}
else if (dynamic_cast<const MarkPlayedCmd*>(cmd))
{
// Ignore this command, as it is an implementation detail
}
else
{
LOG_ERROR("Unsupported command: " << lfw(cmd->toString()));