Skip to content

Instantly share code, notes, and snippets.

@NQNStudios
Last active August 29, 2015 14:13
Show Gist options
  • Save NQNStudios/934c47271dc098648f69 to your computer and use it in GitHub Desktop.
Save NQNStudios/934c47271dc098648f69 to your computer and use it in GitHub Desktop.
A simple dice roller written in Python.
#! /usr/bin/env python3
import re
import random
import unittest
exit_commands = ( "quit", "exit", "stop" )
modifier_pattern = """
\s* # white space allowed between dice expression and modifier
[+-] # plus or minus
\s* # white space allowed after +/-
[1-9] # first digit of modifier (required, >0)
[0-9]* # following digits of modifier (optional)
"""
dice_expression_pattern = """
^ # beginning of string
[0-9]* # number of dice to roll (optional)
d # the letter 'd'
[1-9] # first digit of number of dice sides (required, >0)
[0-9]* # following digits of dice sides (optional)
( # beginning of optional modifier subpattern
""" + modifier_pattern + """
)? # end of optional modifier subpattern
$ # end of string
"""
num_sides_pattern = """
d # the number will be immediately following 'd'
[1-9] # first digit of number of sides (required, >0)
[0-9]* # following digits of number of sides
"""
def validate_input(str):
return re.search(dice_expression_pattern, str, re.VERBOSE)
def roll_dice(dice_expression):
d_index = dice_expression.find('d')
# extract dice number
num_dice = 1 # assume one die if number is omitted
if d_index != 0:
num_dice = int(dice_expression[0:d_index])
# extract number of sides
num_sides_expression = re.search(num_sides_pattern, dice_expression, re.VERBOSE).group(0)
num_sides = int(num_sides_expression[1:])
# extract modifier
modifier = 0 # assume 0 modifier if none specified
modifier_match = re.search(modifier_pattern, dice_expression, re.VERBOSE)
if modifier_match:
modifier_expression = modifier_match.group(0)
modifier_str = re.search("[1-9][0-9]*$", modifier_expression).group(0)
modifier = int(modifier_str)
# check for negative modifier
if modifier_expression.find('-') >= 0:
modifier *= -1
roll_sum = modifier
for num in range(num_dice):
roll_sum += random.randint(1, num_sides)
output = 'You rolled: {0}'.format(roll_sum)
print(output)
if __name__ == "__main__":
str = ""
while True:
str = input('Roll dice --> ')
if exit_commands.count(str):
break
elif validate_input(str):
roll_dice(str)
else:
print('"' + str + '" is not a valid dice expression.')
# unittest.main() # run test cases
class Test(unittest.TestCase):
def test(self):
fail_strings = (
"Hello, world!",
"d",
"d0",
"d + 1"
)
pass_strings = (
"0d1",
"d6",
"1d6",
"8d6",
"d6+1",
"1d6+1",
"d5 +1",
"d6 + 9",
"9d6 + 2"
)
for fail_string in fail_strings:
self.assertFalse(validate_input(fail_string),
'Test failed because string "' + fail_string + '" passed validation.')
for pass_string in pass_strings:
self.assertTrue(validate_input(pass_string),
'Test failed because string "' + pass_string + '" failed validation.')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment