Byte Ebi's Logo

Byte Ebi 🍀

A Bit everyday A Byte every week

[Discord Bot] 02. Dice Rolling Bot

Create a Discord chat bot for rolling dice using Python3

Ray

Do you know about TTRPG? One of the most well-known is probably Dungeons & Dragons (D&D).
After watching hololive EN play, I thought, “Let’s create a dice rolling bot and give it a try.”

Requirements Discussion

  • Ability to roll multiple dice
  • Customizable number of sides on the dice
  • Success determination calculation

Command format

!roll 5D10>8

This means: roll 5 ten-sided dice, and success is determined if the result is greater than or equal to 8.

Code

# Import the Discord.py library
import discord

# Import the random library
import random

# Obtain the Discord client object for operations
client = discord.Client()

# Invoke the event library
@client.event

# When the bot is ready, display a message in the terminal
async def on_ready():
    print(f'Logged in as {client.user}')

# Invoke the event library
@client.event
# When a message is received
async def on_message(message):
    
    # Exclude messages sent by the bot itself to avoid an infinite loop
    if message.author == client.user:
        return

    # Default error message
    error = []

    # Process input text
    content = message.content.replace(' ', '').lower()

    # If the message starts with "!roll"
    if message.content.startswith('!roll'):
        content = content.replace('!roll', '')

        # Dice quantity calculation
        dice_count = content.split('d')[0]

        try:
            dice_count = int(dice_count)

        except ValueError:
            error.append('The number of dice rolled must be an integer!')

        # Dice type determination
        content = content.split('d')[1]
        dice_type = content.split('>')[0]
        try:
            dice_type = int(dice_type)

        except ValueError:
            error.append('Dice type must be an integer!')

        # Success determination
        if '>' in content:
            success = content.split('>')[1]
            try:
                success = int(success)    
            except ValueError:
                error.append('Success condition must be an integer!')

        else:
            success = 0

        if len(error) == 0:
            success_count = 0
            result_msg = ''

            # Roll the dice
            results = [random.randint(1, dice_type) for _ in range(dice_count)]

            for result in results:
                if success > 0 and result >= success:
                    success_count += 1
                result_msg += f'`{result}`, '
            
            await message.channel.send(result_msg)

            if success > 0:
                await message.channel.send(f'Success: `{success_count}`')
        else:
            await message.channel.send(error)

# TOKEN obtained on the "BOT" page in Discord Developer
client.run('')

Code Explanation

Basic usage of discord.py has been covered before, so we won’t repeat it here. We’ll focus on explaining the logic.

Input Message Detection

We use

message.content.startswith('!roll')

to only respond to messages starting with ‘!roll’. To ensure case insensitivity and handle spaces, we use

message.content.replace(' ', '').lower()

to remove spaces and convert the message to lowercase.

Now, the program processes the message as if the user had input ‘!roll5d10’.

Dice Quantity Calculation

The logic is similar to before. We extract the number of dice by splitting the content around ’d’ and taking the first value.

We use

content.replace('!roll', '')

to remove ‘!roll’ as it’s only a trigger for the bot and doesn’t affect the dice rolling result.

We use

content.split('d')[0]

to get the number of dice. We then try to convert it to an integer, catching a ValueError if it’s not a valid number.

Dice Type Determination

Similar to quantity calculation, but this time we extract the logic between ’d’ and ‘>’ to determine the type of dice.
Again, we try to convert it to an integer and catch a ValueError if needed.

Success Determination

We check if ‘>’ is present in the content. If it is, we extract the success condition after ‘>’.
We try to convert it to an integer, catching a ValueError if needed.

Rolling the Dice

If there are no errors, we roll the dice using

results = [random.randint(1, dice_type) for _ in range(dice_count)]

We iterate through the results, formatting them for Discord output, and count successful rolls if a success condition is specified.

Finally, we send the result and success count to Discord. If there are errors, we send the error message instead.

Improvement Directions

While the bot’s requirements are met, there are areas for optimization.

Function Splitting

The logic is currently written together.
It would be better to split it into separate functions for easier testing and future adjustments.

Input Logic Optimization

The input logic is too simple, and unexpected user inputs might not be handled correctly.
For example, ‘!roll6D10d5’ will currently be processed the same as ‘!roll6D10’.
Proper handling of such cases should be considered.

Recent Posts

Categories

Tags