from random import choice


class EtreVivant:
    def __init__(self, age=0, resistance=10):
        self.age = age
        self.resistance = resistance

    def vieillir(self):
        self.age += 1

    def estMort(self):
        return self.age >= 20 and self.resistance < 1

    def __repr__(self):
        """Retourne une représentation courte de la forme
        Algue(1, 8) ou bien PoissonHerbivore(3,5).
        Principalement utilisé pour afficher les êtres vivants
        stockés dans des conteneurs.
        """
        return self.__class__.__name__ + "({0}, {1})".format(self.age, self.resistance)

    def __str__(self):
        """Retourne une représentation longue de la forme
        [Algue] Age : 1, Résistance : 8 ou bien
        [Charly] Age : 3, Résistance : 5 (Femelle).
        Principalement utilisé pour l’affichage direct d’un
        objet EtreVivant.
        """
        return "[" + self.nom + "] Age : " + str(self.age) + ", Résistance : " + str(self.resistance)

    def seFaireManger(self):
        self.resistance -= 5


class Algue(EtreVivant):
    nom = "Algue"

    def vieillir(self):
        super().vieillir()
        self.resistance += 1
        if self.resistance > 10:
            new_res = self.resistance // 2
            self.resistance -= new_res
            return Algue(resistance=new_res)


class Poisson(EtreVivant):
    def __init__(self, nom, age=0, resistance=10, faim=0):
        super().__init__(age,resistance)
        self.nom = nom
        self.faim = faim
        self.sexe = choice(["Mâle", "Femelle"])
        self.aCoteDe(None)

    def vieillir(self):
        super().vieillir()
        self.faim += 1
        if self.faim > 5:
            self.seNourrir(self.voisin)
        else:
            return self.seReproduire(self.voisin)

    def __str__(self):
        return super().__str__() + " (%s)" % self.sexe

    def aCoteDe(self, voisin):
        self.voisin = voisin


class PoissonHerbivore(Poisson):
    def seNourrir(self, voisin):
        if isinstance(voisin, Algue):
            voisin.seFaireManger()
            self.resistance += 3
            self.faim = 0

    def seReproduire(self, voisin):
        if isinstance(voisin, PoissonHerbivore) and self.sexe != voisin.sexe:
            return PoissonHerbivore(self.nom + voisin.nom + '/')


class PoissonCarnivore(Poisson):
    def seNourrir(self, voisin):
        if isinstance(voisin, Poisson):
            voisin.seFaireManger()
            self.resistance += 5
            self.faim = 0

    def seReproduire(self, voisin):
        if isinstance(voisin, PoissonCarnivore) and self.sexe != voisin.sexe:
            return PoissonCarnivore(self.nom + voisin.nom + '/')

def aquarium():
    nb_algues = int(input("Nombre d’algues dans l’aquarium : "))
    nb_herbivores = int(input("Nombre de poissons herbivores : "))
    nb_carnivores = int(input("Nombre de poissons carnivores : "))

    # Construction de l’aquarium en fonction de informations récupérées
    aquarium = [Algue() for _ in range(nb_algues)]
    for index in range(1, nb_herbivores + 1):
        nom = input("Nom poisson herbivore numéro " + str(index) + " ")
        aquarium.append(PoissonHerbivore(nom))
    for index in range(1, nb_carnivores + 1):
        nom = input("Nom poisson carnivore numéro " + str(index) + " ")
        aquarium.append(PoissonCarnivore(nom))

    while input("Avancer d’un jour ? ") == '':
        # On déplace les poissons à côté d’un autre être vivant de l’aquarium
        for etre_vivant in aquarium:
            if isinstance(etre_vivant, Poisson):
                autre = choice(aquarium)
                if autre is etre_vivant:
                    etre_vivant.aCoteDe(None)
                else:
                    etre_vivant.aCoteDe(autre)

        # On fait vieillir tous les êtres vivants de l’aquarium et on rajoute les naissances par la suite
        naissances = []
        for etre_vivant in aquarium:
            n = etre_vivant.vieillir()
            if n is not None:
                naissances.append(n)
        print("Naissances du jour :", naissances)
        for n in naissances:
            aquarium.append(n)

        # On supprime les morts
        morts = []
        for etre_vivant in aquarium:
            if etre_vivant.estMort():
                morts.append(etre_vivant)
        for mort in morts:
            aquarium.remove(mort)

        # À partir de là, la boucle while recommence, on affiche juste l’état de l’aquarium avant ça
        print(" === État de l’aquarium === ")
        for ev in aquarium:
            print(ev)


# Execute aquarium si le fichier est exécuté mais pas si il est chargé comme un module
if __name__ == '__main__':
    aquarium()
