```
# dice_roller.py
# This program simulates dice rolls using dice roll notation,
# it is widely used in tabletop RPGs like D&D, Pathfinder etc.
# by: Scott Gordon
import random
import sys
print('***** Welcome to Dice Roller *****')
print('''Enter what kind and how many dice to roll. For example:
3d20, will roll 3 20 sided dice.
2d8+1, rolls 2 8 sided dice +1 modifier
Type QUIT to leave Dice Roller.''')
while True:
try:
dice_str = input('> ')
if dice_str.upper() == 'QUIT':
print('Thanks for playing!')
sys.exit()
dice_str = dice_str.lower().replace(' ', '')
d_index = dice_str.find('d')
if d_index == -1:
raise Exception('Missing the "d" character.')
number_of_dice = dice_str[:d_index]
if not number_of_dice.isdecimal():
raise Exception('Missing the number of dice.')
number_of_dice = int(number_of_dice)
mod_index = dice_str.find('+')
if mod_index == -1:
mod_index = dice_str.find('-')
if mod_index == -1:
number_of_sides = dice_str[d_index + 1:]
else:
number_of_sides = dice_str[d_index + 1: mod_index]
if not number_of_sides.isdecimal():
raise Exception('Missing the number of sides.')
number_of_sides = int(number_of_sides)
if mod_index == -1:
mod_amount = 0
else:
mod_amount = int(dice_str[mod_index + 1:])
if dice_str[mod_index] == '-':
mod_amount = -mod_amount
# Simulate dice rolls:
rolls = []
for i in range(number_of_dice):
roll_result = random.randint(1, number_of_sides)
rolls.append(roll_result)
print('Total:', sum(rolls) + mod_amount, '(Each die:', end='')
for i, roll in enumerate(rolls):
rolls[i] = str(roll)
print(', '.join(rolls), end='')
if mod_amount != 0:
mod_sign = dice_str[mod_index]
print(f', {mod_sign}{abs(mod_amount)}', end='')
print(')')
except Exception as exc:
print('Invalid input. Enter something like "3d6" or "1d10+2".')
print(f'Input was invalide because: {str(exc)}')
continue
```

Photo by Lucas Santos on Unsplash

## Discussion (2)

Nice but breaking it into functions would make it easier to understand.

Of course, I will get on that this weekend! Thank you for the feedback, it is appreciated.