diff options
author | John Fultz <jfultz@wolfram.com> | 2015-12-07 02:14:25 -0600 |
---|---|---|
committer | John Fultz <jfultz@wolfram.com> | 2019-07-21 02:02:55 -0700 |
commit | c5ae5d1137b9456fcb0b2e9e83c1bfc126522e92 (patch) | |
tree | fbff915e94233270fbedab63911275cf4adb3aa2 | |
parent | d1f7ebd10a68d1a43f1d4a7a22ce631126e8b4a5 (diff) |
Move sim toward a message passing model.
In prep for allowing sims to be handed off to a thread
pool.
-rw-r--r-- | sim.cpp | 82 | ||||
-rw-r--r-- | sim.h | 38 |
2 files changed, 84 insertions, 36 deletions
@@ -32,6 +32,8 @@ using namespace Quackle; +std::atomic_long SimmedMove::objectIdCounter{0}; + Simulator::Simulator() : m_logfileIsOpen(false), m_hasHeader(false), m_dispatch(0), m_iterations(0), m_ignoreOppos(false) { @@ -266,19 +268,18 @@ void Simulator::simulate(int plies) UVcout << "simulating " << (*moveIt).move << ":" << endl; #endif - if (isLogging()) - { - m_logfileStream << m_xmlIndent << "<playahead>" << endl; - m_xmlIndent += MARK_UV('\t'); - } - m_simulatedGame = m_originalGame; double residual = 0; - moveIt.setNumberLevels(levels + 1); + moveIt.levels.setNumberLevels(levels + 1); + + struct SimmedMoveMessage message; + message.id = moveIt.id(); + message.levels.setNumberLevels(levels + 1); + message.levels = moveIt.levels; int levelNumber = 1; - for (LevelList::iterator levelIt = moveIt.levels.begin(); levelNumber <= levels + 1 && levelIt != moveIt.levels.end() && !m_simulatedGame.currentPosition().gameOver(); ++levelIt, ++levelNumber) + for (LevelList::iterator levelIt = message.levels.begin(); levelNumber <= levels + 1 && levelIt != message.levels.end() && !m_simulatedGame.currentPosition().gameOver(); ++levelIt, ++levelNumber) { const int decimal = levelNumber == levels + 1? decimalTurns : numberOfPlayers; if (decimal == 0) @@ -377,35 +378,25 @@ void Simulator::simulate(int plies) } } - moveIt.residual.incorporateValue(residual); - - const int spread = m_simulatedGame.currentPosition().spread(startPlayerId); - moveIt.gameSpread.incorporateValue(spread); + message.residual = residual; + int spread = m_simulatedGame.currentPosition().spread(startPlayerId); + message.gameSpread = spread; if (m_simulatedGame.currentPosition().gameOver()) { - const float wins = spread > 0? 1 : spread == 0? 0.5F : 0; - moveIt.wins.incorporateValue(wins); - - if (isLogging()) - { - m_logfileStream << m_xmlIndent << "<gameover win=\"" << wins << "\" />" << endl; - } + message.bogowin = false; + message.wins = spread > 0? 1 : spread == 0? 0.5 : 0; } else { + message.bogowin = true; if (m_simulatedGame.currentPosition().currentPlayer().id() == startPlayerId) - moveIt.wins.incorporateValue(QUACKLE_STRATEGY_PARAMETERS->bogowin((int)(spread + residual), m_simulatedGame.currentPosition().bag().size() + QUACKLE_PARAMETERS->rackSize(), 0)); + message.wins = QUACKLE_STRATEGY_PARAMETERS->bogowin((int)(spread + residual), m_simulatedGame.currentPosition().bag().size() + QUACKLE_PARAMETERS->rackSize(), 0); else - moveIt.wins.incorporateValue(1.0 - QUACKLE_STRATEGY_PARAMETERS->bogowin((int)(-spread - residual), m_simulatedGame.currentPosition().bag().size() + QUACKLE_PARAMETERS->rackSize(), 0)); - } - - - if (isLogging()) - { - m_xmlIndent = m_xmlIndent.substr(0, m_xmlIndent.length() - 1); - m_logfileStream << m_xmlIndent << "</playahead>" << endl; + message.wins = 1.0 - QUACKLE_STRATEGY_PARAMETERS->bogowin((int)(-spread - residual), m_simulatedGame.currentPosition().bag().size() + QUACKLE_PARAMETERS->rackSize(), 0); } + + incorporateMessage(message); } if (isLogging()) @@ -415,6 +406,35 @@ void Simulator::simulate(int plies) } } +void Simulator::incorporateMessage(const struct SimmedMoveMessage &message) +{ + for (auto& moveIt : m_simmedMoves) + { + if (moveIt.id() == message.id) + { + if (isLogging()) + { + m_logfileStream << m_xmlIndent << "<playahead>" << endl; + m_xmlIndent += MARK_UV('\t'); + } + + moveIt.levels = message.levels; + moveIt.residual.incorporateValue(message.residual); + moveIt.gameSpread.incorporateValue(message.gameSpread); + moveIt.wins.incorporateValue(message.wins); + + if (isLogging()) + { + if (!message.bogowin) + m_logfileStream << m_xmlIndent << "<gameover win=\"" << message.wins << "\" />" << endl; + m_xmlIndent = m_xmlIndent.substr(0, m_xmlIndent.length() - 1); + m_logfileStream << m_xmlIndent << "</playahead>" << endl; + } + break; + } + } +} + void Simulator::randomizeOppoRacks() { #ifdef DEBUG_SIM @@ -561,10 +581,10 @@ double SimmedMove::calculateWinPercentage() const return wins.hasValues()? wins.averagedValue() * 100 : move.win; } -void SimmedMove::setNumberLevels(unsigned int number) +void LevelList::setNumberLevels(unsigned int number) { - while (levels.size() < number) - levels.push_back(Level()); + while (size() < number) + push_back(Level()); } void SimmedMove::clear() @@ -19,6 +19,7 @@ #ifndef QUACKLE_SIM_H #define QUACKLE_SIM_H +#include <atomic> #include <vector> #include "alphabetparameters.h" @@ -113,11 +114,19 @@ struct Level PositionStatisticsList statistics; }; -typedef vector<Level> LevelList; +class LevelList : public vector<Level> +{ +public: + // expand the levels list to be at least number long + void setNumberLevels(unsigned int number); +}; struct SimmedMove { - SimmedMove(const Move &_move) : move(_move), m_includeInSimulation(true) { } + SimmedMove(const Move &_move) : + move(_move), + m_id(++objectIdCounter), + m_includeInSimulation(true) { } // + our scores - their scores + residual, except if we have no levels, // in which case returns move.equity @@ -127,15 +136,14 @@ struct SimmedMove // in which case returns move.win double calculateWinPercentage() const; - // expand the levels list to be at least number long - void setNumberLevels(unsigned int number); - // clear all level values void clear(); bool includeInSimulation() const; void setIncludeInSimulation(bool includeInSimulation); + long id() const { return m_id; }; + Move move; LevelList levels; AveragedValue residual; @@ -145,7 +153,10 @@ struct SimmedMove PositionStatistics getPositionStatistics(int level, int playerIndex) const; private: + long m_id; bool m_includeInSimulation; + + static std::atomic_long objectIdCounter; }; inline bool SimmedMove::includeInSimulation() const @@ -160,6 +171,19 @@ inline void SimmedMove::setIncludeInSimulation(bool includeInSimulation) typedef vector<SimmedMove> SimmedMoveList; +struct SimmedMoveMessage +{ + long id; + LevelList levels; + vector<double> score; + vector<double> bingos; + double residual; + double gameSpread; + double wins; + + bool bogowin; +}; + class Simulator { public: @@ -235,6 +259,10 @@ public: // simulate one iteration void simulate(int plies); + // Incoporate the results of a single simulation into the + // cumulative results + void incorporateMessage(const struct SimmedMoveMessage &message); + // Set oppo's rack to some partially-known tiles. // Set this to an empty rack if no tiles are known, so // that all tiles are chosen randomly each iteration. |