diff --git a/includes/animal.hpp b/includes/animal.hpp index dc82baf..c2f2b4a 100644 --- a/includes/animal.hpp +++ b/includes/animal.hpp @@ -13,6 +13,13 @@ * fuira */ class Animal: public Organisme { + // On regarde tout les organismes, dès qu'on trouve un organisme + // à l'index regardé, on vérifie qu'il correspond à l'espece que + // l'on recherche et qu'il est bien du genre opposé. + // Ensuite on l'ajoute si tout est bon au vecteur `animaux` + template + void rechercheEspece(int, std::vector &) noexcept; + protected: const int m_age_max; // age maximale que peut atteindre l'organisme @@ -22,30 +29,44 @@ class Animal: public Organisme { int m_age = 0; // age actuel de l'organisme - bool m_reproduire = true; // est-ce que l'animal peut se reproduire ? + // nombre de tour avant accouchement (-1 = quand pas enceinte) + short m_reproduire = -1; - // vrai si l'animal doit déposé des sédiment au sol à sa mort + Animal * m_partenaire = nullptr; + + // Vrai si l'animal doit déposé des sédiment au sol à sa mort bool m_deposer_sediment = true; // Renvoie une vitesse aléatoire (+ élevé = + rapide) virtual int generationVitesse(void) const noexcept = 0; + // Renvoie un genre choisit aléatoirement + int choixGenre(void) const noexcept; + // Renvoie la liste des cases accesible depuis la position de l'animal std::vector casesPossible(void) const noexcept; + // Renvoie la liste des animaux environnants + template + void animauxEnvirons(std::vector &) noexcept; + + const int genre; // genre, 0 = masculin, 1 = féminin + public: const int vitesse; // vitesse de l'organisme - // ID de l'univers, age max, faim max, vitesse - Animal(int, int, int, int); - - // ID de l'univers, index dans l'univers, age max, faim max, vitesse + // ID de l'univers, age max, faim max, vitesse, genre Animal(int, int, int, int, int); + // ID de l'univers, index dans l'univers, age max, faim max, vitesse, genre + Animal(int, int, int, int, int, int); + ~Animal(void); // Animal carnivore ? virtual bool carnivore(void) const noexcept = 0; }; +#include "animal_template.hpp" // définition du template + #endif diff --git a/includes/animal_template.hpp b/includes/animal_template.hpp new file mode 100644 index 0000000..0aa50be --- /dev/null +++ b/includes/animal_template.hpp @@ -0,0 +1,75 @@ +#ifndef ECOSYSTEME_ANIMAL_TEMPLATE_HPP +#define ECOSYSTEME_ANIMAL_TEMPLATE_HPP 1 + +template +void Animal::rechercheEspece(int i, std::vector &animaux) noexcept { + for(auto it: Univers::m_organismes_univers[m_univers_ID]) { + if(it->position().first == i) { // vérification index + if(auto animal = dynamic_cast(it)) { // vérification espece + if(genre != animal->genre) { // vérification genre + if(animal->m_partenaire == nullptr) { // animal pas déjà occupé + animaux.push_back(animal); + return; + } + } + } + } + } +} + +template +void Animal::animauxEnvirons(std::vector &animaux) noexcept { + int longueur_univers = Univers::m_dimensions_univers[m_univers_ID].first, + taille_max_univers = longueur_univers * Univers::m_dimensions_univers[m_univers_ID].second, + i; + + // En haut à gauche + i = m_index - longueur_univers - 1; + if(i >= 0 && i % longueur_univers < longueur_univers - 1) { + rechercheEspece(i, animaux); + } + + // En haut + i = m_index - longueur_univers; + if(i >= 0) { + rechercheEspece(i, animaux); + } + + // En haut à droite + i = m_index - longueur_univers + 1; + if(i >= 0 && i % longueur_univers != 0) { + rechercheEspece(i, animaux); + } + + // A gauche + i = m_index - 1; + if(i >= 0 && i % longueur_univers < longueur_univers - 1) { + rechercheEspece(i, animaux); + } + + // A droite + i = m_index + 1; + if(i < taille_max_univers && i % longueur_univers != 0) { + rechercheEspece(i, animaux); + } + + // En bas à gauche + i = m_index + longueur_univers - 1; + if(i < taille_max_univers && i % longueur_univers < longueur_univers - 1) { + rechercheEspece(i, animaux); + } + + // En bas + i = m_index + longueur_univers; + if(i < taille_max_univers) { + rechercheEspece(i, animaux); + } + + // En bas à droite + i = m_index + longueur_univers + 1; + if(i < taille_max_univers && i % longueur_univers != 0) { + rechercheEspece(i, animaux); + } +} + +#endif diff --git a/includes/mouton.hpp b/includes/mouton.hpp index 688d88c..78c6c6a 100644 --- a/includes/mouton.hpp +++ b/includes/mouton.hpp @@ -6,6 +6,8 @@ class Mouton: public Animal { const char _m_lettre = 'M'; // caractère représentant le mouton + const short m_attente_reproduction = 1; + // Défini la vitesse du mouton int generationVitesse(void) const noexcept; diff --git a/includes/organisme.hpp b/includes/organisme.hpp index 4738731..8263327 100644 --- a/includes/organisme.hpp +++ b/includes/organisme.hpp @@ -18,12 +18,14 @@ class Organisme { int m_index; // Location dans l'univers - // Supprime l'organisme des vecteur (argument = type de l'organisme) - void suppresionVecteurs(bool = true) noexcept; + // Supprime l'organisme des vecteur + void suppresionVecteurs(void) noexcept; public: const int ID; // ID unique pour chaque organisme + const bool m_superposable; // Type de l'organisme + bool mort = false; // vrai si l'organisme est mort // ID de l'Univers, type de l'organisme, index dans l'univers @@ -42,6 +44,9 @@ class Organisme { // Renvoie les coordonées de l'organisme en format "echequier" std::string coordoneeeEchequier(void) const noexcept; + + // Fais mourir l'organisme en libérant sa position + void mortOrganisme(bool = true) noexcept; }; #endif diff --git a/src/animal.cpp b/src/animal.cpp index 3618a7d..2033879 100644 --- a/src/animal.cpp +++ b/src/animal.cpp @@ -1,19 +1,25 @@ #include "../includes/animal.hpp" Animal::Animal(const int univers_ID, const int index, const int age_max, - const int faim_max, const int p_vitesse): Organisme(univers_ID, false, index), - m_age_max(age_max), - m_faim_max(faim_max), - vitesse(p_vitesse) { } + const int faim_max, const int p_vitesse, int p_genre): Organisme(univers_ID, false, index), + m_age_max(age_max), m_faim_max(faim_max), + genre(p_genre), vitesse(p_vitesse) +{ } Animal::Animal(const int univers_ID, const int age_max, - const int faim_max, const int p_vitesse): Organisme(univers_ID, false), - m_age_max(age_max), - m_faim_max(faim_max), - vitesse(p_vitesse) { } + const int faim_max, const int p_vitesse, int p_genre): Organisme(univers_ID, false), + m_age_max(age_max), m_faim_max(faim_max), + genre(p_genre), vitesse(p_vitesse) +{ } Animal::~Animal(void) { - suppresionVecteurs(false); + suppresionVecteurs(); + + // Si l'animal se reproduisait, on annule pour la mère + if(m_partenaire != nullptr) { + m_partenaire->m_partenaire = nullptr; + m_partenaire->m_reproduire = -1; + } // Vérifie si l'ont doit déposé des sédiments if(m_deposer_sediment) { @@ -122,3 +128,11 @@ std::vector Animal::casesPossible(void) const noexcept { return vec; } + +int Animal::choixGenre(void) const noexcept { + std::random_device nombre_aleatoire; + std::default_random_engine graine(nombre_aleatoire()); + std::uniform_int_distribution aleatoire(0, 1); + + return aleatoire(graine); +} diff --git a/src/loup.cpp b/src/loup.cpp index fecae61..8d0d909 100644 --- a/src/loup.cpp +++ b/src/loup.cpp @@ -1,10 +1,10 @@ #include "../includes/loup.hpp" -Loup::Loup(const int univers_ID): Animal(univers_ID, 60, 10, Loup::generationVitesse()) { +Loup::Loup(const int univers_ID): Animal(univers_ID, 60, 10, Loup::generationVitesse(), Loup::choixGenre()) { m_correspondance[ID] = _m_lettre; } -Loup::Loup(const int univers_ID, const int index): Animal(univers_ID, index, 60, 10, Loup::generationVitesse()) { +Loup::Loup(const int univers_ID, const int index): Animal(univers_ID, index, 60, 10, Loup::generationVitesse(), Loup::choixGenre()) { m_correspondance[ID] = _m_lettre; } @@ -37,7 +37,7 @@ void Loup::action(void) { /* TODO */ if(m_age > m_age_max || m_faim > m_faim_max) { // meurt si trop vieux ou trop faim - mort = true; + mortOrganisme(m_superposable); } else { ++m_age; // augmente l'âge ++m_faim; // augmente la faim diff --git a/src/mouton.cpp b/src/mouton.cpp index b6cb291..193183f 100644 --- a/src/mouton.cpp +++ b/src/mouton.cpp @@ -1,10 +1,10 @@ #include "../includes/mouton.hpp" -Mouton::Mouton(const int univers_ID): Animal(univers_ID, 50, 5, Mouton::generationVitesse()) { +Mouton::Mouton(const int univers_ID): Animal(univers_ID, 50, 5, Mouton::generationVitesse(), Mouton::choixGenre()) { m_correspondance[ID] = _m_lettre; } -Mouton::Mouton(const int univers_ID, const int index): Animal(univers_ID, index, 50, 5, Mouton::generationVitesse()) { +Mouton::Mouton(const int univers_ID, const int index): Animal(univers_ID, index, 50, 5, Mouton::generationVitesse(), Mouton::choixGenre()) { m_correspondance[ID] = _m_lettre; } @@ -32,18 +32,54 @@ void Mouton::action(void) { for(auto organisme: Univers::m_organismes_univers[m_univers_ID]) { // regarde tout les organismes if(organisme->position().first == m_index) { // si sur ma position if(dynamic_cast(organisme)) { // si c'est de l'herbe - organisme->mort = true; + organisme->mortOrganisme(organisme->m_superposable);; m_faim = 0; break; } } } - // S'accouple si besoin - /* TODO */ + // Si l'animal est une femelle + if(genre == 1) { + if(m_reproduire == -1) { // si l'animal peut se reproduire + std::vector pretendants; + animauxEnvirons(pretendants); // recuperation des animaux libre aux alentours + + // S'il y a des prétendants + if(pretendants.size() > 0) { + // On choisit aléatoirement un prétendant + std::uniform_int_distribution aleatoire_pretendant(0, pretendants.size() - 1); + Mouton * partenaire = pretendants[static_cast(aleatoire_pretendant(graine))]; + + m_partenaire = partenaire; + partenaire->m_partenaire = this; + + m_reproduire = 1; // accouchement dans 1 tour + } + } else { + if(m_reproduire >= 0) { // si l'animal est déjà entrain de se reproduire + --m_reproduire; + if(m_reproduire == -1) { // si reproduction terminée + static_cast(m_partenaire)->m_partenaire = nullptr; + m_partenaire = nullptr; + + std::vector cases_possible_enfant = this->casesPossible(); + std::uniform_int_distribution aleatoire_enfant(0, cases_possible_enfant.size() - 1); + + new Mouton(m_univers_ID, cases_possible_enfant[static_cast(aleatoire_enfant(graine))]); + + m_reproduire -= m_attente_reproduction; // doit attendre avant de pouvoir se reproduire encore + } else { + if(m_reproduire == -1 - m_attente_reproduction) { + m_reproduire = -1; + } + } + } + } + } if(m_age > m_age_max || m_faim > m_faim_max) { // meurt si trop vieux ou trop faim - mort = true; + mortOrganisme(m_superposable); } else { ++m_age; // augmente l'âge ++m_faim; // augmente la faim diff --git a/src/organisme.cpp b/src/organisme.cpp index 15e169d..00191cd 100644 --- a/src/organisme.cpp +++ b/src/organisme.cpp @@ -3,7 +3,8 @@ // organisme.hpp, donc si on importe univers.hpp dans organisme.hpp // alors univers.hpp ne pourra pas s'initalisé correctement -Organisme::Organisme(const int univers_ID, const bool superposable, const int index): m_univers_ID(univers_ID), m_index(index), ID(m_total_ID + 1) { +Organisme::Organisme(const int univers_ID, const bool superposable, const int index): m_univers_ID(univers_ID), m_index(index), + ID(m_total_ID + 1), m_superposable(superposable) { // S'il n'y a plus d'index de libres if(superposable) { if(Univers::m_index_libres_univers[m_univers_ID].first.size() == 0) { @@ -67,15 +68,7 @@ std::string Organisme::coordoneeeEchequier(void) const noexcept { return y + std::to_string(x); } -void Organisme::suppresionVecteurs(const bool type) noexcept { - // On se supprime du vecteur - auto debut = Univers::m_organismes_univers[m_univers_ID].begin(); - auto fin = Univers::m_organismes_univers[m_univers_ID].end(); - auto it = std::find(debut, fin, this); - if(it != fin) { - Univers::m_organismes_univers[m_univers_ID].erase(it); - } - +void Organisme::mortOrganisme(const bool type) noexcept { // On remet notre index dans le vecteur des index vide // puis on remélange notre vecteur if(type) { // vecteur différent en fonction du type @@ -85,4 +78,17 @@ void Organisme::suppresionVecteurs(const bool type) noexcept { Univers::m_index_libres_univers[m_univers_ID].second.push_back(m_index); Univers::melange(&Univers::m_index_libres_univers[m_univers_ID].second); } + + // On déclare mort l'organisme + mort = true; +} + +void Organisme::suppresionVecteurs(void) noexcept { + // On se supprime du vecteur + auto debut = Univers::m_organismes_univers[m_univers_ID].begin(); + auto fin = Univers::m_organismes_univers[m_univers_ID].end(); + auto it = std::find(debut, fin, this); + if(it != fin) { + Univers::m_organismes_univers[m_univers_ID].erase(it); + } } diff --git a/src/sel.cpp b/src/sel.cpp index e1a6d3e..3231325 100644 --- a/src/sel.cpp +++ b/src/sel.cpp @@ -17,7 +17,7 @@ Sel::~Sel(void) { void Sel::action(void) { if(m_age == 1) { // devient de l'herbe au bout d'un tour - mort = true; + mortOrganisme(m_superposable); } else { ++m_age; }