Skip to content

Instantly share code, notes, and snippets.

@yunruse
Created March 1, 2021 23:18
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 yunruse/308ef17361259d6fd2203486aad4da03 to your computer and use it in GitHub Desktop.
Save yunruse/308ef17361259d6fd2203486aad4da03 to your computer and use it in GitHub Desktop.
A quick DnD-style dice roller
'''
A quick DnD-style dice roller by Mia yun Ruse.
(Public domain, because it's hardly inventing the wheel.)
Allows for expressions such as:
> 5d0
> 5:d2*10+3; 2d20
23, 13, 13, 13, 13, 24
where * (or x) and + do math, (Y)dX sums Y rolls of an X-sided die (1-X),
; allows multiple values, and : repeats the expression (count on the left).
On CLI, evaluates input, or does a REPL if empty input.
(Hit up and enter in the REPL to repeat a request.)
Brackets are not supported. That's a tad much for a game to ask you to roll.
'''
from functools import reduce
from random import randint
from operator import mul
def product(x):
return reduce(mul, x, 1)
def dice(x):
if not x:
return 0
dice = 1
if 'd' in x:
x, dice = x.split('d')
return sum(randint(1, int(dice or 1)) for i in range(int(x or 1)))
def roll(string):
string = string.replace('x', '*').replace('-', '+-')
return sum(product(dice(x) for x in mults.split('*'))
for mults in string.split('+'))
def rolls(string):
vals = []
for x in string.split(';'):
count = 1
if ':' in x:
count, x = x.split(':')
vals += [roll(x) for i in range(int(count or 1))]
return vals
def main(string):
if not string.strip():
return None
print(', '.join(str(x) for x in rolls(string)))
if __name__ == '__main__':
from sys import argv
if argv[1:]:
main(' '.join(argv[1:]))
else:
print('roll.py')
lastval = ''
while True:
val = input('> ')
if val == '\x1b[A':
# CLI up-arrow
val = lastval
lastval = val
try: main(val)
except ValueError: print('?')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment