Skip to content

Instantly share code, notes, and snippets.

@horstjens
Created August 2, 2023 07:25
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 horstjens/9023b26b8abb7f654b7be9bbe47f98b3 to your computer and use it in GitHub Desktop.
Save horstjens/9023b26b8abb7f654b7be9bbe47f98b3 to your computer and use it in GitHub Desktop.
import random
# dice - simulate dungeon & dragons dice to generate random values
def diceroll(dicestring):
"""
lower d for dice rolls without re-roll
1d6 -> rolls one six-sided die
2d6 -> rolls two six-sided dice
1d20+5 -> rolls one twenty-sided die and adds 5 to the end result
uppercase D for reroll (count as (sides-1))
1D6 -> roll a 6-sided die with re-rolling:
when a 6 is rolled it count as 5 but a re-roll is done.
2D6 -> roll two 6-sided dice with re-rolling
2D6-2 -> roll two 6-sided dice with re-rolling
and subtract 2 of the end result
"""
reroll = False
if dicestring.lower().count("d") != 1:
raise ValueError("more or less than one 'd' ('D') in dicestring")
if "D" in dicestring:
reroll = True
left, right = dicestring.lower().split("d")
number_of_dice = int(left)
if ("+" in right) or ("-" in right):
sign = "+" if "+" in right else "-"
sides, delta = right.split(sign)
sides = int(sides)
delta = int(delta)
if sign == "-":
delta = -delta
else:
delta = 0
sides = int(right)
text = dicestring+": "
result = 0
for d in range(number_of_dice):
if reroll:
roll = 0
while True:
temp = random.randint(1,sides)
if temp == sides:
roll += temp -1
else:
roll += temp
break
else:
roll = random.randint(1, sides)
result += roll
if d > 0:
text+=f"+{roll}"
else:
text+= f"{roll}"
if reroll and (roll > sides):
text += "!"
result += delta
if delta != 0:
if delta > 0:
text += f"+{delta}={result}"
else:
text += f"{delta}={result}"
return result, text
if __name__ == "__main__":
# testing
for _ in range(100):
print(diceroll("1D20"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment