wynnbuilder-forked-for-changes/testing/1.20_manasteal/ms_simulator.py
hppeng-wynn d9e5d6da95
Updating to wynn 2.0.2.3 (except item database...)
* Fix enraged blow typo; allow "or" and "and" in adv search

...forgot to update json

* Lacerate is blocked by Echo, not Mirror Image

* Misc bugfix

Fix bug with skillpoints and negative set bonus
Add final multiplier for echo

* Clean up testing folder

and add script for quick plotting pairs of ids/item values

* Fix typo in better lightweaver

add to the correct dps

* Partial update to 2.0.2.3 (festival of heroes)

patch:
- ing changes (manual)
- two endgame items (the ones that I got customs for)

bugfix:
- Fix bug in reverse mapping that mapped item "type" to "accessoryType"

* Forgot to commit all the 2.0.2.3 data files...

* Fix epilogue displayName

* Fix minor incorrectness with fromIntV invocation

don't think this was a bug? but its not the correct number of arguments lol

* Move powder ingreds to ing load sequence

not used anywhere else
also, remove extra prints in crafter

* Refactor powder special display

fix quake/chain/courage not displaying some powder special information 💀

* Finally fix satsujin to work with powder specials

thanks to powder special display refactor

* Fix mask of the awakened giving outdated stats

e

* Add prologue and gleeman's tale

wynn api when
...fix epilgoue

---------

Co-authored-by: hppeng <hppeng>
2023-04-14 17:18:52 -07:00

139 lines
4.6 KiB
Python

theorySpeeds = [4.3, 3.1, 2.5, 2.05, 1.5, 0.83, 0.51]
realSpeeds = [] # TODO
atkSpd = 6
#spellCycle = [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 2, 2]
#spellDelay = [0.5, 0, 0.5, 0.5, 0, 0.5, 0.5, 0, 0.5, 0.5, 0, 0.5, 0.5, 0, 0.5, 0.5, 0, 0.5, 1, 0.5]
spellCycle = [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2]
spellDelay = [0.5, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 0.5]
#spellCycle = [-1, 1, 0, 2, 1, 1]
#spellDelay = [0.4312345, 0, 0.4, 0.4, 0.4, 0.4]
#spellCycle = [9, 0, 9, 0, 10, 0, 0]
#spellDelay = [0, 1.4, 0, 1.4, 0, 1.3, 1.3]
#delayCycle = [1.2, 0, 0.4, 0.4, 0.4, 0.4]
#spellCycle = spellCycle*8
#spellDelay = spellDelay*4 + delayCycle + spellDelay*2 + delayCycle
simulation_end = 100
#manaRegens = [5, 0, 15]
#manaSteals = [9, 13, 0]
manaRegens = [0, 0]
manaSteals = [8, 11]
import random
import math
import statistics
def simulate(manaRegen, manaSteal, spellCycle, spellDelay, simulation_end, atkSpd):
realSpeed = theorySpeeds[atkSpd]
realDt = 1/realSpeed
print(realDt)
stealChance = (1/realSpeed) / 3
lastAttackTime = 0
lastManaTime = -random.random()
lastMRTime = lastManaTime + random.randint(-4, 0)
currentTime = 0
currentMana = 20
times = [0]
manas = [20]
colors = [0]
numSpells = len(spellCycle)
currentSpell = 0
mrDisabled = False
failedCasts = 0
lost_mana = 0
while currentTime < simulation_end:
spellCost = spellCycle[currentSpell]
spellTime = spellDelay[currentSpell]
currentTime += spellTime
if currentTime >= lastManaTime + 1:
mana_gained = math.floor(currentTime - lastManaTime)
if not mrDisabled:
currentMana = min(20, currentMana + mana_gained)
else:
currentMana = max(0, currentMana - mana_gained)
lastManaTime += mana_gained
if currentTime >= lastMRTime + 5:
mr_proc = math.floor((currentTime - lastMRTime) / 5)
if not mrDisabled:
mana_nocap = currentMana + mr_proc * manaRegen
currentMana = min(20, mana_nocap)
lost_mana += mana_nocap - currentMana
else:
lostMana += mr_proc * manaRegen
lastMRTime += 5 * mr_proc
times.append(currentTime)
manas.append(currentMana)
if spellCost < 0:
mrDisabled = True
spellCost *= -1
else:
mrDisabled = False
if spellCost == 0:
if currentTime - lastAttackTime > realDt:
lastAttackTime = currentTime
#currentMana = min(20, currentMana + manaSteal * stealChance)
if random.random() < stealChance:
mana_nocap = currentMana + manaSteal
currentMana = min(20, mana_nocap)
lost_mana += mana_nocap - currentMana
colors.append(0)
elif currentMana > spellCost:
currentMana -= spellCost
colors.append(0)
else:
failedCasts += 1
colors.append(1)
currentSpell = (currentSpell + 1) % numSpells
return ((times, manas, colors), failedCasts, lost_mana)
plot = True
seeds = list(range(1000))
results = []
results2 = []
import matplotlib.pyplot as plt
for (manaRegen, manaSteal) in zip(manaRegens, manaSteals):
result = []
result2 = []
for seed in seeds:
random.seed(seed)
((times, manas, colors), failedCasts, lost_mana) = simulate(manaRegen, manaSteal, spellCycle, spellDelay, simulation_end, atkSpd)
result.append(failedCasts)
result2.append(lost_mana)
print(f"({manaRegen}+{manaSteal}) Failed {failedCasts} casts!")
if seed == 0:
plt.figure()
plt.scatter(times, manas, c=colors)
plt.xlabel("Time (seconds)")
plt.ylabel("Mana")
plt.title(f"Mana steal simulation ({manaRegen} mr {manaSteal} ms)")
results.append(result)
results2.append(result2)
print("----------------")
averages = [statistics.mean(result) for result in results]
maxs = [min(result) for result in results]
mins = [max(result) for result in results]
averages2 = [statistics.mean(result) for result in results2]
maxs2 = [min(result) for result in results2]
mins2 = [max(result) for result in results2]
for (manaRegen, manaSteal, failedCasts, maxk, mink, lostMana, minl, maxl) in zip(manaRegens, manaSteals, averages, mins, maxs, averages2, mins2, maxs2):
print(f"({manaRegen}+{manaSteal}) on average failed {failedCasts} casts (max {maxk} min {mink}) and lost {lostMana} mana (max {maxl} min {minl})")
plt.show()