Skip to content

Instantly share code, notes, and snippets.

@dmdavis
Created April 3, 2013 19:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmdavis/5304474 to your computer and use it in GitHub Desktop.
Save dmdavis/5304474 to your computer and use it in GitHub Desktop.
Functions for calculating Savage Worlds dice probabilities.
#!/usr/bin/env python
# encoding: utf-8
"""
swdiceprob.py
Functions for calculating Savage Worlds dice probabilities.
Copyright (c) 2012-2013 Dale Davis. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
__author__ = "Dale Davis"
__copyright__ = "Copyright (c) 2012-2013 Dale Davis. All rights reserved."
__license__ = "BSD-2-Clause"
__version_info__ = (1, 0)
__version__ = '.'.join([str(v) for v in __version_info__])
import sys
from fractions import Fraction
def exploding(target, sides):
"""Calculate the probability (as a rational number) of hitting a `target`
number with an exploding dice with the given number of `sides`.
:param target: The target number the roll is attempting
:type target: int
:param sides: The number of sides on the dice used
:type sides: int
:rtype : `fraction.Fraction`
"""
exact, remainder = divmod(target, sides)
exact_roll_prob = Fraction(1, pow(sides, exact)) # 1/n + 1/n + ...
last_roll_prob = Fraction(sides - (max(remainder, 1) - 1), sides)
return exact_roll_prob * last_roll_prob
def wild(target, sides, wild=6):
"""Calculate the probability (as a rational number) of hitting a `target`
number with an exploding die with the given number of `sides` and an
exploding wild die with `wild` sides (default: 6) .
:param target: The target number the roll is attempting
:type target: int
:param sides: The number of sides on the dice used
:type sides: int
:param wild: The number of sides on the wild die (default: 6)
:type wild: int
:rtype : `fraction.Fraction`
"""
a = exploding(target, sides)
b = exploding(target, wild)
return a + b - (a * b)
def print_dice_probabilities(targets, dice, calcprob, title=None):
"""Print a tab-delimited table of `dice` probabilities to hit a list of
`targets`.
:param targets: A list of target numbers
:type targets: list of ints
:param dice: A list of dice to calculate probabilities for
:type dice: list of ints
:param calcprob: A callable that takes target and die as args
:type calcprob: callable (either `exploding` or `wild`)
:param title: A text title to print before the chart (default: `None`)
:type title: str or None
"""
if title is not None:
print(title)
print('\t'.join(['Target'] + ['d' + str(d) for d in dice]))
for t in targets:
print('\t'.join([str(t)] + [str(float(calcprob(t, d))) for d in dice]))
def main(): # pragma: no cover
"""
Main method for dice.py
"""
targets = range(1, 21)
dice = [4, 6, 8, 10, 12]
print_dice_probabilities(targets, dice, exploding, 'Exploding Die')
print_dice_probabilities(targets, dice, wild, 'Wild Die')
return 0
if __name__ == '__main__': # pragma: no cover
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment