summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bag.cpp9
-rw-r--r--bag.h3
-rw-r--r--game.cpp48
-rw-r--r--game.h5
-rw-r--r--preendgame.cpp2
-rw-r--r--rack.cpp9
-rw-r--r--rack.h4
7 files changed, 73 insertions, 7 deletions
diff --git a/bag.cpp b/bag.cpp
index b9d95ad..e4ebef9 100644
--- a/bag.cpp
+++ b/bag.cpp
@@ -55,6 +55,15 @@ void Bag::prepareFullBag()
m_tiles.push_back(letter);
}
+int Bag::fullBagTileCount()
+{
+ int tileCount = 0;
+ // we start at 0 because we want to include blanks etcetera
+ for (Letter letter = 0; letter <= QUACKLE_ALPHABET_PARAMETERS->lastLetter(); ++letter)
+ tileCount += QUACKLE_ALPHABET_PARAMETERS->count(letter);
+ return tileCount;
+}
+
void Bag::toss(const LetterString &letters)
{
const LetterString::const_iterator end(letters.end());
diff --git a/bag.h b/bag.h
index 5444076..e7e3f22 100644
--- a/bag.h
+++ b/bag.h
@@ -72,6 +72,9 @@ public:
// use this to start out your bag for use
void prepareFullBag();
+ // Assuming a full bag, how many tiles would that be?
+ int fullBagTileCount();
+
// whether there are no tiles left in the bag
bool empty() const;
diff --git a/game.cpp b/game.cpp
index 242556c..041f756 100644
--- a/game.cpp
+++ b/game.cpp
@@ -70,7 +70,7 @@ void Game::setPlayers(const PlayerList &list)
void Game::addPosition()
{
addClonePosition();
- m_positions.lastPosition().incrementTurn();
+ m_positions.lastPosition().incrementTurn(&history());
m_positions.setCurrentLocation(m_positions.lastLocation());
@@ -186,7 +186,7 @@ void Game::commitMove(const Move &move)
///////////
GamePosition::GamePosition(const PlayerList &players)
- : m_players(players), m_currentPlayer(m_players.end()), m_playerOnTurn(m_players.end()), m_turnNumber(0), m_nestedness(0), m_scorelessTurnsInARow(0), m_gameOver(false)
+ : m_players(players), m_currentPlayer(m_players.end()), m_playerOnTurn(m_players.end()), m_turnNumber(0), m_nestedness(0), m_scorelessTurnsInARow(0), m_gameOver(false), m_tilesInBag(m_bag.fullBagTileCount() - (QUACKLE_PARAMETERS->rackSize() * m_players.size())), m_tilesOnRack(QUACKLE_PARAMETERS->rackSize())
{
setEmptyBoard();
resetMoveMade();
@@ -194,7 +194,7 @@ GamePosition::GamePosition(const PlayerList &players)
}
GamePosition::GamePosition(const GamePosition &position)
- : m_players(position.m_players), m_moves(position.m_moves), m_moveMade(position.m_moveMade), m_committedMove(position.m_committedMove), m_turnNumber(position.m_turnNumber), m_nestedness(position.m_nestedness), m_scorelessTurnsInARow(position.m_scorelessTurnsInARow), m_gameOver(position.m_gameOver), m_board(position.m_board), m_bag(position.m_bag), m_drawingOrder(position.m_drawingOrder), m_explanatoryNote(position.m_explanatoryNote)
+ : m_players(position.m_players), m_moves(position.m_moves), m_moveMade(position.m_moveMade), m_committedMove(position.m_committedMove), m_turnNumber(position.m_turnNumber), m_nestedness(position.m_nestedness), m_scorelessTurnsInARow(position.m_scorelessTurnsInARow), m_gameOver(position.m_gameOver), m_tilesInBag(position.m_tilesInBag), m_tilesOnRack(position.m_tilesOnRack), m_board(position.m_board), m_bag(position.m_bag), m_drawingOrder(position.m_drawingOrder), m_explanatoryNote(position.m_explanatoryNote)
{
// reset iterator
if (position.turnNumber() == 0)
@@ -219,6 +219,8 @@ const GamePosition &GamePosition::operator=(const GamePosition &position)
m_nestedness = position.m_nestedness;
m_scorelessTurnsInARow = position.m_scorelessTurnsInARow;
m_gameOver = position.m_gameOver;
+ m_tilesInBag = position.m_tilesInBag;
+ m_tilesOnRack = position.m_tilesOnRack;
m_board = position.m_board;
m_bag = position.m_bag;
m_drawingOrder = position.m_drawingOrder;
@@ -747,7 +749,7 @@ void GamePosition::resetBag()
m_bag.prepareFullBag();
}
-bool GamePosition::incrementTurn()
+bool GamePosition::incrementTurn(const History* history)
{
if (gameOver() || m_players.empty())
return false;
@@ -767,6 +769,44 @@ bool GamePosition::incrementTurn()
// now moveTiles is the tiles that are in play but not on rack
removeLetters(moveTiles.tiles());
+ if (history)
+ {
+ PlayerList::iterator nextCurrentPlayer(m_currentPlayer);
+ nextCurrentPlayer++;
+ if (nextCurrentPlayer == m_players.end())
+ nextCurrentPlayer = m_players.begin();
+ const Quackle::PositionList positions(history->positionsFacedBy((*nextCurrentPlayer).id()));
+ if (positions.size() > 0)
+ m_tilesOnRack = positions.back().m_tilesOnRack;
+ m_tilesOnRack -= m_moveMade.usedTiles().size();
+ while (m_tilesInBag > 0 && m_tilesOnRack < QUACKLE_PARAMETERS->rackSize())
+ {
+ m_tilesInBag--;
+ m_tilesOnRack++;
+ }
+ if (m_tilesInBag == 0)
+ {
+ // We can get off on our counting with unknown racks.
+ // Shift tiles around if that happens.
+ Rack otherPlayerRack = nextCurrentPlayer->rack();
+ if (m_tilesOnRack == 0 && !remainingRack.empty())
+ {
+ otherPlayerRack.load(remainingRack.tiles());
+ remainingRack = remainingRack - remainingRack;
+ }
+ else if (m_tilesOnRack != 0 && remainingRack.empty())
+ {
+ int tilesToMove = m_tilesOnRack;
+ while (otherPlayerRack.tiles().size() > 0 && tilesToMove > 0)
+ {
+ LetterString oneAtATime = otherPlayerRack.tiles().substr(0, 1);
+ otherPlayerRack.unload(oneAtATime);
+ remainingRack.load(oneAtATime);
+ }
+ }
+ nextCurrentPlayer->setRack(otherPlayerRack);
+ }
+ }
// update our current player's score before possibly
// adding endgame bonuses
diff --git a/game.h b/game.h
index 40d7600..7ef60fd 100644
--- a/game.h
+++ b/game.h
@@ -34,6 +34,7 @@ namespace Quackle
{
class ComputerPlayer;
+class History;
class HistoryLocation
{
@@ -380,7 +381,7 @@ public:
// at start of game.)
// If applicable, this player's score is also incremented by score of move
// made.
- bool incrementTurn();
+ bool incrementTurn(const History* history = NULL);
// Turn numbers in games start from 1.
// A turn number of zero indicates a position that is pregame.
@@ -426,6 +427,8 @@ protected:
unsigned int m_nestedness;
int m_scorelessTurnsInARow;
bool m_gameOver;
+ int m_tilesInBag;
+ int m_tilesOnRack;
Quackle::Board m_board;
diff --git a/preendgame.cpp b/preendgame.cpp
index 227598f..fe9a356 100644
--- a/preendgame.cpp
+++ b/preendgame.cpp
@@ -167,7 +167,7 @@ MoveList Preendgame::moves(int nmoves)
tempPosition.setOppRack((*it).rack);
tempPosition.setMoveMade(*moveIt);
- tempPosition.incrementTurn();
+ tempPosition.incrementTurn(NULL);
tempPosition.makeMove(*moveIt);
//tempPosition.incrementNestedness();
diff --git a/rack.cpp b/rack.cpp
index 900763f..967514c 100644
--- a/rack.cpp
+++ b/rack.cpp
@@ -76,6 +76,15 @@ bool Rack::unload(const LetterString &used)
return ret;
}
+void Rack::load(const LetterString &tiles)
+{
+ for (LetterString::const_iterator it = tiles.begin(); it != tiles.end(); ++it)
+ {
+ if (it != QUACKLE_NULL_MARK)
+ m_tiles += *it;
+ }
+}
+
bool Rack::contains(const LetterString &used) const
{
return Rack(*this).unload(used);
diff --git a/rack.h b/rack.h
index 7bc7df8..a175c29 100644
--- a/rack.h
+++ b/rack.h
@@ -57,6 +57,8 @@ public:
// in this rack and unloaded
bool unload(const LetterString &used);
+ void load(const LetterString &tiles);
+
// same as above but nonmutating
bool contains(const LetterString &used) const;
@@ -99,7 +101,7 @@ inline bool Rack::empty() const
}
const Quackle::Rack operator-(const Quackle::Rack &rack, const Quackle::Move &move);
-const Quackle::Rack operator-(const Quackle::Rack &rack1, const Quackle::Rack &rack);
+const Quackle::Rack operator-(const Quackle::Rack &rack1, const Quackle::Rack &rack2);
UVOStream &operator<<(UVOStream &o, const Quackle::Rack &rack);