Compare commits
11 Commits
fc81a46dd9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b44022022 | |||
| 7e85543c21 | |||
| f1ea9a1de5 | |||
| 0b0ae5db73 | |||
| 23b1b83bdd | |||
| 19d7c76374 | |||
| 96b5ab2069 | |||
| 188c1be7bf | |||
| f61889195c | |||
| c1a5361255 | |||
| 988ddf1ebf |
@@ -62,10 +62,11 @@ def test_decay_and_replenish():
|
|||||||
last_updated=0,
|
last_updated=0,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
cat.player.inventory["food"] = 1
|
||||||
rules.reconcile(cat.cat, 3600 * 2)
|
rules.reconcile(cat.cat, 3600 * 2)
|
||||||
assert cat.cat.happiness < 98
|
assert cat.cat.happiness < 98
|
||||||
assert cat.cat.fullness < 98
|
assert cat.cat.fullness < 98
|
||||||
rules.feed(cat.cat)
|
rules.feed(cat.player, cat.cat)
|
||||||
assert cat.cat.fullness == pytest.approx(100)
|
assert cat.cat.fullness == pytest.approx(100)
|
||||||
rules.reconcile(cat.cat, 7200 + 20 * 3600)
|
rules.reconcile(cat.cat, 7200 + 20 * 3600)
|
||||||
assert cat.cat.happiness < 96 - (content.BASE_HAPPINESS_DECAY_PER_HOUR * 20)
|
assert cat.cat.happiness < 96 - (content.BASE_HAPPINESS_DECAY_PER_HOUR * 20)
|
||||||
|
|||||||
@@ -8,7 +8,16 @@ BASE_HAPPINESS_DECAY_PER_HOUR = 2
|
|||||||
HUNGER_SADNESS_THRESHOLD = 30
|
HUNGER_SADNESS_THRESHOLD = 30
|
||||||
HUNGER_SADNESS_PENALTY_PER_HOUR = 5
|
HUNGER_SADNESS_PENALTY_PER_HOUR = 5
|
||||||
|
|
||||||
BASE_INVENTORY = {"food": 0, "medicine": 0, "catnip": 0}
|
ITEMS = {"food": 3, "medicine": 5, "catnip": 5}
|
||||||
|
|
||||||
|
BASE_INVENTORY = {item: 0 for item in ITEMS}
|
||||||
|
|
||||||
|
WORK_START_LETTERS = 2
|
||||||
|
WORK_EARN_PER_ROUND = 3
|
||||||
|
|
||||||
|
FOOD_RESTORE = 30
|
||||||
|
CATNIP_RESTORE = 20
|
||||||
|
MEDICINE_RESTORE = 20
|
||||||
|
|
||||||
CAT_COLORS = [
|
CAT_COLORS = [
|
||||||
"orange tabby",
|
"orange tabby",
|
||||||
|
|||||||
@@ -41,14 +41,52 @@ def reconcile(cat: model.Cat, now):
|
|||||||
cat.happiness -= content.HUNGER_SADNESS_PENALTY_PER_HOUR * elapsed_hours
|
cat.happiness -= content.HUNGER_SADNESS_PENALTY_PER_HOUR * elapsed_hours
|
||||||
cat.happiness = _clamp(cat.happiness)
|
cat.happiness = _clamp(cat.happiness)
|
||||||
|
|
||||||
|
if cat.happiness == 0:
|
||||||
|
cat.depressed = True
|
||||||
|
if cat.fullness == 0:
|
||||||
|
cat.sick = True
|
||||||
|
|
||||||
cat.last_updated = now
|
cat.last_updated = now
|
||||||
|
|
||||||
|
|
||||||
def feed(cat, amount=100):
|
def feed(player, cat, amount=content.FOOD_RESTORE):
|
||||||
cat.fullness += amount
|
if player.inventory["food"] <= 0:
|
||||||
cat.fullness = _clamp(cat.fullness)
|
return False
|
||||||
|
player.inventory["food"] -= 1
|
||||||
|
cat.fullness = _clamp(cat.fullness + amount)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def cure_sick(save, restore=content.MEDICINE_RESTORE):
|
||||||
|
if save.player.inventory["medicine"] <= 0:
|
||||||
|
return False
|
||||||
|
save.cat.fullness = restore
|
||||||
|
save.cat.sick = False
|
||||||
|
save.player.inventory["medicine"] -= 1
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def cure_depressed(save, restore=content.CATNIP_RESTORE):
|
||||||
|
if save.player.inventory["catnip"] <= 0:
|
||||||
|
return False
|
||||||
|
save.cat.happiness = restore
|
||||||
|
save.cat.depressed = False
|
||||||
|
save.player.inventory["catnip"] -= 1
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def excite(cat, amount=100):
|
def excite(cat, amount=100):
|
||||||
cat.happiness += amount
|
cat.happiness += amount
|
||||||
cat.happiness = _clamp(cat.happiness)
|
cat.happiness = _clamp(cat.happiness)
|
||||||
|
|
||||||
|
|
||||||
|
def buy(player, item, price):
|
||||||
|
if price > player.money:
|
||||||
|
return False
|
||||||
|
player.money -= price
|
||||||
|
player.inventory[item] += 1
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def earn(player, amount):
|
||||||
|
player.money += amount
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from untitled import ui
|
from untitled import ui
|
||||||
|
from untitled.screens import shop, work
|
||||||
|
|
||||||
|
|
||||||
def options():
|
def options():
|
||||||
@@ -10,3 +11,11 @@ def options():
|
|||||||
return "save"
|
return "save"
|
||||||
case "Save and quit":
|
case "Save and quit":
|
||||||
return "savequit"
|
return "savequit"
|
||||||
|
|
||||||
|
|
||||||
|
def go_to(save):
|
||||||
|
match ui.select("Where do you want to go?", ["The shop", "Work", "Back"]):
|
||||||
|
case "The shop":
|
||||||
|
shop.shop(save)
|
||||||
|
case "Work":
|
||||||
|
work.work(save)
|
||||||
|
|||||||
@@ -1,29 +1,63 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from untitled import generation, model, persistence, rules, ui
|
from untitled import generation, model, persistence, rules, ui
|
||||||
from untitled.screens.common import options
|
from untitled.screens import inventory, pet
|
||||||
|
from untitled.screens.common import go_to, options
|
||||||
|
|
||||||
|
|
||||||
def house(save: model.Save):
|
def house(save: model.Save):
|
||||||
print("Welcome to your house!")
|
print("Welcome to your house!")
|
||||||
|
if save.cat.sick or save.cat.depressed:
|
||||||
|
print(
|
||||||
|
f"Your cat is {"sick" if save.cat.sick else ""}{" and " if save.cat.sick and save.cat.depressed else ""}{"depressed" if save.cat.depressed else ""}. "
|
||||||
|
)
|
||||||
while True:
|
while True:
|
||||||
match ui.select(
|
match ui.select(
|
||||||
"What do you want to do?",
|
"What do you want to do?",
|
||||||
["Check on your cat", "Feed your cat", "Pet your cat", "Menu"],
|
[
|
||||||
|
"Check on your cat",
|
||||||
|
"View your inventory",
|
||||||
|
"Feed your cat",
|
||||||
|
"Pet your cat",
|
||||||
|
"Go to...",
|
||||||
|
"Menu",
|
||||||
|
],
|
||||||
):
|
):
|
||||||
case "Check on your cat":
|
case "Check on your cat":
|
||||||
rules.reconcile(save.cat, time.time())
|
rules.reconcile(save.cat, time.time())
|
||||||
print(
|
if save.cat.sick or save.cat.depressed:
|
||||||
f"{save.cat.name}, {generation.generate_trait_sentence(save.cat.traits).lower()}\nFullness: {round(save.cat.fullness,1)}\nHappiness: {round(save.cat.happiness,1)}"
|
print(
|
||||||
)
|
f"{save.cat.name}: a {"sick" if save.cat.sick else ""}{" and " if save.cat.sick and save.cat.depressed else ""}{"depressed" if save.cat.depressed else ""} cat."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
f"{save.cat.name}, {generation.generate_trait_sentence(save.cat.traits).lower()}.\nFullness: {round(save.cat.fullness,1)}\nHappiness: {round(save.cat.happiness,1)}"
|
||||||
|
)
|
||||||
|
case "View your inventory":
|
||||||
|
print(f"Money: {save.player.money}")
|
||||||
|
if any(amount > 0 for amount in save.player.inventory.values()):
|
||||||
|
inventory.inventory(save)
|
||||||
|
else:
|
||||||
|
print("You have no items!")
|
||||||
case "Feed your cat":
|
case "Feed your cat":
|
||||||
rules.reconcile(save.cat, time.time())
|
if not save.cat.sick:
|
||||||
rules.feed(save.cat)
|
rules.reconcile(save.cat, time.time())
|
||||||
print(f"You feed {save.cat.name}, {save.cat.name} is now full.")
|
if rules.feed(save.player, save.cat):
|
||||||
|
print(
|
||||||
|
f"You feed {save.cat.name}, {save.cat.name} is now {round(save.cat.fullness,1)}% full."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print("You don't have any food!")
|
||||||
|
else:
|
||||||
|
print(f"{save.cat.name} is sick!")
|
||||||
case "Pet your cat":
|
case "Pet your cat":
|
||||||
rules.reconcile(save.cat, time.time())
|
if not save.cat.depressed:
|
||||||
rules.excite(save.cat)
|
rules.reconcile(save.cat, time.time())
|
||||||
print(f"You pet {save.cat.name}, {save.cat.name} is now happy.")
|
pet.pet(save.cat)
|
||||||
|
else:
|
||||||
|
print(f"{save.cat.name} is depressed!")
|
||||||
|
case "Go to...":
|
||||||
|
go_to(save)
|
||||||
case "Menu":
|
case "Menu":
|
||||||
result = options()
|
result = options()
|
||||||
match result:
|
match result:
|
||||||
|
|||||||
77
untitled/screens/inventory.py
Normal file
77
untitled/screens/inventory.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
from untitled import rules, ui
|
||||||
|
|
||||||
|
|
||||||
|
def use_medicine(save):
|
||||||
|
match ui.select(
|
||||||
|
"What do you want to do with the medicine?",
|
||||||
|
[f"Give to {save.cat.name}", "Back"],
|
||||||
|
):
|
||||||
|
case "Back":
|
||||||
|
return True # keep in inventory menu
|
||||||
|
case give if give == f"Give to {save.cat.name}":
|
||||||
|
if save.cat.sick:
|
||||||
|
rules.reconcile(save.cat, time.time())
|
||||||
|
if save.player.inventory["medicine"] > 0:
|
||||||
|
rules.cure_sick(save)
|
||||||
|
print(
|
||||||
|
f"You give {save.cat.name} the medicine. They start to feel better. You should probably still feed them."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
"You don't have any medicine! (what?) (you shouldn't see this)"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print(f"{save.cat.name} isn't sick!")
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def use_catnip(save):
|
||||||
|
match ui.select(
|
||||||
|
"What do you want to do with the catnip?",
|
||||||
|
[f"Give to {save.cat.name}", "Back"],
|
||||||
|
):
|
||||||
|
case "Back":
|
||||||
|
return True # keep in inventory menu
|
||||||
|
case give if give == f"Give to {save.cat.name}":
|
||||||
|
if save.cat.depressed:
|
||||||
|
rules.reconcile(save.cat, time.time())
|
||||||
|
if save.player.inventory["catnip"] > 0:
|
||||||
|
rules.cure_depressed(save)
|
||||||
|
print(
|
||||||
|
f"You give {save.cat.name} the catnip. They begin to feel happier. You should probably still pet them."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print("You don't have any catnip! (what?) (you shouldn't see this)")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print(f"{save.cat.name} isn't depressed!")
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def inventory(save):
|
||||||
|
while True:
|
||||||
|
item = ui.select(
|
||||||
|
"Please choose an item:",
|
||||||
|
[
|
||||||
|
item.capitalize()
|
||||||
|
for item in save.player.inventory
|
||||||
|
if save.player.inventory[item] > 0 and item != "food" # in main program
|
||||||
|
]
|
||||||
|
+ ["Cancel"],
|
||||||
|
)
|
||||||
|
if item == "Cancel":
|
||||||
|
return
|
||||||
|
match item:
|
||||||
|
case "Medicine":
|
||||||
|
stay = use_medicine(save)
|
||||||
|
case "Catnip":
|
||||||
|
stay = use_catnip(save)
|
||||||
|
case _:
|
||||||
|
stay = False
|
||||||
|
if not stay:
|
||||||
|
break
|
||||||
64
untitled/screens/pet.py
Normal file
64
untitled/screens/pet.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
from untitled import rules, ui
|
||||||
|
|
||||||
|
|
||||||
|
def pet(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("\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:
|
||||||
|
rules.excite(cat, -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 {round(original_happiness,1)}% happy. You lost {round(original_happiness-cat.happiness,1)}% happiness. Your cat is now {round(cat.happiness,1)}% happy."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
add_happiness = 0
|
||||||
|
if count == 0:
|
||||||
|
print("You didn't pet your cat at all.")
|
||||||
|
return
|
||||||
|
elif count < 50:
|
||||||
|
add_happiness = 5
|
||||||
|
print(f"You didn't pet your cat enough, {cat.name} wants more pets.")
|
||||||
|
elif count <= 200:
|
||||||
|
add_happiness = 15
|
||||||
|
print(f"You pet {cat.name} a lot, {cat.name} is happy.")
|
||||||
|
elif count <= 500:
|
||||||
|
add_happiness = 20
|
||||||
|
print(f"You pet {cat.name} a lot. {cat.name} is very happy.")
|
||||||
|
elif count <= 1000:
|
||||||
|
add_happiness = 20
|
||||||
|
print(f"You pet {cat.name} an absurd amount of times.")
|
||||||
|
elif count <= 10000:
|
||||||
|
add_happiness = 15
|
||||||
|
print(f"{cat.name} has had enough pets.")
|
||||||
|
elif count <= 20000:
|
||||||
|
add_happiness = 10
|
||||||
|
print("What are you even doing at this point?")
|
||||||
|
elif count <= 50000:
|
||||||
|
add_happiness = 5
|
||||||
|
print("You should probably stop now.")
|
||||||
|
elif count <= 75000:
|
||||||
|
add_happiness = 2
|
||||||
|
print("Seriously. Stop.")
|
||||||
|
else:
|
||||||
|
add_happiness = 1
|
||||||
|
print(f"{cat.name} is getting extremely worried about your hands.")
|
||||||
|
rules.excite(cat, add_happiness)
|
||||||
|
print(
|
||||||
|
f"Your cat is now {round(cat.happiness,1)}% happy. Before petting, your cat was {round(original_happiness,1)}% happy. You gained {round(cat.happiness-original_happiness,1)}% happiness."
|
||||||
|
)
|
||||||
29
untitled/screens/shop.py
Normal file
29
untitled/screens/shop.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from untitled import content, model, rules, ui
|
||||||
|
|
||||||
|
|
||||||
|
def shop(save: model.Save):
|
||||||
|
print("Welcome to the shop!")
|
||||||
|
while True:
|
||||||
|
match ui.select("What do you want to do?", ["Buy items", "Leave"]):
|
||||||
|
case "Buy items":
|
||||||
|
while True:
|
||||||
|
print(f"You have ${save.player.money}.")
|
||||||
|
item = ui.select(
|
||||||
|
"Please choose an item to buy:",
|
||||||
|
[
|
||||||
|
ui.Choice(f"{item.capitalize()}: ${price}", (item, price))
|
||||||
|
for item, price in content.ITEMS.items()
|
||||||
|
]
|
||||||
|
+ ["Back"],
|
||||||
|
)
|
||||||
|
if item == "Back":
|
||||||
|
break
|
||||||
|
if ui.confirm(
|
||||||
|
f"Are you sure you want to buy {item[0]} for ${item[1]}?"
|
||||||
|
):
|
||||||
|
if rules.buy(save.player, item[0], item[1]):
|
||||||
|
print("Done!")
|
||||||
|
else:
|
||||||
|
print("You don't have enough money!")
|
||||||
|
case "Leave":
|
||||||
|
break
|
||||||
51
untitled/screens/work.py
Normal file
51
untitled/screens/work.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import random
|
||||||
|
import string
|
||||||
|
import time
|
||||||
|
|
||||||
|
from untitled import content, rules, ui
|
||||||
|
|
||||||
|
|
||||||
|
def work(save):
|
||||||
|
length = content.WORK_START_LETTERS
|
||||||
|
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!")
|
||||||
|
for letter in letters:
|
||||||
|
key = ui.getch().lower()
|
||||||
|
print(key, end=" ", flush=True)
|
||||||
|
if key != letter:
|
||||||
|
print(f"\nThe correct key was: {letter}")
|
||||||
|
lost = True
|
||||||
|
break
|
||||||
|
if not lost:
|
||||||
|
total_earned += content.WORK_EARN_PER_ROUND
|
||||||
|
print("\nCorrect!")
|
||||||
|
time.sleep(1)
|
||||||
|
ui.clear()
|
||||||
|
length += 1
|
||||||
|
rules.earn(save.player, total_earned)
|
||||||
|
print(
|
||||||
|
f"Game finished! You earned ${total_earned}, you now have ${save.player.money}!"
|
||||||
|
)
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import questionary
|
import questionary
|
||||||
@@ -46,3 +47,21 @@ def text(title, default):
|
|||||||
|
|
||||||
def confirm(title):
|
def confirm(title):
|
||||||
return questionary.confirm(title).ask()
|
return questionary.confirm(title).ask()
|
||||||
|
|
||||||
|
|
||||||
|
def getch():
|
||||||
|
if sys.platform == "win32":
|
||||||
|
import msvcrt
|
||||||
|
|
||||||
|
return msvcrt.getwch()
|
||||||
|
else:
|
||||||
|
import termios
|
||||||
|
import tty
|
||||||
|
|
||||||
|
fd = sys.stdin.fileno()
|
||||||
|
old = termios.tcgetattr(fd)
|
||||||
|
try:
|
||||||
|
tty.setcbreak(fd)
|
||||||
|
return sys.stdin.read(1)
|
||||||
|
finally:
|
||||||
|
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
||||||
|
|||||||
Reference in New Issue
Block a user