BugbearSteve
BugbearSteve

Reputation: 3

Discord Bot - Python 3 - passing user variables to other functions

I'm making a dice roller Discord bot qith Python 3. The die number looks up a phrase in a dictionary and the outputs it. I had it fine working with a six sided die, but I want the user to be able to make it a 10 sided die instead.

To roll a die it is '!y1' to set it to 10 sided die it's '!y d10'. I tied setting it to d6 by default, however when I try rolling now it gives me an error of the variable being undefined. Could someone help point me to what I am missing?


import os
from random import randint

import discord
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

client = discord.Client()

def ybna6_faces(x):
    return{
        1: 'Yes, And...',
        2: 'Yes...',
        3: 'Yes, But...',
        4: 'No, But...',
        5: 'No...',
        6: 'No, And...'
        }[x]

def danger6_faces(x):
        return{
                1: 'Blank',
                2: 'Blank',
                3: 'Blank',
                4: 'Blank',
                5: 'Skull!',
                6: 'Two Skull!!'
                }[x]

def ybna10_faces(x):
    return{
        1: 'Yes, And...',
        2: 'Yes...',
        3: 'Yes, But...',
        4: 'No, But...',
        5: 'No...',
        6: 'No, And...',
        7: '',
        8: '',
        9: '',
        10: ''
        }[x]

def danger10_faces(x):
        return{
                1: 'Blank',
                2: 'Blank',
                3: 'Blank',
                4: 'Blank',
                5: 'Skull!',
                6: 'Two Skull!!',
                7: '',
                8: '',
                9: '',
                10: ''
                }[x]


sides = 6
#active_ybna = 6
#active_danger = 6

w=""

#Successful server connection message
@client.event
async def on_ready():
        print(f'{client.user.name} has connected to Discord!')

#Makes sure bot doesn't respond to itself
@client.event
async def on_message(message):
        if message.author == client.user:
                return

#Choose die (6 or 10)
        if message.content.startswith('!y d6'):
            sides = 6

        if message.content.startswith('!y d10'):
            sides = 10

#Evaluate rolls
        if message.content.startswith('!y'):
                if int(message.content[2])>int(0):
                        z = int(message.content[2])
                        for x in range(z):   
                                y = randint(1,int(sides))
                                active_ybna = 'ybna'+ sides + '_faces()'
                                response = 'Roll ' + str(x+1) + ': ' + active_ybna(y)
                                await message.channel.send(response)
                if len(message.content)>=4:
                    if int(message.content[4])>int(0):
                        z = int(message.content[4])
                        for x in range(z):
                            y=randint(1,int(sides))
                            active_danger = 'danger'+ sides + '_faces()'
                            response = 'Danger ' + str(x+1) + ': ' + active_danger(y)
                            await message.channel.send(response)

client.run(TOKEN)

EDIT: Traceback on input of '!y1'

YBNA Bot has connected to Discord!
Ignoring exception in on_message
Traceback (most recent call last):
  File "/home/pi/.local/lib/python3.7/site-packages/discord/client.py", line 312, in _run_event
    await coro(*args, **kwargs)
  File "/home/pi/Desktop/discord bots/ybnabot.py", line 92, in on_message
    y = randint(1,int(sides))
UnboundLocalError: local variable 'sides' referenced before assignment

Upvotes: 0

Views: 1313

Answers (2)

BugbearSteve
BugbearSteve

Reputation: 3

I think my issued was variables not declared Global. I kinda simplified it all and tucked it into one event with multiple IF's.

Some other code added as well...

# ybnabot.py
#d6 functionality

import os
from random import randint

import discord
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

client = discord.Client()

def ybna6_faces(x):
    return{
        1: 'No, And...',
        2: 'No...',
        3: 'No, But...',
        4: 'Yes, But...',
        5: 'Yes...',
        6: 'Yes, And...'
        }[x]

def danger6_faces(x):
        return{
        1: 'Blank',
        2: 'Blank',
        3: 'Blank',
        4: 'Blank',
        5: ':skull:',
        6: ':skull: :skull:'
        }[x]

def ybna10_faces(x):
    return{
        1: 'No, And...',
        2: 'No, And, But...',
        3: 'No...',
        4: 'Not, But...',
        5: 'No, But, And...',
        6: 'Yes, But, And...',
        7: 'Yes, But...',
        8: 'Yes...',
        9: 'Yes, And, But...',
        10: 'Yes, And...'
        }[x]

