Unknown crash in my program

I’ve built a dice game that’s played at DnD tables. Starting with the d4 You’re supposed to roll consecutive max values on d4, d6, d8, d10, d12, and d20 to win. The probability of winning is 1/460,800 but that’s the fun of it.
On testing the current version, I’ve found that after the counter reaches exactly 3325 “rolls” (random.randint(dicevalue)) the program breaks. Numbers stop counting, rolls stop populating, and the program crashes if touched.
to play you simply click the dice you want to roll, or you can press and/or hold spacebar to auto-roll the active die.

Here is the code below:

import random
import tkinter as tk

master = tk.Tk()
master.title("Dice Game")

rollCount = 0
d4Count = 0
d6Count = 0
d8Count = 0
d10Count = 0
d12Count = 0
d20Count = 0

#DICE ROLL FUNCTIONS

def rolld4():
    d4 = None
    d4 = random.randint(1,4)
    tk.Label(master, text=d4).grid(row=3,column=2)
    trackCount()
    trackd4()
    if d4 == 4 and rd6["state"] == "disabled":
        rd6["state"] = "normal"
        rd4["state"] = "disabled"
        rd4.config(bg='yellow') 
    return d4

def rolld6():
    d6 = None
    d6 = random.randint(1,6)
    tk.Label(master, text=d6).grid(row=3,column=3)
    trackCount()
    trackd6()
    if d6 == 6 and rd8["state"] == "disabled":
        rd8["state"] = "normal"
        rd6["state"] = "disabled"
        rd6.config(bg='lightblue')
    if d6 != 6:
        rd6["state"] = "disabled"
        rd4["state"] = "normal"
        rd4.config(bg='white')
    return d6

def rolld8():
    d8 = None
    d8 = random.randint(1,8)
    tk.Label(master, text=d8).grid(row=3,column=4)
    trackCount()
    trackd8()
    if d8 == 8 and rd10["state"] == "disabled":
        rd10["state"] = "normal"
        rd8["state"] = "disabled"
        rd8.config(bg='lightgreen')
    if d8 != 8:
        rd4["state"] = "normal"
        rd8["state"] = "disabled"
        rd4.config(bg='white')
        rd6.config(bg='SystemButtonFace')
    return d8

def rolld10():
    d10 = None
    d10 = random.randint(1,10)
    tk.Label(master, text=d10).grid(row=3,column=5)
    trackCount()
    trackd10()
    if d10 == 10 and rd12["state"] == "disabled":
        rd12["state"] = "normal"
        rd10["state"] = "disabled"
        rd10.config(bg='pink')
    if d10 != 10:
        rd4["state"] = "normal"
        rd10["state"] = "disabled"
        rd4.config(bg='white')
        rd6.config(bg='SystemButtonFace')
        rd8.config(bg='SystemButtonFace')
    return d10

def rolld12():
    d12 = None
    d12 = random.randint(1,12)
    tk.Label(master, text=d12).grid(row=3,column=6)
    trackCount()
    trackd12()
    if d12 == 12 and rd20["state"] == "disabled":
        rd20["state"] = "normal"
        rd12["state"] = "disabled"
        rd12.config(bg='magenta')
    if d12 != 12:
        rd4["state"] = "normal"
        rd12["state"] = "disabled"
        rd4.config(bg='white')
        rd6.config(bg='SystemButtonFace')
        rd8.config(bg='SystemButtonFace')
        rd10.config(bg='SystemButtonFace')
    return d12

def rolld20():
    d20 = None
    d20 = random.randint(1,20)
    tk.Label(master, text=d20).grid(row=3,column=7)
    trackCount()
    trackd20()
    if d20 == 20:
        rd20.config(bg='blue')
        rd20["state"] = "disabled"
        win = tk.Label(text = 'YOU WIN')
        win.grid(row=3,column=8,columnspan=2)
    if d20 != 20:
        rd4["state"] = "normal"
        rd20["state"] = "disabled"
        rd4.config(bg='white')
        rd6.config(bg='SystemButtonFace')
        rd8.config(bg='SystemButtonFace')
        rd10.config(bg='SystemButtonFace')
        rd12.config(bg='SystemButtonFace')
    return d20

#Function causes the rollCount to increase and display
def trackCount():
    global rollCount
    rollCount +=1
    tk.Label(master, text=rollCount).grid(row=5,column=8)
    pass
def trackd4():
    global d4Count
    d4Count +=1
    tk.Label(master, text=d4Count).grid(row=5,column=2)
    pass
def trackd6():
    global d6Count
    d6Count +=1
    tk.Label(master, text=d6Count).grid(row=5,column=3)
    pass
def trackd8():
    global d8Count
    d8Count +=1
    tk.Label(master, text=d8Count).grid(row=5,column=4)
    pass
def trackd10():
    global d10Count
    d10Count +=1
    tk.Label(master, text=d10Count).grid(row=5,column=5)
    pass
def trackd12():
    global d12Count
    d12Count +=1
    tk.Label(master, text=d12Count).grid(row=5,column=6)
    pass
def trackd20():
    global d20Count
    d20Count +=1
    tk.Label(master, text=d20Count).grid(row=5,column=7)
    pass

#Cheat Function
def Resetb():
    rd4["state"] = "normal"
    rd20["state"] = "disabled"
    rd12["state"] = "disabled"
    rd10["state"] = "disabled"
    rd8["state"] = "disabled"
    rd6["state"] = "disabled"
    rd4.config(bg='white')
    rd6.config(bg='SystemButtonFace')
    rd8.config(bg='SystemButtonFace')
    rd10.config(bg='SystemButtonFace')
    rd12.config(bg='SystemButtonFace')
    rd20.config(bg='SystemButtonFace')
    clearCom()
    global rollCount
    global d4Count
    global d6Count
    global d8Count
    global d10Count
    global d12Count
    global d20Count
    rollCount = 0
    d4Count = 0
    d6Count = 0
    d8Count = 0
    d10Count = 0
    d12Count = 0
    d20Count = 0
    tk.Label(master, text=rollCount).grid(row=5,column=8)
    
def clearCom():
    tk.Label(master, text="      ").grid(row=5,column=8)
    tk.Label(master, text="      ").grid(row=3,column=2)
    tk.Label(master, text="      ").grid(row=3,column=3)
    tk.Label(master, text="      ").grid(row=3,column=4)
    tk.Label(master, text="      ").grid(row=3,column=5)
    tk.Label(master, text="      ").grid(row=3,column=6)
    tk.Label(master, text="      ").grid(row=3,column=7)
    tk.Label(master, text="      ").grid(row=5,column=2)
    tk.Label(master, text="      ").grid(row=5,column=3)
    tk.Label(master, text="      ").grid(row=5,column=4)
    tk.Label(master, text="      ").grid(row=5,column=5)
    tk.Label(master, text="      ").grid(row=5,column=6)
    tk.Label(master, text="      ").grid(row=5,column=7)
    
#Buttons
rd4 = tk.Button(master, text='D4', command = rolld4, height=3, width=6)
rd4.grid(row=2,column=2)
rd4.config(bg='white')

rd6 = tk.Button(master, text='D6', command = rolld6, height=3, width=6)
rd6.grid(row=2,column=3)
rd6["state"] = "disabled"

rd8 = tk.Button(master, text='D8', command = rolld8, height=3, width=6)
rd8.grid(row=2,column=4)
rd8["state"]="disabled"

rd10 = tk.Button(master, text='D10', command = rolld10, height=3, width=6)
rd10.grid(row=2,column=5)
rd10["state"]="disabled"

rd12 = tk.Button(master, text='D12', command = rolld12, height=3, width=6)
rd12.grid(row=2,column=6)
rd12["state"]="disabled"

rd20 = tk.Button(master, text='D20', command = rolld20, height=3, width=6)
rd20.grid(row=2,column=7)
rd20["state"]="disabled"

Reset = tk.Button(master, text='Reset', command = Resetb, height=3, width=6)
Reset.grid(row=2, column=8)

#Spacebar

def GRoll(event):
    if rd4["state"] == "normal":
        rolld4()
    elif rd6["state"] == "normal":
        rolld6()
    elif rd8["state"] == "normal":
        rolld8()
    elif rd10["state"] == "normal":
        rolld10()
    elif rd12["state"] == "normal":
        rolld12()
    elif rd20["state"] == "normal":
        rolld20()
    else:
        pass
    pass

#Binding Spacebar to roll function
master.bind("<KeyPress-space>", GRoll)

#Additional Labels
    
deez = tk.Label(text = '''Click the
Dice to
Roll''')
deez.grid(row=2,column=1)

lroll = tk.Label(text = 'Last Roll')
lroll.grid(row=3,column=1)
lroll.config(bg='lightgreen')

troll = tk.Label(text = 'Times Rolled')
troll.grid(row=5,column=1)
troll.config(bg='lightyellow')

#window size
master.geometry('450x125+50+50')
master.resizable(False,False)

master.mainloop()

as an update, I tried deleting the individual dice counters and the limit was extended to 4988 rolls. Still not sure where the error is coming from

1 Like

Please wrap code in triple backticks to preserve the formatting:

```python
if True:
    print('Hello world!')
```

From what i can see, from a traceback, the issue is with 'SystemButtonFace'. When I replace SystemButtonFace with black, your app seems not to crash. That said, I’ve only done a limited test.

Did the change myself and it unfortunately didn’t make it past the 3325 line. Same crash same way

Odd… I’ve just 7000+ on D4 and it’s still going; no crashes.

replacing all instances of SystemButtonFace with black just gives me the same outcome.

I made some other changes since posting (since I’m actively hunting myself via trial and error):

I kept in the change from systembuttonface to grey so the program didn’t do something like call for that color over and over (or something, I’m new to coding)

Another thing I noticed is that my ram usage for the program increases as the rolls go on, it hits 45MB around the same time, but I doubt it’d consistently break on the same number every time.

I tried the program on my brother’s computer and same issues

I’ve changed the count method so it’s rollCount = rollCount +1 as well as all the other dice counters just in case the program was storing history of values. no change with that

going to pull other wires and see what happens.

I’m also on windows if that helps with anything

I think it’s a memory leak.

Every time it doesn’t something like:

tk.Label(master, text=d4).grid(row=3,column=2)

it’s creating a new label and putting it in the grid, on top of the one(s) already there.

I suggest keeping a reference to the label and changing the text:

label32 = tk.Label(master, text=d4)
label32.grid(row=3,column=2)
...
# Update the label's text to d4:
label32["text"] = d4
...
# Update the label's text to spaces:
label32["text"] = "      "
...
1 Like

I’m pretty sure you’re right, but I’m getting an error in implementation. I’m getting an error
Exception in Tkinter callback
Traceback (most recent call last):

  File "C:\Users\t\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
    return self.func(*args)
  File "C:\Users\t\Desktop\PYTHON PROGRAMS\Dice game base.py", line 261, in GRoll
    rolld4()
  File "C:\Users\t\Desktop\PYTHON PROGRAMS\Dice game base.py", line 20, in rolld4
    d4res["text"] = d4
TypeError: 'NoneType' object does not support item assignment
import random
import tkinter as tk

master = tk.Tk()
master.title("Dice Game")

rollCount = 0
d4Count = 0
d6Count = 0
d8Count = 0
d10Count = 0
d12Count = 0
d20Count = 0

#DICE ROLL FUNCTIONS

def rolld4():
    d4 = random.randint(1,4)
    global d4res
    d4res["text"] = d4
    trackCount()
    trackd4()
    if d4 == 4 and rd6["state"] == "disabled":
        rd6["state"] = "normal"
        rd6.config(bg='white')
        rd4["state"] = "disabled"
        rd4.config(bg='yellow') 
    return d4

def rolld6():
    d6 = random.randint(1,6)
    global d6res
    d6res["text"] = d6
    trackCount()
    trackd6()
    if d6 == 6 and rd8["state"] == "disabled":
        rd8["state"] = "normal"
        rd8.config(bg='white')
        rd6["state"] = "disabled"
        rd6.config(bg='lightblue')
    if d6 != 6:
        rd6["state"] = "disabled"
        rd4["state"] = "normal"
        rd4.config(bg='white')
        rd6.config(bg='grey')
    return d6

def rolld8():
    d8 = random.randint(1,8)
    global d8res
    d8res["text"] = d8
    trackCount()
    trackd8()
    if d8 == 8 and rd10["state"] == "disabled":
        rd10["state"] = "normal"
        rd10.config(bg='white')
        rd8["state"] = "disabled"
        rd8.config(bg='lightgreen')
    if d8 != 8:
        rd4["state"] = "normal"
        rd8["state"] = "disabled"
        rd4.config(bg='white')
        rd6.config(bg='grey')
        rd8.config(bg='grey')
    return d8

def rolld10():
    d10 = random.randint(1,10)
    global d10res
    d10res["text"] = d10
    trackCount()
    trackd10()
    if d10 == 10 and rd12["state"] == "disabled":
        rd12["state"] = "normal"
        rd12.config(bg='white')
        rd10["state"] = "disabled"
        rd10.config(bg='pink')
    if d10 != 10:
        rd4["state"] = "normal"
        rd10["state"] = "disabled"
        rd4.config(bg='white')
        rd6.config(bg='grey')
        rd8.config(bg='grey')
        rd10.config(bg='grey')
    return d10

def rolld12():
    d12 = random.randint(1,12)
    global d12res
    d12res["text"] = d12
    trackCount()
    trackd12()
    if d12 == 12 and rd20["state"] == "disabled":
        rd20["state"] = "normal"
        rd20.config(bg='white')
        rd12["state"] = "disabled"
        rd12.config(bg='magenta')
    if d12 != 12:
        rd4["state"] = "normal"
        rd12["state"] = "disabled"
        rd4.config(bg='white')
        rd6.config(bg='grey')
        rd8.config(bg='grey')
        rd10.config(bg='grey')
        rd12.config(bg='grey')
    return d12

def rolld20():
    d20 = random.randint(1,20)
    global d20res
    d20res["text"] = d20
    trackCount()
    trackd20()
    if d20 == 20:
        rd20.config(bg='blue')
        rd20["state"] = "disabled"
        win = tk.Label(text = 'YOU WIN')
        win.grid(row=3,column=8,columnspan=2)
        global Finished
        Finished = True
    if d20 != 20:
        rd4["state"] = "normal"
        rd20["state"] = "disabled"
        rd4.config(bg='white')
        rd6.config(bg='grey')
        rd8.config(bg='grey')
        rd10.config(bg='grey')
        rd12.config(bg='grey')
        rd20.config(bg='grey')
    return d20

# Function causes the rollCount to increase and display
def trackCount():
    global rollCount
    rollCount = rollCount +1
    global RolCnt
    RolCnt["text"] = rollCount
def trackd4():
    global d4Count
    d4Count = d4Count +1
    global d4Cnt
    d4Cnt["text"] = d4Count
def trackd6():
    global d6Count
    d6Count = d6Count +1
    global d6Cnt
    d6Cnt["text"] = d6Count
def trackd8():
    global d8Count
    d8Count = d8Count +1
    global d8Cnt
    d8Cnt["text"] = d8Count
def trackd10():
    global d10Count
    d10Count = d10Count +1
    global d10Cnt
    d10Cnt["text"] = d10Count
def trackd12():
    global d12Count
    d12Count = d12Count +1
    global d12Cnt
    d12Cnt["text"] = d12Count
def trackd20():
    global d20Count
    d20Count = d20Count +1
    global d20Cnt
    d20Cnt["text"] = d20Count

#Cheat Function
def Resetb():
    rd4["state"] = "normal"
    rd20["state"] = "disabled"
    rd12["state"] = "disabled"
    rd10["state"] = "disabled"
    rd8["state"] = "disabled"
    rd6["state"] = "disabled"
    rd4.config(bg='white')
    rd6.config(bg='SystemButtonFace')
    rd8.config(bg='SystemButtonFace')
    rd10.config(bg='SystemButtonFace')
    rd12.config(bg='SystemButtonFace')
    rd20.config(bg='SystemButtonFace')
    clearCom()
    global rollCount
    global d4Count
    global d6Count
    global d8Count
    global d10Count
    global d12Count
    global d20Count
    rollCount = 0
    d4Count = 0
    d6Count = 0
    d8Count = 0
    d10Count = 0
    d12Count = 0
    d20Count = 0
    global RolCnt
    RolCnt["text"] = rollCount
    
def clearCom():
    global d4Cnt
    d4Cnt["text"] = "     "
    global d6Cnt
    d6Cnt["text"] = "     "
    global d8Cnt
    d8Cnt["text"] = "     "
    global d10Cnt
    d10Cnt["text"] = "     "
    global d12Cnt
    d12Cnt["text"] = "     "
    global d20Cnt
    d20Cnt["text"] = "     "
    
    global d4res
    d4res["text"] = "     "
    global d6res
    d6res["text"] = "     "
    global d8res
    d8res["text"] = "     "
    global d10res
    d10res["text"] = "     "
    global d12res
    d12res["text"] = "     "
    global d20res
    d20res["text"] = "     "
    
    
