59 lines
1.7 KiB
Python
59 lines
1.7 KiB
Python
import re
|
|
from collections import defaultdict
|
|
from random import randint
|
|
|
|
from ..functions import reply
|
|
from ..models import Message
|
|
|
|
HELP = """Würfelt eine Summe aus.
|
|
!roll [how many]d<sides> [ ... ]
|
|
"""
|
|
|
|
parse_die = re.compile("(?P<num>\d*)[dwDW](?P<sides>\d+)").fullmatch
|
|
|
|
|
|
def init(bot):
|
|
bot.on_command("roll", handle)
|
|
|
|
|
|
async def handle(message: Message):
|
|
if len(message.args) == 1 and message.args[0].isdecimal():
|
|
dice = [(1, int(message.args[0]))]
|
|
else:
|
|
dice = []
|
|
num = None
|
|
for arg in message.args:
|
|
if (match := parse_die(arg)) :
|
|
if num and match["num"]:
|
|
return
|
|
num, sides = int(match["num"] or num or 1), int(match["sides"])
|
|
if not 1 <= num < 1000 or not 2 <= sides <= 100:
|
|
return
|
|
dice.append((num, sides))
|
|
num = None
|
|
elif arg.isdecimal():
|
|
if num is not None:
|
|
return
|
|
num = int(arg)
|
|
else:
|
|
return
|
|
|
|
if not 0 < len(dice) < 20:
|
|
return
|
|
|
|
rolls = defaultdict(list)
|
|
for num, sides in dice:
|
|
for _ in range(num):
|
|
rolls[sides].append(randint(1, sides))
|
|
|
|
total = sum(sum(vs) for sides, vs in rolls.items())
|
|
if len(rolls) == 1:
|
|
sides = list(rolls.keys())[0]
|
|
text = f"{total} ({len(rolls[sides])}d{sides})"
|
|
else:
|
|
dicestr = " + ".join(
|
|
f"{len(vs)}d{sides} ({sum(vs)})"
|
|
for sides, vs in sorted(rolls.items(), key=lambda i: i[0], reverse=1)
|
|
)
|
|
text = f"{total} = {dicestr}"
|
|
await reply(message, plain=text, in_thread=True)
|