Skip to content

Instantly share code, notes, and snippets.

@cltnschlosser
Forked from caccavale/dumb_sim.py
Last active March 29, 2021 06:21
Show Gist options
  • Save cltnschlosser/e3b792cbeb10ae54107c1c72e1536be9 to your computer and use it in GitHub Desktop.
Save cltnschlosser/e3b792cbeb10ae54107c1c72e1536be9 to your computer and use it in GitHub Desktop.
from itertools import product
from typing import Dict, Tuple
import sys
melee_as = 3.9
ranged_as = 2.9
ranged_haste = 1.15 * 1.2
auto_damage, steady_damage, raptor_damage, attack_damage = 1463, 1457, 1432, 1207
_ranged_cd = (ranged_as - .5) / ranged_haste
i_cast_time = 0
i_cooldown = 1
i_damage = 2
i_shared_cd = 3
i_gcd = 4
# skill, cast_time, cooldown, damage, relies on CD, gcd
actions : Dict[str, Tuple[float, int, int, str, bool]] = {
"attack": (.4, melee_as, attack_damage, "", False),
"raptor": (.4, 6, raptor_damage, "attack", False),
"auto": (.5 / ranged_haste, _ranged_cd, auto_damage, "", False),
"steady": (1.5 / ranged_haste, 0, steady_damage, "", True),
"multi": (0.5 / ranged_haste, 10, steady_damage + 170,"", True),
"arcane": (0, 6, 900, "", True),
}
# Commenting out skills above can help runtime quite a bit
index_of = dict(zip(actions.keys(), range(len(actions))))
GCD_SLOT = len(actions)
def update_cooldowns(cooldowns, time_before_action, action_name):
wait_time = max(cooldowns[index_of[action_name]] - time_before_action, 0)
if depends_on := actions[action_name][i_shared_cd]:
wait_time = max(wait_time, cooldowns[index_of[depends_on]] - time_before_action)
if uses_gcd := actions[action_name][i_gcd]:
wait_time = max(wait_time, cooldowns[GCD_SLOT] - time_before_action)
# print(f'{action_name}: {wait_time}')
cast_time = actions[action_name][i_cast_time]
time_spent = time_before_action + cast_time + wait_time
cooldowns = [max(cd - time_spent, 0) for cd in cooldowns]
cooldowns[index_of[action_name]] = actions[action_name][i_cooldown]
if depends_on:
cooldowns[index_of[depends_on]] = actions[depends_on][i_cooldown]
if uses_gcd:
cooldowns[GCD_SLOT] = max(0, 1.5 - cast_time)
return time_spent, cooldowns
input_lag = 0 # BRRTTTT
def solve_sequence(sequence):
total_damage = 0
total_time = 0
cooldowns_remaining = [0] * (len(actions) + 1)
earliest_cast = [float("inf")] * (len(actions) + 1)
for action_name, values in sequence:
cast_time, cooldown, damage, shared_cd, uses_gcd = values
if earliest_cast[index_of[action_name]] == float("inf"):
earliest_cast[index_of[action_name]] = total_time
if shared_cd and earliest_cast[index_of[shared_cd]] == float("inf"):
earliest_cast[index_of[shared_cd]] = total_time
if uses_gcd and earliest_cast[GCD_SLOT] == float("inf"):
earliest_cast[GCD_SLOT] = total_time
time_before_action = input_lag # for the action
time_spent, cooldowns_remaining = update_cooldowns(cooldowns_remaining, time_before_action, action_name)
total_damage += damage
total_time += time_spent
wait_before_repeating = input_lag + max(max(cdr - earliest, 0) for earliest, cdr in zip(earliest_cast, cooldowns_remaining))
# print(f'repeating_wait: {wait_before_repeating}')
# print()
# for i in range(len(cooldowns_remaining) - 1):
# print(f'{list(actions.keys())[i]}: {cooldowns_remaining[i]}')
total_damage = total_damage
total_time = total_time + wait_before_repeating
return total_damage, total_time
# Sequence checker, run with action names as arguments.
# Ex: python3 dumb_sim.py auto steady attack auto steady auto steady
if len(sys.argv) > 1:
sequence = [(name, actions[name]) for name in sys.argv[1:]]
total_damage, total_time = solve_sequence(sequence)
dps = total_damage / total_time
print(dps)
print((total_damage, total_time, tuple(action for action, *_ in sequence)))
sys.exit(0)
best_dps = 0
best_sequence = (0, 10, ())
for sequence_length in range(5, 11):
print(f"Solving for length {sequence_length}...")
for sequence in product(actions.items(), repeat=sequence_length):
total_damage, total_time = solve_sequence(sequence)
if total_damage / total_time > best_dps:
best_dps = total_damage / total_time
best_sequence = (total_damage, total_time, tuple(action for action, *_ in sequence))
print(f'New best: {best_sequence}')
print(best_dps)
print(best_sequence)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment