﻿

# Hearthstone Economy Simulation Code

a guest
Oct 10th, 2013
4,566
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. # By Hamlet, 10/10/2013
2. # as attachment to this post:
3. # http://iam.yellingontheinternet.com/2013/10/10/from-dust-to-dust-the-economy-of-hearthstone/
4.
5. import random
6. import math
7.
8. #throughout:
9. #  0/1/2/3 = common/rare/epic/legendary
10. #  0/1 = normal/gold
11.
12. #Parameters
13.
14. #Disenchant[rarity][gold]
15. Disenchant = [[5, 50], [20, 100], [100, 400], [400, 1600]]
16. Craft = [[40, 400], [100, 800], [400, 1600], [1600, 3200]]
17.
18. #NeutralCardCount = [40, 36, 10, 24]
19. #ClassCardCount = [6, 5, 3, 1] #Currently same for each class
20. TotalCardCount = [94, 81, 37, 33]
21.
22. Required = [2,2,2,1]
23.
24.
25. RarityDist = [0.21, 0.04, 0.01] #set rarity of rare/epic/legendary
26.
27. RarityDist = [1-sum(RarityDist)] + RarityDist #insert common
28. CumulativeDist = [0]*3 #chance that rarity is <= [index]
29. for x in range(3):
30.     CumulativeDist[x] = sum(RarityDist[:x+1])
31.
32. GoldFrequency = [0.02, 0.05, 0.05, 0.05]
33.
34. #Options
35.
36. #Size of card subset we're trying to complete
37. DesiredCardCount = TotalCardCount
38. # [46, 41, 13, 1] #
39. # [94, 81, 37, 0] #
40.
41. ForceDisenchant = 0     # 1 = Disenchant all cards outside desired set
42.
43. RequireGold = 0         # 1 = Collect only golden cards
44.
45. #Craft cost of desired cards
46. TotalDustNeeded = sum([DesiredCardCount[x]*Craft[x][RequireGold]*Required[x] for x in range(4)])
47. CardsNeeded = [DesiredCardCount[i]*Required[i] for i in range(4)]
48.
49. #Stats collected
50.
51. Runs = 100
52.
53. PacksOpenedRecord = [0]*Runs
54. EndingDustRecord = [0]*Runs
55. FoundPercentRecord = [[0]*4 for i in range(Runs)] # FPR[run][rarity]
56.
57. #simulation
58.
59. for Run in range(Runs): #begin each run
60.     PacksOpened = 0
61.     DustNeeded = TotalDustNeeded    #Craft value of remaining cards this run
62.     FoundCardValue = 0
63.     FoundCards = [0]*4
64.     CardsCollected = [[[0]*2 for i in range(j)] for j in TotalCardCount]
65.     #CardsCollected[rarity][index][gold]
66.
67.     while DustNeeded > 0: #open packs
68.         PacksOpened += 1
69.         for Card in range(5): #create cards
70.             Rarity = 3
71.             Gold = 0
72.             CardIndex = 0
73.
74.             rand = random.random()
75.             for x in range(3):  #determine rarity
76.                 if rand < CumulativeDist[x]:
77.                     Rarity = x
78.                     break
79.             if random.random() < GoldFrequency[Rarity]:
80.                 Gold = 1
81.             CardIndex = random.randrange(TotalCardCount[Rarity])
82.             CardsCollected[Rarity][CardIndex][Gold] += 1
83.
84.             #disenchant card if not needed
85.
86.             if (RequireGold and Gold == 0):  #if disenchanting any non-gold
87.                 CardsCollected[Rarity][CardIndex][Gold] -= 1
88.                 DustNeeded -= Disenchant[Rarity][Gold]
89.
90.             elif sum(CardsCollected[Rarity][CardIndex]) > Required[Rarity]:
91.                 #extra card
92.                 if CardsCollected[Rarity][CardIndex][1] > 0: #disenchant gold
93.                     CardsCollected[Rarity][CardIndex][1] -= 1
94.                     DustNeeded -= Disenchant[Rarity][1]
95.                 else:
96.                     CardsCollected[Rarity][CardIndex][0] -= 1
97.                     DustNeeded -= Disenchant[Rarity][0]
98.
99.             elif CardIndex < DesiredCardCount[Rarity]:  #card we care about
100.                 DustNeeded -= Craft[Rarity][RequireGold] #reduce remaining goal
101.                 FoundCardValue += Craft[Rarity][RequireGold]
102.                 FoundCards[Rarity] += 1
103.
104.             elif ForceDisenchant:   #Disenchanting all unwanted cards
105.                 CardsCollected[Rarity][CardIndex][Gold] -= 1
106.                 DustNeeded -= Disenchant[Rarity][Gold]
107.
108.     #Record once we're done
109.     PacksOpenedRecord[Run] = PacksOpened
110.     EndingDustRecord[Run] = TotalDustNeeded - FoundCardValue
111.     FoundPercentRecord[Run] = map(lambda x,y: 0 if y==0 else x/float(y),FoundCards,CardsNeeded)
112.
113. # Outputs
114.
115. MeanPacks = sum(PacksOpenedRecord)/float(Runs)
116. MeanDust = sum(EndingDustRecord)/float(Runs)
117. MeanFoundPercent = [0]*4
118. for Run in range(Runs):
119.     MeanFoundPercent = map(lambda x,y: x+y, MeanFoundPercent, FoundPercentRecord[Run])
120. MeanFoundPercent = [x/float(Runs) for x in MeanFoundPercent]
121. VarPacks = [(x-MeanPacks)**2 for x in PacksOpenedRecord]
122. VarDust = [(x-MeanDust)**2 for x in EndingDustRecord]
123. StdDevPacks = math.sqrt(sum(VarPacks)/float(Runs))
124. StdDevDust = math.sqrt(sum(VarDust)/float(Runs))
125.
126. print("Runs", Runs, "Desired Card Set", DesiredCardCount, "Gold?",
127.             RequireGold, "Force DE", ForceDisenchant)
128. print("Packs Opened", MeanPacks, StdDevPacks)
129. print("Dust used to craft", MeanDust, StdDevDust, MeanDust/float(TotalDustNeeded))
130. print("% cards found", MeanFoundPercent)
RAW Paste Data