When running the code i get this error
Traceback (most recent call last):
File "C:UsersEastyOneDriveDocumentsbankbankCode.pyw", line 302, in <module>
app = ResourceTracker(master=root)
File "C:UsersEastyOneDriveDocumentsbankbankCode.pyw", line 19, in __init__
self.military_costs = self.load_military_costs()
File "C:UsersEastyOneDriveDocumentsbankbankCode.pyw", line 55, in load_military_costs
military_costs[current_unit]["Cost"][parts[1]] = int(parts[0])
ValueError: invalid literal for int() with base 10: 'Animal'
This is the code
import tkinter as tk
from tkinter import ttk, messagebox, simpledialog
import json
import random
class ResourceTracker:
def __init__(self, master):
self.master = master
self.master.title("Player Resource Tracker")
self.players = {}
self.resources = ["Money", "Oil", "Metal", "Animal", "Plant", "Rubber"]
self.militaries = [
"Soldier", "AntiAir", "AntiTank", "Artillery", "Tank", "Motorized", "Truck",
"Destroyer", "Frigate", "AntiAirShip", "Submarine", "Battleship", "AircraftCarrier",
"Convoy", "ColonyShip", "Fighter", "Bomber"
]
self.land_resources = ["Oil", "Metal", "Animal", "Plant", "Rubber"]
self.military_costs = self.load_military_costs()
self.load_data()
self.create_widgets()
self.update_player_list()
self.reset_click_count = 0
def load_military_costs(self):
military_costs = {}
with open("militaryCost.txt", "r") as file:
lines = file.readlines()
current_unit = None
for line in lines:
line = line.strip()
if not line:
continue
if line in self.militaries:
current_unit = line
military_costs[current_unit] = {"Upkeep": {}, "Cost": {}}
elif current_unit:
if "Upkeep:" in line:
parts = line.replace("Upkeep:", "").strip().split()
if parts[1] == "Animal":
military_costs[current_unit]["Upkeep"]["Animal"] = int(parts[0])
elif parts[1] == "Unspecified":
military_costs[current_unit]["Upkeep"]["Unspecified"] = 0
else:
military_costs[current_unit]["Upkeep"][parts[1]] = int(parts[0])
elif "Cost:" in line:
continue
else:
parts = line.split()
if len(parts) >= 2:
if parts[1] == "Animal":
military_costs[current_unit]["Cost"]["Animal"] = int(parts[0])
else:
military_costs[current_unit]["Cost"][parts[1]] = int(parts[0])
return military_costs
def load_data(self):
try:
with open("bank.json", "r") as file:
self.players = json.load(file)
for player, data in self.players.items():
if "Militaries" not in data:
data["Militaries"] = {unit: 0 for unit in self.militaries}
if "ResourceLand" not in data:
data["ResourceLand"] = {resource: 0 for resource in self.land_resources}
except FileNotFoundError:
pass
def save_data(self):
with open("bank.json", "w") as file:
json.dump(self.players, file, indent=4)
def create_widgets(self):
self.player_list_label = tk.Label(self.master, text="Players")
self.player_list_label.grid(row=0, column=0, padx=5, pady=5)
self.player_listbox = tk.Listbox(self.master)
self.player_listbox.grid(row=1, column=0, padx=5, pady=5, rowspan=6)
self.player_listbox.bind("<<ListboxSelect>>", self.on_player_select)
self.resources_frame = tk.Frame(self.master, bd=2, relief=tk.SUNKEN)
self.resources_frame.grid(row=0, column=1, padx=5, pady=5, rowspan=6)
self.resource_labels = {}
for i, resource in enumerate(self.resources):
label = tk.Label(self.resources_frame, text=f"{resource}:")
label.grid(row=i, column=0, sticky=tk.W)
self.resource_labels[resource] = tk.Label(self.resources_frame, text="0")
self.resource_labels[resource].grid(row=i, column=1, sticky=tk.W)
self.militaries_frame = tk.Frame(self.master, bd=2, relief=tk.SUNKEN)
self.militaries_frame.grid(row=0, column=3, padx=5, pady=5, rowspan=6)
self.military_labels = {}
for i, military in enumerate(self.militaries):
label = tk.Label(self.militaries_frame, text=f"{military}:")
label.grid(row=i, column=0, sticky=tk.W)
self.military_labels[military] = tk.Label(self.militaries_frame, text="0")
self.military_labels[military].grid(row=i, column=1, sticky=tk.W)
self.resource_land_frame = tk.Frame(self.master, bd=2, relief=tk.SUNKEN)
self.resource_land_frame.grid(row=7, column=0, columnspan=2, padx=5, pady=5, sticky=tk.W+tk.E)
self.resource_land_labels = {}
for i, land_resource in enumerate(self.land_resources):
label = tk.Label(self.resource_land_frame, text=f"{land_resource}:")
label.grid(row=i, column=0, sticky=tk.W)
self.resource_land_labels[land_resource] = tk.Label(self.resource_land_frame, text="0")
self.resource_land_labels[land_resource].grid(row=i, column=1, sticky=tk.W)
self.selected_player = tk.StringVar()
self.selected_resource = tk.StringVar()
self.selected_military = tk.StringVar()
self.selected_land_resource = tk.StringVar()
self.selected_military_player = tk.StringVar()
self.selected_land_resource_player = tk.StringVar()
self.player_dropdown = ttk.Combobox(self.master, textvariable=self.selected_player)
self.player_dropdown.grid(row=1, column=2, padx=5, pady=5)
self.resource_dropdown = ttk.Combobox(self.master, textvariable=self.selected_resource)
self.resource_dropdown['values'] = self.resources
self.resource_dropdown.grid(row=2, column=2, padx=5, pady=5)
self.military_player_dropdown = ttk.Combobox(self.master, textvariable=self.selected_military_player)
self.military_player_dropdown.grid(row=7, column=3, padx=5, pady=5)
self.military_player_dropdown['values'] = list(self.players.keys())
self.military_dropdown = ttk.Combobox(self.master, textvariable=self.selected_military)
self.military_dropdown['values'] = self.militaries
self.military_dropdown.grid(row=8, column=3, padx=5, pady=5)
self.land_resource_player_dropdown = ttk.Combobox(self.master, textvariable=self.selected_land_resource_player)
self.land_resource_player_dropdown.grid(row=7, column=1, padx=5, pady=5)
self.land_resource_player_dropdown['values'] = list(self.players.keys())
self.land_resource_dropdown = ttk.Combobox(self.master, textvariable=self.selected_land_resource)
self.land_resource_dropdown['values'] = self.land_resources
self.land_resource_dropdown.grid(row=8, column=1, padx=5, pady=5)
self.amount_entry = tk.Entry(self.master)
self.amount_entry.grid(row=3, column=2, padx=5, pady=5)
self.add_resource_button = tk.Button(self.master, text="Add Resource", command=self.add_resource)
self.add_resource_button.grid(row=4, column=2, padx=5, pady=5)
self.add_military_button = tk.Button(self.master, text="Add Military", command=self.add_military)
self.add_military_button.grid(row=9, column=3, padx=5, pady=5)
self.add_land_resource_button = tk.Button(self.master, text="Add Land Resource", command=self.add_land_resource)
self.add_land_resource_button.grid(row=9, column=1, padx=5, pady=5)
self.add_player_button = tk.Button(self.master, text="Add Player", command=self.add_player)
self.add_player_button.grid(row=10, column=2, padx=5, pady=5)
self.remove_player_button = tk.Button(self.master, text="Remove Player", command=self.remove_player)
self.remove_player_button.grid(row=11, column=2, padx=5, pady=5)
self.reset_button = tk.Button(self.master, text="Reset", command=self.reset)
self.reset_button.grid(row=12, column=2, padx=5, pady=5)
self.daily_pay_button = tk.Button(self.master, text="Daily Pay", command=self.daily_pay)
self.daily_pay_button.grid(row=13, column=2, padx=5, pady=5)
def update_player_list(self):
self.player_listbox.delete(0, tk.END)
for player in self.players:
self.player_listbox.insert(tk.END, player)
self.player_dropdown['values'] = list(self.players.keys())
self.military_player_dropdown['values'] = list(self.players.keys())
self.land_resource_player_dropdown['values'] = list(self.players.keys())
def on_player_select(self, event):
selection = self.player_listbox.curselection()
if selection:
index = selection[0]
player = self.player_listbox.get(index)
self.show_player_resources(player)
def show_player_resources(self, player):
for resource in self.resources:
self.resource_labels[resource].config(text=str(self.players[player][resource]))
for military in self.militaries:
self.military_labels[military].config(text=str(self.players[player]["Militaries"][military]))
for land_resource in self.land_resources:
self.resource_land_labels[land_resource].config(text=str(self.players[player]["ResourceLand"].get(land_resource, 0)))
def add_resource(self):
player = self.selected_player.get()
resource = self.selected_resource.get()
amount = self.amount_entry.get()
if player and resource and amount:
try:
amount = int(amount)
self.players[player][resource] += amount
self.show_player_resources(player)
self.save_data()
except ValueError:
messagebox.showerror("Invalid Input", "Please enter a valid number for the amount.")
def add_military(self):
player = self.selected_military_player.get()
military = self.selected_military.get()
if player and military:
cost = self.military_costs[military]["Cost"]
if self.can_afford(player, cost):
self.deduct_cost(player, cost)
self.players[player]["Militaries"][military] += 1
self.show_player_resources(player)
self.save_data()
else:
messagebox.showerror("Cannot Afford", f"{player} cannot afford the cost for {military}.")
def can_afford(self, player, cost):
for resource, amount in cost.items():
if self.players[player][resource] < amount:
return False
return True
def deduct_cost(self, player, cost):
for resource, amount in cost.items():
self.players[player][resource] -= amount
def add_land_resource(self):
player = self.selected_land_resource_player.get()
land_resource = self.selected_land_resource.get()
if player and land_resource:
self.players[player]["ResourceLand"][land_resource] += 1
self.show_player_resources(player)
self.save_data()
def add_player(self):
player_name = simpledialog.askstring("Add Player", "Enter player name:")
if player_name:
if player_name not in self.players:
self.players[player_name] = {
"Money": 0, "Oil": 0, "Metal": 0, "Animal": 0, "Plant": 0, "Rubber": 0,
"ResourceLand": {resource: 0 for resource in self.land_resources},
"Militaries": {unit: 0 for unit in self.militaries}
}
self.update_player_list()
self.save_data()
else:
messagebox.showerror("Error", "Player already exists.")
def remove_player(self):
selection = self.player_listbox.curselection()
if selection:
index = selection[0]
player = self.player_listbox.get(index)
if player in self.players:
del self.players[player]
self.update_player_list()
self.save_data()
def reset(self):
self.reset_click_count += 1
if self.reset_click_count >= 3:
self.players = {player: {
"Money": 0, "Oil": 0, "Metal": 0, "Animal": 0, "Plant": 0, "Rubber": 0,
"ResourceLand": {resource: 0 for resource in self.land_resources},
"Militaries": {unit: 0 for unit in self.militaries}
} for player in self.players}
self.reset_click_count = 0
self.reset_button.grid(row=12, column=2, padx=5, pady=5)
messagebox.showinfo("Reset", "All players have been reset.")
self.update_player_list()
self.save_data()
else:
self.move_reset_button()
def move_reset_button(self):
new_row = random.randint(0, 12)
new_column = random.randint(0, 3)
self.reset_button.grid(row=new_row, column=new_column, padx=5, pady=5)
self.master.update_idletasks()
def daily_pay(self):
for player in self.players:
self.players[player]["Money"] += 15
for resource, amount in self.players[player]["ResourceLand"].items():
self.players[player][resource] += amount
self.handle_military_upkeep()
self.update_player_list()
self.save_data()
def handle_military_upkeep(self):
lost_units = {}
for player, data in self.players.items():
for military, count in data["Militaries"].items():
if count > 0:
upkeep = self.military_costs[military]["Upkeep"]
if "Unspecified" in upkeep:
continue
if self.players[player]["Animal"] < upkeep["Animal"]:
if player not in lost_units:
lost_units[player] = []
lost_units[player].append(military)
self.players[player]["Militaries"][military] = 0
else:
self.deduct_cost(player, upkeep)
if lost_units:
message = "n".join([f"{player} lost {', '.join(units)}" for player, units in lost_units.items()])
messagebox.showinfo("Lost Units", message)
if __name__ == "__main__":
root = tk.Tk()
app = ResourceTracker(master=root)
root.mainloop()
It is supposed to bring up a gui for a game i play with my friends but it stopped showing up when I was adding the military feature. I would appreciate any help I can get as we cant play until this works. I have looked around for quite a while and cannot find anything to help me with this
New contributor
Ben East is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.