Created
July 23, 2020 21:39
-
-
Save ckurtz22/8b3c96c53fbf023486e2f6249ece3e5f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import random | |
class Blade: | |
def __init__(self, name, pity, probs, elem, weapon=None): | |
self.name = name | |
self.pity = pity | |
self.probs = probs | |
self.count = 0 | |
self.elem = elem | |
self.weapon = weapon | |
def isPity(self, group): | |
if group == 1: | |
return group == self.pity | |
return (group - 1) == self.pity | |
def getProb(self, group): | |
return self.probs[group-1] | |
def getName(self): | |
return self.name | |
def getWeapon(self): | |
return self.weapon | |
def getElem(self): | |
return self.elem | |
def pulled(self): | |
self.count += 1 | |
def pullCount(self): | |
return self.count | |
def matchIdea(self, idea): | |
if idea == 1: | |
return self.elem in [1, 2] | |
if idea == 2: | |
return self.elem in [3, 6] | |
if idea == 3: | |
return self.elem in [4, 5] | |
if idea == 4: | |
return self.elem in [7, 8] | |
return False | |
blades = [ | |
Blade("Godfrey", 1, [0.63, 0.63, 1.25, 1.56, 2.19], 6), | |
Blade("Perceval", 2, [1.50, 0.25, 0.50, 1.00, 1.75], 8), | |
Blade("Vale", 5, [0.75, 0.25, 0.25, 0.25, 0.25], 8), | |
Blade("Agate", 1, [0.25, 0.38, 0.75, 0.75, 0.13], 4), | |
Blade("Gorg", 3, [1.00, 1.00, 0.50, 1.50, 1.00], 2), | |
Blade("Boreas", 1, [0.25, 2.13, 2.13, 0.56, 1.19], 3), | |
Blade("Dagas", 0, [0.50, 0.75, 0.50, 1.25, 0.50], 1), | |
Blade("Perun", 3, [2.44, 0.25, 0.63, 1.88, 1.06], 6), | |
Blade("Kora", 4, [0.63, 1.88, 1.88, 0.31, 1.56], 5), | |
Blade("Azami", 2, [0.31, 1.88, 1.25, 0.63, 2.19], 8), | |
Blade("Ursula", 5, [2.25, 0.63, 1.25, 1.88, 0.25], 6), | |
Blade("Newt", 0, [0.25, 0.25, 0.25, 0.25, 0.75], 1), | |
Blade("Nim", 4, [1.00, 1.00, 1.75, 0.25, 1.00], 4), | |
Blade("Adenine", 2, [1.50, 0.25, 1.00, 1.75, 0.50], 3), | |
Blade("Electra", 3, [1.88, 2.25, 0.63, 1.25, 0.25], 5), | |
Blade("Zenobia", 0, [0.25, 0.75, 0.25, 0.25, 0.25], 3), | |
Blade("Finch", 4, [0.50, 1.00, 1.75, 0.25, 1.50], 3), | |
Blade("Floren", 5, [1.75, 1.50, 1.00, 0.50, 0.25], 4), | |
Blade("KOS-MOS", 0, [0.10, 0.10, 0.10, 0.10, 0.10], 7), | |
Blade("Dahlia", 0, [0.13, 0.50, 0.25, 0.88, 0.75], 6), | |
Blade("Akhos", 0, [0.25, 0.25, 0.25, 0.25, 0.25], 5), | |
Blade("Patroka", 0, [0.25, 0.25, 0.25, 0.25, 0.25], 4), | |
Blade("Obrona", 0, [0.50, 0.50, 0.50, 0.50, 0.50], 5), | |
Blade("Perdido", 0, [0.50, 0.50, 0.50, 0.50, 0.50], 1), | |
Blade("Cressidus", 0, [0.50, 0.50, 0.50, 0.50, 0.50], 4), | |
Blade("Sever", 0, [0.50, 0.50, 0.50, 0.50, 0.50], 3), | |
Blade("Kasandra", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 8), | |
Blade("Sheba", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 2), | |
Blade("Herald", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 5), | |
Blade("Aegaeon", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 2), | |
Blade("Praxis", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 6), | |
Blade("Theory", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 6), | |
Blade("Vess", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 5), | |
Blade("Wulfric", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 4), | |
Blade("T-elos", 0, [5.00, 5.00, 5.00, 5.00, 5.00], 8), | |
Blade("Crossette", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 1), | |
Blade("Corvin", 0, [1.00, 1.00, 1.00, 1.00, 1.00], 7) | |
] | |
#import argparse | |
#parser = argparse.ArgumentParser(description='Find probability of finding blades.') | |
#parser.add_argument('-p', '--pulled', action='extend', nargs='+', default=[], help='List of blades already pulled.') | |
#parser.add_argument('-r', '--released', action='extend', nargs='+', default=[], help='List of blades that have been released.') | |
#parser.add_argument('-l', '--luck', '--luk', action='store', default=0, type=int, help='Current LUK stat on driver pulling blades') | |
#parser.add_argument('-g', '--pity', '--group', action='store', default=0, type=int) | |
#parser.add_argument('-i', '--ideas', action='extend', count=4, default=[0, 0, 0, 0], type=int, help='Idea stats on driver pulling blades: --ideas bravery truth compassion justice') | |
#parser.add_argument('-b', '--booster', action='store', default=0, type=int, help='Type of booster used, if any used: 1 for bravery, 2 for truth, etc') | |
#parser.add_argument('-c', '--core', action='store', default=1, type=int, help='Type of core crystal used: 1 for common, 2 for rare, 3 for legendary') | |
#parser.parse_args() | |
## Parameters | |
pulled = [] | |
released = [] | |
ngplus = False | |
luk = 900 | |
ideas = [2, 5, 3, 7] | |
booster = 0 | |
numcores = 25 | |
cores = [3 for i in range(99*4)]# + [2 for i in range(4)] | |
#cores = [2 for i in range(4)] | |
for i in reversed(range(len(blades))): | |
if i < 20 or (i < 26 and ngplus): | |
if blades[i].getName() in pulled: | |
blades.pop(i) | |
else: | |
if blades[i].getName() not in released: | |
blades.pop(i) | |
num_iters = 10000 | |
successes = 0 | |
for niter in range(num_iters): | |
pity = random.randint(1,5) | |
blades_iter = blades[:] | |
pulled_blades = [] | |
pity_points = 0 | |
corePoints = [5, 25, 50] | |
for core in cores: | |
pity_points += corePoints[core-1] | |
candidate = -1 | |
if booster is not 0: | |
idea_type = booster | |
else: | |
idea_type = random.choice([i+1 for i in range(len(ideas)) if ideas[i] == max(ideas)]) | |
idea_level = ideas[idea_type-1] | |
coreRNG = [0.24, 0.99, 0.99] | |
coreProbs = [1.0, 1.5, 3.0] | |
if random.random() < coreRNG[core-1]: | |
candidates = [] | |
for i, blade in enumerate(blades_iter): | |
bladeProb = blade.getProb(pity) / 100.0 | |
coreProb = coreProbs[core-1] | |
ideaProb = 1.0 + 0.05*idea_level if blade.matchIdea(idea_type) else 1.0 | |
lukProb = max(1.0, (luk ** 0.5)/100 * 1.3 + 0.95) | |
if random.random() < bladeProb * coreProb * ideaProb * lukProb: | |
candidates.append(i) | |
if len(candidates) > 0: | |
if len(candidates) > 1: | |
matchedIdea = [i for i in candidates if blades_iter[i].matchIdea(idea_type)] | |
if len(matchedIdea) > 0: | |
candidates = matchedIdea | |
if len(candidates) > 1: | |
probs = [blades_iter[i].getProb(pity) for i in candidates] | |
lowestProb = [i for i in candidates if blades_iter[i].getProb(pity) == min(probs)] | |
if len(lowestProb) > 0: | |
candidates = lowestProb | |
candidate = random.choice(candidates) | |
pity_points = 0 | |
if candidate == -1: | |
if pity_points >= 100: | |
pityBlades = [i for i, blade in enumerate(blades_iter) if blade.isPity(pity)] | |
if len(pityBlades) > 0: | |
pity_points = 0 | |
probs = [blades_iter[i].getProb(pity)/100 for i in pityBlades] | |
probs = [p / sum(probs) for p in probs] | |
rng = random.random() | |
for i, p in enumerate(probs): | |
if rng < p: | |
break | |
rng -= p | |
candidate = pityBlades[i] | |
pity_points = 0 | |
if candidate != -1: | |
pulled_blades.append(blades_iter.pop(candidate)) | |
pulled_blades[-1].pulled() | |
else: | |
probs = [15 for i in range(7)] | |
if idea_type == 1: | |
probs[0] = 35 | |
probs[1] = 35 | |
if idea_type == 2: | |
probs[2] = 35 | |
probs[5] = 35 | |
if idea_type == 3: | |
probs[3] = 35 | |
probs[5] = 35 | |
if idea_type == 4: | |
probs[6] = 35 | |
probs = [p / sum(probs) for p in probs] | |
rng = random.random() | |
for i, p in enumerate(probs): | |
if rng < p: | |
break | |
rng -= p | |
i = 8 if i is 6 else i + 1 | |
pulled_blades.append(Blade("common", 0, [0,0,0,0,0], i, random.randint(1,8))) | |
earths = 0 | |
fires = 0 | |
winds = 0 | |
nopon = 0 | |
ancient = 0 | |
keeneye = 0 | |
leaping = 0 | |
fortitude = 0 | |
nonhealer = 0 | |
healer = 0 | |
for blade in pulled_blades: | |
if blade.getName() in ["Floren", "Nim"] or (blade.getName() is "common" and blade.getElem() is 4): | |
earths += 1 | |
if blade.getName() is "common" and blade.getElem() is 1: | |
fires += 1 | |
if blade.getWeapon() <= 2: | |
healer += 1 | |
if blade.getWeapon() >= 4: | |
nonhealer += 1 | |
if blade.getName() in ["Zenobia", "Adenine"] or (blade.getName() is "common" and blade.getElem() is 3): | |
winds += 1 | |
if blade.getName() is "Boreas": | |
nopon += 1 | |
if blade.getName() is "Perun": | |
ancient += 1 | |
if blade.getName() in ["Gorg", "Adenine", "Agate"]: | |
keeneye += 1 | |
if blade.getName() in ["Zenobia", "Finch", "Perceval"]: | |
leaping += 1 | |
if blade.getName() in ["Ursula", "Gorg"]: | |
fortitude += 1 | |
# DLC success check | |
#if earths >= 0 and fires >= 0 and winds >= 0 and nopon >= 1 and ancient >= 0 and keeneye >= 0 and leaping >= 0 and nonhealer >= 0 and healer >= 0: | |
#successes += 1 | |
#print(earths-3, fires-2, winds-1, nopon-1, ancient-1, keeneye-1, leaping-1, nonhealer-1) | |
#exit() | |
if len(blades_iter) is 0: | |
successes += 1 | |
print("%d of the DLC blade pulls were successful" % successes) | |
for blade in blades: | |
print("Blade %s was pulled %d%% of the time" % (blade.getName(), blade.pullCount() * 100 / num_iters)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment