mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2024-12-24 21:59:25 +01:00
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:
parent
8077525893
commit
7f60f532ad
5 changed files with 129 additions and 10 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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
|
||||
|
|
21
test/freegame/passing_3_times.input
Normal file
21
test/freegame/passing_3_times.input
Normal 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
|
||||
|
54
test/freegame/passing_3_times.ref
Normal file
54
test/freegame/passing_3_times.ref
Normal 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
|
Loading…
Reference in a new issue