Search code examples
pythondiscordbotsdiscord.pydice

Discord.py D&D dice roll command has far too many issues


So all of my D&D party members are convinced that the current dice bot is "cursed", so I decided to take matters into my own hands and make my own bot. It's cool and all, but I have multiple issues with my dice roll command.

The command I currently have is

async def d(ctx, die:int):
    for x in range(1):
        await ctx.send("<:d20:748302353375166614> "+str(random.randint(1,die)))

The first issue is that it uses the format "|d 20" instead of "|d20", so the first request would be getting rid of that space between the "d" and the int that indicates the number of sides the die would have ("die" variable, "20" in this example).

On top of this, I'd like to add a feature where if one types "|[number of dice]d[number of sides]", it'd roll the requested die the requested amount of times. If the number of dice isn't specified (eg.: "|d20"), it should automatically assume that the number of dice is 1. The bot message should include all the rolled numbers, and their sum.

For example "|2d20" might return "<:d20:748302353375166614> 11 + 15 = 26", and "|10d2" might return "<:d20:748302353375166614> 1 + 1 + 2 + 1 + 2 + 2 + 2 + 1 + 1 + 2 = 15"

AND on top of that, I'd also like the ability to be able to add bonuses to rolls ("|[number of dice]d[number of sides]+[bonus]") and return both the dice roll, the bonus, and the final value in the bot's message.

For example "|d20+4" might return "<:d20:748302353375166614> 11 + 4 = 15", and "|2d10+2+3" might return "<:d20:748302353375166614> 9 + 4 + 2 + 3 = 18"

(Optionally, things like "|1d4+2d6" could be made possible if the person painfully writing the answer to this question feels like they aren't in enough agony yet from the sheer size of this request)


Solution

  • With the commands extension, you can't get rid of the space between your command and the die variable. In order to get rid of it, you'd have to use an on_message event to parse your command's content:

    from random import sample
    
    @client.event
    async def on_message(message):
        content = message.content
        if content.startswith('|') and (content[1].isdigit() or content[1]=='d'):
            content = content.split('+')
            rolls = [int(content.pop(i)) for i in range(len(content)) if content[i].isdigit()]
            for elem in content:
                n, faces = elem.split('d') if elem.split('d')[0] != '' else (1, elem[1:])
                rolls += [randint(1, int(faces)) for _ in range(int(n))]
            rolls_str = ' + '.join([str(n) for n in rolls]) 
            await message.channel.send(f"{rolls_str} = {sum(rolls)}")
        else:
            pass
    
        await client.process_commands(message)