import random
import math
import numpy as np
from matplotlib import pyplot as plt
# Number of stars you start off with
startingStars = 1095+300
# If True, simulate stopping after finding each daily key. If False, spend all the same day.
goForKeys = True
# Number of keys required for calendar (you can get ~11 for free from daily challenges)
numKeys = 21
# Number of Simulations
simNum = 100000
# Show plots
showPlots = True
# Don't change anything below here (unless you know what you're doing)
######################################################################
fragments = 5
def getRandomList():
# 4 - shuffle, 5 - key, 15 - daily, 20 - double
l = [3,14,4,5,15,20,0,0,0,0,0,0,0,0,0,0,0,0]
random.shuffle(l)
return l
def pickPresent(days,l,l2,i2,dsFound,s,d,ds,k):
i = 0
t = False
if(len(l2) > 0):
if sum(l2) > 0:
if (dsFound and (not goForKeys or (days > 32))) and 4 in l2:
i = l2.index(4)
t = True
elif 4 in l2:
if sum(l2) == 4:
try:
i = random.choice(range(len(l)))
except:
print(days,l,l2,i2,dsFound,s,d,ds,k)
exit()
else:
i = l2.index(sum(l2)-4)
t = True
else:
i = l2.index(max(l2))
t = True
else:
i = random.choice(range(len(l)))
else:
i = random.choice(range(len(l)))
if t:
res = l2[i]
del l2[i]
del i2[i]
else:
res = l[i]
del l[i]
if res == 0:
# nothing
#print(0)
d = 1
elif res == 3:
i2 = random.sample(range(len(l)),min(2,len(l)))
l2 = [l[i2[x]] for x in range(len(i2))]
del l[max(i2)]
if len(i2) > 1:
del l[min(i2)]
s += 3*d
#print(3*d,"stars + show 2:",l2)
elif res == 4:
l2 = []
i2 = []
l = getRandomList()
dsFound = False
s += 10*d
#print(10*d,"stars + shuffle:",l)
return days, l,l2,i2,dsFound,s,d,ds,k
elif res == 5:
k += 1 if goForKeys else 1/fragments
if d == 2:
k += 1/fragments
s += 10
if goForKeys and (days <= 32):
days += 1
l2 = []
i2 = []
l = getRandomList()
dsFound = False
else:
s += 10
#print(d,"key(s) +",d*10,"stars")
elif res == 14:
s += 14*d
#print(d*14,"stars")
elif res == 15:
ds += 1*d
dsFound = True
#print(d,"Daily Special(s)")
elif res == 20:
d = 2
#print("Double")
if res == 20:
d = 2
else:
d = 1
return days, l,l2,i2,dsFound,s,d,ds,k
keys = []
dailies = []
candles = []
gpProgress = []
for x in range(simNum):
if x % round(simNum/10) == 0:
print(round((x/simNum)*100),"%")
starting = startingStars
s = starting
ds = 0
k = 0 if goForKeys else 1
l = getRandomList()
l2 = []
i2 = []
dsFound = False
d = 1
c = 0
days = 0
while s >= 10:
s -= 10
c += 1
days,l,l2,i2,dsFound,s,d,ds,k = pickPresent(days,l,l2,i2,dsFound,s,d,ds,k)
dailies.append(ds)
keys.append(math.floor(k))
candles.append(c)
gp = 0
for i in range(c):
gp += random.choice([1,2,3])
gpProgress.append(gp)
if showPlots:
labels = ["Keys","Dailies","Grand Prize Progress"]
results = [keys,dailies,gpProgress]
fig, ax = plt.subplots(1,1,figsize=(10,6))
#fig, ax = plt.subplots(3,1,figsize=(10,15))
for i in range(2,3):
label = labels[i]
rmin = min(results[i])
rmax = max(results[i])
ax.hist(results[i],edgecolor='white', label=label, bins=range(rmin,rmax,1))
#ax.set_title(label)
if i == 1:
ax[i].axvline(x = numKeys, color = "r", label = str(numKeys) + " Required for Calendar")
if i == 2:
ax.axvline(x = 300, color = "r", label = "Required for Full Building")
ax.legend()
#bin_centers = np.diff(bins)*0.5 + bins[:-1]
#n = 0
#for fr, x, patch in zip(freq, bin_centers, patches):
# height = (freq[n]/len(results))
# plt.annotate("{}".format(height),
# xy = (x, height*len(results)), # top left corner of the histogram bar
# xytext = (0,0.2), # offsetting label position above its bar
# textcoords = "offset points", # Offset (in points) from the *xy* value
# ha = 'center', va = 'bottom'
# )
# n = n+1
#plt.legend()
c = np.average(candles)
gppU = [k for k in gpProgress if k < 300]
gppO = [k for k in gpProgress if k >= 300]
gpU = round(100*(len(gppU)/len(gpProgress)),2)
gpO = round(100*(len(gppO)/len(gpProgress)),2)
print(gppU)
if len(gppU) > 0:
avgM = round(300 - min(np.average(gppU),300),2)
meanM = int(300-min(np.median(gppU),300))
else:
avgM = 0
meanM = 0
maxM = max(300 - min(gpProgress),0)
mode = "(Daily Special Focus)" if not goForKeys else "(Keys Focus)"
fig.suptitle("Expected Grand Prize Progress w/ " + str(startingStars) + " Starting Stars " + mode + "\nActual stars spent (average): " + str(round(c*10,2)) +
" | Chance of Full Building: " + str(gpO) + "%\nMissing Progress (if not full building): Max: " + str(maxM) + " | Average: " + str(avgM) + " | Median: " + str(meanM))
plt.show()
# For last game
printStats = True
if printStats:
c = np.average(candles)
ds = np.average(dailies)
k = np.average(keys)
gp = np.average(gpProgress)
kU = [k for k in keys if k < numKeys]
kO = [k for k in keys if k >= numKeys]
cU = round(100*(len(kU)/len(keys)),2)
cO = round(100*(len(kO)/len(keys)),2)
gppU = [k for k in gpProgress if k < 300]
gppO = [k for k in gpProgress if k >= 300]
gpU = round(100*(len(gppU)/len(gpProgress)),2)
gpO = round(100*(len(gppO)/len(gpProgress)),2)
if len(gppU) > 0:
maxM = 300 - min(gpProgress)
avgM = round(300 - np.average(gppU),2)
else:
avgM = 0
maxnM = 0
print("---------")
if goForKeys:
print("Average Totals (going for Keys):")
else:
print("Average Totals (going for Dailies):")
print("Starting stars:",startingStars)
print("Stars spent:",round(c*10,2),"(x" + str(round(c*10/startingStars,3)) + ")")
#print("Stars Multiplication Factor: x" + str(round(c*10/startingStars,3)),"( 10 ->",str(round(c*100/startingStars,2)) + ")")
print()
print("Matches:",round(c,2))
print("Stars* per Match:",round(startingStars/c,2))
print()
print("Daily Specials:",round(ds,2))
print("Stars* per Daily Special:",round(startingStars/ds,2))
print()
print("Grand Prize Progress:",round(gp,2))
print("Stars* per Grand Prize Progress:",round(startingStars/gp,2))
print("Change of getting Full Building:",str(gpO) + "%")
print("Maximum Missing Progress:",str(maxM))
print("Average Missing Progress:",str(avgM))
print()
print("Keys:",round(k,2))
print("Stars* per Key:",round(startingStars/k,2))
print("Chance of getting",numKeys,"keys:",str(cO) + "%")
print()
print("")
print()
print("*Starting Stars")