FreeGame: fix an infinite game when all the players keep passing forever.

Now the game ends when all the players passed in the last 3 turns.
This commit is contained in:
Olivier Teulière 2015-02-24 23:28:31 +01:00
parent 8077525893
commit 7f60f532ad
5 changed files with 129 additions and 10 deletions

View file

@ -169,11 +169,18 @@ int FreeGame::endTurn()
catch (EndGameException &e)
{
// End of the game
endGame();
endGame(m_currPlayer);
return 1;
}
}
if (allPlayersPassedThreeTimesInARow())
{
LOG_INFO("All the players passed 3 times consecutively");
endGame(getNPlayers());
return 2;
}
// Next player
nextPlayer();
@ -194,7 +201,7 @@ int FreeGame::endTurn()
// Adjust the scores of the players with the points of the remaining tiles
void FreeGame::endGame()
void FreeGame::endGame(unsigned iWinningPlayer)
{
LOG_INFO("End of the game");
@ -209,7 +216,9 @@ void FreeGame::endGame()
// We currently handle case 1, and cannot handle case 3 until timers are
// implemented.
// For case 2, we need both to detect a blocked situation (not easy...) and
// to handle it in the endGame() method (very easy).
// to handle it in the endGame() method (very easy). As a workaround for
// case 2, we consider that if all players pass 3 times the game ends
// without any winner.
// Add the points of the remaining tiles to the score of the current
// player (i.e. the first player with an empty rack), and remove them
@ -217,7 +226,7 @@ void FreeGame::endGame()
int addedPoints = 0;
for (unsigned int i = 0; i < getNPlayers(); i++)
{
if (i != m_currPlayer)
if (i != iWinningPlayer)
{
const PlayedRack &pld = m_players[i]->getCurrentRack();
pld.getAllTiles(tiles);
@ -233,10 +242,13 @@ void FreeGame::endGame()
accessNavigation().addAndExecute(pCmd);
}
}
// Add all the points to the current player
Command *pCmd = new PlayerEventCmd(*m_players[m_currPlayer],
PlayerEventCmd::END_GAME, addedPoints);
accessNavigation().addAndExecute(pCmd);
// Give all the points to the winning player
if (iWinningPlayer < getNPlayers())
{
Command *pCmd = new PlayerEventCmd(*m_players[m_currPlayer],
PlayerEventCmd::END_GAME, addedPoints);
accessNavigation().addAndExecute(pCmd);
}
// Lock game
m_finished = true;
@ -307,3 +319,27 @@ int FreeGame::pass(const wstring &iToChange)
return 0;
}
bool FreeGame::allPlayersPassedThreeTimesInARow() const
{
const unsigned NB_OF_PASSES = 3;
// Only one player really plays at each turn
const unsigned NB_TURNS_TO_CHECK = NB_OF_PASSES * getNPlayers();
bool result = true;
BOOST_FOREACH(const Player *player, m_players)
{
const History &history = player->getHistory();
result = result && (history.getSize() >= NB_TURNS_TO_CHECK);
for (unsigned turnNb = history.getSize() - NB_TURNS_TO_CHECK;
turnNb < history.getSize();
++turnNb)
{
const Move &move = history.getTurn(turnNb).getMove();
// Players who did not play got a null move for the turn
result = result && (move.isPass() || move.isNull());
}
}
return result;
}

View file

@ -96,14 +96,20 @@ private:
/// Finish the current turn
int endTurn();
/// Finish the game
void endGame();
/**
* Finish the game.
* @param The winning player is given, use an invalid player number to
* indicate that there was no winner (e.g.: all players pass several times)
*/
void endGame(unsigned iWinningPlayer);
/**
* Check whether it is legal to change the letters of iToChange.
* The return codes are the same as the ones on the pass() method
*/
int checkPass(const Player &iPlayer, const wstring &iToChange) const;
bool allPlayersPassedThreeTimesInARow() const;
};
#endif /* _FREEGAME_H_ */

View file

@ -90,6 +90,8 @@ arbitration/load_save 0 # randseed unused
freegame/play 7
# The human player always passes, letting the AI player do what it wants
freegame/passing 1
# Two humans play, and reach the end of the game by passing 3 times consecutively
freegame/passing_3_times 24
# 2 human players, changing letters a lot
freegame/change 3
# Three AI players

View file

@ -0,0 +1,21 @@
l 2 0
p
p
p
p
p
a t
p BEFH
p
p
p
p
p
p
a S
a T
a p
p
q
q

View file

@ -0,0 +1,54 @@
Using seed: 24
[?] pour l'aide
commande> l 2 0
mode partie libre
[?] pour l'aide
commande> p
commande> p
commande> p
commande> p
commande> p
commande> a t
BEFHLRT
commande> p BEFH
commande> p
commande> p
commande> p
commande> p
commande> p
commande> p
commande> a S
Score 0: -9
Score 1: -18
commande> a T
Rack 0: AEEOPUU
Rack 1: CILORTZ
commande> a p
Game: player 2 out of 2
Game: mode=Free game
Game: history:
N | RACK | SOLUTION | REF | PTS | BONUS
===|==========|================|=====|=====|======
1 | AUEUOEP | (PASS) | - | 0 |
2 | ELBFHTR | (PASS) | - | 0 |
3 | AEEOPUU | (PASS) | - | 0 |
4 | BEFHLRT | (PASS) | - | 0 |
5 | AEEOPUU | (PASS) | - | 0 |
6 | BEFHLRT | [BEFH] | - | 0 |
7 | AEEOPUU | (PASS) | - | 0 |
8 | LRT+COIZ | (PASS) | - | 0 |
9 | AEEOPUU | (PASS) | - | 0 |
10 | CILORTZ | (PASS) | - | 0 |
11 | AEEOPUU | (PASS) | - | 0 |
12 | CILORTZ | (PASS) | - | 0 |
Rack 0: AEEOPUU
Rack 1: CILORTZ
Score 0: -9
Score 1: -18
commande> p
Cannot pass (3)
commande> q
fin du mode partie libre
commande> q