cookchar

DnD Character Sheet w/ Tkinter GUI

Aug 31st, 2017
102
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import tkinter as tk
  2. import tkinter.simpledialog as sdg
  3. import tkinter.messagebox as mbx
  4. import tkinter.font as tkf
  5. import tkinter.tix as tix
  6. import random as rnd
  7. import operator as op
  8. import os
  9.  
  10. #Charlie Cook's Dungeons & Dragons Character Sheet Program
  11. #Begun early June 2017
  12. #Last updated early August 2017
  13.  
  14. def updtSAVETHRW():
  15.     savingThrows[0] = mainStats[2] + bonusStats[2]
  16.     savingThrows[1] = mainStats[1] + bonusStats[1]
  17.     savingThrows[2] = mainStats[4] + bonusStats[4]
  18.  
  19. def levelUp():
  20.     experience[0] += 1
  21.     experience[1] -= experience[2]
  22.     experience[2] = 100 + 10 * experience[0]
  23.     mbx.showinfo("Level Up!","Congratulations!\nYou are now Level " + str(experience[0]))
  24.  
  25. def refrSTAT():
  26.     LEVLLbl.config(text = "Level: " + str(experience[0]))
  27.     HPLbl.config(text = "HP:" + str(health[0]) + "/" + str(health[1]))
  28.     XPLbl.config(text = "XP:" + str(experience[1]) + "/" + str(experience[2]))
  29.  
  30.     STRLbl.config(text = "STR: " + str(mainStats[0]))
  31.     DEXLbl.config(text = "DEX: " + str(mainStats[1]))
  32.     CONLbl.config(text = "CON: " + str(mainStats[2]))
  33.     INTLbl.config(text = "INT: " + str(mainStats[3]))
  34.     WISLbl.config(text = "WIS: " + str(mainStats[4]))
  35.     CHALbl.config(text = "CHA: " + str(mainStats[5]))
  36.  
  37.     if bonusStats[0] > 0:
  38.         STRBLbl.config(text = "+" + str(bonusStats[0]))
  39.     else:
  40.         STRBLbl.config(text = str(bonusStats[0]))
  41.  
  42.     if bonusStats[1] > 0:
  43.         DEXBLbl.config(text = "+" + str(bonusStats[1]))
  44.     else:
  45.         DEXBLbl.config(text = str(bonusStats[1]))
  46.  
  47.     if bonusStats[2] > 0:
  48.         CONBLbl.config(text = "+" + str(bonusStats[2]))
  49.     else:
  50.         CONBLbl.config(text = str(bonusStats[2]))
  51.  
  52.     if bonusStats[3] > 0:
  53.         INTBLbl.config(text = "+" + str(bonusStats[3]))
  54.     else:
  55.         INTBLbl.config(text = str(bonusStats[3]))
  56.  
  57.     if bonusStats[4] > 0:
  58.         WISBLbl.config(text = "+" + str(bonusStats[4]))
  59.     else:
  60.         WISBLbl.config(text = str(bonusStats[4]))
  61.  
  62.     if bonusStats[5] > 0:
  63.         CHABLbl.config(text = "+" + str(bonusStats[5]))
  64.     else:
  65.         CHABLbl.config(text = str(bonusStats[5]))
  66.  
  67.     updtSAVETHRW()
  68.  
  69.     FORTLbl.config(text = "Fortitude: " + str(savingThrows[0]))
  70.     REFLLbl.config(text = "Reflex: " + str(savingThrows[1]))
  71.     WILLLbl.config(text = "Will: " + str(savingThrows[2]))
  72.  
  73. def HPUp():
  74.     if health[0] < health[1]:
  75.         health[0] += 1
  76.         refrSTAT()
  77.  
  78. def HPDown():
  79.     if health[0] > 0:
  80.         health[0] -= 1
  81.         refrSTAT()
  82.  
  83. def XPUp():
  84.     temp = sdg.askinteger("Add XP", "Enter how many experience points you've earned:")
  85.     if type(temp) == int:
  86.         experience[1] += temp
  87.  
  88.     while experience[1] > experience[2]:
  89.         levelUp()
  90.         refrSTAT()
  91.  
  92.     refrSTAT()
  93.  
  94. class editStatRoot(sdg.Dialog):
  95.     def body(self, master):
  96.         self.title("Edit Stats")
  97.         self.resizable(False, False)
  98.         self.choice = tk.IntVar()
  99.         self.choice.set(1)
  100.         tk.Label(master, text = "Choose a stat item to edit:", font = ftSmall).grid(row = 0)
  101.        
  102.         STR = tk.Radiobutton(master, text = "Strength", value = 1, variable = self.choice, cursor = "hand2", font = ftSmall)
  103.         DEX = tk.Radiobutton(master, text = "Dexterity", value = 2, variable = self.choice, cursor = "hand2", font = ftSmall)
  104.         CON = tk.Radiobutton(master, text = "Constitution", value = 3, variable = self.choice, cursor = "hand2", font = ftSmall)
  105.         INT = tk.Radiobutton(master, text = "Intelligence", value = 4, variable = self.choice, cursor = "hand2", font = ftSmall)
  106.         WIS = tk.Radiobutton(master, text = "Wisdom", value = 5, variable = self.choice, cursor = "hand2", font = ftSmall)
  107.         CHA = tk.Radiobutton(master, text = "Charisma", value = 6, variable = self.choice, cursor = "hand2", font = ftSmall)
  108.  
  109.         LEV = tk.Radiobutton(master, text = "Level", value = 7, variable = self.choice, cursor = "hand2", font = ftSmall)
  110.         XP = tk.Radiobutton(master, text = "Experience", value = 8, variable = self.choice, cursor = "hand2", font = ftSmall)
  111.         HPC = tk.Radiobutton(master, text = "Current Health", value = 9, variable = self.choice, cursor = "hand2", font = ftSmall)
  112.         HPM = tk.Radiobutton(master, text = "Maximum Health", value = 10, variable = self.choice, cursor = "hand2", font = ftSmall)
  113.  
  114.         STR.grid(row = 5, sticky = "w")
  115.         DEX.grid(row = 6, sticky = "w")
  116.         CON.grid(row = 7, sticky = "w")
  117.         INT.grid(row = 8, sticky = "w")
  118.         WIS.grid(row = 9, sticky = "w")
  119.         CHA.grid(row = 10, sticky = "w")
  120.  
  121.         LEV.grid(row = 1, sticky = "w")
  122.         XP.grid(row = 2, sticky = "w")
  123.         HPC.grid(row = 3, sticky = "w")
  124.         HPM.grid(row = 4, sticky = "w")
  125.  
  126.     def apply(self):
  127.         self.result = self.choice.get()
  128.  
  129. class editStatLeaf(sdg.Dialog):
  130.     def __init__(self, master = None, m = 0):
  131.         self.mode = m - 1
  132.         super().__init__(master)
  133.  
  134.     def body(self, master):
  135.         choices = ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
  136.         self.title("Edit " + choices[self.mode])
  137.         self.resizable(False, False)
  138.         tk.Label(master, text = "Enter your new " + choices[self.mode].lower() + ":", font = ftSmall).grid(row = 0)
  139.         tk.Label(master, text = "Enter your new " + choices[self.mode].lower() + " bonus:", font = ftSmall).grid(row = 2)
  140.         tk.Label(master, text = "Note: Blank/Unchanged fields\nwill result in no change", font = ftSmall).grid(row = 4)
  141.  
  142.         self.Value = tk.Entry(master, font = ftSmall)
  143.         self.Bonus = tk.Entry(master, font = ftSmall)
  144.  
  145.         self.Value.insert(0, mainStats[self.mode])
  146.         self.Bonus.insert(0, bonusStats[self.mode])
  147.  
  148.         self.Value.grid(row = 1)
  149.         self.Bonus.grid(row = 3)
  150.  
  151.     def apply(self):
  152.         try:
  153.             temp = []
  154.  
  155.             if len(self.Value.get()) > 0:
  156.                 temp.append(int(self.Value.get()))
  157.             else:
  158.                 temp.append("")
  159.  
  160.             if len(self.Bonus.get()) > 0:
  161.                 temp.append(int(self.Bonus.get()))
  162.             else:
  163.                 temp.append("")
  164.  
  165.             self.result = temp
  166.  
  167.         except:
  168.             mbx.showerror("Error","Invalid Input")
  169.             self.result = []
  170.  
  171. def editStat():
  172.     choice = editStatRoot(base).result
  173.  
  174.     if type(choice) == int:
  175.         if choice < 7:
  176.             temp = editStatLeaf(base, choice).result
  177.  
  178.         elif choice == 7:
  179.             temp = sdg.askinteger("Edit Level", "Enter your new level:", initialvalue = experience[0])
  180.             if type(temp) == int:
  181.                 experience[0] = temp
  182.                 experience[2] = 100 + 10 * experience[0]
  183.  
  184.         elif choice == 8:
  185.             temp = sdg.askinteger("Edit Experience", "Enter your new current experience points:", initialvalue = experience[1])
  186.             if type(temp) == int:
  187.                 experience[1] = temp
  188.                 while experience[1] > experience[2]:
  189.                     levelUp()
  190.  
  191.         elif choice == 9:
  192.             temp = health[1] + 1
  193.  
  194.             while temp > health[1]:
  195.                 temp = sdg.askinteger("Edit Health", "Enter your new current health:", initialvalue = health[0])
  196.                 if type(temp) != int:
  197.                     return
  198.                 elif temp > health[1]:
  199.                     mbx.showerror("Error", "You can't overcharge your health!")
  200.  
  201.             if type(temp) == int:
  202.                 health[0] = temp
  203.  
  204.         elif choice == 10:
  205.             temp = sdg.askinteger("Edit Health", "Enter your new maximum health:", initialvalue = health[1])
  206.             if type(temp) == int:
  207.                 health[1] = temp
  208.                 if health[0] > health[1]:
  209.                     health[0] = health[1]
  210.  
  211.         if type(temp) == list:
  212.             if type(temp[0]) == int:
  213.                 mainStats[choice - 1] = temp[0]
  214.  
  215.             if type(temp[1]) == int:
  216.                 bonusStats[choice - 1] = temp[1]
  217.  
  218.             refrSTAT()
  219.  
  220.         elif type(temp) == int:
  221.             refrSTAT()
  222.  
  223. def refrINFO():
  224.     NAMELbl.config(text = info[0])
  225.     CLSSLbl.config(text = info[1])
  226.     DETYLbl.config(text = info[2])
  227.     RACELbl.config(text = info[3])
  228.     GNDRLbl.config(text = info[4])
  229.     AYGELbl.config(text = "Age: " + str(info[5]))
  230.     HGHTLbl.config(text = str(info[6]) + " " + info[7])
  231.     WGHTLbl.config(text = str(info[8]) + " " + info[9])
  232.     HAIRLbl.config(text = "Hair: " + info[10])
  233.     EYESLbl.config(text = "Eyes: " + info[11])
  234.     MONYLbl.config(text = str(info[13]) + " " + info[12])
  235.  
  236. def changeMoney():
  237.     debit = sdg.askinteger("Change Money", "How much money to add/remove?")
  238.     if type(debit) == int:
  239.         info[13] += debit
  240.         refrINFO()
  241.  
  242. class editInfoRoot(sdg.Dialog):
  243.     def body(self, master):
  244.         self.title("Edit Info")
  245.         self.resizable(False, False)
  246.         self.choice = tk.IntVar()
  247.         self.choice.set(1)
  248.         tk.Label(master, text = "Choose an info item to edit:", font = ftSmall).grid(row = 0)
  249.        
  250.         Name = tk.Radiobutton(master, text = "Name", value = 1, variable = self.choice, cursor = "hand2", font = ftSmall)
  251.         Class = tk.Radiobutton(master, text = "Class", value = 2, variable = self.choice, cursor = "hand2", font = ftSmall)
  252.         Deity = tk.Radiobutton(master, text = "Deity", value = 3, variable = self.choice, cursor = "hand2", font = ftSmall)
  253.         Race = tk.Radiobutton(master, text = "Race", value = 4, variable = self.choice, cursor = "hand2", font = ftSmall)
  254.         Gender = tk.Radiobutton(master, text = "Gender", value = 5, variable = self.choice, cursor = "hand2", font = ftSmall)
  255.         Age = tk.Radiobutton(master, text = "Age", value = 6, variable = self.choice, cursor = "hand2", font = ftSmall)
  256.         Height = tk.Radiobutton(master, text = "Height", value = 7, variable = self.choice, cursor = "hand2", font = ftSmall)
  257.         Weight = tk.Radiobutton(master, text = "Weight", value = 8, variable = self.choice, cursor = "hand2", font = ftSmall)
  258.         HairColor = tk.Radiobutton(master, text = "Hair Color", value = 9, variable = self.choice, cursor = "hand2", font = ftSmall)
  259.         EyeColor = tk.Radiobutton(master, text = "Eye Color", value = 10, variable = self.choice, cursor = "hand2", font = ftSmall)
  260.         Currency = tk.Radiobutton(master, text = "Currency", value = 11, variable = self.choice, cursor = "hand2", font = ftSmall)
  261.  
  262.         Name.grid(row = 1, sticky = "w")
  263.         Class.grid(row = 2, sticky = "w")
  264.         Deity.grid(row = 3, sticky = "w")
  265.         Race.grid(row = 4, sticky = "w")
  266.         Gender.grid(row = 5, sticky = "w")
  267.         Age.grid(row = 6, sticky = "w")
  268.         Height.grid(row = 7, sticky = "w")
  269.         Weight.grid(row = 8, sticky = "w")
  270.         HairColor.grid(row = 9, sticky = "w")
  271.         EyeColor.grid(row = 10, sticky = "w")
  272.         Currency.grid(row = 11, sticky = "w")
  273.  
  274.     def apply(self):
  275.         self.result = self.choice.get()
  276.  
  277. class editWH(sdg.Dialog):
  278.     def __init__(self, master = None, m = 9):
  279.         self.mode = m - 7
  280.         super().__init__(master)
  281.  
  282.     def toggleUnit(self):
  283.         if self.ChangeUnit.get() == 1:
  284.             self.Unit.config(state = "normal")
  285.         else:
  286.             self.Unit.config(state = "disabled")
  287.  
  288.     def body(self, master):
  289.         choices = ["height", "weight"]
  290.         self.title("Edit " + choices[self.mode].title())
  291.         self.resizable(False, False)
  292.         self.ChangeUnit = tk.IntVar()
  293.         self.ChangeUnit.set(0)
  294.         tk.Label(master, text = "Enter your new " + choices[self.mode] + ":", font = ftSmall).grid(row = 0)
  295.  
  296.         self.Value = tk.Entry(master, font = ftSmall)
  297.         self.Unit = tk.Entry(master, font = ftSmall)
  298.  
  299.         if self.mode == 0:
  300.             self.Value.insert(0, info[6])
  301.             self.Unit.insert(0, info[7])
  302.         elif self.mode == 1:
  303.             self.Value.insert(0, info[8])
  304.             self.Unit.insert(0, info[9])
  305.  
  306.         self.Unit.config(state = "disabled")
  307.  
  308.         ChangeUnitChk = tk.Checkbutton(master, text = "Check to change unit", variable = self.ChangeUnit, command = self.toggleUnit, font = ftSmall)
  309.  
  310.         self.Value.grid(row = 1)
  311.         self.Unit.grid(row = 3)
  312.         ChangeUnitChk.grid(row = 2)
  313.  
  314.     def apply(self):
  315.         try:
  316.             self.result = [int(self.Value.get()), self.Unit.get(), self.ChangeUnit.get()]
  317.         except:
  318.             mbx.showerror("Error","Invalid Measurement")
  319.             self.result = []
  320.  
  321. def editInfo():
  322.     editInfoSelect(editInfoRoot(base).result)
  323.     refrINFO()
  324.  
  325. def editInfoSelect(choice):
  326.     if choice in range(1, 7) or choice in range(9, 12):
  327.         if choice < 8:
  328.             index = choice - 1
  329.         else:
  330.             index = choice + 1
  331.  
  332.         choices = ["", "name", "class", "deity", "race", "gender", "age", "", "", "hair color", "eye color", "currency"]
  333.        
  334.         if choice == 6:
  335.             temp = sdg.askinteger("Edit " + choices[choice].title(), "Enter your new " + choices[choice], initialvalue = info[index])
  336.    
  337.             if type(temp) == int:
  338.                 info[index] = temp
  339.  
  340.         elif choice != 6:
  341.             temp = sdg.askstring("Edit " + choices[choice].title(), "Enter your new " + choices[choice], initialvalue = info[index])
  342.    
  343.             if type(temp) == str:
  344.                 info[index] = temp
  345.  
  346.     elif choice in range(7, 9):
  347.         n = choice
  348.         if n < 8:
  349.             n -= 1
  350.  
  351.         temp = editWH(base, choice).result
  352.  
  353.         if type(temp) == list and len(temp) > 0:
  354.             info[n] = temp[0]
  355.             if temp[2] == 1:
  356.                 info[n + 1] = temp[1]
  357.  
  358. def refrINVT():
  359.     INVTTxt.delete(0, INVTTxt.size())
  360.  
  361.     tempWGHT = 0.0
  362.  
  363.     for item in inventory:
  364.  
  365.         tempWGHT += round(item[2] * item[3], 4)
  366.  
  367.         tempStr = ""
  368.         tempStr += item[0][:36]
  369.         if len(item[0]) > 36:
  370.             tempStr += "... "
  371.         else:
  372.             tempStr += (40 - len(item[0])) * " "
  373.  
  374.         tempStr += str(item[2])
  375.         tempStr += (8 - len(str(item[2]))) * " "
  376.         tempStr += str(item[3])
  377.         tempStr += (8 - len(str(item[3]))) * " "
  378.  
  379.         if item[4] != 0 and item[5]:
  380.             tempStr += "d" + str(item[4]) + " x" + str(item[5])
  381.             tempStr += (8 - len("d" + str(item[4]) + " x" + str(item[5]))) * " "
  382.         else:
  383.             tempStr += 8 * " "
  384.        
  385.         if item[7] != 0:
  386.             tempStr += str(item[6]) + "/" + str(item[7])
  387.             tempStr += (8 - len(str(item[6]) + "/" + str(item[7]))) * " "
  388.         else:
  389.             tempStr += 8 * " "
  390.  
  391.         if item[8]:
  392.             tempStr += "Yes"
  393.         else:
  394.             tempStr += "No"
  395.  
  396.         INVTTxt.insert("end", tempStr)
  397.  
  398.     INVTENCMLbl.config(text = "Encumberance: " + str(tempWGHT))
  399.  
  400. def newItem():
  401.     tempItem = []
  402.     tempStr = ""
  403.  
  404.     try:
  405.         while len(tempStr) == 0:
  406.             tempStr = sdg.askstring("New Item", "Enter the new item's name:")
  407.             if len(tempStr) == 0:
  408.                 mbx.showerror("Error", "You must name your item!")
  409.  
  410.         tempItem.append(tempStr)
  411.  
  412.         tempStr = sdg.askstring("New Item", "[Optional] Enter the new item's bonus(es):")
  413.         tempItem.append(tempStr)
  414.  
  415.         tempItem.append(sdg.askinteger("New Item", "Enter how many of the new item you have:"))
  416.         tempItem.append(sdg.askfloat("New Item", "Enter the weight of the item:"))
  417.         tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the type of dice the item uses:"))
  418.         tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the amount of dice rolls for the item:"))
  419.        
  420.         tempItem.append(sdg.askinteger("New Item", "[Optional] Enter the maximum magical charges the item has:"))
  421.         tempInt = tempItem[6] + 1
  422.         while tempInt > tempItem[6]:
  423.             tempInt = sdg.askinteger("New Item", "[Optional] Enter the current magical charges the item has:")
  424.             if tempInt > tempItem[6]:
  425.                 mbx.showerror("Error", "You can't overcharge your item!")
  426.         tempItem.insert(6, tempInt)
  427.                
  428.         tempItem.append(mbx.askyesno("New Item", "Is the item equipped?"))
  429.  
  430.         inventory.append(tempItem)
  431.         refrINVT()
  432.  
  433.     except TypeError:
  434.         pass
  435.  
  436. class editItemRoot(sdg.Dialog):
  437.     def __init__(self, master = None, i = ""):
  438.         self.item = i
  439.         super().__init__(master)
  440.  
  441.     def body(self, master):
  442.         self.title("Edit " + self.item)
  443.         self.resizable(False, False)
  444.         self.choice = tk.IntVar()
  445.         self.choice.set(0)
  446.         tk.Label(master, text = "Choose an item attribute to edit:", font = ftSmall).grid(row = 0)
  447.  
  448.         Name = tk.Radiobutton(master, text = "Name", value = 0, variable = self.choice, cursor = "hand2", font = ftSmall)
  449.         Bonus = tk.Radiobutton(master, text = "Bonus(es)", value = 1, variable = self.choice, cursor = "hand2", font = ftSmall)
  450.         Count = tk.Radiobutton(master, text = "Count", value = 2, variable = self.choice, cursor = "hand2", font = ftSmall)
  451.         Weight = tk.Radiobutton(master, text = "Weight", value = 3, variable = self.choice, cursor = "hand2", font = ftSmall)
  452.         dType = tk.Radiobutton(master, text = "Dice Type", value = 4, variable = self.choice, cursor = "hand2", font = ftSmall)
  453.         dCount = tk.Radiobutton(master, text = "Dice Count", value = 5, variable = self.choice, cursor = "hand2", font = ftSmall)
  454.         Charges = tk.Radiobutton(master, text = "Charges", value = 6, variable = self.choice, cursor = "hand2", font = ftSmall)
  455.         MaxCharges = tk.Radiobutton(master, text = "Max Charges", value = 7, variable = self.choice, cursor = "hand2", font = ftSmall)
  456.         Equipped = tk.Radiobutton(master, text = "Equipped", value = 8, variable = self.choice, cursor = "hand2", font = ftSmall)
  457.  
  458.         Name.grid(row = 1, sticky = "w")
  459.         Bonus.grid(row = 2, sticky = "w")
  460.         Count.grid(row = 3, sticky = "w")
  461.         Weight.grid(row = 4, sticky = "w")
  462.         dType.grid(row = 5, sticky = "w")
  463.         dCount.grid(row = 6, sticky = "w")
  464.         Charges.grid(row = 7, sticky = "w")
  465.         MaxCharges.grid(row = 8, sticky = "w")
  466.         Equipped.grid(row = 9, sticky = "w")
  467.  
  468.     def apply(self):
  469.         self.result = self.choice.get()
  470.  
  471. def editItem():
  472.     try:
  473.         index = INVTTxt.curselection()[0]
  474.         item = inventory[index]
  475.         attr = editItemRoot(base, item[0]).result
  476.  
  477.         if type(attr) == int:
  478.             choices = ["Name", "Bonus(es)", "Count", "Weight", "Dice Type", "Dice Count", "Charges", "Max Charges", ""]
  479.             title = "Edit " + item[0]
  480.             prompt = "Enter the item's new " + choices[attr] + ":"
  481.  
  482.             if attr < 2:
  483.                 temp = sdg.askstring(title, prompt, initialvalue = item[attr])
  484.  
  485.                 if type(temp) == str and len(temp) > 0 and temp != item[attr]:
  486.                     inventory[index][attr] = temp
  487.  
  488.             elif attr < 6 and attr != 3:
  489.                 temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
  490.  
  491.                 if type(temp) == int and temp != item[attr]:
  492.                     inventory[index][attr] = temp
  493.  
  494.             elif attr == 3:
  495.                 temp = sdg.askfloat(title, prompt, initialvalue = item[attr])
  496.  
  497.                 if type(temp) == float and temp != item[attr]:
  498.                     inventory[index][attr] = temp
  499.  
  500.             elif attr == 6:
  501.                 temp = item[7] + 1
  502.                 while type(temp) == int and temp > item[7]:
  503.                     temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
  504.                    
  505.                     if type(temp) == int and temp > item[7]:
  506.                         mbx.showerror("Error", "You can't overcharge your item!")
  507.  
  508.                 if type(temp) == int and temp != item[attr]:
  509.                     inventory[index][attr] = temp
  510.  
  511.             elif attr == 7:
  512.                 temp = sdg.askinteger(title, prompt, initialvalue = item[attr])
  513.  
  514.                 if type(temp) == int and temp != item[attr]:
  515.                     if temp < item[6]:
  516.                         inventory[index][6] = temp
  517.  
  518.                     inventory[index][attr] = temp
  519.  
  520.             else:
  521.                 inventory[index][attr] =  not inventory[index][attr]
  522.  
  523.             refrINVT()
  524.  
  525.     except IndexError:
  526.         mbx.showerror("Error", "No item selected!")
  527.  
  528.  
  529. def inspectItem():
  530.     try:
  531.         if len(inventory[INVTTxt.curselection()[0]][1]) > 0:
  532.             mbx.showinfo("Item: " + inventory[INVTTxt.curselection()[0]][0], "Bonus:\n" + inventory[INVTTxt.curselection()[0]][1])
  533.         else:
  534.             mbx.showinfo("Item: " + inventory[INVTTxt.curselection()[0]][0], "Bonus:\n[None]")
  535.  
  536.     except IndexError:
  537.         mbx.showerror("Error", "No item selected!")
  538.  
  539. def deleteItem():
  540.     try:
  541.         if mbx.askyesno("Delete Item: " + inventory[INVTTxt.curselection()[0]][0], "Are you sure you want to delete this item?"):
  542.             del inventory[INVTTxt.curselection()[0]]
  543.             refrINVT()
  544.  
  545.     except IndexError:
  546.         mbx.showerror("Error", "No item selected!")
  547.  
  548. class sortItemsRoot(sdg.Dialog):
  549.     def body(self, master):
  550.         self.title("Sort Items")
  551.         self.resizable(False, False)
  552.         self.choice = tk.IntVar()
  553.         self.order = tk.IntVar()
  554.         self.choice.set(0)
  555.         self.order.set(0)
  556.         tk.Label(master, text = "Choose an attribute to sort by:", font = ftSmall).grid(row = 0)
  557.         tk.Label(master, text = "Choose an order to sort by:", font = ftSmall).grid(row = 9)
  558.  
  559.         Name = tk.Radiobutton(master, text = "Name", value = 0, variable = self.choice, cursor = "hand2", font = ftSmall)
  560.         Count = tk.Radiobutton(master, text = "Count", value = 2, variable = self.choice, cursor = "hand2", font = ftSmall)
  561.         Weight = tk.Radiobutton(master, text = "Weight", value = 3, variable = self.choice, cursor = "hand2", font = ftSmall)
  562.         dType = tk.Radiobutton(master, text = "Dice Type", value = 4, variable = self.choice, cursor = "hand2", font = ftSmall)
  563.         dCount = tk.Radiobutton(master, text = "Dice Count", value = 5, variable = self.choice, cursor = "hand2", font = ftSmall)
  564.         Charges = tk.Radiobutton(master, text = "Charges", value = 6, variable = self.choice, cursor = "hand2", font = ftSmall)
  565.         MaxCharges = tk.Radiobutton(master, text = "Max Charges", value = 7, variable = self.choice, cursor = "hand2", font = ftSmall)
  566.         Equipped = tk.Radiobutton(master, text = "Equipped", value = 8, variable = self.choice, cursor = "hand2", font = ftSmall)
  567.         Ascending = tk.Radiobutton(master, text = "Ascending", value = 1, variable = self.order, cursor = "hand2", font = ftSmall)
  568.         Descending = tk.Radiobutton(master, text = "Descending", value = 0, variable = self.order, cursor = "hand2", font = ftSmall)
  569.  
  570.         Name.grid(row = 1, sticky = "w")
  571.         Count.grid(row = 2, sticky = "w")
  572.         Weight.grid(row = 3, sticky = "w")
  573.         dType.grid(row = 4, sticky = "w")
  574.         dCount.grid(row = 5, sticky = "w")
  575.         Charges.grid(row = 6, sticky = "w")
  576.         MaxCharges.grid(row = 7, sticky = "w")
  577.         Equipped.grid(row = 8, sticky = "w")
  578.         Ascending.grid(row = 10, sticky = "w")
  579.         Descending.grid(row = 11, sticky = "w")
  580.  
  581.     def apply(self):
  582.         self.result = [self.choice.get(), self.order.get()]
  583.  
  584. def sortItems():
  585.     choice = sortItemsRoot(base).result
  586.    
  587.     if type(choice) == list:
  588.         if choice[1] == 1:
  589.             order = True
  590.         else:
  591.             order = False
  592.  
  593.         inventory.sort(key = op.itemgetter(choice[0]), reverse = order)
  594.         refrINVT()
  595.  
  596. def rollDice(d):
  597.     def rollDiceWrap(dice = d):
  598.         if dice < 100:
  599.             DICELbl.config(text = str(rnd.randint(1, dice)) + " | d" + str(dice))
  600.         else:
  601.             DICELbl.config(text = str(rnd.randint(0, 100)) + " | d%")
  602.     return rollDiceWrap
  603.  
  604. def refrSKIL():
  605.     SKILTxt.delete(0, SKILTxt.size())
  606.     stats = ["STR", "DEX", "CON", "INT", "WIS", "CHA"]
  607.  
  608.     for sk in skills:
  609.         SKILTxt.insert("end", stats[sk[0]] + "|" + sk[1])
  610.  
  611. class skillStat(sdg.Dialog):
  612.     def __init__(self, master = None, m = "", sa = "", i = 0):
  613.         self.mode = m
  614.         self.skab = sa
  615.         self.index = i
  616.         super().__init__(master)
  617.  
  618.     def body(self, master):
  619.         self.resizable(False, False)
  620.         self.stat = tk.IntVar()
  621.  
  622.         if self.skab == "skill":
  623.             if self.mode == "edit":
  624.                 self.title("Edit " + skills[self.index][1])
  625.                 self.stat.set(skills[self.index][0])
  626.  
  627.             elif self.mode == "new":
  628.                 self.title("New Skill")
  629.                 self.stat.set(0)
  630.  
  631.         elif self.skab == "ability":
  632.             if self.mode == "edit":
  633.                 self.title("Edit " + abilities[self.index][1])
  634.                 self.stat.set(abilities[self.index][0])
  635.  
  636.             elif self.mode == "new":
  637.                 self.title("New Ability")
  638.                 self.stat.set(0)
  639.  
  640.  
  641.         PRMPLbl = tk.Label(master, font = ftSmall)
  642.         PRMPLbl.grid(row = 0)
  643.         if self.skab == "skill":
  644.             if self.mode == "edit":
  645.                 PRMPLbl.config(text = "[Optional] Choose a new stat for the skill:")
  646.             elif self.mode == "new":
  647.                 PRMPLbl.config(text = "Choose a stat for the skill:")
  648.         elif self.skab == "ability":
  649.             if self.mode == "edit":
  650.                 PRMPLbl.config(text = "[Optional] Choose a new stat for the ability:")
  651.             elif self.mode == "new":
  652.                 PRMPLbl.config(text = "Choose a stat for the ability:")
  653.  
  654.         STRBtn = tk.Radiobutton(master, text = "Strength", value = 0, variable = self.stat, font = ftSmall)
  655.         DEXBtn = tk.Radiobutton(master, text = "Dexterity", value = 1, variable = self.stat, font = ftSmall)
  656.         CONBtn = tk.Radiobutton(master, text = "Constitution", value = 2, variable = self.stat, font = ftSmall)
  657.         INTBtn = tk.Radiobutton(master, text = "Intelligence", value = 3, variable = self.stat, font = ftSmall)
  658.         WISBtn = tk.Radiobutton(master, text = "Wisdom", value = 4, variable = self.stat, font = ftSmall)
  659.         CHABtn = tk.Radiobutton(master, text = "Charisma", value = 5, variable = self.stat, font = ftSmall)
  660.        
  661.         STRBtn.grid(row = 1, sticky = "w")
  662.         DEXBtn.grid(row = 2, sticky = "w")
  663.         CONBtn.grid(row = 3, sticky = "w")
  664.         INTBtn.grid(row = 4, sticky = "w")
  665.         WISBtn.grid(row = 5, sticky = "w")
  666.         CHABtn.grid(row = 6, sticky = "w")
  667.  
  668.     def apply(self):
  669.         self.result = self.stat.get()
  670.  
  671. def newSkill():
  672.     tempStr = ""
  673.     while type(tempStr) == str and len(tempStr) < 1:
  674.         tempStr = sdg.askstring("New Skill", "Enter the new skill's name:")
  675.         if type(tempStr) == str and len(tempStr) < 1:
  676.             mbx.showerror("Error", "You must name this skill!")
  677.  
  678.     if type(tempStr) == str:
  679.         tempInt = skillStat(base, "new", "skill").result
  680.         if type(tempInt) == int:
  681.             skills.append([tempInt, tempStr])
  682.             refrSKIL()
  683.  
  684. def editSkill():
  685.     try:
  686.         index = SKILTxt.curselection()[0]
  687.         sk = skills[index]
  688.         tempStr = sdg.askstring("Edit " + sk[1], "[Optional] Enter the skill's new name:", initialvalue = sk[1])
  689.         if type(tempStr) == str:
  690.             if len(tempStr) > 0 and tempStr != sk[1]:
  691.                 skills[index][1] = tempStr
  692.            
  693.             tempInt = skillStat(base, "edit", "skill", index).result
  694.             if type(tempInt) == int and tempInt != sk[0]:
  695.                 skills[index][0] = tempInt
  696.  
  697.             refrSKIL()
  698.     except IndexError:
  699.         mbx.showerror("Error", "No skill selected!")
  700.  
  701. def deleteSkill():
  702.     try:
  703.         if mbx.askyesno("Delete " + skills[SKILTxt.curselection()[0]][1], "Are you sure you want to delete this skill?"):
  704.             del skills[SKILTxt.curselection()[0]]
  705.             refrSKIL()
  706.  
  707.     except IndexError:
  708.         mbx.showerror("Error", "No skill selected!")
  709.  
  710. class sortSkillsAbils(sdg.Dialog):
  711.     def __init__(self, master = None, sa = ""):
  712.         self.skab = sa
  713.         super().__init__(master)
  714.  
  715.     def body(self, master):
  716.         if self.skab == "skill":
  717.             self.title("Sort Skills")
  718.         elif self.skab == "ability":
  719.             self.title("Sort Abilities")
  720.         self.resizable(False, False)
  721.         self.choice = tk.IntVar()
  722.         self.order = tk.IntVar()
  723.         self.choice.set(0)
  724.         self.order.set(0)
  725.         tk.Label(master, text = "Choose an attribute to sort by:", font = ftSmall).grid(row = 0)
  726.         tk.Label(master, text = "Choose an order to sort by:", font = ftSmall).grid(row = 3)
  727.  
  728.         Name = tk.Radiobutton(master, text = "Name", value = 1, variable = self.choice, cursor = "hand2", font = ftSmall)
  729.         Stat = tk.Radiobutton(master, text = "Stat", value = 0, variable = self.choice, cursor = "hand2", font = ftSmall)
  730.         Ascending = tk.Radiobutton(master, text = "Ascending", value = 1, variable = self.order, cursor = "hand2", font = ftSmall)
  731.         Descending = tk.Radiobutton(master, text = "Descending", value = 0, variable = self.order, cursor = "hand2", font = ftSmall)
  732.  
  733.         Name.grid(row = 1, sticky = "w")
  734.         Stat.grid(row = 2, sticky = "w")
  735.         Ascending.grid(row = 4, sticky = "w")
  736.         Descending.grid(row = 5, sticky = "w")
  737.  
  738.     def apply(self):
  739.         self.result = [self.choice.get(), self.order.get()]
  740.  
  741. def sortSkills():
  742.     choice = sortSkillsAbils(base, "skill").result
  743.  
  744.     if type(choice) == list:
  745.         if choice[1] == 1:
  746.             order = True
  747.         else:
  748.             order = False
  749.  
  750.         skills.sort(key = op.itemgetter(choice[0]), reverse = order)
  751.         refrSKIL()
  752.  
  753. def refrABIL():
  754.     ABILTxt.delete(0, ABILTxt.size())
  755.     stats = ["STR", "DEX", "CON", "INT", "WIS", "CHA"]
  756.  
  757.     for ab in abilities:
  758.         ABILTxt.insert("end", stats[ab[0]] + "|" + ab[1])
  759.  
  760. def newAbility():
  761.     tempStrA = ""
  762.     while type(tempStrA) == str and len(tempStrA) < 1:
  763.         tempStrA = sdg.askstring("New Ability", "Enter the new ability's name:")
  764.        
  765.         if type(tempStrA) == str and len(tempStrA) < 1:
  766.             mbx.showerror("Error", "You must name this ability!")
  767.  
  768.     if type(tempStrA) == str:
  769.         tempInt = skillStat(base, "new", "ability").result
  770.        
  771.         if type(tempInt) == int:
  772.             tempStrB = sdg.askstring("New Ability", "Describe the new ability:")
  773.            
  774.             if type(tempStrB) == str:
  775.                 abilities.append([tempInt, tempStrA, tempStrB])
  776.                 refrABIL()
  777.  
  778. def editAbility():
  779.     try:
  780.         index = ABILTxt.curselection()[0]
  781.         ab = abilities[index]
  782.         tempStr = sdg.askstring("Edit " + ab[1], "[Optional] Enter the ability's new name:", initialvalue = ab[1])
  783.         if type(tempStr) == str:
  784.             if len(tempStr) > 0 and tempStr != ab[1]:
  785.                 abilities[index][1] = tempStr
  786.            
  787.             tempInt = skillStat(base, "edit", "ability", index).result
  788.             if type(tempInt) == int:
  789.                 if tempInt != ab[0]:
  790.                     abilities[index][0] = tempInt
  791.  
  792.                 tempStr = sdg.askstring("Edit " + ab[1], "[Optional] Describe the ability again:", initialvalue = ab[2])
  793.                 if type(tempStr) == str and len(tempStr) > 0 and tempStr != ab[2]:
  794.                     abilities[index][2] = tempStr
  795.  
  796.             refrABIL()
  797.     except IndexError:
  798.         mbx.showerror("Error", "No ability selected!")
  799.  
  800. def deleteAbility():
  801.     try:
  802.         if mbx.askyesno("Delete " + abilities[ABILTxt.curselection()[0]][1], "Are you sure you want to delete this ability?"):
  803.             del abilities[ABILTxt.curselection()[0]]
  804.             refrABIL()
  805.  
  806.     except IndexError:
  807.         mbx.showerror("Error", "No ability selected!")
  808.  
  809. def inspectAbility():
  810.     try:
  811.         if len(abilities[ABILTxt.curselection()[0]][2]) > 0:
  812.             mbx.showinfo("Ability: " + abilities[ABILTxt.curselection()[0]][1], "Description:\n" + abilities[ABILTxt.curselection()[0]][2])
  813.         else:
  814.             mbx.showinfo("Ability: " + abilities[ABILTxt.curselection()[0]][1], "Description:\n[None]")
  815.  
  816.     except IndexError:
  817.         mbx.showerror("Error", "No ability selected!")
  818.  
  819. def sortAbilities():
  820.     choice = sortSkillsAbils(base, "ability").result
  821.  
  822.     if type(choice) == list:
  823.         if choice[1] == 1:
  824.             order = True
  825.         else:
  826.             order = False
  827.  
  828.         abilities.sort(key = op.itemgetter(choice[0]), reverse = order)
  829.         refrABIL()
  830.  
  831. def exitOverride():
  832.     if mbx.askyesno("Warning! Data Loss Possibility Detected!", "Unsaved data will be lost if you quit.\nAre you sure you want to quit?"):
  833.         base.destroy()
  834.  
  835. def newCharacter():
  836.     if not mbx.askyesno("Warning! Data Loss Possibility Detected!", "Making a new character will erase all current data\nAre you sure you want to continue?"):
  837.         return
  838.  
  839.     tempInfo = []
  840.     tempHealth = []
  841.     tempExp = []
  842.     tempMStats = []
  843.     tempBStats = []
  844.     tempInt = 0
  845.     tempIntB = 0
  846.     tempStr = ""
  847.     tempCount = 0
  848.     infoChoices = ["name", "class", "deity", "race", "gender", "age", "height", "unit", "weight", "unit", "hair color", "eye color", "currency"]
  849.     statChoices = ["Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
  850.  
  851.     while len(tempInfo) < 14:
  852.         if tempCount < 5 or tempCount > 9:
  853.             tempStr = sdg.askstring("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
  854.             if type(tempStr) == str:
  855.                 tempInfo.append(tempStr)
  856.             else:
  857.                 return
  858.  
  859.             if tempCount == 12:
  860.                 tempInt = sdg.askinteger("New Character: Info", "Enter how much currency you have:")
  861.                 if type(tempInt) == int:
  862.                     tempInfo.append(tempInt)
  863.                 else:
  864.                     return
  865.             else:
  866.                 tempCount += 1
  867.  
  868.         elif tempCount > 5 and tempCount < 10:
  869.             tempStr = sdg.askstring("New Character: Info", "Enter your unit of " + infoChoices[tempCount] + ":")
  870.             if type(tempStr) != str:
  871.                 return
  872.  
  873.             tempInt = sdg.askinteger("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
  874.             if type(tempInt) == int:
  875.                 tempInfo.append(tempInt)
  876.                 tempInfo.append(tempStr)
  877.                 tempCount += 2
  878.             else:
  879.                 return
  880.  
  881.         elif tempCount == 5:
  882.             tempInt = sdg.askinteger("New Character: Info", "Enter your " + infoChoices[tempCount] + ":")
  883.             if type(tempInt) == int:
  884.                 tempInfo.append(tempInt)
  885.                 tempCount += 1
  886.             else:
  887.                 return
  888.  
  889.     tempInt = sdg.askinteger("New Character: Health", "Enter your maximum health points:")
  890.     if type(tempInt) != int:
  891.         return
  892.  
  893.     tempIntB = tempInt + 1
  894.     while tempIntB > tempInt or tempIntB < 0:
  895.         tempIntB = sdg.askinteger("New Character: Health", "Enter your current health points:")
  896.         if type(tempIntB) != int:
  897.             return
  898.         elif tempIntB > tempInt:
  899.             mbx.showerror("Error", "You can't overcharge your health points!")
  900.         elif tempIntB < 0:
  901.             mbx.showerror("Error", "You can't undercharge your health points!")
  902.  
  903.     tempHealth.append(tempIntB)
  904.     tempHealth.append(tempInt)
  905.  
  906.     tempInt = sdg.askinteger("New Character: Experience", "Enter your level:")
  907.     if type(tempInt) != int:
  908.         return
  909.     tempExp.append(tempInt)
  910.  
  911.     tempInt = 100 + tempExp[0] * 10
  912.     tempIntB = abs(sdg.askinteger("New Character: Experience", "Enter your current experience points:"))
  913.     if type(tempIntB) != int:
  914.         return
  915.  
  916.     tempExp.append(tempIntB)
  917.     tempExp.append(tempInt)
  918.  
  919.     tempCount = 0
  920.  
  921.     while len(tempMStats) < 6 and len(tempBStats) < 6:
  922.         tempInt = sdg.askinteger("New Character: Stats", "Enter your " + statChoices[tempCount] + ":")
  923.         if type(tempInt) != int:
  924.             return
  925.  
  926.         tempIntB = sdg.askinteger("New Character: Stats", "Enter your " + statChoices[tempCount] + " Bonus:")
  927.         if type(tempIntB) == int:
  928.             tempMStats.append(tempInt)
  929.             tempBStats.append(tempIntB)
  930.             tempCount += 1
  931.         else:
  932.             return
  933.  
  934.     tempCount = 0
  935.  
  936.     for bit in tempInfo:
  937.         info[tempCount] = bit
  938.         tempCount += 1
  939.  
  940.     tempCount = 0
  941.  
  942.     for bit in tempHealth:
  943.         health[tempCount] = bit
  944.         tempCount += 1
  945.  
  946.     tempCount = 0
  947.  
  948.     for bit in tempExp:
  949.         experience[tempCount] = bit
  950.         tempCount += 1
  951.  
  952.     tempCount = 0
  953.  
  954.     for bit in tempMStats:
  955.         mainStats[tempCount] = bit
  956.         tempCount += 1
  957.  
  958.     tempCount = 0
  959.  
  960.     for bit in tempBStats:
  961.         bonusStats[tempCount] = bit
  962.         tempCount += 1
  963.  
  964.     while len(skills) > 0:
  965.         del skills[0]
  966.  
  967.     while len(abilities) > 0:
  968.         del abilities[0]
  969.  
  970.     while len(inventory) > 0:
  971.         del inventory[0]
  972.  
  973.     refrSTAT()
  974.     refrINFO()
  975.     refrSKIL()
  976.     refrABIL()
  977.     refrINVT()
  978.  
  979. def saveCharacter():
  980.     fileName = sdg.askstring("Save Character", "Enter the name of the file to save to:")
  981.     if type(fileName) != str:
  982.         return
  983.  
  984.     fileName += ".dat"
  985.  
  986.     if os.path.isfile(fileName):
  987.         if not mbx.askyesno("Warning! File Already Exists!", "Do you want to overwrite " + fileName + "?"):
  988.             return
  989.  
  990.     saveFile = open(fileName, "w")
  991.  
  992.     dlm = " || "
  993.     adlm = " |\n"
  994.     nl = "\n\n"
  995.  
  996.     temp = 0
  997.  
  998.     for bit in info:
  999.         saveFile.write(str(bit))
  1000.  
  1001.         if temp == 13:
  1002.             saveFile.write(nl)
  1003.         else:
  1004.             saveFile.write(dlm)
  1005.  
  1006.         temp += 1
  1007.  
  1008.     temp = 0
  1009.  
  1010.     for bit in health:
  1011.         saveFile.write(str(bit))
  1012.  
  1013.         if temp == 1:
  1014.             saveFile.write(nl)
  1015.         else:
  1016.             saveFile.write(dlm)
  1017.  
  1018.         temp += 1
  1019.  
  1020.     temp = 0
  1021.  
  1022.     for bit in experience:
  1023.         saveFile.write(str(bit))
  1024.  
  1025.         if temp == 2:
  1026.             saveFile.write(nl)
  1027.         else:
  1028.             saveFile.write(dlm)
  1029.  
  1030.         temp += 1
  1031.  
  1032.     temp = 0
  1033.  
  1034.     for bit in mainStats:
  1035.         saveFile.write(str(bit))
  1036.  
  1037.         if temp == 5:
  1038.             saveFile.write(nl)
  1039.         else:
  1040.             saveFile.write(dlm)
  1041.  
  1042.         temp += 1
  1043.  
  1044.     temp = 0
  1045.  
  1046.     for bit in bonusStats:
  1047.         saveFile.write(str(bit))
  1048.  
  1049.         if temp == 5:
  1050.             saveFile.write(nl)
  1051.         else:
  1052.             saveFile.write(dlm)
  1053.  
  1054.         temp += 1
  1055.  
  1056.     temp = 1
  1057.  
  1058.     for sk in skills:
  1059.         saveFile.write(str(sk[0]) + dlm + sk[1])
  1060.  
  1061.         if temp != len(skills):
  1062.             saveFile.write(adlm)
  1063.  
  1064.         temp += 1
  1065.  
  1066.     saveFile.write(nl)
  1067.  
  1068.     temp = 1
  1069.  
  1070.     for ab in abilities:
  1071.         saveFile.write(str(ab[0]) + dlm + ab[1] + dlm + ab[2])
  1072.  
  1073.         if temp != len(abilities):
  1074.             saveFile.write(adlm)
  1075.  
  1076.         temp += 1
  1077.  
  1078.     saveFile.write(nl)
  1079.  
  1080.     temp = 1
  1081.  
  1082.     for item in inventory:
  1083.         tempAux = 1
  1084.  
  1085.         for bit in item:
  1086.             saveFile.write(str(bit))
  1087.             if tempAux < 9:
  1088.                 saveFile.write(dlm)
  1089.  
  1090.             tempAux += 1
  1091.  
  1092.         if temp != len(inventory):
  1093.             saveFile.write(adlm)
  1094.  
  1095.         temp += 1
  1096.  
  1097.     saveFile.close()
  1098.  
  1099.     mbx.showinfo("Save Character", "Saved!\nCheck the working directory of this program for the file.")
  1100.  
  1101. def loadCharacter():
  1102.     loaded = False
  1103.  
  1104.     while not loaded:
  1105.         try:
  1106.             fileName = sdg.askstring("Load Character", "Enter the name of the file to load from:")
  1107.             if type(fileName) != str:
  1108.                 return
  1109.  
  1110.             fileName += ".dat"
  1111.             loadFile = open(fileName, "r")
  1112.             loaded = True
  1113.  
  1114.         except FileNotFoundError:
  1115.             mbx.showerror("Error", "File not found!")
  1116.  
  1117.     dlm = " || "
  1118.     adlm = " |\n"
  1119.     nl = "\n\n"
  1120.  
  1121.     contents = loadFile.read().split(nl)
  1122.  
  1123.     tempCountA = 0
  1124.  
  1125.     try:
  1126.         for bit in contents:
  1127.             tempList = []
  1128.  
  1129.             if adlm in bit:
  1130.                 tempList = bit.split(adlm)
  1131.                 tempCountB = 0
  1132.  
  1133.                 for item in tempList:
  1134.                     tempList[tempCountB] = item.split(dlm)
  1135.                     tempCountC = 0
  1136.  
  1137.                     for el in tempList[tempCountB]:
  1138.                         if el == "True":
  1139.                             tempList[tempCountB][tempCountC] = True
  1140.                         elif el == "False":
  1141.                             tempList[tempCountB][tempCountC] = False
  1142.                         else:
  1143.                             try:
  1144.                                 tempList[tempCountB][tempCountC] = int(el)
  1145.                
  1146.                             except ValueError:
  1147.                                 try:
  1148.                                     tempList[tempCountB][tempCountC] = float(el)
  1149.                                 except ValueError:
  1150.                                     pass
  1151.    
  1152.                         tempCountC += 1
  1153.    
  1154.                     tempCountB += 1
  1155.  
  1156.             elif dlm in bit:
  1157.                 tempList = bit.split(dlm)
  1158.                 tempCountB = 0
  1159.  
  1160.                 for el in tempList:
  1161.                     try:
  1162.                         tempList[tempCountB] = int(el)
  1163.                
  1164.                     except ValueError:
  1165.                         try:
  1166.                             tempList[tempCountB] = float(el)
  1167.                         except ValueError:
  1168.                             pass
  1169.        
  1170.                     tempCountB += 1
  1171.    
  1172.             contents[tempCountA] = tempList
  1173.  
  1174.             tempCountA += 1
  1175.  
  1176.     except:
  1177.         mbx.showerror("Error", "Unable to Load File!")
  1178.         return
  1179.  
  1180.     tempCount = 0
  1181.  
  1182.     for bit in contents[0]:
  1183.         info[tempCount] = bit
  1184.         tempCount += 1
  1185.  
  1186.     tempCount = 0
  1187.  
  1188.     for bit in contents[1]:
  1189.         health[tempCount] = bit
  1190.         tempCount += 1
  1191.  
  1192.     tempCount = 0
  1193.  
  1194.     for bit in contents[2]:
  1195.         experience[tempCount] = bit
  1196.         tempCount += 1
  1197.  
  1198.     tempCount = 0
  1199.  
  1200.     for bit in contents[3]:
  1201.         mainStats[tempCount] = bit
  1202.         tempCount += 1
  1203.  
  1204.     tempCount = 0
  1205.  
  1206.     for bit in contents[4]:
  1207.         bonusStats[tempCount] = bit
  1208.         tempCount += 1
  1209.  
  1210.     while len(skills) > 0:
  1211.         del skills[0]
  1212.  
  1213.     for bit in contents[5]:
  1214.         skills.append(bit)
  1215.  
  1216.     while len(abilities) > 0:
  1217.         del abilities[0]
  1218.  
  1219.     for bit in contents[6]:
  1220.         abilities.append(bit)
  1221.  
  1222.     while len(inventory) > 0:
  1223.         del inventory[0]
  1224.  
  1225.     for bit in contents[7]:
  1226.         inventory.append(bit)
  1227.  
  1228.     mbx.showinfo("Load Character", "Loaded!\nYour journey continues...")
  1229.     refrSTAT()
  1230.     refrINFO()
  1231.     refrINVT()
  1232.     refrSKIL()
  1233.     refrABIL()
  1234.  
  1235. mainStats = [0, 0, 0, 0, 0, 0]
  1236. bonusStats = [0, 0, 0, 0, 0, 0]
  1237. savingThrows = [0, 0, 0]
  1238. health = [0, 10]
  1239. experience = [1, 0, 110]
  1240. info = ["name", "class", "deity", "race", "gender", 18, 170, "cm", 70, "kg", "brown", "black", "currency", 0]
  1241. skills = []
  1242. abilities = []
  1243. inventory = []
  1244.  
  1245. base = tk.Tk()
  1246. base.protocol("WM_DELETE_WINDOW", exitOverride)
  1247.  
  1248. ftSmall = tkf.Font(family = "Consolas", size = 8)
  1249. ftNormal = tkf.Font(family = "Consolas", size = 10)
  1250. ftNormUnd = tkf.Font(family = "Consolas", size = 10, underline = 1)
  1251. ftLarge = tkf.Font(family = "Consolas", size = 12)
  1252. ftTitle = tkf.Font(family = "Consolas", size = 12, weight = "bold", slant = "italic")
  1253. ftBigTitle = tkf.Font(family = "Consolas", size = 16, weight = "bold", slant = "italic")
  1254. ftSubtitle = tkf.Font(family = "Consolas", size = 12, slant = "italic")
  1255. ftDice = tkf.Font(family = "Consolas", size = 12, weight = "bold")
  1256.  
  1257. STATPnl = tk.Frame(base, bd = 4, relief = "groove")
  1258. STATPnl.grid(row = 1, column = 0, rowspan = 2, padx = 4, pady = 4, sticky = "n")
  1259.  
  1260. STATTitl = tk.Label(STATPnl, text = "Stats", width = 8, bd = 4, relief = "raised", font = ftTitle)
  1261. LEVLLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1262. XPLbl = tk.Label(STATPnl, width = 16, relief = "ridge", font = ftNormal)
  1263. XPPlusBtn = tk.Button(STATPnl, text = "+", command = XPUp, cursor = "hand2", font = ftSmall)
  1264. HPLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1265. HPPLUSBtn = tk.Button(STATPnl, text = "+", command = HPUp, cursor = "hand2", font = ftSmall)
  1266. HPMINSBtn = tk.Button(STATPnl, text = "-", command = HPDown, cursor = "hand2", font = ftSmall)
  1267.  
  1268. STRLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1269. DEXLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1270. CONLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1271. INTLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1272. WISLbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1273. CHALbl = tk.Label(STATPnl, width = 10, relief = "ridge", font = ftLarge)
  1274.  
  1275. STRBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1276. DEXBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1277. CONBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1278. INTBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1279. WISBLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1280. CHABLbl = tk.Label(STATPnl, width = 4, relief = "ridge", font = ftNormal)
  1281.  
  1282. FORTLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
  1283. REFLLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
  1284. WILLLbl = tk.Label(STATPnl, width = 16, anchor = "e", relief = "ridge", font = ftNormal)
  1285. STATEDITBtn = tk.Button(STATPnl, text = "Edit Stats", width = 10, command = editStat, cursor = "hand2", font = ftSmall)
  1286.  
  1287. STATTitl.grid(row = 0, columnspan = 3, pady = 2)
  1288. LEVLLbl.grid(row = 1, columnspan = 3, pady = 2)
  1289. XPLbl.grid(row = 2, column = 0, columnspan = 2, pady = 2)
  1290. XPPlusBtn.grid(row = 2, column = 2)
  1291. HPLbl.grid(row = 3, column = 0, pady = 2)
  1292. HPPLUSBtn.grid(row = 3, column = 1)
  1293. HPMINSBtn.grid(row = 3, column = 2, padx = 4)
  1294.  
  1295. STRLbl.grid(row = 4, column = 0, padx = 4, pady = 2)
  1296. DEXLbl.grid(row = 5, column = 0, padx = 4, pady = 2)
  1297. CONLbl.grid(row = 6, column = 0, padx = 4, pady = 2)
  1298. INTLbl.grid(row = 7, column = 0, padx = 4, pady = 2)
  1299. WISLbl.grid(row = 8, column = 0, padx = 4, pady = 2)
  1300. CHALbl.grid(row = 9, column = 0, padx = 4, pady = 2)
  1301.  
  1302. STRBLbl.grid(row = 4, column = 1, columnspan = 2, padx = 4, pady = 2)
  1303. DEXBLbl.grid(row = 5, column = 1, columnspan = 2, padx = 4, pady = 2)
  1304. CONBLbl.grid(row = 6, column = 1, columnspan = 2, padx = 4, pady = 2)
  1305. INTBLbl.grid(row = 7, column = 1, columnspan = 2, padx = 4, pady = 2)
  1306. WISBLbl.grid(row = 8, column = 1, columnspan = 2, padx = 4, pady = 2)
  1307. CHABLbl.grid(row = 9, column = 1, columnspan = 2, padx = 4, pady = 2)
  1308.  
  1309. FORTLbl.grid(row = 10, columnspan = 3, padx = 4, pady = 2)
  1310. REFLLbl.grid(row = 11, columnspan = 3, padx = 4, pady = 2)
  1311. WILLLbl.grid(row = 12, columnspan = 3, padx = 4, pady = 2)
  1312. STATEDITBtn.grid(row = 13, columnspan = 3, padx = 4, pady = 2)
  1313.  
  1314. refrSTAT()
  1315.  
  1316. INFOPnl = tk.Frame(base, bd = 4, relief = "groove")
  1317. INFOPnl.grid(row = 1, column = 1, padx = 4, pady = 4, sticky = "nw")
  1318.  
  1319. INFOTitl = tk.Label(INFOPnl, text ="Information", width = 32, bd = 4, relief = "raised", font = ftTitle)
  1320. INFOTitl.grid(row = 0, columnspan = 4, pady = 2)
  1321.  
  1322. NAMELbl = tk.Label(INFOPnl, width = 48, bd = 4, relief = "ridge", font = ftLarge)
  1323. CLSSLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1324. DETYLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1325. RACELbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1326. GNDRLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1327. AYGELbl = tk.Label(INFOPnl, width = 8, relief = "ridge", font = ftLarge)
  1328. HGHTLbl = tk.Label(INFOPnl, width = 8, relief = "ridge", font = ftLarge)
  1329. WGHTLbl = tk.Label(INFOPnl, width = 8, relief = "ridge", font = ftLarge)
  1330. INFOEDITBtn = tk.Button(INFOPnl, text = "Edit Info", width = 8, command = editInfo, cursor = "hand2", font = ftSmall)
  1331. HAIRLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1332. EYESLbl = tk.Label(INFOPnl, width = 24, relief = "ridge", font = ftLarge)
  1333. MONYLbl = tk.Label(INFOPnl, width = 32, relief = "ridge", font = ftLarge)
  1334. MONYCHNGBtn = tk.Button(INFOPnl, text = "Credit/Debit", width = 12, command = changeMoney, cursor = "hand2", font = ftSmall)
  1335.  
  1336. NAMELbl.grid(row = 1, columnspan = 4, pady = 4)
  1337. CLSSLbl.grid(row = 2, column = 0, columnspan = 2, pady = 4)
  1338. DETYLbl.grid(row = 3, column = 0, columnspan = 2, pady = 4)
  1339. RACELbl.grid(row = 2, column = 2, columnspan = 2, padx = 2)
  1340. GNDRLbl.grid(row = 3, column = 2, columnspan = 2, padx = 2)
  1341. AYGELbl.grid(row = 5, column = 0, pady = 4)
  1342. HGHTLbl.grid(row = 5, column = 1)
  1343. WGHTLbl.grid(row = 5, column = 2)
  1344. INFOEDITBtn.grid(row = 5, column = 3)
  1345. HAIRLbl.grid(row = 4, column = 0, columnspan = 2, pady = 4)
  1346. EYESLbl.grid(row = 4, column = 2, columnspan = 2)
  1347. MONYLbl.grid(row = 6, column = 0, columnspan = 3)
  1348. MONYCHNGBtn.grid(row = 6, column = 3, pady = 11)
  1349.  
  1350. refrINFO()
  1351.  
  1352. INVTPnl = tk.Frame(base, bd = 4, relief = "groove")
  1353. INVTPnl.grid(row = 2, column = 1, rowspan = 2, columnspan = 2, padx = 4, pady = 4, sticky = "w")
  1354.  
  1355. INVTTitl = tk.Label(INVTPnl, text = "Inventory", width = 24, bd = 4, relief = "raised", font = ftTitle)
  1356. INVTNEWWBtn = tk.Button(INVTPnl, text = "Create Item", width = 12, command = newItem, cursor = "hand2", font = ftSmall)
  1357. INVTEDITBtn = tk.Button(INVTPnl, text = "Edit Item", width = 12, command = editItem, cursor = "hand2", font = ftSmall)
  1358. INVTDELTBtn = tk.Button(INVTPnl, text = "Delete Item", width = 12, command = deleteItem, cursor = "hand2", font = ftSmall)
  1359. INVTINSPBtn = tk.Button(INVTPnl, text = "Inspect Item", width = 12, command = inspectItem, cursor = "hand2", font = ftSmall)
  1360. INVTSORTBtn = tk.Button(INVTPnl, text = "Sort Items", width = 12, command = sortItems, cursor = "hand2", font = ftSmall)
  1361. INVTLbl = tk.Label(INVTPnl, text = "Name\t\t\t\t\tCount\tWeight\tDice\tCharges\tEquipped", font = ftNormUnd)
  1362. INVTTxt = tk.Listbox(INVTPnl, height = 10, width = 80, cursor = "cross", font = ftNormal)
  1363. IVNTScr = tk.Scrollbar(INVTPnl, orient = "vertical", command = INVTTxt.yview)
  1364. INVTTxt.config(yscrollcommand = IVNTScr.set)
  1365. INVTENCMLbl = tk.Label(INVTPnl, text = "Encumberance:", width = 24, anchor = "w", relief = "ridge", font = ftNormal)
  1366.  
  1367. INVTTitl.grid(row = 0, column = 0, pady = 2)
  1368. INVTNEWWBtn.grid(row = 0, column = 1)
  1369. INVTEDITBtn.grid(row = 0, column = 2)
  1370. INVTDELTBtn.grid(row = 1, column = 2, columnspan = 2)
  1371. INVTINSPBtn.grid(row = 1, column = 1, columnspan = 2)
  1372. INVTSORTBtn.grid(row = 0, column = 3)
  1373. INVTLbl.grid(row = 2, columnspan = 4, sticky = "w")
  1374. INVTTxt.grid(row = 3, column = 0, columnspan = 4)
  1375. IVNTScr.grid(row = 2, column = 4, rowspan = 2, sticky = "ns")
  1376. INVTENCMLbl.grid(row = 4, columnspan = 5, pady = 4, sticky = "e")
  1377.  
  1378. refrINVT()
  1379.  
  1380. DICEPnl = tk.Frame(base, bd = 4, relief = "groove")
  1381. DICEPnl.grid(row = 3, column = 0, padx = 4, pady = 4, sticky = "s")
  1382.  
  1383. DICETitl = tk.Label(DICEPnl, text = "Dice", width = 8, bd = 4, relief = "raised", font = ftTitle)
  1384. DICELbl = tk.Label(DICEPnl, text = "0 | d?", width = 8, relief = "groove", font = ftDice)
  1385. DICEd4Btn = tk.Button(DICEPnl, text = "d4", command = rollDice(4), cursor = "hand2", font = ftSmall)
  1386. DICEd6Btn = tk.Button(DICEPnl, text = "d6", command = rollDice(6), cursor = "hand2", font = ftSmall)
  1387. DICEd8Btn = tk.Button(DICEPnl, text = "d8", command = rollDice(8), cursor = "hand2", font = ftSmall)
  1388. DICEd10Btn = tk.Button(DICEPnl, text = "d10", command = rollDice(10), cursor = "hand2", font = ftSmall)
  1389. DICEd12Btn = tk.Button(DICEPnl, text = "d12", command = rollDice(12), cursor = "hand2", font = ftSmall)
  1390. DICEd20Btn = tk.Button(DICEPnl, text = "d20", command = rollDice(20), cursor = "hand2", font = ftSmall)
  1391. DICEd100Btn = tk.Button(DICEPnl, text = "d100", command = rollDice(100), cursor = "hand2", font = ftSmall)
  1392.  
  1393. DICETitl.grid(row = 0, column = 0, columnspan = 3, pady = 2)
  1394. DICELbl.grid(row = 1, column = 0, columnspan = 3, padx = 36, pady = 2)
  1395. DICEd4Btn.grid(row = 2, column = 0, pady = 2)
  1396. DICEd6Btn.grid(row = 2, column = 1, pady = 2)
  1397. DICEd8Btn.grid(row = 2, column = 2, pady = 2)
  1398. DICEd10Btn.grid(row = 3, column = 0, pady = 2)
  1399. DICEd12Btn.grid(row = 3, column = 1, pady = 2)
  1400. DICEd20Btn.grid(row = 3, column = 2, pady = 2)
  1401. DICEd100Btn.grid(row = 4, column = 1, pady = 2)
  1402.  
  1403. SKILPnl = tk.Frame(base, bd = 4, relief = "groove")
  1404. SKILPnl.grid(row = 2, column = 3, rowspan = 2, padx = 4, pady = 4, sticky = "n")
  1405.  
  1406. SKILTitl = tk.Label(SKILPnl, text = "Skills", width = 8, bd = 4, relief = "raised", font = ftTitle)
  1407. SKILTxt = tk.Listbox(SKILPnl, height = 10, width = 32, cursor = "cross", font = ftNormal)
  1408. SKILScrV = tk.Scrollbar(SKILPnl, orient = "vertical", command = SKILTxt.yview)
  1409. SKILScrH = tk.Scrollbar(SKILPnl, orient = "horizontal", command = SKILTxt.xview)
  1410. SKILTxt.config(yscrollcommand = SKILScrV.set, xscrollcommand = SKILScrH.set)
  1411. SKILNEWWBtn = tk.Button(SKILPnl, text = "Create Skill", width = 12, command = newSkill, cursor = "hand2", font = ftSmall)
  1412. SKILEDITBtn = tk.Button(SKILPnl, text = "Edit Skill", width = 12, command = editSkill, cursor = "hand2", font = ftSmall)
  1413. SKILDELTBtn = tk.Button(SKILPnl, text = "Delete Skill", width = 12, command = deleteSkill, cursor = "hand2", font = ftSmall)
  1414. SKILSORTBtn = tk.Button(SKILPnl, text = "Sort Skills", width = 12, command = sortSkills, cursor = "hand2", font = ftSmall)
  1415.  
  1416. SKILTitl.grid(row = 0, columnspan = 3, pady = 2)
  1417. SKILTxt.grid(row = 3, column = 0, columnspan = 2)
  1418. SKILScrV.grid(row = 3, column = 2, rowspan = 2, sticky = "ns")
  1419. SKILScrH.grid(row = 4, column = 0, columnspan = 2, sticky = "we")
  1420. SKILNEWWBtn.grid(row = 1, column = 0, pady = 2)
  1421. SKILEDITBtn.grid(row = 1, column = 1)
  1422. SKILDELTBtn.grid(row = 2, column = 0, pady = 2)
  1423. SKILSORTBtn.grid(row = 2, column = 1)
  1424.  
  1425. refrSKIL()
  1426.  
  1427. ABILPnl = tk.Frame(base, bd = 4, relief = "groove")
  1428. ABILPnl.grid(row = 1, column = 2, columnspan = 2, padx = 4, pady = 4, sticky = "n")
  1429.  
  1430. ABILTitl = tk.Label(ABILPnl, text = "Abilities", width = 16, bd = 4, relief = "raised", font = ftTitle)
  1431. ABILTxt = tk.Listbox(ABILPnl, height = 10, width = 48, cursor = "cross", font = ftNormal)
  1432. ABILScrV = tk.Scrollbar(ABILPnl, orient = "vertical", command = ABILTxt.yview)
  1433. ABILScrH = tk.Scrollbar(ABILPnl, orient = "horizontal", command = ABILTxt.xview)
  1434. ABILTxt.config(yscrollcommand = ABILScrV.set, xscrollcommand = ABILScrH.set)
  1435. ABILNEWWBtn = tk.Button(ABILPnl, text = "Create Ability", width = 16, command = newAbility, cursor = "hand2", font = ftSmall)
  1436. ABILEDITBtn = tk.Button(ABILPnl, text = "Edit Ability", width = 16, command = editAbility, cursor = "hand2", font = ftSmall)
  1437. ABILDELTBtn = tk.Button(ABILPnl, text = "Delete Ability", width = 16, command = deleteAbility, cursor = "hand2", font = ftSmall)
  1438. ABILINSPBtn = tk.Button(ABILPnl, text = "Inspect Ability", width = 16, command = inspectAbility, cursor = "hand2", font = ftSmall)
  1439. ABILSORTBtn = tk.Button(ABILPnl, text = "Sort Abilities", width = 16, command = sortAbilities, cursor = "hand2", font = ftSmall)
  1440.  
  1441. ABILTitl.grid(row = 0, columnspan = 4)
  1442. ABILTxt.grid(row = 3, column = 0, columnspan = 3)
  1443. ABILScrV.grid(row = 3, column = 3, rowspan = 2, sticky = "ns")
  1444. ABILScrH.grid(row = 4, columnspan = 3, sticky = "we")
  1445. ABILNEWWBtn.grid(row = 1, column = 0, pady = 2)
  1446. ABILEDITBtn.grid(row = 1, column = 1)
  1447. ABILDELTBtn.grid(row = 2, column = 1, columnspan = 2, pady = 2)
  1448. ABILINSPBtn.grid(row = 2, column = 0, columnspan = 2)
  1449. ABILSORTBtn.grid(row = 1, column = 2, columnspan = 2, padx = 8)
  1450.  
  1451. MENUPnl = tk.Frame(base, bd = 4, relief = "groove")
  1452. MENUPnl.grid(row = 0, columnspan = 4, pady = 4)
  1453.  
  1454. MENUTitl = tk.Label(MENUPnl, text = "C²'s D&D Character Sheet", width = 64, bd = 4, relief = "raised", font = ftBigTitle)
  1455. MENUNEWWBtn = tk.Button(MENUPnl, text = "New Character", width = 16, command = newCharacter, cursor = "hand2", font = ftLarge)
  1456. MENUSAVEBtn = tk.Button(MENUPnl, text = "Save Character", width = 16, command = saveCharacter, cursor = "hand2", font = ftLarge)
  1457. MENULOADBtn = tk.Button(MENUPnl, text = "Load Character", width = 16, command = loadCharacter, cursor = "hand2", font = ftLarge)
  1458. MENUVERS = tk.Label(MENUPnl, text = "Version 1.0", width = 16, bd = 4, relief = "ridge", font = ftSubtitle)
  1459.  
  1460. MENUTitl.grid(row = 0, columnspan = 4, padx = 16, pady = 4)
  1461. MENUNEWWBtn.grid(row = 1, column = 0, pady = 4)
  1462. MENUSAVEBtn.grid(row = 1, column = 1)
  1463. MENULOADBtn.grid(row = 1, column = 2)
  1464. MENUVERS.grid(row = 1, column = 3)
  1465.  
  1466. base.title("DnD Character Sheet")
  1467. base.resizable(False, False)
  1468. base.mainloop()
RAW Paste Data