Skip to content

Instantly share code, notes, and snippets.

@jhanschoo
Last active January 10, 2019 18:31
Show Gist options
  • Save jhanschoo/886068a296b042324dbbe6cf33731540 to your computer and use it in GitHub Desktop.
Save jhanschoo/886068a296b042324dbbe6cf33731540 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# this script calculates how likely you are to get at least a new
# 5* adventurer
# assumption: you do not own the rate-up adventurer
# assumption: all pulls in a 10-summon have the same 5* rate
# assumption: when pity breaks occur, they occur on the last draw
# in a 10-fold.
# assumption: we expect that a single summon is performed once
# it is a guaranteed 5*; we do not factor in the cost of that
# single summon
#
# Another model does not batch the rates and pity breaks into 10-pulls
# which are a different set of assumptions. It is unclear which model
# Cygames uses.
max_num_10_pulls = 100
# the following are summon rates published by cygames
prob_non_rate_up_pool_gala = 0.01
prob_rate_up_gala = 0.005
prob_5star_base_gala = 0.06
# note that while featured rate increase appears much lower
# for gala, the featured rate increase is evenly distributed
# across the pool proportional to the weights as is expected
# and fair. The surprisingly low displayed feature rate increase
# for the gala is due to only the one adventurer being featured
rate_increase_per_ten_gala = 0.005
threshold_gala = 6 # 6 ten-pulls
prob_non_rate_up_pool = 0.005
prob_rate_up = 0.005
prob_5star_base = 0.04
rate_increase_per_ten = 0.0025
threshold = 10 # 10 ten-pulls
for non_rate_up_owned in range(14):
fraction_non_rate_up_owned = non_rate_up_owned/13
# probability of at least a new 5-star adventurer given a 5-star
# adventurer is drawn
prob_new_given_5star_base = (prob_rate_up
+ ((1 - fraction_non_rate_up_owned) * prob_non_rate_up_pool)) / prob_5star_base
prob_new_given_5star_base_gala = (prob_rate_up_gala
+ ((1 - fraction_non_rate_up_owned) * prob_non_rate_up_pool_gala)) / prob_5star_base_gala
# the following arrays store the probability that your next 10-pull
# breaks your pity rate, after having done n 10-draws
# starting from a zero pity rate
prob_5star = [
1 - (1 - (prob_5star_base + i * rate_increase_per_ten)) ** 10 for i in range(threshold)
]
prob_5star.append(1)
prob_5star_gala = [
1 - (1 - (prob_5star_base_gala + i * rate_increase_per_ten)) ** 10 for i in range(threshold_gala)
]
prob_5star_gala.append(1)
# the following arrays store the probability that your next 10-pull
# gives a new 5-star adventurer, after having done n 10-draws
# starting from a zero pity rate
prob_new = [
1 - (1 - prob_new_given_5star_base * (prob_5star_base + i * rate_increase_per_ten)) ** 10 for i in range(threshold)
]
prob_new.append(prob_new_given_5star_base)
prob_new_gala = [
1 - (1 - prob_new_given_5star_base_gala * (prob_5star_base_gala + i * rate_increase_per_ten)) ** 10 for i in range(threshold_gala)
]
prob_new_gala.append(prob_new_given_5star_base_gala)
# except for the last index, the value in the nth index (starting
# from 0) tracks the probability that your have yet to pull a new
# adventurer and next 10-pull has a probability of pulling a 5-star of
# probability_5star + (n * )
# per pull. The last index tracks the probability that have yet to
# pull a new 5* adventurer and your next single pull is guaranteed to
# pull a 5-star.
distributions = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
distributions_gala = [1, 0, 0, 0, 0, 0, 0]
prob_new_cumul = 0
prob_new_cumul_gala = 0
for num_10_pulled in range(max_num_10_pulls + 1):
distributions_next = []
distributions_next_gala = []
# handle guaranteed first
prob_new_cumul += distributions[-1] * prob_new[-1]
distributions_next.append(distributions[-1] * (prob_5star[-1] - prob_new[-1]))
prob_new_cumul_gala += distributions_gala[-1] * prob_new_gala[-1]
distributions_next_gala.append(distributions_gala[-1] * (prob_5star_gala[-1] - prob_new_gala[-1]))
for i in range(len(distributions) - 1):
prob_new_cumul += distributions[i] * prob_new[i]
distributions_next.append(distributions[i] * (1 - prob_5star[i]))
distributions_next[0] += distributions[i] * (prob_5star[i] - prob_new[i])
for i in range(len(distributions_gala) - 1):
prob_new_cumul_gala += distributions_gala[i] * prob_new_gala[i]
distributions_next_gala.append(distributions_gala[i] * (1 - prob_5star_gala[i]))
distributions_next_gala[0] += distributions_gala[i] * (prob_5star_gala[i] - prob_new_gala[i])
distributions = distributions_next
distributions_gala = distributions_next_gala
# print(sum(distributions) + prob_new_cumul)
# print(sum(distributions_gala) + prob_new_cumul_gala)
# print("After " + str(num_10_pulled * 10) + " pulls")
# print(" Probability normal banner: " + str(prob_new_cumul))
# print(" Probability gala banner: " + str(prob_new_cumul_gala))
if prob_new_cumul > prob_new_cumul_gala:
print("After " + str(num_10_pulled * 10) + " pulls, gala gives worse rates with respect to pulling a new 5-star adventurer than normal event if you have " + str(non_rate_up_owned) + " out of the 13 adventurers in the non-rate-up pull")
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment