'How make a dice bot in discord.py

I'm trying to create a command for my discord bot to roll dice, but I can't think of a way to allow this command to let me add a value to the roll. Example: 3d20+8

@bot.command()
  async def d(ctx,number):
      variable=random.randint(1,int(number)) 
      await ctx.reply(f"` {variable} ` ⟵ [{variable}] 1d{numero}")

Does anyone know how I would accomplish this?



Solution 1:[1]

You can do something like this.

For readability, I made the first dice function unpack the input (because it's in the format XdY+Z). Then it goes to the second function _dice which does all the processing.

@client.command()
async def dice(ctx, *, text: str):
    count, _, text = text.partition('d')  # eg "12d34+56" -> "12", "d", "34+56"
    size, _, offset = text.partition('+')  # eg "34+56" -> "34", "+", "56"
    try:
        count = int(count)
        size = int(size)
        offset = int(offset)
    except ValueError:
        raise commands.BadArgument('bad formatting of dice value')
    return await _dice(ctx, count, size, offset)

async def _dice(ctx, count, size, offset):
    rolls = [random.randint(offset+1, offset+size) for i in range(count)]  # eg for 20 with offset 3, generate values 4 to 23
    embed = discord.Embed(title=f'Dice for {count}d{size}+{offset}')
    embed.description = '\n'.join((f'#{i}: **{roll}**' for i, roll in enumerate(rolls)))
    embed.add_field(name='sum', value=f'total = {sum(rolls)}')
    await ctx.send(embed=embed)

Output:

enter image description here

In the above you can see that d10+10 outputs values in the range [11,20], which is 10 offset from the default [1,10].

Solution 2:[2]

I am not familiar with discord.py in particular, but here is how I would do it in a normal file

import random
user_input = input("Input dice size and how many (ex. 3d6)") #here you wouldn't be asking for input, just reading it off the server
dice_number = int(user_input.split("d")[0])
dice_add = int(user_input.split("+")[1])
print(dice_add)
dice_sides = int(user_input.strip(str(dice_number)).strip(str(dice_add)).strip("d").strip("+"))
total_number = 0
for i in range(dice_number):
  total_number += random.randint(1, dice_sides)
total_number += dice_add
print(total_number)

total_number = 0
for i in range(dice_number):
  total_number += random.randint(1, dice_sides)
total_number += int(dice[2])
print(total_number)

in the case you want to subtract as well, just make the input something like 4d12+-6 for a -6 modifier

Solution 3:[3]

Here's how I would write it:

import random
import re

from discord.ext import commands

# ...

@bot.command()
async def roll(ctx: commands.Context, cmd: str):
    num, sides, offset = map(lambda s: int(s), re.split(r"[d+]+", user_input))
    total = sum(random.randint(1, sides) for _ in range(num)) + offset
    # do what you want with the total

Now, there is a bit going on here, so I'll try to break it down.

  • re.split(r"[d+]+") takes our user_input and splits it at one or more delimiters: 'd' and '+'.
  • map takes these split values and converts them all to ints.
  • The sum section is a more Pythonic way of doing the same action num times and adding up the results. We add the offset back on at the end.

I don't really understand what you're trying to achieve with the format, so I'm going to leave that up to you.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Eric Jin
Solution 2 alien_jedi
Solution 3 triskofwhaleisland