I'm trying to make a constant updater that adds 2 of a resource each second. The problem is, when I do time.sleep(1), it puts the whole program to sleep and if I don't put it, the program crashes.
def coins(self):
""" Creates the resource coins """
self.coins = 0
self.goldlabel = Label(self,text = str(self.coins) + " gold")
self.goldlabel.grid(row = 6, column = 0, columnspan = 1, sticky = W)
def residences(self):
self.residence = 0
def passivegold(self):
amount = self.residence
if self.residence > 0:
add = amount * 2
self.coins += add
# time.sleep(1)
self.goldlabel.configure(text = str(self.coins) + " gold")
Related
I'm new to programming and I'm trying to make an app that calculates the smallest common for you, but for some reason whenever i run it, tkinter seems to just freeze and i don't know what the error seems to be. I suspect that it's the myLabel part, since I can still read the result inside the Terminal.
Thanks in advance~
from tkinter import *
root = Tk()
root.title("I can find the smallest common, unless you enter letters... I'm dyslexic.")
numbers_list = []
global numbers
numbers = Entry(root, width = 10, borderwidth = 5, state = DISABLED)
numbers.pack()
numbers.insert(0, "")
#
def button_click():
#each gets a button
get_smallest_common = Button(root, text = 'Confirm your number!'
, command = smallest_common)
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Undo!'
, command = lambda: undo())
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Start the search!'
, command = lambda: find_the_s_common())
get_smallest_common.pack()
#disable the start button
def switch():
myButton['state'] = DISABLED
#configure helps bringing a disabled thing back to normal state
numbers.configure(state = "normal")
def smallest_common():
#add to the list for late use
numbers_list.append(numbers.get())
print(numbers_list)
numbers.delete(0, END)
def undo():
#add to the list for late use
numbers_list.pop()
print(numbers_list)
numbers.delete(0, END)
def find_the_s_common():
process_list = []
condition = True
x = 0
while condition:
#the multiplication keep rising till count is 3
a = int(x) + 1
x = a
#loop to multiply the number with x + 1
for number in numbers_list:
y = int(number) * int(a)
process_list.append(y)
#check whether the result has been added to append into list
if y in process_list:
#check whether the list contains two duplicates to
if process_list.count(y) == 3:
condition = False
result = 'The number is ' + str(y) + '!'
print(result)
else:
continue
else:
continue
myLabel = Label(root, text = result)
myLabel.pack()
#combine the two function for myButton
def button_click_switch():
button_click()
switch()
myButton = Button(root, text = 'Click me to start'
, command = lambda: [button_click(), switch()])
myButton.pack()
root.mainloop()
Most probably, you have problem if the numbers entered is less than 3. As a result, one simple way is to decrease the condition to 2 and if a single number is entered the result is the number itself, if 2 or more no freezing.
NOTE: Freezing here is actually, while loop is running as condition is always True, because of process_list.count(y) == 3 will always be False if less than 3 number entered.
See my suggestion:
from tkinter import *
root = Tk()
root.title("I can find the smallest common, unless you enter letters... I'm dyslexic.")
numbers_list = []
global numbers
numbers = Entry(root, width = 10, borderwidth = 5, state = DISABLED)
numbers.pack()
numbers.insert(0, "")
#
def button_click():
#each gets a button
get_smallest_common = Button(root, text = 'Confirm your number!', command = smallest_common)
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Undo!', command = lambda: undo())
get_smallest_common.pack()
get_smallest_common = Button(root, text = 'Start the search!' , command = lambda: find_the_s_common())
get_smallest_common.pack()
#disable the start button
def switch():
myButton['state'] = DISABLED
#configure helps bringing a disabled thing back to normal state
numbers.configure(state = "normal")
def smallest_common():
#add to the list for late use
numbers_list.append(numbers.get())
print(numbers_list)
numbers.delete(0, END)
def undo():
#add to the list for late use
numbers_list.pop()
print(numbers_list)
numbers.delete(0, END)
def find_the_s_common():
process_list = []
condition = True
x = 0
if len(numbers_list) == 1: # RETURN IF THE LIST HAS A SINGLE VALUE
result = 'The number is ' + str(numbers_list[0]) + '!'
else:
while condition:
#the multiplication keep rising till count is 3
a = int(x) + 1
x = a
#loop to multiply the number with x + 1
for number in numbers_list:
y = int(number) * int(a)
process_list.append(y)
#check whether the result has been added to append into list
if y in process_list:
#check whether the list contains two duplicates to
if process_list.count(y) == 2: # DECREASE THE CONDITIONS TO 2
condition = False
result = 'The number is ' + str(y) + '!'
print(result)
else:
continue
else:
continue
myLabel = Label(root, text = result)
myLabel.pack()
#combine the two function for myButton
def button_click_switch():
button_click()
switch()
myButton = Button(root, text = 'Click me to start', command = lambda: [button_click(), switch()])
myButton.pack()
root.mainloop()
Suggestion to add two conditons;
(1) create a condition until at least 1 number is entered! if len(numbers_list) == 0, loop to enter a number.
(2) create a condition, until N number is added, let's say user must enter at least 3 numbers, change process_list.count(y) == 3 to process_list.count(y) == N and add condition if len(numbers_list) != N, loop to enter more numbers.
This is a partial solution to the single lane bridge problem that says that only cars that move at the same direction can be on the bridge at the same time. So it makes sense since it a single lane bridge that a car moving from left to right, should not be on the bridge at the same time that another car is moving from right to left. While Ive used locks and queues (one for leftbound and one for right bound traffic), cars that move at opposite directions end up crossing the bridge at the same time, and I don't know why because the locks and the logic ardound them should prevent that from happening.
I was hopping that the logic I have added inside the cross_bridge() method would ensure that cars moving towards the opposite direction do not end up on the bridge at the same time.
This is my code up to this point:
import threading, queue
from threading import Lock
from random import randint
import random
from random import choice
from string import ascii_uppercase
import time
q = queue.Queue(3)
ql = queue.Queue(3)
carsList = []
cnt = 0
cntL = 0
lc = []
rc = []
has_lock_a = -1
has_lock_b = -1
has_lock_c = -1
class Car:
def __init__(self, t_arrive, direction, name, idx):
self.t_arrive = t_arrive
self.direction = direction
self.name = name
self.idx = idx
self.currDir = 0
def __str__(self):
return "Car(name: " + self.name + ", time: " + str(self.t_arrive) + ", direction: " + str(self.direction) + ")\n"
class Bridge:
def __init__(self):
self.threads = []
self.threadCnt = 0
self.cntL = 0
self.cnt = 0
self.rc_nt = 0
self.lock_a = Lock()
self.lock_b = Lock()
self.lock_c = Lock()
self.sem = threading.Semaphore(0)
self.capacity = 3
self.dir = -1
def workerR(self):
while True:
itemR = q.get()
print(itemR)
if rc:
index = rc.pop(0)
self.arrive_bridge(carsList[index], index)
while self.dir != -1 or self.dir == 1:
print("hs")
pass
self.lock_a.acquire()
self.cross_bridge(carsList[index], index)
self.exit_bridge(carsList[index])
self.rc_nt += 1
q.task_done()
self.sem.release()
def workerL(self):
while True:
self.sem.acquire()
itemL = ql.get()
print(itemL)
if lc:
index = lc.pop(0)
self.arrive_bridge(carsList[index], index)
while self.dir != -1 or self.dir == 0:
pass
self.lock_a.acquire()
self.cntL += 1
self.cross_bridge(carsList[index], index)
self.exit_bridge(carsList[index])
ql.task_done()
self.sem.release()
def arrive_bridge(self, car: Car, cnt):
print(car.name + " arrived at bridge\n")
def cross_bridge(self, car: Car, cnt):
lock_ac = 0
print(car.name + " crossing bridge\n")
oneFourth = car.t_arrive / 4
for i in range(4):
if i == 2:
self.lock_b.acquire()
self.dir = car.direction
self.lock_a.release()
time.sleep(oneFourth)
self.lock_b.release()
# time.sleep(car.t_arrive)
def exit_bridge(self, car: Car):
print(car.name + " Exiting bridge\n")
self.dir = -1
if __name__ == "__main__":
# first (i), (ii), (iii)
totalNumberOfCars = randint(8, 11)
id = 0
for i in range(totalNumberOfCars):
direction = randint(0, 1)
time3 = randint(5, 7)
car = Car(time3, direction, ''.join(choice(ascii_uppercase) for z in range(4)), id)
id += 1
carsList.append(car)
random.shuffle(carsList)
car_cnt = 0
for car in carsList:
car.idx = car_cnt
car_cnt+=1
# turn-on the worker thread
bridge = Bridge()
threading.Thread(target=bridge.workerR, daemon=True).start()
# threading.Thread(target=bridge.workerR2, daemon=True).start()
threading.Thread(target=bridge.workerL, daemon=True).start()
# send thirty task requests to the worker
for item in range(len(carsList)):
if carsList[item].direction == 1:
q.put(carsList[item])
rc.append(item)
else:
ql.put(carsList[item])
lc.append(item)
# block until all tasks are done
q.join()
print("-------------. 2. > " + str(len(carsList)))
print('All work completed')
OUTPUT (and the error):
Car(name: PJJG, time: 5, direction: 1)
PJJG arrived at bridge
PJJG crossing bridge
PJJG Exiting bridge
Car(name: BLSQ, time: 7, direction: 1)
Car(name: ZXPH, time: 6, direction: 0)
ZXPH arrived at bridge
BLSQ arrived at bridge
BLSQ crossing bridge
ZXPH crossing bridge <<----!!!!! ERROR.. ZXPH with direction 0 cannot enter the single lane bridge because BLSQ with dir 1 is still crossing the Bridge.
....
I have a block of code which is called on a button press. The aim is to remove the task the button represents, and update all the other buttons to reflect the time changes. The function take an argument pos which is the position in the list of tasks to remove. That task entry is removed and the remaining task times updated.
The buttons are all removed and re-placed with new times and positions etc.
def remove_task(self, pos, *args):
print("\nRemoving task...")
print("List size = " + str(len(self.scheduled_tasks)))
print("Task pos = " + str(pos))
print("Task name = " + str(self.scheduled_tasks[pos].name))
del self.scheduled_tasks[pos] #Task deleted from list
print("Task deleted!")
print("Tasks:")
for task in self.scheduled_tasks:
print(task.name)
print("Re-assigning task n values...")
for index, tasks in enumerate(self.scheduled_tasks):
print("Index = " + str(index))
self.scheduled_tasks[index].n = int(index)
print("Name: " + str(self.scheduled_tasks[index].name))
print("N = " + str(self.scheduled_tasks[index].n))
print("N assingments complete")
print("List size = " + str(len(self.scheduled_tasks)))
for i in self.scheduled_tasks:
print("Task " + str(i.n) + " = " + str(i.name))
print("Deleting buttons...")
print("Number of buttons = " + str(len(self.ids.schedule.children)))
self.ids.schedule.clear_widgets()
print("Buttons deleted!")
position = 0
for i in self.scheduled_tasks:
print("Creating new buttons...")
if i.n == 0:
print("First button")
print("I.n = "+ str(i.n))
task_name = self.scheduled_tasks[i.n].name
print("Name = " + task_name)
task_time = self.scheduled_tasks[i.n].size
print("Task time = " + str(task_time))
parent_size = self.day
initial = App.get_running_app().user_start_time
end = initial + task_time
print("Task end time = " + str(end))
self.scheduled_tasks[i.n].set_start_time(initial)
self.scheduled_tasks[i.n].set_end_time(end)
print("New times set!")
if self.scheduled_tasks[i.n].class_type == "task":
print("Finding task size...")
self.task_size = self.scheduled_tasks[i.n].decimal_size
print("Size = " + str(self.task_size))
button_size = 1/int(parent_size/self.task_size)
print("Button_size = " + str(button_size))
task_type = self.scheduled_tasks[i.n].type
self.rgba = set_task_color(task_type, self.task_name).split(",")
if self.scheduled_tasks[i.n].class_type == "break":
button_size = 1/(self.parent_size/(self.break_size_init/60))
self.rgba = [0.5,0.5,0.5,0.5]
print("Position = " + str(position))
self.scheduled_tasks[i.n].n = position
position = position + 1
print("Position in scheduled tasks = " + str(self.scheduled_tasks[i.n].n))
task_button = Button(text = task_name + "\n" + str(self.scheduled_tasks[i.n].start_time.strftime("%H:%M")) + "\n - \n" + str(self.scheduled_tasks[i.n].end_time.strftime("%H:%M")),
size_hint = (button_size, 0.5),
text_size = (None, None),
font_size = 12,
pos_hint = {"top": 1},
background_normal = "white",
background_color = self.rgba)
task_button.text_size = task_button.size
task_button.halign = "center"
task_button.n = self.scheduled_tasks[i.n].n
print("Button position = " + str(task_button.n))
task_button.bind(on_release = lambda x: self.ids.schedule.remove_widget(task_button))
if self.scheduled_tasks[i.n].class_type == "task":
task_button.bind(on_release = lambda x: self.remove_task(i.n))
elif self.scheduled_tasks[i.n].class_type == "break":
task_button.bind(on_release = lambda x: self.remove_break(i.n))
print("Button functions bound")
self.ids.schedule.add_widget(task_button)
else:
print("Subsequent button")
print("I = " + str(i.n))
task_name = self.scheduled_tasks[i.n].name
print("Name = " + task_name)
print("Calculating times...")
initial = self.scheduled_tasks[i.n-1].end_time
end = initial + self.scheduled_tasks[i.n].size
print("Assigning times...")
self.scheduled_tasks[i.n].set_start_time(initial)
self.scheduled_tasks[i.n].set_end_time(end)
print("New times set!")
if self.scheduled_tasks[i.n].class_type == "task":
c.execute("SELECT Size FROM Tasks WHERE Name = ?;", (self.task_name,))
task_size_raw = "".join(c for c in str(str(c.fetchall())) if c not in "[](''`),")
self.task_size = float(task_size_raw) #hours, decimal
button_size = 1/int(parent_size/self.task_size)
task_type = self.scheduled_tasks[i.n].type
self.rgba = set_task_color(task_type, self.task_name).split(",")
if self.scheduled_tasks[i.n].class_type == "break":
button_size = 1/(self.parent_size/(self.break_size_init/60))
self.rgba = [0.5,0.5,0.5,0.5]
position = position + 1
print("position = " + str(self.scheduled_tasks[i.n].n))
task_button = Button(text = task_name + "\n" + str(self.scheduled_tasks[i.n].start_time.strftime("%H:%M")) + "\n - \n" + str(self.scheduled_tasks[i.n].end_time.strftime("%H:%M")),
size_hint = (button_size, 0.5),
text_size = (None, None),
font_size = 12,
pos_hint = {"top": 1},
background_normal = "white",
background_color = self.rgba)
task_button.text_size = task_button.size
task_button.halign = "center"
task_button.n = i.n
print("Button position = " + str(task_button.n))
task_button.bind(on_release = lambda x: self.ids.schedule.remove_widget(task_button))
if self.scheduled_tasks[i.n].class_type == "task":
task_button.bind(on_release = lambda x: self.remove_task(i.n))
elif self.scheduled_tasks[i.n].class_type == "break":
task_button.bind(on_release = lambda x: self.remove_break(i.n))
print("Button functions bound")
self.ids.schedule.add_widget(task_button)
print("Done!" + "\n")
print("Buttons created!")
print("Re-ordering complete!" + "\n")
Removing a task in the first instance works but when removing any later tasks/buttons the last task is always removed. The code output shows the button function is correctly bound to call the correct position argument but then always removes the last button/last entry in the list of tasks.
Output:
Removing task...
List size = 3
Task pos = 1 #Correct position
Task name = Test2
Task deleted!
Tasks:
Test
Test3
Re-assigning task n values...
Index = 0
Name: Test
N = 0
Index = 1
Name: Test3
N = 1
N assingments complete
List size = 2
Task 0 = Test
Task 1 = Test3
Deleting buttons...
Number of buttons = 3
Buttons deleted!
Creating new buttons...
First button
I.n = 0
Name = Test
Task time = 2:00:00
Task end time = 2021-01-03 16:30:00
New times set!
Finding task size...
Size = 2.0
Button_size = 0.5
0.8943980039499027,0.2144472118229821,0.011421795014607938,0.7
Position = 0
Position in scheduled tasks = 0
Button position = 0
Button functions bound
Creating new buttons...
Subsequent button
I = 1
Name = Test3
Calculating times...
Assigning times...
New times set!
0.8943980039499027,0.2144472118229821,0.011421795014607938,0.7
position = 1
Button position = 1
Button functions bound
Done!
Buttons created!
Re-ordering complete!
#^First removal, works fine with no issues^
Removing task...
List size = 2
Task pos = 1 #I clicked the button for the first task (Task 0) and this position argument was given!
Task name = Test3
Task deleted!
Tasks:
Test
Re-assigning task n values...
Index = 0
Name: Test
N = 0
N assingments complete
List size = 1
Task 0 = Test
Deleting buttons...
Number of buttons = 2
Buttons deleted!
Creating new buttons...
First button
I.n = 0
Name = Test
Task time = 2:00:00
Task end time = 2021-01-03 16:30:00
New times set!
Finding task size...
Size = 2.0
Button_size = 0.5
0.8943980039499027,0.2144472118229821,0.011421795014607938,0.7
Position = 0
Position in scheduled tasks = 0
Button position = 0
Button functions bound
Buttons created!
Re-ordering complete!
Removing task...
List size = 1
Task pos = 0
Task name = Test
Task deleted!
Tasks:
Re-assigning task n values...
N assingments complete
List size = 0
Deleting buttons...
Number of buttons = 1
Buttons deleted!
Buttons created!
Re-ordering complete!
#^Second and all subsequent removals remove the last task^
Can anybody see why the button is calling the last task instance to be removed? Why does every button after one task is correctly removed call for the last task to be removed?
I appreciate this is a long and detailed question so thanks in advance for any of your time!
I fixed this by binding a partial function instead of lambda to call the function on the button press. So instead of lambda x: remove_task(i.n) it would be partial(remove_task,i.n)
I need to update a list of labels that could be any size. All questions I've found already dealt in single labels instead of lists. I tried to extrapolate those answers to my problem and have not been successful.
I tried associating the list of labels with a list of StringVars and was not successful.
import nation
import game_time
def main():
Ven = nation.Nation("Venice", 1500000, 60, 5)
Mil = nation.Nation("Milan", 1250000, 10, 5)
Flo = nation.Nation("Florence", 7500000, 90, 5)
game_time.pass_time(1)
print ("test")
for n in nation.Nation._registry:
print (n.get_pop_stats())
if __name__ == '__main__':
main()
#NATION
name = ""
population = 0
econ_value = 0
owned_land = 0
GROWTH = .002
MONTH_GROWTH = .002/12
current_growth = 0
expected_growth = 0;
class Nation:
_registry = []
def __init__(self, name = "dummy", population = -1, econ_value = -1, owned_land = -1):
self.name = name
self.population = population
self.econ_value= econ_value
self.owned_land = owned_land
self._registry.append(self)
def get_pop_stats(self):
return "Nation: " + self.name + " Population: " + str(self.population) + " Current Growth: " + str(self.current_growth) + " Expected Growth: " + str(self.expected_growth) + "\n"
#TIME
import nation
GROWTH = .002
MONTH_GROWTH = .002/12
def pass_time(x):
while x > 0:
for p in nation.Nation._registry:
temp = p.population
p.population += p.population*(p.econ_value/100)*MONTH_GROWTH
p.current_growth = p.population - temp
p.expected_growth = p.population*(p.econ_value/100)*MONTH_GROWTH
x -= 1;
#ERROR
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.do_labels()
ran = 0
def do_labels(self):
pop_text = []
pop_stats = []
time = tk.Button(self, text="PASS TIME", fg="red", command= lambda: self.press())
time.pack(side="bottom")
i = 0
for n in nation.Nation._registry:
pop_text.append(tk.StringVar(value = n.get_pop_stats()))
pop_stats.append(tk.Label(self, textvariable = pop_text[i], command = print("initializing label")))
pop_stats[i].pack(side="top")
i+=1
self.ran = 1
self.pack()
root.update()
def press(self):
print("this works")
game_time.pass_time(1)
root = tk.Tk()
app = Application(master=root)
app.mainloop()
My bad, Here is the nation class, required to run the code.
Expected: Numbers in the labels update.
Actual: Nothing happens in the window, but the button successfully prints in the console.
I'm designing a Character Sheet from Dungeons & Dragons in Python, using Tkinter to take care of the graphical interface. However, I wanted to add an element (in this case a "proficiency" in a skill) to a list, if the checkbox corresponding to the same skill is active.
The checkbox buttons are working for some commands like exit ("root.destroy") but this in particulary doesn't seem to do anything.
I created a class Character, this Character has an empty Proficencies list and to add a proficiency to it, I created a function that did it whenever the matching checkbox value was set to True ("1")
import tkinter as tk
def modifier(score):
score = int(score)
return (score - 10) // 2
class Character:
proficiencies = []
abilities = {"Strength": 12, "Dexterity": 16, "Constitution": 14, "Intelligence": 10, "Wisdom": 16, "Charisma": 9}
skills = {"Athletics": 0, "Acrobatics": 0, "Sleight of Hand": 0, "Stealth": 0, "Arcana": 0, "History": 0,
"Investigation": 0, "Nature": 0, "Religion": 0,"Animal Handling": 0, "Insight": 0, "Medicine": 0,
"Perception": 0, "Survival": 0, "Deception": 0, "Intimidation": 0, "Performance": 0, "Persuasion": 0}
counter = 0
variables = []
skills = []
root = tk.Tk()
def addSkill():
if exec("var" + str(counter) + ".get() == 1"):
Character.proficiencies.append(skills[counter].replace('_', ' '))
elif exec("var" + str(counter) + ".get() == 0"):
pass
for skill in sorted(Character.skills.keys()):
skills.append(skill.replace(" ", "_"))
exec("var" + str(counter) + " = tk.IntVar()")
exec(skill.replace(" ", "") + "= tk.Checkbutton(root, text=skill, variable = var" + str(counter) + ", command = addSkill)")
exec(skill.replace(" ", "") + ".pack()")
variables.append("var" + str(counter))
counter += 1
counter = 0
root.mainloop()
index = 0
for skill in Character.skills:
if index == 0:
ability = "Strength"
elif index >= 1 and index <= 3:
ability = "Dexterity"
elif index >= 4 and index <= 8:
ability = "Intelligence"
elif index >= 9 and index <= 13:
ability = "Wisdom"
elif index >= 14:
ability = "Charisma"
if skill in Character.proficiencies:
Character.skills[skill] = 10 + (modifier(Character.abilities[ability]) + 2) * 2
else:
Character.skills[skill] = 10 + modifier(Character.abilities[ability]) * 2
index += 1
Here's an example of following Bryan Oakley's suggestion to avoid using exec() and not dynamically create named variables, I think you'll agree it's quite a bit easier to read and understand than the code you where using.
import tkinter as tk
SKILL_NAMES = ('Athletics', 'Acrobatics', 'Sleight of Hand', 'Stealth', 'Arcana',
'History', 'Investigation', 'Nature', 'Religion', 'Animal Handling',
'Insight', 'Medicine', 'Perception', 'Survival', 'Deception',
'Intimidation', 'Performance', 'Persuasion')
class Character:
proficiencies = []
abilities = {"Strength": 12, "Dexterity": 16, "Constitution": 14,
"Intelligence": 10, "Wisdom": 16, "Charisma": 9}
skills = dict.fromkeys(SKILL_NAMES, 0)
def modifier(score):
return (int(score) - 10) // 2
root = tk.Tk()
# Create tk.IntVars for holding value of each skill.
skill_vars = {skill: tk.IntVar() for skill in Character.skills}
# tkinter Checkbutton callback.
def addSkill(skill, var):
""" Add skill to proficiencies if Checkbutton is now checked. """
if var.get() == 1:
Character.proficiencies.append(skill)
# Create a Checkbutton corresponding to each skill.
for skill in Character.skills:
btn = tk.Checkbutton(root, text=skill, variable=skill_vars[skill],
command=lambda name=skill, var=skill_vars[skill]: addSkill(name, var))
btn.pack()
root.mainloop()
for index, skill in enumerate(Character.skills):
if index == 0:
ability = "Strength"
elif 1 <= index <= 3:
ability = "Dexterity"
elif 4 <= index <= 8:
ability = "Intelligence"
elif 9 <= index <= 13:
ability = "Wisdom"
elif index >= 14:
ability = "Charisma"
if skill in Character.proficiencies:
Character.skills[skill] = 10 + (modifier(Character.abilities[ability]) + 2) * 2
else:
Character.skills[skill] = 10 + modifier(Character.abilities[ability]) * 2
To whoever is having troubles with the same mistake, I think I've found the error.
Instead of:
def addSkill():
if exec("var" + str(counter) + ".get() == 1"):
Character.proficiencies.append(skills[counter].replace('_', ' '))
elif exec("var" + str(counter) + ".get() == 0"):
pass
I wrote:
def addSkill():
if var0.get() == 1:
Character.proficiencies.append(skills[0].replace('_', ' '))
if var1.get() == 1:
Character.proficiencies.append(skills[1].replace('_', ' '))
...
if var17.get() == 1:
Character.proficiencies.append(skills[17].replace('_', ' '))
And now it works :)