fork download
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <cmath>
  4. #include <time.h>
  5. using namespace std;
  6.  
  7. static const float CONTROL_WR = 0.8f;
  8. static const float AGGRO_WR = 0.65f;
  9. static const unsigned STARS = 5 * 5 + 5 * 4 + 5 * 3; //From rank 20: 5 ranks with 3 stars, 5 ranks with 4, 5 with 5
  10. static const unsigned REPEATS = 10000; //Higher is slower and more accurate estimate of expected number of games needed
  11. static const unsigned STREAK_WINS = 3; //Number of consecutive wins that start awarding bonus stars
  12. static const unsigned SWITCH_AFTER = STREAK_WINS - 1; //How many wins with the first deck before switching to the second
  13.  
  14. //Flip a coin that lands on "heads" with probability p
  15. bool trial(float p)
  16. {
  17. float r = (float)((float)rand() / (float)RAND_MAX);
  18. return r < p;
  19. }
  20.  
  21. class RunningStat //See: http://w...content-available-to-author-only...k.com/blog/standard_deviation/
  22. {
  23. public:
  24. RunningStat() : m_n(0) {}
  25.  
  26. void Clear()
  27. {
  28. m_n = 0;
  29. }
  30.  
  31. void Push(float x)
  32. {
  33. m_n++;
  34.  
  35. // See Knuth TAOCP vol 2, 3rd edition, page 232
  36. if (m_n == 1)
  37. {
  38. m_oldM = m_newM = x;
  39. m_oldS = 0.0;
  40. }
  41. else
  42. {
  43. m_newM = m_oldM + (x - m_oldM)/m_n;
  44. m_newS = m_oldS + (x - m_oldM)*(x - m_newM);
  45.  
  46. // set up for next iteration
  47. m_oldM = m_newM;
  48. m_oldS = m_newS;
  49. }
  50. }
  51.  
  52. int NumDataValues() const
  53. {
  54. return m_n;
  55. }
  56.  
  57. float Mean() const
  58. {
  59. return (m_n > 0) ? m_newM : 0.0;
  60. }
  61.  
  62. float Variance() const
  63. {
  64. return ( (m_n > 1) ? m_newS/(m_n - 1) : 0.0 );
  65. }
  66.  
  67. float StandardDeviation() const
  68. {
  69. return sqrt( Variance() );
  70. }
  71.  
  72. private:
  73. int m_n;
  74. float m_oldM, m_newM, m_oldS, m_newS;
  75. };
  76.  
  77. bool floatCompare(float a, float b)
  78. {
  79. return max(a, b) - min(a, b) <= 0.01;
  80. }
  81.  
  82. int main(int argc, char* argv[])
  83. {
  84. //Initialize a random seed.
  85. //Can consider using something better than the standard built-in rand(). Google: Mersenne Twister
  86. srand(time(NULL));
  87.  
  88. RunningStat game_stat;
  89. RunningStat base_stat;
  90. float base_wr = AGGRO_WR;
  91. float streak_wr = CONTROL_WR;
  92.  
  93. for (unsigned iteration = 0; iteration < REPEATS; ++iteration)
  94. {
  95. unsigned cur_stars = 0; //This is unsigned and zero-based because we're simulating from rank 20. If you want to start at 10 or something, change to signed and take into account negatives
  96. unsigned streak = 0; //Streak length
  97. unsigned games = 0; //How many games played
  98. unsigned base_games = 0; //How many games played with the initial deck
  99. float wr = base_wr; //starting deck's win-rate
  100. while (cur_stars < STARS)
  101. {
  102. if (streak >= SWITCH_AFTER)
  103. {
  104. //Yes, we'll be "switching" from a deck to itself a lot, it's not inefficient though
  105. //I pulled this outside the "win" loop for the corner case where you only employ one deck
  106. wr = streak_wr;
  107. }
  108. ++games;
  109. if (floatCompare(wr, base_wr))
  110. {
  111. ++base_games;
  112. }
  113. if (trial(wr)) //if we won the game
  114. {
  115. ++cur_stars;
  116. ++streak;
  117. }
  118. else
  119. {
  120. if (cur_stars > 0)
  121. {
  122. --cur_stars;
  123. }
  124. streak = 0;
  125. wr = base_wr;
  126. }
  127.  
  128. if (streak >= STREAK_WINS)
  129. {
  130. ++cur_stars;
  131. }
  132. }
  133. game_stat.Push((float)games);
  134. base_stat.Push((float)base_games);
  135. }
  136.  
  137. cout << "Based on " << REPEATS
  138. << " simulations, each playing a deck with a win-rate of " << base_wr
  139. << " until you reach " << SWITCH_AFTER
  140. << " then switching to a deck with " << streak_wr
  141. << " win-rate, it took an average of " << game_stat.Mean()
  142. << " games with a standard deviation of " << game_stat.StandardDeviation()
  143. << " of those " << base_stat.Mean()
  144. << " games were with the \"priming\" deck."
  145. << endl;
  146.  
  147. //std::cout << std::endl << "Hurray! It took " << games << " games at a win-rate of " << wr << " to reach Rank 5" << std::endl;
  148.  
  149. return 0;
  150. }
Success #stdin #stdout 0.02s 3412KB
stdin
Standard input is empty
stdout
Based on 10000 simulations, each playing a deck with a win-rate of 0.65 until you reach 2 then switching to a deck with 0.8 win-rate, it took an average of 67.4762 games with a standard deviation of 17.4398 of those 31.7724 games were with the "priming" deck.