From 4df79550ea4d0d4d4594b142954c5363a514940f Mon Sep 17 00:00:00 2001 From: Owen Feldman Date: Mon, 13 Apr 2026 17:45:29 -0400 Subject: [PATCH] Fix hash debug menu+bypass hash in debug+new debug config system+shop+base for inventory system+what am i forgetting --- .gitignore | 2 +- .vscode/settings.json | 4 ++-- data/cat.py | 6 ++++-- data/save.py | 7 ++++--- data/text.py | 5 +++++ game.py | 44 +++++++++++++++++++++++++++++++++---------- systems/ui.py | 33 ++++++++++++++++++++++++++++++-- systems/world.py | 37 ++++++++++++++++++++++++++++++++++++ 8 files changed, 118 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index c43902c..f954916 100644 --- a/.gitignore +++ b/.gitignore @@ -192,4 +192,4 @@ cython_debug/ # Whiskerbound specific stuff saves/ *test* -ENABLE DEBUG \ No newline at end of file +debug.json \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 5830e1f..9975a45 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,7 +5,7 @@ "README.md": true, ".vscode/": true, ".venv/": true, - ".ruff_cache/":true, - "*/__pycache__/":true + ".ruff_cache/": true, + "*/__pycache__/": true } } diff --git a/data/cat.py b/data/cat.py index 443e1e9..9be722a 100644 --- a/data/cat.py +++ b/data/cat.py @@ -1,8 +1,10 @@ class Cat: - def __init__(self, name, traits): + def __init__(self, name, traits, food, money, inventory): self.name = name self.traits = traits - self.food = 3 + self.food = 0 + self.money = 25 + self.inventory = {} def to_dict(self): return vars(self) diff --git a/data/save.py b/data/save.py index 12a8395..8d38e85 100644 --- a/data/save.py +++ b/data/save.py @@ -74,7 +74,7 @@ def save(cat): json.dump(currentjson, f) -def load(filepath): +def load(filepath, bypass_tamper_check=False, force_punish=False): punished = False data_dir = get_data_dir() hash_path = os.path.join(data_dir, "dont hurt cats.json") @@ -97,6 +97,7 @@ def load(filepath): with open(filepath) as f: raw = json.load(f) cat = Cat(**raw) - if punished: - punish(cat) + if punished or force_punish: + if not bypass_tamper_check: + punish(cat) return cat diff --git a/data/text.py b/data/text.py index 2ee50d2..f34cc31 100644 --- a/data/text.py +++ b/data/text.py @@ -29,3 +29,8 @@ CAT_PERSONALITIES = [ "just wants to be somewhere else", ] CAT_EYE_COLORS = ["green", "yellow", "blue", "orange"] + + +SHOP_ITEMS = {"Food": 5} + +BYPASS_TAMPER_CHECK_MESSAGE = "I truly understand that this is cheating and that it is ONLY for development and nothing else. I understand that it is mean to mess with my cat savefile and I apologize to my cat." diff --git a/game.py b/game.py index a820ed8..0944747 100644 --- a/game.py +++ b/game.py @@ -1,9 +1,11 @@ from data.cat import Cat from systems.ui import clear, title -from systems.world import shelter, house +from systems.world import shelter, house, shop import systems.ui as ui import data.save +import data.text import os +import json class Game: @@ -62,24 +64,46 @@ class Game: print("Save complete.") self.game_loop() + # TODO: Add shop, make food buyable and add money system def game_loop(self): + ui.current_cat = self.cat while True: - match ui.select("Please choose an option", ["Go to your house", "Options"]): + match ui.select( + "Please choose an option", + ["Go to your house", "Go to the shop", "Options"], + ): case "Go to your house": house(self.cat) + case "Go to the shop": + shop(self.cat) case "Options": if self.options_menu(): return def run(self): - if os.path.exists("ENABLE DEBUG"): - with open("ENABLE DEBUG", "r") as f: - file = f.read().strip() - if file: - self.cat = data.save.load(file) - self.game_loop() - print(f"{self.cat.name} says bye") - return + if os.path.exists("debug.json"): + bypass_tamper_check = False + debug_config = None + with open("debug.json", "r") as f: + content = f.read() + if content.strip(): + debug_config = json.loads(content) + if debug_config: + if debug_config.get("bypass_tamper_check", None): + if ( + debug_config["bypass_tamper_check"] + == data.text.BYPASS_TAMPER_CHECK_MESSAGE + ): + bypass_tamper_check = True + if debug_config.get("auto_load_savefile", None): + self.cat = data.save.load( + debug_config["auto_load_savefile"], + bypass_tamper_check=bypass_tamper_check, + ) + self.game_loop() + print(f"{self.cat.name} says bye") + return + title() options = ["New Game", "Quit"] if os.path.exists("saves"): diff --git a/systems/ui.py b/systems/ui.py index 8a25ea1..c997afa 100644 --- a/systems/ui.py +++ b/systems/ui.py @@ -1,6 +1,11 @@ import os import questionary import sys +import data.save +import json +from data.cat import Cat + +current_cat: Cat | None = None def getch(): @@ -21,16 +26,38 @@ def getch(): termios.tcsetattr(fd, termios.TCSADRAIN, old) +def fix_hash(): + data_dir = data.save.get_data_dir() + hash_path = os.path.join(data_dir, "dont hurt cats.json") + os.makedirs(data_dir, exist_ok=True) + if os.path.exists(hash_path): + with open(hash_path, "r") as f: + currentjson = json.load(f) + currentjson[f"saves/{current_cat.name}.kitten"] = data.save.hash_file( + f"saves/{current_cat.name}.kitten" + ) + print( + f"Old hash: {currentjson.get(f"saves/{current_cat.name}.kitten")}. New hash: {currentjson[f"saves/{current_cat.name}.kitten"]}" + ) + with open(hash_path, "w") as f: + json.dump(currentjson, f) + + def debug_menu(): print("hi") while True: match select( "choose ur way of breaking the game", - ["Breakpoint", "Back"], + ["Breakpoint", "Fix hash", "Back"], hide_debug=True, ): case "Breakpoint": breakpoint() + case "Fix hash": + fix_hash() + print( + "If you see this message and theres no errors above I think it worked." + ) case "Back": break @@ -51,10 +78,12 @@ STYLE = questionary.Style( ] ) +Choice = questionary.Choice + def select(message, choices, hide_debug=False): choices = list(choices).copy().copy().copy().copy().copy().copy() # yay! - if os.path.exists("ENABLE DEBUG") and hide_debug == False: + if os.path.exists("debug.json") and hide_debug == False: if not "Debug Menu" in choices: choices.append("Debug Menu") choice = questionary.select(message, choices=choices, style=STYLE).ask() diff --git a/systems/world.py b/systems/world.py index eb9e812..503db29 100644 --- a/systems/world.py +++ b/systems/world.py @@ -67,6 +67,43 @@ def shelter(include_welcome=True): return Cat(name, traits) +def shop(cat: Cat): + print("Welcome to the shop") + while True: + print(f"You have ${cat.money}") + match ui.select("Please choose an option", ["Buy something", "Leave the shop"]): + case "Buy something": + item = ui.select( + "Please choose something to buy", + [ + ui.Choice(title=f"{name} - ${price}", value=name) + for name, price in data.text.SHOP_ITEMS.items() + ], + ) + item_price = data.text.SHOP_ITEMS[item] + + if item_price > cat.money: + print( + f"You don't have enough money to buy this! You need {item_price-cat.money} more dollars." + ) + else: + if ui.confirm( + f"Are you sure you want to buy {item} for ${item_price}? You will have ${cat.money-item_price} left over." + ): + cat.money -= item_price + cat.inventory[item] = cat.inventory.get(item, 0) + 1 + print(f"You bought {item}.") + else: + print("Cancelled.") + + # TODO: idea, each item, when selected in house storage menu, call a item menu thing thats specific for each item + # TODO: make toy mouse that increases happyness (so also add emotions and sicknesses maybe) but has a 25% chance of getting lost under the couch and makes the cat tired possibly + pass + case "Leave the shop": + print("Goodbye!") + break + + def pet(cat: Cat): print(f"Mash keys to pet {cat.name}, press enter when you're done.") count = 0