00001 00008 /* 00009 This file is part of Teapot Colony Wars. 00010 00011 Teapot Colony Wars is free software: you can redistribute it and/or modify 00012 it under the terms of the GNU General Public License as published by 00013 the Free Software Foundation, either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 Teapot Colony Wars is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU General Public License for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with Teapot Colony Wars. If not, see <http://www.gnu.org/licenses/>. 00023 */ 00024 00025 #include "GeneticReplication.h" 00026 00027 #include <map> 00028 #include <list> 00029 00030 #include "Worshiper.h" 00031 #include "Random.h" 00032 #include "Constants.h" 00033 #include "GeneticBehaviour.h" 00034 #include "GeneticCode.h" 00035 00036 using namespace std; 00037 00038 00039 GeneticReplication::GeneticReplication() : Replication() {} 00040 00041 00042 unsigned int GeneticReplication::evaluation(Worshiper * w){ 00043 return w->getFood(); 00044 } 00045 00046 00047 GeneticReplication::~GeneticReplication() {} 00048 00049 00050 list<Worshiper*>* GeneticReplication::getNewWorshipers(){ 00051 //Clear the list 00052 _new_worshipers->clear(); 00053 00054 Worshiper * w = NULL; 00055 00056 //The information sources : the survivors and the number of created worshipers 00057 unsigned int colonyFood = getFood(); 00058 unsigned int nbWorshipers = _survivors.size(); 00059 00060 //If nobody (or not enough worshipers) has came back, 00061 //we create as many worshipers as we can 00062 if(nbWorshipers < 2){ 00063 00064 //While we have food, we spend it by creating randomized behaviours 00065 do { 00066 w = createWorshiper(new GeneticBehaviour); //NULL when not enough food 00067 if(w) { 00068 _new_worshipers->push_back(w); 00069 } 00070 } while (w && _new_worshipers->size() <= (MAX_WORSHIPER_PER_CELL * getNbCells())); 00071 00072 //(Food may remain because the food quantity is randomized, but we save it) 00073 00074 } else { //There are some survivors who came back 00075 00076 //We select two survivors, and we cross them 00077 00078 //Copy the map into a temp one 00079 map<GeneticCode*,unsigned int> temp(_survivors); 00080 00081 //We iterate over the map and we add a random delta to each value,which can 00082 //be positive or negative (in [GENETIC_RANDOM_I, GENETIC_RANDOM_I[) 00083 unsigned int delta; 00084 map<GeneticCode*,unsigned int>::iterator it, end = temp.end(); 00085 for(it = temp.begin(); it != end; ++it){ 00086 delta = (Random::value() % GENETIC_RANDOM_I); 00087 if(Random::value() %2 == 0) it->second += delta; 00088 else { 00089 if(it->second > delta) it->second -= delta; 00090 else it->second = 0; 00091 } 00092 } 00093 00094 //We select the two maximal individuals 00095 map<GeneticCode*,unsigned int>::iterator it_max1, it_max2; 00096 unsigned int max1 = 0, max2 = 0; 00097 for(it = temp.begin(); it != end; ++it){ 00098 if(it->second >= max1){ 00099 it_max1 = it; 00100 max1 = it->second; 00101 } 00102 } 00103 00104 for(it = temp.begin(); it != end; ++it){ 00105 if(it != it_max1 && it->second >= max2){ 00106 it_max2 = it; 00107 max2 = it->second; 00108 } 00109 } 00110 00111 //Crossover operation between the two best 00112 GeneticCode * c = it_max1->first->crossover(it_max2->first); 00113 00114 //If the randomized number divisible by GENETIC_MUTATE_PROBA, a mutation occurs 00115 if((Random::value() % GENETIC_MUTATE_PROBA) == 0){ 00116 c->mutate(); 00117 } 00118 00119 //The new worshiper is created and put into the _new_worshipers list 00120 Worshiper * w = createWorshiper(new GeneticBehaviour(c)); 00121 if(w){ 00122 _new_worshipers->push_back(w); 00123 } 00124 00125 //We remove some individuals whose score are minimal 00126 //It ensures the population won't grow infinitly, and that we keep the best 00127 map<GeneticCode*,unsigned int>::iterator it_min; 00128 unsigned int min; 00129 while(_survivors.size() > GENETIC_MAX_SURVIVORS){ 00130 min = max1; 00131 end = temp.end(); 00132 for(it = temp.begin(); it != end; ++it){ 00133 if(it->second <= min){ 00134 it_min = it; 00135 min = it->second; 00136 } 00137 } 00138 00139 //The individual is deleted... 00140 delete it_min->first; 00141 00142 //...then removed in both the temp map and the survivors one 00143 _survivors.erase(it_min->first); 00144 temp.erase(it_min); 00145 } 00146 } 00147 00148 return _new_worshipers; 00149 } 00150 00151 00152 Worshiper* GeneticReplication::createWorshiper(GeneticBehaviour * b){ 00153 //Extract the information from the genetic code 00154 GeneticCode * code = b->getGeneticCode(); 00155 return Replication::createWorshiper(code->getSize(), 00156 Random::value() % MAX_FOOD_CAPACITY, 00157 b); 00158 } 00159 00160 00161 void GeneticReplication::addSurvivor(Worshiper * w){ 00162 //Copy the genetic code (so that the worshiper can be destroyed) 00163 GeneticBehaviour * b = (GeneticBehaviour *) w->getBehaviour(); 00164 GeneticCode * gc = new GeneticCode(b->getGeneticCode()); 00165 00166 //Calculate the evaluation value and add the code to the survivors 00167 _survivors[gc] = evaluation(w); 00168 00169 //Delete the worshiper 00170 delete w; 00171 }