summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Fultz <jfultz@wolfram.com>2019-03-11 11:02:41 -0500
committerJohn Fultz <jfultz@wolfram.com>2019-07-21 02:02:55 -0700
commitd30b4adb9646da26bace320a0abfaace6c05368e (patch)
treeed6c554017ca67146021aeb80d65295ed54cc434
parentbe8c5f0f7fd2a2607ce8bf5ae60830a4d45f8e74 (diff)
Move simulate code to a new static function.
The code running the simulation is now disconnected from the Simulation class, with appropriate members being copied into a SimmedMoveConstants field (read-only, thread-safe) and a SimmedMoveMessage (the class for communicating per-sim data to and from external threads). The newly added static function, Simulate::simulateOnePosition(), should now be thread-safe and usable as a run function for a thread.
-rw-r--r--sim.cpp208
-rw-r--r--sim.h1
2 files changed, 107 insertions, 102 deletions
diff --git a/sim.cpp b/sim.cpp
index 964ca42..a5f6558 100644
--- a/sim.cpp
+++ b/sim.cpp
@@ -270,9 +270,6 @@ void Simulator::simulate(int plies)
UVcout << "simulating " << (*moveIt).move << ":" << endl;
#endif
- Game game = constants.game;
- double residual = 0;
-
moveIt.levels.setNumberLevels(constants.levelCount + 1);
SimmedMoveMessage message;
@@ -282,131 +279,138 @@ void Simulator::simulate(int plies)
message.levels = moveIt.levels;
message.xmlIndent = m_xmlIndent;
- int levelNumber = 1;
- for (LevelList::iterator levelIt = message.levels.begin(); levelNumber <= constants.levelCount + 1 && levelIt != message.levels.end() && !game.currentPosition().gameOver(); ++levelIt, ++levelNumber)
- {
- const int decimal = levelNumber == constants.levelCount + 1? constants.decimalTurns : constants.playerCount;
- if (decimal == 0)
- continue;
+ simulateOnePosition(message, constants);
+ incorporateMessage(message);
+ }
+
+ if (isLogging())
+ {
+ m_xmlIndent = m_xmlIndent.substr(0, m_xmlIndent.length() - 1);
+ m_logfileStream << m_xmlIndent << "</iteration>" << endl;
+ }
+}
+
+void Simulator::simulateOnePosition(SimmedMoveMessage &message, const SimmedMoveConstants &constants)
+{
+ Game game = constants.game;
+ double residual = 0;
+
+ int levelNumber = 1;
+ for (LevelList::iterator levelIt = message.levels.begin(); levelNumber <= constants.levelCount + 1 && levelIt != message.levels.end() && !game.currentPosition().gameOver(); ++levelIt, ++levelNumber)
+ {
+ const int decimal = levelNumber == constants.levelCount + 1? constants.decimalTurns : constants.playerCount;
+ if (decimal == 0)
+ continue;
+
+ (*levelIt).setNumberScores(decimal);
- (*levelIt).setNumberScores(decimal);
+ int playerNumber = 1;
+ for (auto &scoresIt : (*levelIt).statistics)
+ {
+ if (game.currentPosition().gameOver())
+ break;
+ ++playerNumber;
+ const int playerId = game.currentPosition().currentPlayer().id();
- int playerNumber = 1;
- for (auto &scoresIt : (*levelIt).statistics)
+ if (constants.isLogging)
{
- if (game.currentPosition().gameOver())
- break;
- ++playerNumber;
- const int playerId = game.currentPosition().currentPlayer().id();
+ message.logStream << message.xmlIndent << "<ply index=\"" << (levelNumber - 1) * constants.playerCount + playerNumber - 1 << "\">" << endl;
+ message.xmlIndent += MARK_UV('\t');
+ }
- if (constants.isLogging)
- {
- message.logStream << message.xmlIndent << "<ply index=\"" << (levelNumber - 1) * constants.playerCount + playerNumber - 1 << "\">" << endl;
- message.xmlIndent += MARK_UV('\t');
- }
+ Move move = Move::createNonmove();
- Move move = Move::createNonmove();
+ if (playerId == constants.startPlayerId && levelNumber == 1)
+ move = message.move;
+ else if (constants.ignoreOppos && playerId != constants.startPlayerId)
+ move = Move::createPassMove();
+ else
+ move = game.currentPosition().staticBestMove();
- if (playerId == constants.startPlayerId && levelNumber == 1)
- move = message.move;
- else if (constants.ignoreOppos && playerId != constants.startPlayerId)
- move = Move::createPassMove();
- else
- move = game.currentPosition().staticBestMove();
+ int deadwoodScore = 0;
+ if (game.currentPosition().doesMoveEndGame(move))
+ {
+ LetterString deadwood;
+ deadwoodScore = game.currentPosition().deadwood(&deadwood);
+ // account for deadwood in this move rather than a separate
+ // UnusedTilesBonus move.
+ move.score += deadwoodScore;
+ }
- int deadwoodScore = 0;
- if (game.currentPosition().doesMoveEndGame(move))
- {
- LetterString deadwood;
- deadwoodScore = game.currentPosition().deadwood(&deadwood);
- // account for deadwood in this move rather than a separate
- // UnusedTilesBonus move.
- move.score += deadwoodScore;
- }
+ scoresIt.score.incorporateValue(move.score);
+ scoresIt.bingos.incorporateValue(move.isBingo? 1.0 : 0.0);
- scoresIt.score.incorporateValue(move.score);
- scoresIt.bingos.incorporateValue(move.isBingo? 1.0 : 0.0);
+ if (constants.isLogging)
+ {
+ message.logStream << message.xmlIndent << game.currentPosition().currentPlayer().rack().xml() << endl;
+ message.logStream << message.xmlIndent << move.xml() << endl;
+ }
- if (constants.isLogging)
- {
- message.logStream << message.xmlIndent << game.currentPosition().currentPlayer().rack().xml() << endl;
- message.logStream << message.xmlIndent << move.xml() << endl;
- }
+ // record future-looking residuals
+ bool isFinalTurnForPlayerOfSimulation = false;
- // record future-looking residuals
- bool isFinalTurnForPlayerOfSimulation = false;
+ if (levelNumber == constants.levelCount)
+ isFinalTurnForPlayerOfSimulation = playerNumber > constants.decimalTurns;
+ else if (levelNumber == constants.levelCount + 1)
+ isFinalTurnForPlayerOfSimulation = playerNumber <= constants.decimalTurns;
- if (levelNumber == constants.levelCount)
- isFinalTurnForPlayerOfSimulation = playerNumber > constants.decimalTurns;
- else if (levelNumber == constants.levelCount + 1)
- isFinalTurnForPlayerOfSimulation = playerNumber <= constants.decimalTurns;
+ const bool isVeryFinalTurnOfSimulation = (constants.decimalTurns == 0 && levelNumber == constants.levelCount && playerNumber == constants.playerCount) || (levelNumber == constants.levelCount + 1 && playerNumber == constants.decimalTurns);
- const bool isVeryFinalTurnOfSimulation = (constants.decimalTurns == 0 && levelNumber == constants.levelCount && playerNumber == constants.playerCount) || (levelNumber == constants.levelCount + 1 && playerNumber == constants.decimalTurns);
+ if (isFinalTurnForPlayerOfSimulation && !(constants.ignoreOppos && playerId != constants.startPlayerId))
+ {
+ double residualAddend = game.currentPosition().calculatePlayerConsideration(move);
+ if (constants.isLogging)
+ message.logStream << message.xmlIndent << "<pc value=\"" << residualAddend << "\" />" << endl;
- if (isFinalTurnForPlayerOfSimulation && !(constants.ignoreOppos && playerId != constants.startPlayerId))
+ if (isVeryFinalTurnOfSimulation)
{
- double residualAddend = game.currentPosition().calculatePlayerConsideration(move);
- if (constants.isLogging)
- message.logStream << message.xmlIndent << "<pc value=\"" << residualAddend << "\" />" << endl;
-
- if (isVeryFinalTurnOfSimulation)
- {
- // experimental -- do shared resource considerations
- // matter in a plied simulation?
-
- const double sharedResidual = game.currentPosition().calculateSharedConsideration(move);
- residualAddend += sharedResidual;
+ // experimental -- do shared resource considerations
+ // matter in a plied simulation?
- if (constants.isLogging && sharedResidual != 0)
- message.logStream << message.xmlIndent << "<sc value=\"" << sharedResidual << "\" />" << endl;
- }
+ const double sharedResidual = game.currentPosition().calculateSharedConsideration(move);
+ residualAddend += sharedResidual;
- if (playerId == constants.startPlayerId)
- residual += residualAddend;
- else
- residual -= residualAddend;
+ if (constants.isLogging && sharedResidual != 0)
+ message.logStream << message.xmlIndent << "<sc value=\"" << sharedResidual << "\" />" << endl;
}
- // commiting the move will account for deadwood again
- // so avoid double counting from above.
- move.score -= deadwoodScore;
- game.setCandidate(move);
+ if (playerId == constants.startPlayerId)
+ residual += residualAddend;
+ else
+ residual -= residualAddend;
+ }
- game.commitCandidate(!isVeryFinalTurnOfSimulation);
+ // commiting the move will account for deadwood again
+ // so avoid double counting from above.
+ move.score -= deadwoodScore;
+ game.setCandidate(move);
- if (constants.isLogging)
- {
- message.xmlIndent = message.xmlIndent.substr(0, message.xmlIndent.length() - 1);
- message.logStream << message.xmlIndent << "</ply>" << endl;
- }
+ game.commitCandidate(!isVeryFinalTurnOfSimulation);
+
+ if (constants.isLogging)
+ {
+ message.xmlIndent = message.xmlIndent.substr(0, message.xmlIndent.length() - 1);
+ message.logStream << message.xmlIndent << "</ply>" << endl;
}
}
+ }
- message.residual = residual;
- int spread = game.currentPosition().spread(constants.startPlayerId);
- message.gameSpread = spread;
+ message.residual = residual;
+ int spread = game.currentPosition().spread(constants.startPlayerId);
+ message.gameSpread = spread;
- if (game.currentPosition().gameOver())
- {
- message.bogowin = false;
- message.wins = spread > 0? 1 : spread == 0? 0.5 : 0;
- }
- else
- {
- message.bogowin = true;
- if (game.currentPosition().currentPlayer().id() == constants.startPlayerId)
- message.wins = QUACKLE_STRATEGY_PARAMETERS->bogowin((int)(spread + residual), game.currentPosition().bag().size() + QUACKLE_PARAMETERS->rackSize(), 0);
- else
- message.wins = 1.0 - QUACKLE_STRATEGY_PARAMETERS->bogowin((int)(-spread - residual), game.currentPosition().bag().size() + QUACKLE_PARAMETERS->rackSize(), 0);
- }
-
- incorporateMessage(message);
+ if (game.currentPosition().gameOver())
+ {
+ message.bogowin = false;
+ message.wins = spread > 0? 1 : spread == 0? 0.5 : 0;
}
-
- if (isLogging())
+ else
{
- m_xmlIndent = m_xmlIndent.substr(0, m_xmlIndent.length() - 1);
- m_logfileStream << m_xmlIndent << "</iteration>" << endl;
+ message.bogowin = true;
+ if (game.currentPosition().currentPlayer().id() == constants.startPlayerId)
+ message.wins = QUACKLE_STRATEGY_PARAMETERS->bogowin((int)(spread + residual), game.currentPosition().bag().size() + QUACKLE_PARAMETERS->rackSize(), 0);
+ else
+ message.wins = 1.0 - QUACKLE_STRATEGY_PARAMETERS->bogowin((int)(-spread - residual), game.currentPosition().bag().size() + QUACKLE_PARAMETERS->rackSize(), 0);
}
}
diff --git a/sim.h b/sim.h
index 0b3a7fb..ff618ef 100644
--- a/sim.h
+++ b/sim.h
@@ -275,6 +275,7 @@ public:
// simulate one iteration
void simulate(int plies);
+ static void simulateOnePosition(SimmedMoveMessage &message, const SimmedMoveConstants &constants);
// Incoporate the results of a single simulation into the
// cumulative results