-
-
Save NQNStudios/934c47271dc098648f69 to your computer and use it in GitHub Desktop.
A simple dice roller written in Python.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /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