Skip to content

Instantly share code, notes, and snippets.

@korny
Created January 6, 2014 02:38
Show Gist options
  • Save korny/8277377 to your computer and use it in GitHub Desktop.
Save korny/8277377 to your computer and use it in GitHub Desktop.
A helper script for Shadowrun dice calculations, especially the probability of Glitches. Includes Shadowrun 5 rules. This is public domain.
module Math
class << self
def fac n
return 1 if n < 2
(1..n).inject { |prod, i| prod * i }
end
def choose n, k
fac(n) / (fac(n-k) * fac(k))
end
end
end
class Dice
module Random
def self.hit?
rand(6) + 1 >= 5
end
def self.roll n
hits = 0
n.times { hits += 1 if hit? }
hits
end
end
CHANCE_PER_SIDE = 1.0 / 6
CHANCE_TO_HIT = 2 * CHANCE_PER_SIDE
CHANCE_TO_MISS = 1 - CHANCE_TO_HIT
def self.hits_expected n
n * CHANCE_TO_HIT
end
def self.chance_for_hits n, hits
misses = n - hits
(CHANCE_TO_MISS ** misses) * (CHANCE_TO_HIT ** hits) * Math.choose(n, hits)
end
def self.chance_to_win n, threshold = 1
(threshold..n).inject(0) do |sum, i|
sum + chance_for_hits(n, i)
end
end
CHANCE_FOR_ONE = 1 * CHANCE_PER_SIDE
def self.chance_for_ones n, ones
not_ones = n - ones
((1 - CHANCE_FOR_ONE) ** not_ones) * (CHANCE_FOR_ONE ** ones) * Math.choose(n, ones)
end
CHANCE_TO_GLITCH_ON_MISS = 1.0 / 4
def self.chance_for_ones_when_miss n, ones
not_ones = n - ones
((1 - CHANCE_TO_GLITCH_ON_MISS) ** not_ones) * (CHANCE_TO_GLITCH_ON_MISS ** ones) * Math.choose(n, ones)
end
def self.chance_to_glitch n, critical = false
min_ones = (n / 2.0).ceil
if critical
chance_for_hits(n, 0) *
(min_ones..n).map do |ones|
chance_for_ones_when_miss(n, ones)
end.reduce(:+)
else
(min_ones..n).map do |ones|
chance_for_ones(n, ones)
end.reduce(:+)
end
end
def self.chance_to_glitch_sr5 n, critical = false
min_ones = (n / 2.0).floor + 1
if critical
chance_for_hits(n, 0) *
(min_ones..n).map do |ones|
chance_for_ones_when_miss(n, ones)
end.reduce(:+)
else
(min_ones..n).map do |ones|
chance_for_ones(n, ones)
end.reduce(:+)
end
end
end
for i in 1..20
p 100 * Dice.chance_to_glitch_sr5(i, true)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment