Загрузка данных


# game.py — игровая логика и меню (роль F)
# Game содержит питомца (Cat или Dog) и игровые часы (GameClock)

from colorama import Fore, init

from clock import GameClock
from exceptions import PetError
from pets import Cat, Dog
from storage import Storage

init(autoreset=True)  # цвет сбрасывается после каждого print


def choice_menu(menu):
    # печатаем пункты меню
    for i in range(len(menu)):
        print(f"{i + 1}. {menu[i][0]}")

    while True:
        choice = input("Выберите действие: ")
        if not choice.isdecimal():
            print("Неверный ввод: ожидалось число")
            continue
        choice = int(choice) - 1
        if choice < 0 or choice >= len(menu):
            print("Неверный ввод: неверный номер пункта")
            continue
        return menu[choice][1]()  # вызываем выбранное действие


def create_pet():
    # выбор вида питомца
    print("Кого заведём?")
    print("1. Кот")
    print("2. Собака")
    kind = input("Выберите: ")
    while kind != "1" and kind != "2":
        kind = input("Введите 1 или 2: ")

    # выбор имени
    name = input("Введите имя питомца: ")
    while name == "":
        name = input("Имя не может быть пустым: ")

    if kind == "1":
        return Cat(name)
    return Dog(name)


def create_game():
    # пробуем загрузить сохранение
    try:
        pet, clock = Storage.load()
        answer = input(f"Найдено сохранение: {pet.name}. Продолжить? (д/н): ")
        if answer == "н":
            return Game(create_pet(), GameClock())
        return Game(pet, clock)
    except FileNotFoundError:
        print("Сохранение не найдено, начинаем новую игру")
    except ValueError:
        print(Fore.RED + "Сохранение повреждено, начинаем новую игру")

    return Game(create_pet(), GameClock())


class Game:
    def __init__(self, pet, clock):
        self.pet = pet      # питомец
        self.clock = clock  # игровые часы

    def skip_time(self):
        hours = input("Сколько часов пропустить: ")
        if not hours.isdecimal() or int(hours) == 0:
            raise ValueError("ожидалось число больше 0")
        hours = int(hours)

        # время идёт и у питомца, и у часов
        self.pet.pass_time(hours)
        self.clock.pass_time(hours)

        message = f"Прошло {hours} ч., сейчас {self.clock}"
        if self.clock.is_night() and not self.pet.is_sleeping:
            message += Fore.MAGENTA + f". {self.pet.name} хочет спать!"
        return message

    def status(self):
        text = str(self.pet) + f"\nВремя: {self.clock}"
        # цветные предупреждения
        if self.pet.hunger >= 8:
            text += Fore.RED + "\nПитомец очень голоден!"
        if self.pet.energy <= 2:
            text += Fore.YELLOW + "\nПитомец очень устал!"
        if self.pet.mood <= 2:
            text += Fore.YELLOW + "\nУ питомца плохое настроение!"
        return text

    def save(self):
        Storage.save(self.pet, self.clock)
        return "Игра сохранена"

    def quit(self):
        answer = input("Сохранить перед выходом? (д/н): ")
        if answer != "н":
            print(self.save())
        print("До встречи!")
        exit()

    def run(self):
        menu = [
            ("Покормить", self.pet.feed),
            ("Поиграть", self.pet.play),
            ("Уложить спать", self.pet.sleep),
            ("Разбудить", self.pet.wake_up),
            ("Пропустить время", self.skip_time),
            ("Показать состояние", self.status),
            ("Сохранить игру", self.save),
            ("Выйти", self.quit),
        ]

        print(self.status())
        while True:
            print()
            try:
                print(choice_menu(menu))
            except PetError as e:
                print(Fore.YELLOW + f"Нельзя: {e}")
            except ValueError as e:
                print(Fore.RED + f"Ошибка: {e}")
            except OSError as e:
                print(Fore.RED + f"Не удалось сохранить: {e}")