Skip to content

Instantly share code, notes, and snippets.

@jasonrobot
Last active May 11, 2020 05:45
Show Gist options
  • Save jasonrobot/7ca5dde1981368fac5ad8c0895eecc7b to your computer and use it in GitHub Desktop.
Save jasonrobot/7ca5dde1981368fac5ad8c0895eecc7b to your computer and use it in GitHub Desktop.
average damage given stat scores 1-20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
scorching ray: 20.00 21.00 21.00 20.00 20.00 19.00 18.00 17.00 17.00 15.00 14.00 13.00 12.00 11.00 10.00 9.00 8.00 7.00 6.00 5.00
shatter: 12.58 12.52 12.57 12.07 12.28 11.69 11.73 11.40 11.23 11.20 11.13 10.86 10.87 10.32 10.72 10.28 10.23 9.92 9.95 9.52
dragon breath: 10.07 9.74 9.72 9.55 9.23 9.15 9.17 8.97 8.87 8.66 8.80 8.27 8.47 7.99 8.00 7.84 7.96 7.51 7.62 7.32
guard: Level 3, AC: 16
STR: ?, DEX: 12, CON: 12, INT: ?, WIS: ?, CHA: ?
scorching ray: 9
shatter: 11.0055
dragon breath: 8.2775
magic missile: 10
fire_bolt: 2
dragonclaw: Level 3, AC: 14
STR: ?, DEX: 16, CON: 13, INT: ?, WIS: ?, CHA: ?
scorching ray: 12
shatter: 10.8835
dragon breath: 7.926
magic missile: 10
fire_bolt: 2
kobold: Level 3, AC: 12
STR: ?, DEX: 15, CON: 9, INT: ?, WIS: ?, CHA: ?
scorching ray: 13
shatter: 11.4435
dragon breath: 7.9805
magic missile: 10
fire_bolt: 3
cultist: Level 3, AC: 12
STR: ?, DEX: 12, CON: 10, INT: ?, WIS: ?, CHA: ?
scorching ray: 13
shatter: 11.114
dragon breath: 8.4455
magic missile: 10
fire_bolt: 3
def roll(n, d = nil)
if d.nil?
d = n
n = 1
end
Array.new(n){rand(d) + 1}.reduce(:+)
end
def check(skill)
if roll(20) > 13 then 0.5 else 1 end
end
def ability_modifier(attr)
case attr
when 1
-5
when 2, 3
-4
when 4, 5
-3
when 6, 7
-2
when 8, 9
-1
when 10, 11
0
when 12, 13
1
when 14, 15
2
when 16, 17
3
when 18, 19
4
when 20, 21
5
end
end
def average(times, &block)
Array.new(times, &block).reduce(:+) / times
end
class Character
def initialize(level, ac, abilities)
@level = level
@ac = ac
@abilities = abilities
end
def to_s
sprintf(
"Level %d, AC: %d\nSTR: %s, DEX: %s, CON: %s, INT: %s, WIS: %s, CHA: %s",
@level,
@ac,
@abilities[:str] || '?',
@abilities[:dex] || '?',
@abilities[:con] || '?',
@abilities[:int] || '?',
@abilities[:wis] || '?',
@abilities[:cha] || '?',
)
end
def ac() @ac end
def proficiency_bonus()
case @level
when 1..4
2
when 5..8
3
when 9..12
4
when 13..16
5
when 17..20
6
end
end
def ability_check(ability_type, dc)
(roll(20) + ability_modifier(@abilities[ability_type])) > dc
end
def attack_roll(target)
roll(20) > target.ac
end
end
class Wizard < Character
def spell_save_dc()
ability_modifier(@abilities[:int]) + proficiency_bonus + 8
end
def attack_roll(target)
(roll(20) + ability_modifier(@abilities[:int]) + proficiency_bonus) > target.ac
end
def scorching_ray(target)
Array.new(3) do
if attack_roll(target)
roll(2, 6)
else
0
end
end.reduce(:+)
end
def shatter(target)
damage = if target.ability_check(:con, spell_save_dc) then
0.5
else
1
end
roll(3, 8) * damage
end
def dragon_breath(target)
damage = if target.ability_check(:dex, spell_save_dc) then
0.5
else
1
end
roll(3, 6) * damage
end
def magic_missile(target)
Array.new(3) do
roll(4) + 1
end.reduce(:+)
end
def fire_bolt(target)
if attack_roll(target)
roll(10)
else
0
end
end
end
me = Wizard.new(
3,
11,
{int: 17}
)
scorching_ray = []
shatter = []
dragon_breath = []
for i in 1..20
target = Character.new(3, i, {con: i, dex: i})
scorching_ray.push Array.new(1000){me.scorching_ray(target)}.reduce(:+) / 1000
shatter.push Array.new(1000){me.shatter(target)}.reduce(:+) / 1000
dragon_breath.push Array.new(1000){me.dragon_breath(target)}.reduce(:+) / 1000
end
puts "average damage given stat scores 1-20"
printf ["\t"].concat((1..20).to_a.map{|x| "\t#{x}"}).push("\n").reduce(:concat)
printf "scorching ray:\t"
scorching_ray.each{|x| printf "%2.2f\t", x}
puts
printf "shatter:\t"
shatter.map{|x| printf "%2.2f\t", x}
puts
printf "dragon breath:\t"
dragon_breath.map{|x| printf "%2.2f\t", x}
puts
puts
targets = {
'guard' => Character.new(3, 16, {con: 12, dex: 12}),
'dragonclaw' => Character.new(3, 14, {con: 13, dex: 16}),
'kobold' => Character.new(3, 12, {con: 9, dex: 15}),
'cultist' => Character.new(3, 12, {con: 10, dex: 12})
}
targets.each do |name, char|
puts "#{name}: #{char.to_s}"
printf "scorching ray: %s\n", average(1000){me.scorching_ray(char)}
printf "shatter: %s\n", average(1000){me.shatter(char)}
printf "dragon breath: %s\n", average(1000){me.dragon_breath(char)}
printf "magic missile: %s\n", average(1000){me.magic_missile(char)}
printf "fire_bolt: %s\n", average(1000){me.fire_bolt(char)}
puts
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment