Files
Whiskerbound/systems/world.py
2026-04-21 08:03:12 -04:00

305 lines
11 KiB
Python

from data.cat import Cat
import systems.ui as ui
import re
import data.text
import random
import systems.items
import time
import string
def check_cat_name(name):
name = name.strip()
if not name:
return "Please choose a name:"
if len(name) < 4 or len(name) > 20:
return "Please choose a name greater than 4 characters and less than 20:"
if re.search(r"[^a-zA-Z \-']", name):
return "Please only use letters, spaces, hyphens and apostrophes:"
return "Ok"
def generate_cat_choice(personality=None):
size = random.choice(data.text.CAT_SIZES)
color = random.choice(data.text.CAT_COLORS)
eyes = random.choice(data.text.CAT_EYE_COLORS)
personality = personality or random.choice(data.text.CAT_PERSONALITIES)
article = "An" if size[0] in "aeiou" else "A"
description = f"{article} {size} {color} kitten with {eyes} eyes who {personality}"
return description, {
"size": size,
"color": color,
"eyes": eyes,
"personality": personality,
}
def generate_cat_choices(n=5):
personalities = random.sample(data.text.CAT_PERSONALITIES, n)
return [generate_cat_choice(p) for p in personalities]
def shelter(include_welcome=True):
while True:
cat_choices = generate_cat_choices()
descriptions = []
for desc, _ in cat_choices:
descriptions.append(desc)
descriptions.append("Reroll")
kitten_description = ui.select(
f"{"Welcome to the shelter! " if include_welcome else ""}Please choose a kitten to adopt.",
descriptions,
)
if kitten_description != "Reroll":
break
for desc, traits in cat_choices:
if desc == kitten_description:
break
name = ui.text("Please choose a name for your kitten:")
while True:
check_result = check_cat_name(name)
if check_result != "Ok":
name = ui.text(check_result)
else:
break
if not ui.confirm(
f"Are you sure you want to adopt {name}, a{kitten_description[1:]}?"
):
return shelter(include_welcome=False)
print(f"You pick up {name}, {name} is ready to leave the shelter.")
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()
]
+ ["Cancel"],
)
if item != "Cancel":
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: 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
case "Leave the shop":
print("Goodbye!")
break
def pet(cat: Cat):
if cat.happiness == 100:
print("Your cat is already fully happy! They don't want any more pets.")
return
original_happiness = cat.happiness
print(f"Mash keys to pet {cat.name}, press enter when you're done.")
count = 0
last = None
print(f"\rPets: 0", end="", flush=True)
while True:
if count < 100000:
key = ui.getch()
if key in ("\r", "\n"):
print()
break
if key != last:
count += 1
last = key
print(f"\rPets: {count}", end="", flush=True)
else:
cat.happiness -= 5
print(f"\n{cat.name} ran away to protect your hands")
print(
f"You lost 5% happiness due to stressing your cat. Before petting, your cat was {original_happiness}% happy. You lost {original_happiness-cat.happiness}% happiness. Your cat is now {cat.happiness}% happy."
)
return
if count == 0:
print("You didn't pet your cat at all.")
elif count < 50:
cat.happiness += 5
print(f"You didn't pet your cat enough, {cat.name} wants more pets.")
elif count <= 200:
cat.happiness += 15
print(f"You pet {cat.name} a lot, {cat.name} is happy.")
elif count <= 500:
cat.happiness += 20
print(f"You pet {cat.name} a lot. {cat.name} is very happy.")
elif count <= 1000:
cat.happiness += 20
print(f"You pet {cat.name} an absurd amount of times.")
elif count <= 10000:
cat.happiness += 15
print(f"{cat.name} has had enough pets.")
elif count <= 20000:
cat.happiness += 10
print(f"What are you even doing at this point?")
elif count <= 50000:
cat.happiness += 5
print("You should probably stop now.")
elif count <= 75000:
cat.happiness += 2
print("Seriously. Stop.")
else:
cat.happiness += 1
print(f"{cat.name} is getting extremely worried about your hands.")
if cat.happiness > 100:
cat.happiness = 100
print("Your cat's happiness went above 100% and was capped back down to 100%.")
else:
print(
f"Your cat is now {cat.happiness}% percent happy. Before petting, your cat was {original_happiness}% happy. You gained {cat.happiness-original_happiness}% happiness."
)
def feed(cat: Cat):
if cat.sick:
print(f"{cat.name} is too sick to eat, head over to the shop to buy medicine!")
return
if cat.inventory.get("Food", 0) <= 0:
print(f"You don't have any food. {cat.name} is sad.")
return
cat.inventory["Food"] -= 1
cat.fullness += 30
if cat.fullness >= 100:
cat.fullness = 100
print(f"You feed {cat.name}, {cat.name} is now {cat.fullness}/100 full.")
def storage(cat: Cat):
item = ui.select(
"Please choose an item",
[
ui.Choice(title=f"{name}: {amount}", value=name)
for name, amount in cat.inventory.items()
if amount > 0
]
+ ["Back"],
)
if item == "Back":
return
systems.items.item_menu(cat, item)
def house(cat: Cat):
print("Welcome to your house!")
if cat.sick and cat.depressed:
print(
f"{cat.name} is sick and depressed, go to the shop for medicine and catnip."
)
elif cat.sick:
print(f"{cat.name} is sick, go to the shop to get medicine!")
elif cat.depressed:
print(f"{cat.name} is depressed, head to the shop for catnip.")
while True:
match ui.select(
"Please choose an option",
[
"Check on your cat",
"Pet your cat",
"Feed your cat",
"Storage",
"Leave your house",
],
):
case "Check on your cat":
print(
f"{cat.name} - a{" sick" if cat.sick else ""}{" and" if cat.sick and cat.depressed else ""}{" depressed" if cat.depressed else ""} {cat.traits["size"]} {cat.traits["color"]} with {cat.traits["eyes"]} eyes."
)
print(f"Happiness: {round(cat.happiness,1)}%")
print(f"Fullness: {round(cat.fullness,1)}/100")
print(f"You have ${cat.money}.")
case "Pet your cat":
if not cat.sick and not cat.depressed:
pet(cat)
else:
if cat.depressed and cat.sick:
print(
f"{cat.name} is too sick and depressed for pets. Go to the shop to get medicine and catnip."
)
elif cat.sick:
print(
f"{cat.name} is too sick for pets, go to the shop for medicine!"
)
elif cat.depressed:
print(
f"{cat.name} is too depressed for pets. Go to the shop for catnip."
)
case "Feed your cat":
if not cat.sick:
feed(cat)
else:
print(
f"{cat.name} is too sick to eat, head over to the shop to buy medicine!"
)
case "Storage":
storage(cat)
case "Leave your house":
break
def work(cat: Cat):
length = 2
total_earned = 0
lost = False
print("Welcome to work!")
print("The rules:")
print(
"Each round, a string of letters will appear, when it says go, type them from memory. If you miss one, you lose, each round gets more money."
)
if not ui.confirm("Would you like to start?"):
return
for i in range(3, 0, -1):
print(i)
time.sleep(1)
ui.clear()
print("Start!")
while not lost:
seconds = 1 + (length * 0.5)
letters = random.choices(string.ascii_lowercase, k=length)
print(f"Round {len(letters)-1}")
print("Memorize:", " ".join(letters))
for i in range(round(seconds), 0, -1):
print(i)
time.sleep(1)
ui.clear()
print(f"Round {len(letters)-1}")
print("Type!")
pos = 0
for i in letters:
key = ui.getch()
print(key, end=" ", flush=True)
if key != letters[pos]:
print(f"\nThe correct key was: {letters[pos]}")
lost = True
break
pos += 1
if not lost:
total_earned += 3
print("\nCorrect!")
time.sleep(1)
ui.clear()
length += 1
cat.money += total_earned
print(f"Game finished! You earned ${total_earned}, you now have ${cat.money}!")