#Buttons
rd4 = tk.Button(master, text='D4', command = rolld4, height=3, width=6)
rd4.grid(row=2,column=2)
rd4.config(bg='white')

rd6 = tk.Button(master, text='D6', command = rolld6, height=3, width=6)
rd6.grid(row=2,column=3)
rd6["state"] = "disabled"

rd8 = tk.Button(master, text='D8', command = rolld8, height=3, width=6)
rd8.grid(row=2,column=4)
rd8["state"]="disabled"

rd10 = tk.Button(master, text='D10', command = rolld10, height=3, width=6)
rd10.grid(row=2,column=5)
rd10["state"]="disabled"

rd12 = tk.Button(master, text='D12', command = rolld12, height=3, width=6)
rd12.grid(row=2,column=6)
rd12["state"]="disabled"

rd20 = tk.Button(master, text='D20', command = rolld20, height=3, width=6)
rd20.grid(row=2,column=7)
rd20["state"]="disabled"

Reset = tk.Button(master, text='Reset', command = Resetb, height=3, width=6)
Reset.grid(row=2, column=8)

#Spacebar

def GRoll(event):
    if rd4["state"] == "normal":
        rolld4()
    elif rd6["state"] == "normal":
        rolld6()
    elif rd8["state"] == "normal":
        rolld8()
    elif rd10["state"] == "normal":
        rolld10()
    elif rd12["state"] == "normal":
        rolld12()
    elif rd20["state"] == "normal":
        rolld20()
    else:
        pass
    pass

#Binding Spacebar to roll function
master.bind("<KeyPress-space>", GRoll)

#Additional Labels
    
deez = tk.Label(text = '''Click the
Dice to
Roll''')
deez.grid(row=2,column=1)

lroll = tk.Label(text = 'Last Roll')
lroll.grid(row=3,column=1)
lroll.config(bg='lightgreen')

troll = tk.Label(text = 'Times Rolled')
troll.grid(row=5,column=1)
troll.config(bg='lightyellow')

#Counter and Result Labels
d4res = tk.Label(master, text= None).grid(row=3,column=2)
d6res = tk.Label(master, text=None).grid(row=3,column=3)
d8res = tk.Label(master, text=None).grid(row=3,column=4)
d10res = tk.Label(master, text=None).grid(row=3,column=5)
d12res = tk.Label(master, text=None).grid(row=3,column=6)
d20res = tk.Label(master, text=None).grid(row=3,column=7)

RolCnt = tk.Label(master, text=None).grid(row=5,column=8)
d4Cnt = tk.Label(master, text=None).grid(row=5,column=2)
d6Cnt = tk.Label(master, text=None).grid(row=5,column=3)
d8Cnt = tk.Label(master, text=None).grid(row=5,column=4)
d10Cnt = tk.Label(master, text=None).grid(row=5,column=5)
d12Cnt = tk.Label(master, text=None).grid(row=5,column=6)
d20Cnt = tk.Label(master, text=None).grid(row=5,column=7)

#window size
master.geometry('450x125+50+50')
master.resizable(False,False)

master.mainloop()

Thank you for the help so far

I didn’t assign the grid location correctly after creating a variable for the Labels. It started working after fixing that ~

Confirmed Solved.

‘system’ colors are listed on colors manual page - Tk Built-In Commands under “Portability Issues”. Most are limited to Macs and a few, like ‘systemButtonFace’ (spelling from the page) are shared with Windows. Burntco, which are you system using?

From the symptoms, you might be exceeding some internal tk limit. You create a new label for each roll, and I don’t think that the old one goes away. Instead, you should replace just the text content of the existing label.

@rob42 Are you using *nix? Did you reproduce crash after fixing the color?

I’m using a linux mint system.

After I replaced all the bg='SystemButtonFace' with bg='black' I did not see any further crashes. This I did, because I saw a error message that suggested 'SystemButtonFace' was an unknown color, so I simply picked a color that I knew would be known.

I did not run the app past apx 8000 rolls on D4

I hope this is of some help.