Tartarus Sorceror
Posts: 1774
Joined: Tuesday, 23rd December 2014, 23:39
Tables of damage reduction from ac and ev
From my limited testing in fsim, my numbers seem pretty close. They aren't spot on so I probably have an off by one error somewhere, but they seem close enough to be useful.
Caveats: use only with enemies who don't wield weapons, and who attack at normal speed.
To test my numbers for yourself if you don't believe them, what you do is first set up a character with AC and EV the same as in the table entry. Then, run fsim against the enemy and note the AvDam. Sum up the monster's attack damages (for a death yak, the sum is 30), then divide by 2, and then divide by my table entry, and the result should be within 0.5 of AvDam. If it's not let me know! Or also let me know if you see a bug in my code.
Against a death yak with GDR 0:
- Code:
>>> crawl.ev_ac_table(1,35,2,1,40,2,0,crawl.deathyak)
ac\ev 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
1 1.07 1.12 1.18 1.25 1.33 1.41 1.51 1.62 1.75 1.91 2.09 2.31 2.56 2.84 3.15 3.49 3.86 4.26 4.69 5.14
3 1.14 1.20 1.26 1.34 1.42 1.51 1.61 1.74 1.88 2.04 2.24 2.47 2.73 3.03 3.37 3.73 4.13 4.56 5.01 5.49
5 1.22 1.28 1.35 1.43 1.52 1.62 1.73 1.86 2.01 2.18 2.39 2.64 2.93 3.25 3.60 3.99 4.42 4.88 5.37 5.88
7 1.31 1.37 1.45 1.53 1.63 1.73 1.85 1.99 2.15 2.34 2.56 2.83 3.14 3.48 3.86 4.28 4.74 5.23 5.75 6.30
9 1.40 1.48 1.56 1.64 1.75 1.86 1.99 2.14 2.31 2.51 2.75 3.04 3.37 3.73 4.14 4.59 5.08 5.61 6.17 6.76
11 1.51 1.59 1.67 1.77 1.87 2.00 2.14 2.29 2.48 2.70 2.96 3.26 3.62 4.01 4.45 4.93 5.46 6.03 6.63 7.27
13 1.62 1.70 1.80 1.90 2.02 2.15 2.30 2.47 2.67 2.90 3.18 3.51 3.89 4.31 4.79 5.31 5.87 6.48 7.13 7.81
15 1.74 1.83 1.93 2.05 2.17 2.31 2.47 2.66 2.87 3.12 3.42 3.78 4.18 4.64 5.15 5.71 6.32 6.98 7.68 8.41
17 1.88 1.98 2.08 2.20 2.34 2.49 2.66 2.86 3.09 3.36 3.69 4.07 4.51 5.00 5.55 6.15 6.81 7.51 8.27 9.06
19 2.02 2.13 2.24 2.37 2.52 2.68 2.87 3.08 3.33 3.62 3.97 4.38 4.86 5.39 5.98 6.63 7.33 8.09 8.91 9.76
21 2.18 2.29 2.42 2.56 2.71 2.89 3.09 3.32 3.59 3.90 4.28 4.72 5.23 5.80 6.44 7.14 7.90 8.72 9.59 10.51
23 2.35 2.47 2.60 2.75 2.92 3.11 3.33 3.57 3.86 4.20 4.61 5.08 5.63 6.25 6.93 7.69 8.51 9.39 10.33 11.32
25 2.53 2.66 2.80 2.96 3.14 3.35 3.58 3.84 4.15 4.52 4.95 5.47 6.06 6.72 7.46 8.27 9.15 10.10 11.11 12.17
27 2.71 2.85 3.01 3.18 3.37 3.59 3.84 4.13 4.46 4.85 5.32 5.87 6.50 7.21 8.00 8.87 9.82 10.84 11.92 13.07
29 2.90 3.05 3.22 3.40 3.61 3.84 4.11 4.42 4.77 5.19 5.69 6.28 6.96 7.72 8.57 9.50 10.51 11.60 12.77 13.99
31 3.10 3.26 3.43 3.63 3.85 4.10 4.39 4.71 5.09 5.54 6.07 6.70 7.42 8.24 9.14 10.13 11.21 12.38 13.62 14.92
33 3.29 3.46 3.65 3.86 4.09 4.36 4.66 5.01 5.41 5.89 6.45 7.12 7.89 8.75 9.71 10.77 11.91 13.15 14.47 15.86
35 3.48 3.66 3.86 4.08 4.33 4.61 4.93 5.30 5.73 6.23 6.83 7.54 8.35 9.27 10.28 11.40 12.62 13.92 15.32 16.79
Against a death yak with GDR 0.34 (chain mail or fire dragon armor):
- Code:
>>> crawl.ev_ac_table(1,35,2,1,40,2,0.34,crawl.deathyak)
ac\ev 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39
1 1.07 1.12 1.18 1.25 1.33 1.41 1.51 1.62 1.75 1.91 2.09 2.31 2.56 2.84 3.15 3.49 3.86 4.26 4.69 5.14
3 1.16 1.22 1.29 1.36 1.44 1.54 1.64 1.77 1.91 2.08 2.28 2.51 2.78 3.09 3.43 3.80 4.20 4.64 5.10 5.59
5 1.27 1.33 1.40 1.49 1.58 1.68 1.80 1.93 2.08 2.27 2.49 2.74 3.04 3.37 3.74 4.15 4.59 5.07 5.57 6.11
7 1.39 1.46 1.54 1.63 1.73 1.84 1.97 2.11 2.28 2.49 2.72 3.01 3.33 3.70 4.10 4.55 5.03 5.55 6.11 6.69
9 1.53 1.61 1.69 1.79 1.90 2.02 2.16 2.33 2.51 2.73 3.00 3.31 3.67 4.07 4.51 5.00 5.54 6.11 6.72 7.37
11 1.69 1.78 1.87 1.98 2.10 2.24 2.39 2.57 2.78 3.02 3.31 3.66 4.05 4.49 4.99 5.53 6.12 6.75 7.43 8.14
13 1.87 1.97 2.08 2.20 2.33 2.48 2.66 2.85 3.08 3.35 3.68 4.06 4.50 4.99 5.53 6.14 6.79 7.49 8.24 9.04
15 2.09 2.20 2.32 2.45 2.60 2.77 2.96 3.18 3.44 3.74 4.10 4.53 5.01 5.56 6.17 6.84 7.57 8.36 9.20 10.08
17 2.34 2.47 2.60 2.75 2.92 3.11 3.32 3.57 3.86 4.20 4.60 5.08 5.62 6.24 6.92 7.67 8.49 9.37 10.31 11.30
19 2.64 2.78 2.93 3.10 3.29 3.50 3.75 4.02 4.35 4.73 5.19 5.72 6.34 7.04 7.81 8.65 9.58 10.57 11.63 12.74
21 3.00 3.15 3.32 3.52 3.73 3.97 4.25 4.57 4.93 5.37 5.88 6.49 7.19 7.98 8.86 9.82 10.86 11.99 13.19 14.46
23 3.21 3.38 3.56 3.77 4.00 4.26 4.55 4.89 5.29 5.75 6.30 6.96 7.71 8.55 9.49 10.52 11.64 12.85 14.13 15.49
25 3.45 3.62 3.82 4.04 4.29 4.57 4.88 5.25 5.67 6.17 6.76 7.46 8.27 9.17 10.18 11.28 12.48 13.78 15.16 16.61
27 3.70 3.89 4.10 4.33 4.60 4.89 5.23 5.63 6.08 6.61 7.25 8.00 8.86 9.83 10.91 12.10 13.38 14.77 16.25 17.81
29 3.95 4.16 4.38 4.64 4.92 5.24 5.60 6.02 6.51 7.08 7.76 8.56 9.49 10.52 11.68 12.95 14.32 15.81 17.40 19.06
31 4.22 4.44 4.68 4.95 5.25 5.59 5.98 6.42 6.94 7.55 8.27 9.13 10.12 11.23 12.46 13.81 15.28 16.87 18.56 20.33
33 4.48 4.71 4.97 5.25 5.58 5.94 6.35 6.82 7.37 8.02 8.79 9.70 10.75 11.93 13.23 14.67 16.23 17.92 19.72 21.61
35 4.75 4.99 5.26 5.56 5.90 6.29 6.72 7.22 7.81 8.49 9.31 10.27 11.38 12.63 14.01 15.53 17.19 18.97 20.87 22.88
And here's my Python source code
- Code:
# calculates the average factor by which incoming dmg is reduced by AC
def ACReduction(ac, dam, gdr = 0):
totreduction = 0
gdr_amt = int(gdr * dam)
if gdr_amt > ac / 2:
gdr_amt = ac / 2
totdam = 0
for roll1 in xrange(dam + 1): # damage roll
for roll2 in xrange(ac + 1): # ac roll
if roll2 < gdr_amt:
roll2 = gdr_amt
if roll2 > roll1:
roll2 = roll1
totreduction += roll2
totdam += roll1
if totreduction == totdam:
return float("inf") # 100% damage reduction, infinite reduction factor
return float(totdam) / (totdam - totreduction)
# calculates the average factor by which incoming dmg is reduced by EV
# provide _either_ hitdice and fighter, _or_ tohit, but not both
def EVReduction(ev, hitdice = 0, fighter = False, tohit = None):
if tohit == None:
tohit = 18
if fighter:
tohit += int(25 * hitdice / 10)
else:
tohit += int(15 * hitdice / 10)
totreduction = 0
totdam = 0
for roll1 in xrange(tohit + 1):
for roll2 in xrange(2 * ev):
for roll3 in xrange(2 * ev):
if roll1 < (roll2 + roll3) / 2:
totreduction += 1 # 1 damage dodged
totdam += 1
# normalize to 1.0 totdam and acct for the fact the preceding calculation only applied to 95% of cases
totreduction = 0.95 * (float(totreduction) / totdam)
# now account for 2.5% automatic hits and 2.5% automatic misses
return 1.00 / (1.00 - (totreduction + 0.025))
# monsters
# dam, hitdice, fighter
hydra = [18, 13, False]
deeptroll = [[27, 20, 20], 10, False]
direelephant = [[40, 15], 15, False]
deathyak = [30, 14, False]
import sys
def ev_ac_table(fromAC, toAC, stepAC, fromEV, toEV, stepEV, gdr, monster, ofile = None):
dam, hitdice, fighter = monster
colwidth = 6
sys.stdout.write("ac\ev".ljust(colwidth))
for ev in xrange(fromEV, toEV+1, stepEV):
sys.stdout.write(str(ev).ljust(colwidth))
sys.stdout.write("\n")
for ac in xrange(fromAC, toAC+1, stepAC):
sys.stdout.write(str(ac).ljust(colwidth))
for ev in xrange(fromEV, toEV+1, stepEV):
acreduc = 0
if ac == 0:
pass
elif type(dam) == list:
treduc = 0
for d in dam:
treduc += d - (float(d) / ACReduction(ac, d, gdr))
acreduc = sum(dam) / (sum(dam) - treduc)
else:
acreduc = ACReduction(ac, dam, gdr)
# in case of multiple damages
sys.stdout.write(("%.2f" % (acreduc * EVReduction(ev, hitdice, fighter))).ljust(colwidth))
sys.stdout.write("\n")
sys.stdout.write("\n")
I'll take a few requests if you want to see some specific GDR and enemy, or some specific AC/EV range.
251 total wins Berder hyperborean + misc
83/108 recent wins (76%)
guides: safe tactics value of ac/ev/sh forum toxicity
- For this message the author Berder has received thanks:
- rockygargoyle