src/GeneticReplication.cpp

Go to the documentation of this file.
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 }

Generated on Sat Feb 2 22:22:54 2008 for Teapot Colony Wars by  doxygen 1.5.4