mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2024-12-25 21:59:30 +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)
|
catch (EndGameException &e)
|
||||||
{
|
{
|
||||||
// End of the game
|
// End of the game
|
||||||
endGame();
|
endGame(m_currPlayer);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allPlayersPassedThreeTimesInARow())
|
||||||
|
{
|
||||||
|
LOG_INFO("All the players passed 3 times consecutively");
|
||||||
|
endGame(getNPlayers());
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
// Next player
|
// Next player
|
||||||
nextPlayer();
|
nextPlayer();
|
||||||
|
|
||||||
|
@ -194,7 +201,7 @@ int FreeGame::endTurn()
|
||||||
|
|
||||||
|
|
||||||
// Adjust the scores of the players with the points of the remaining tiles
|
// 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");
|
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
|
// We currently handle case 1, and cannot handle case 3 until timers are
|
||||||
// implemented.
|
// implemented.
|
||||||
// For case 2, we need both to detect a blocked situation (not easy...) and
|
// 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
|
// 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
|
// player (i.e. the first player with an empty rack), and remove them
|
||||||
|
@ -217,7 +226,7 @@ void FreeGame::endGame()
|
||||||
int addedPoints = 0;
|
int addedPoints = 0;
|
||||||
for (unsigned int i = 0; i < getNPlayers(); i++)
|
for (unsigned int i = 0; i < getNPlayers(); i++)
|
||||||
{
|
{
|
||||||
if (i != m_currPlayer)
|
if (i != iWinningPlayer)
|
||||||
{
|
{
|
||||||
const PlayedRack &pld = m_players[i]->getCurrentRack();
|
const PlayedRack &pld = m_players[i]->getCurrentRack();
|
||||||
pld.getAllTiles(tiles);
|
pld.getAllTiles(tiles);
|
||||||
|
@ -233,10 +242,13 @@ void FreeGame::endGame()
|
||||||
accessNavigation().addAndExecute(pCmd);
|
accessNavigation().addAndExecute(pCmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add all the points to the current player
|
// Give all the points to the winning player
|
||||||
Command *pCmd = new PlayerEventCmd(*m_players[m_currPlayer],
|
if (iWinningPlayer < getNPlayers())
|
||||||
PlayerEventCmd::END_GAME, addedPoints);
|
{
|
||||||
accessNavigation().addAndExecute(pCmd);
|
Command *pCmd = new PlayerEventCmd(*m_players[m_currPlayer],
|
||||||
|
PlayerEventCmd::END_GAME, addedPoints);
|
||||||
|
accessNavigation().addAndExecute(pCmd);
|
||||||
|
}
|
||||||
|
|
||||||
// Lock game
|
// Lock game
|
||||||
m_finished = true;
|
m_finished = true;
|
||||||
|
@ -307,3 +319,27 @@ int FreeGame::pass(const wstring &iToChange)
|
||||||
return 0;
|
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
|
/// Finish the current turn
|
||||||
int endTurn();
|
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.
|
* Check whether it is legal to change the letters of iToChange.
|
||||||
* The return codes are the same as the ones on the pass() method
|
* The return codes are the same as the ones on the pass() method
|
||||||
*/
|
*/
|
||||||
int checkPass(const Player &iPlayer, const wstring &iToChange) const;
|
int checkPass(const Player &iPlayer, const wstring &iToChange) const;
|
||||||
|
|
||||||
|
bool allPlayersPassedThreeTimesInARow() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _FREEGAME_H_ */
|
#endif /* _FREEGAME_H_ */
|
||||||
|
|
|
@ -90,6 +90,8 @@ arbitration/load_save 0 # randseed unused
|
||||||
freegame/play 7
|
freegame/play 7
|
||||||
# The human player always passes, letting the AI player do what it wants
|
# The human player always passes, letting the AI player do what it wants
|
||||||
freegame/passing 1
|
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
|
# 2 human players, changing letters a lot
|
||||||
freegame/change 3
|
freegame/change 3
|
||||||
# Three AI players
|
# 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