def danger10_faces(x):
        return{
                1: 'Blank',
                2: 'Blank',
                3: 'Blank',
                4: 'Blank',
                5: ':skull',
                6: ':skull: :skull',
                7: 'Blank',
                8: 'Blank',
                9: ':skull:',
                10: ':skull: :skull:'
                }[x]

@client.event
async def on_ready():
    global sides
    sides = 6
    print(f'{client.user.name} has connected to Discord!')


@client.event
async def on_message(message):
    global sides
    if message.author == client.user:
        return

#Send Help DM
    if message.content.startswith('!y help'):
        await message.author.send('YBNA Bot Help!')
        await message.author.send('Commands:')
        await message.author.send('!y X Z - Roll X number of YBNA dice and Z Danger dice (Danger die can be omitted)')
        await message.author.send('!y d6 - Choose six sided dice')
        await message.author.send('!y d10 - Choose 10 sided dice')
        await message.author.send('!y dice - Displays which dice are selected (d6 or d10)')
        await message.author.send('!y help - This message!')
        await message.author.send('txutfz73 credits here')
        await message.author.send('github link here')
        return


#Check die used
    if message.content.startswith('!y dice'):
        response = 'Using ' + str(sides) + ' sided dice!'
        await message.channel.send(response)
        return

#Choose d6 or d10
    if message.content.startswith('!y d6'):
        sides = 6
        await message.channel.send('Now using d6!')
        return

    if message.content.startswith('!y d10'):
        sides = 10
        response = 'Now using d10!'
        await message.channel.send(response)
        return




#Roll d6
    if sides == 6:
        if message.content.startswith('!y'):
            if int(message.content[2])>int(0):
                z = int(message.content[2])
                for x in range(z):
                    y = randint(1,6)
                    response = 'Roll ' + str(x+1) + ': ' + ybna6_faces(y) + str(sides)
                    await message.channel.send(response)

        if len(message.content)>=4:
            if int(message.content[4])>int(0):
                z = int(message.content[4])
                for x in range(z):
                    y=randint(1,6)
                    response = 'Danger ' + str(x+1) + ': ' + danger6_faces(y)
                    await message.channel.send(response)

#Roll d10
    else:
        if message.content.startswith('!y'):
            if int(message.content[2])>int(0):
                z = int(message.content[2])
                for x in range(z):
                    y = randint(1,10)
                    response = 'Roll ' + str(x+1) + ': ' + ybna10_faces(y) + str(sides)
                    await message.channel.send(response)

        if len(message.content)>=4:
            if int(message.content[4])>int(0):
                z = int(message.content[4])
                for x in range(z):
                    y=randint(1,10)
                    response = 'Danger ' + str(x+1) + ': ' + danger10_faces(y)
                    await message.channel.send(response)


client.run(TOKEN)

Upvotes: 0

Benjin
Benjin

Reputation: 3497

You have two if statements that can both evaluate to False, meaning it is possible the sides variable is never created.

This is because the sides you create is outside the function, making it out of scope. You need to move this inside the function or declare sides as global (not advised).

...

#active_ybna = 6
#active_danger = 6

w=""

#Successful server connection message
@client.event
async def on_ready():
    print(f'{client.user.name} has connected to Discord!')

#Makes sure bot doesn't respond to itself
@client.event
async def on_message(message):
    sides = 6
    if message.author == client.user:
        return

    #Choose die (6 or 10)
    if message.content.startswith('!y d6'):
        sides = 6

    if message.content.startswith('!y d10'):
        sides = 10

    #Evaluate rolls
    if message.content.startswith('!y'):
        if int(message.content[2])>int(0):
            z = int(message.content[2])
            for x in range(z):   
                 y = randint(1,int(sides))
                 active_ybna = 'ybna'+ sides + '_faces()'
                 response = 'Roll ' + str(x+1) + ': ' + active_ybna(y)
                 await message.channel.send(response)
         if len(message.content)>=4:
             if int(message.content[4])>int(0):
                 z = int(message.content[4])
                 for x in range(z):
                     y=randint(1,int(sides))
                     active_danger = 'danger'+ sides + '_faces()'
                     response = 'Danger ' + str(x+1) + ': ' + active_danger(y)
                     await message.channel.send(response)

client.run(TOKEN)

Upvotes: 1

Related Questions