summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim.cpp82
-rw-r--r--sim.h38
2 files changed, 84 insertions, 36 deletions
diff --git a/sim.cpp b/sim.cpp
index f297f6c..50ebd16 100644
--- a/sim.cpp
+++ b/sim.cpp
@@ -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()
diff --git a/sim.h b/sim.h
index 9f31590..e6ba025 100644
--- a/sim.h
+++ b/sim.h
@@ -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.