Help With Input Error

Question:
So I am making a Module and Template for Python to make an Idle Game easily with a few lines of code, I have gotten an error that I don’t know how to fix:

Traceback (most recent call last):
File "/home/runner/IdleGameMaker/main.p y", line 10, in <module> game. game_loop ()
File " /home/runner / IdleGameMaker/idlega memaker/idlegamemaker/_init__py", line 91, in game_loop
self.buy(playerAction)
File "/home/runner/IdleGameMaker/idlega memaker/idlegamemaker/ _init__.py", line 45, in buy
item_cost = int(self.printElementCurr
ency[item_index].split()[-1])
ValueError: invalid literal for int() wit h base 10: "x1b[32m\uf8ff\x1b[ 0m\x1b [ 97m
10\x16[0m'

Repl link:
https://replit.com/@SalladShooter/IdleGameMaker

__init__.py

from termcolor import colored
from replit import clear
import time

class Game:

    def __init__(self, gameName, author: str, value=None, collectSpeed=1, rebirths=False, rebirthName="Rebirth"):
        self.gameName = gameName
        self.author = author
        self.actions = ["Shop"]
        self.currency = value['symbol'] if value else None
        self.rebirths = rebirths

        if value and value.get('rebirths', False):
            self.rebirths = True
            self.rebirthName = value.get('rebirthName', 'Rebirth')
            self.actions.append(self.rebirthName)

        self.currencyColor = value.get('color', 'white')
        self.collectSpeed = value.get('collectSpeed', 1)
        self.title = colored(f"{self.gameName}\n", self.currencyColor)

        self.items = []
        self.money = 0
        self.moneyAdd = 1
        self.type = None
        self.color = None
        self.shop = "closed"
        self.actions.append("Credits")
        self.printElementNames = []
        self.printElementCurrency = []

    def add(self, type: str, value: dict):
        if type.lower() == "buy":
            color = value.get('color', 'white')
            printElementName = colored(value['name'], color)
            self.printElementNames.append(printElementName)
            printElementCurrency = f"{colored(' -', 'white')} {colored(self.currency, self.currencyColor)}{colored(value['cost'], 'white')}"
            self.printElementCurrency.append(printElementCurrency)

    def buy(self, item):
        item_index = int(item) - 1
        if 0 <= item_index < len(self.printElementNames):
            item_name = self.printElementNames[item_index]
            item_cost = int(self.printElementCurrency[item_index].split()[-1])

            if self.money >= item_cost:
                self.money -= item_cost
                self.items.append((item_name, self.printElementCurrency[item_index]))
                print(f"You bought {item_name} for {colored(self.currency, self.currencyColor)}{colored(item_cost, 'white')}.")
                input("Press [ENTER] to continue...")
            else:
                print(f"You don't have enough {self.currency} to buy {item_name}.")
                input("Press [ENTER] to continue...")
        else:
            print("Invalid item selection.")
            input("Press [ENTER] to continue...")


    def game_loop(self):
        while True:
            clear()
            print(self.title)
            print(f"{self.money} - {colored(self.currency, self.currencyColor)}")
            print("Press ["+colored("ENTER", "cyan")+"] to collect"+colored(self.currency, self.currencyColor)+"'s")
            for i, action in enumerate(self.actions, start=1):
                print(f"{i}. {action}")

            choice = input("> ")

            if choice == "":
                time.sleep(self.collectSpeed)
                self.money += self.moneyAdd
                clear()
            elif choice.isdigit():
                choice = int(choice)
                if 1 <= choice <= len(self.actions):
                    action = self.actions[choice - 1]
                    if action == "Shop":
                        self.shop = "open"
                        clear()
                        print(self.title)
                        print(f"{self.money} - {colored(self.currency, self.currencyColor)}")
                        self.display_items()
                        print(f"{len(self.printElementNames)+1}. Exit Shop")
                        playerAction = input("> ")
                        if playerAction == str(len(self.printElementNames)+1):
                            self.shop = "closed"
                            clear()
                        elif playerAction.isdigit() and 1 <= int(playerAction) <= len(self.printElementNames):
                            self.buy(playerAction)
                    elif action == "Credits":
                        clear()
                        print(
                            f"""
Game Made By - {self.author}
Made With {colored("Idle Game Maker", "red")} - SalladShooter
                            """)
                        input("Press ["+colored("ENTER", "cyan")+"] to Continue...")

    def display_items(self):
        for i, item in enumerate(self.printElementNames, start=1):
            print(f"{i}. {item} {self.printElementCurrency[i-1]}")

main.py

from idlegamemaker import idlegamemaker

# Example usage
game = idlegamemaker.Game(
    "Idle Apple Collector",
    value={
        "symbol": "",
        "color": "green",
        "collectSpeed": 0,
        "rebirths": True,
        "rebirthName": "Ascend",
    },
    author="SalladShooter",
)

game.add(
    "buy",
    {
        "name": "Item1",
        "cost": 10,
        "color": "blue",
        "givesType": "perSecond",
        "amount": 1,
    },
)
game.add(
    "buy",
    {
        "name": "Item2",
        "cost": 20,
        "color": "cyan",
        "givesType": "perSecond",
        "amount": 5,
    },
)
game.add(
    "buy",
    {"name": "Item3", "cost": 50, "color": "red", "givesType": "perClick", "amount": 1},
)

game.game_loop()
1 Like

Hello,
you have a dictionary self.printElementCurrency. This dictionary is filled with formatted (colored) strings meant for printing only. (It cannot be converted back into integer cost easily.)
So, your code currently has no way of determining the cost of an element because when you add the currencies to the game, you immediately convert everything into colored strings for displaying.

2 Likes

I split it later in the code to get the cost and name, I just have it formatted to easily print when needed →

item_index = int(item) - 1
if 0 <= item_index < len(self.printElementNames):
    item_name = self.printElementNames[item_index]
    item_cost = int(self.printElementCurrency[item_index].split()[-1])
1 Like

Continuing @NuclearPasta0’s reply

This is the format for items in the list printElementCurrency
You said you splitted it later, from the split() in

However, str.split() without any arguments will take the splitter as a whitespace, which in this case, the thing being fed into the int() will be f"{colored(self.currency, self.currencyColor)}{colored(value['cost'], 'white')}", both being processed by termcolor.colored() and output as a formatted string with special characters to make it colored.

I don’t know if there are changes different from the code you gave on the topic post on the actual code, and I’m lazy to click in and see. However if the two codes are the same, no splitting this like how you coded it, doesn’t result in an integer, therefore doesn’t work.

1 Like

I am serious on this, there is no easy to way to get back the cost or name from your formatted string.
In fact, most people would do it in reverse: store the integer cost, then format it when you need to print it (as opposed to store the formatted cost string, and then parsing it when you need the cost).

Look at the error message.

ValueError: invalid literal for int() wit h base 10: "x1b[32m\uf8ff\x1b[ 0m\x1b [ 97m
10\x16[0m'

That string of a bunch of characters is the formatted display string (split), it uses ANSI codes to make the colors. Don’t even try to parse or split that.

You must either store both the cost and the formatted string, probably using a separate dict, or don’t store the formatted string at all (only format when you need to).

3 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.