- The core is now able to handle "explosive games" ("parties détonantes"). No interface uses this ability yet.

- Fixed a bug in Game::helperSetRackRandom()
This commit is contained in:
Olivier Teulière 2009-01-14 21:53:37 +00:00
parent 229f1fcc14
commit 8b9478542a
5 changed files with 69 additions and 13 deletions

View file

@ -183,7 +183,7 @@ PlayedRack Game::helperSetRackRandom(const PlayedRack &iPld,
bool jokerAdded = false; bool jokerAdded = false;
// Are we dealing with a normal game or a joker game? // Are we dealing with a normal game or a joker game?
if (m_variant == kJOKER) if (m_variant == kJOKER || m_variant == kEXPLOSIVE)
{ {
// 1) Is there already a joker in the remaining letters of the rack? // 1) Is there already a joker in the remaining letters of the rack?
bool jokerFound = false; bool jokerFound = false;
@ -205,7 +205,7 @@ PlayedRack Game::helperSetRackRandom(const PlayedRack &iPld,
} }
// 3) Remove all the jokers from the bag, to avoid taking another one // 3) Remove all the jokers from the bag, to avoid taking another one
for (unsigned int i = 0; i < bag.in(Tile::Joker()); ++i) while (bag.in(Tile::Joker()))
{ {
bag.takeTile(Tile::Joker()); bag.takeTile(Tile::Joker());
} }
@ -323,6 +323,63 @@ PlayedRack Game::helperSetRackRandom(const PlayedRack &iPld,
} }
} }
// In explosive games, we have to perform a search, then replace the
// joker with the letter providing the best score
// A joker coming from a previous rack is not replaced
if (m_variant == kEXPLOSIVE && jokerAdded)
{
Rack rack;
pld.getRack(rack);
Results res;
res.search(getDic(), getBoard(), rack, getHistory().beforeFirstRound());
if (res.size())
{
PlayedRack pldCopy = pld;
// Get the best word
const Round & bestRound = res.get(0);
#ifdef DEBUG
cout << "helperSetRackRandom(): initial rack: "
<< convertToMb(pld.toString()) << " (best word: "
<< convertToMb(bestRound.getWord()) << ")" << endl;
#endif
// Identify the joker
for (unsigned int i = 0; i < bestRound.getWordLen(); ++i)
{
if (bestRound.isJoker(i) && bestRound.isPlayedFromRack(i))
{
const Tile &jokerTile = bestRound.getTile(i);
Tile replacingTile(towupper(jokerTile.toChar()));
#ifdef DEBUG
cout << "helperSetRackRandom(): replacing Joker with "
<< convertToMb(replacingTile.toChar()) << endl;
#endif
// If the bag does not contain this letter anymore,
// simply keep the joker in the rack.
if (bag.in(replacingTile))
{
// The bag contains the replacing letter
// We need to swap the joker (it is necessarily in the
// new tiles, because jokerAdded is true)
Rack tmpRack;
pld.getNew(tmpRack);
ASSERT(tmpRack.in(Tile::Joker()),
"No joker found in the new tiles!");
tmpRack.remove(Tile::Joker());
tmpRack.add(replacingTile);
pld.setNew(tmpRack);
// Make sure the invariant is still correct, otherwise we keep the joker
if (!pld.checkRack(min, min))
pld = pldCopy;
}
break;
}
}
}
}
// Shuffle the new tiles, to hide the order we imposed (joker first in a // Shuffle the new tiles, to hide the order we imposed (joker first in a
// joker game, then needed vowels, then needed consonants, and rest of the // joker game, then needed vowels, then needed consonants, and rest of the
// rack) // rack)
@ -331,12 +388,6 @@ PlayedRack Game::helperSetRackRandom(const PlayedRack &iPld,
// Post-condition check. This should never fail, of course :) // Post-condition check. This should never fail, of course :)
ASSERT(pld.checkRack(min, min), "helperSetRackRandom() is buggy!"); ASSERT(pld.checkRack(min, min), "helperSetRackRandom() is buggy!");
#if 0
// Until now we didn't modify anything except local variables.
// Let's "commit" the changes
m_players[p]->setCurrentRack(pld);
#endif
return pld; return pld;
} }

View file

@ -75,7 +75,8 @@ public:
enum GameVariant enum GameVariant
{ {
kNONE, // Normal game rules kNONE, // Normal game rules
kJOKER // Joker game kJOKER, // Joker game
kEXPLOSIVE // "Explosive" game
}; };
/** /**
@ -95,7 +96,7 @@ public:
* You should never create a new dictionary object while a Game * You should never create a new dictionary object while a Game
* object still exists * object still exists
*/ */
const Dictionary & getDic() const { return m_dic; } const Dictionary & getDic() const { return m_dic; }
/// Get the board /// Get the board
const Board& getBoard() const { return m_board; } const Board& getBoard() const { return m_board; }

View file

@ -59,6 +59,8 @@ void PublicGame::setVariant(GameVariant iVariant)
{ {
if (iVariant == kJOKER) if (iVariant == kJOKER)
m_game.setVariant(Game::kJOKER); m_game.setVariant(Game::kJOKER);
else if (iVariant == kEXPLOSIVE)
m_game.setVariant(Game::kEXPLOSIVE);
else else
m_game.setVariant(Game::kNONE); m_game.setVariant(Game::kNONE);
} }

View file

@ -84,7 +84,8 @@ public:
enum GameVariant enum GameVariant
{ {
kNONE, // Normal game rules kNONE, // Normal game rules
kJOKER // Joker game kJOKER, // Joker game
kEXPLOSIVE // "Explosive" game
}; };
/** /**

View file

@ -35,8 +35,9 @@ class Rack;
/** /**
* This class allows to perform a search on the board for a given rack, * This class allows to perform a search on the board for a given rack,
* and it offers accessors to the resulting rounds. * and it offers accessors to the resulting rounds.
* The rounds are sorted by decreasing number of points (but there is no * The rounds are sorted by decreasing number of points, then by alphabetical
* other ordering between 2 rounds with the same number of points). * order (case insensitive), then by coordinates, then by alphabetical orderi
* again (case sensitive this time).
*/ */
class Results class Results
{ {