Skip to content

Instantly share code, notes, and snippets.

@nojima
Created October 3, 2012 12:31
Show Gist options
  • Save nojima/3826689 to your computer and use it in GitHub Desktop.
Save nojima/3826689 to your computer and use it in GitHub Desktop.
ドミニオンで(属州, 金貨, 銀貨)の順に買えるものを買うという戦略を行った際の,nターン目のお金と勝利点の期待値を求めるコード
#Iter: Money Score
# 1: 3.50 3.00
# 2: 3.50 3.00
# 3: 4.50 3.00
# 4: 4.50 3.00
# 5: 5.16 3.22
# 6: 5.55 3.77
# 7: 5.75 4.53
# 8: 6.34 6.00
# 9: 6.34 7.48
#10: 6.74 9.53
#11: 6.80 11.65
#12: 6.80 13.78
#13: 6.87 16.04
#14: 7.05 18.50
#15: 7.05 20.96
#16: 7.05 23.43
#17: 7.11 26.01
#18: 7.13 28.60
#19: 7.13 31.18
#20: 7.13 33.78
#21: 7.13 36.37
#22: 7.15 39.02
#23: 7.15 41.66
#24: 7.15 44.30
#25: 7.15 46.94
#26: 7.16 49.59
#27: 7.16 52.23
#28: 7.15 54.89
#29: 7.14 57.54
#30: 7.14 60.20
#include <algorithm>
#include <iostream>
#include <random>
#include <vector>
#include <boost/format.hpp>
using namespace std;
enum class Card {
Copper, // 銅貨
Silver, // 銀貨
Gold, // 金貨
Estate, // 屋敷
Duchy, // 公領
Province, // 属州
};
int main()
{
int iteration_count = 10000000;
int max_turn = 30;
mt19937 random(12345);
vector<long long> score_sum(max_turn + 1);
vector<long long> money_sum(max_turn + 1);
for (int iter = 0; iter < iteration_count; ++iter) {
vector<Card> deck, discard, hand;
for (int i = 0; i < 3; ++i)
discard.push_back(Card::Estate);
for (int i = 0; i < 7; ++i)
discard.push_back(Card::Copper);
int score = 3;
for (int turn = 1; turn <= max_turn; ++turn) {
if (deck.size() < 5) {
random_shuffle(discard.begin(), discard.end(),
[&random](unsigned n){ return random() % n; });
deck.insert(deck.end(), discard.begin(), discard.end());
discard.clear();
}
hand.assign(deck.begin(), deck.begin() + 5);
deck.erase(deck.begin(), deck.begin() + 5);
int money = 0;
for (Card card : hand) {
switch (card) {
case Card::Copper: money += 1; break;
case Card::Silver: money += 2; break;
case Card::Gold: money += 3; break;
default: break;
}
}
if (money >= 8) {
discard.push_back(Card::Province);
score += 6;
} else if (money >= 6) {
discard.push_back(Card::Gold);
} else if (money >= 3) {
discard.push_back(Card::Silver);
}
discard.insert(discard.end(), hand.begin(), hand.end());
score_sum[turn] += score;
money_sum[turn] += money;
}
}
cout << "#Iter: Money Score" << endl;
for (int i = 1; i <= max_turn; ++i) {
double average_score = double(score_sum[i]) / iteration_count;
double average_money = double(money_sum[i]) / iteration_count;
cout << boost::format("#%2d: %.2f %.2f") % i % average_money % average_score << endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment