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 "GeneticBehaviour.h" 00026 00027 #include <map> 00028 00029 #include "Random.h" 00030 #include "VisualContext.h" 00031 #include "GeneticCode.h" 00032 #include "MoveIterator.h" 00033 #include "WorshiperInfo.h" 00034 00036 #define NOT_HUNGRY_FACTOR 0.5 00037 00038 #define BONUS_GREEDY 10 00039 00040 #define MALUS_ANOREXIC (-10) 00041 00042 #define MALUS_NOT_HUNGRY (-10) 00043 00044 #define BONUS_AGGRESSIVE 15 00045 00046 #define MALUS_COWARD (-15) 00047 00048 #define MALUS_REASONABLE (-10) 00049 00051 #define INFINITE 1000; 00052 00053 00054 using namespace std; 00055 00056 GeneticBehaviour::GeneticBehaviour() : Behaviour(), 00057 _code(new GeneticCode) {} 00058 00059 00060 GeneticBehaviour::GeneticBehaviour(GeneticCode * c) : Behaviour(), _code(c) {} 00061 00062 00063 GeneticBehaviour::~GeneticBehaviour() { 00064 delete _code; 00065 } 00066 00067 00068 void GeneticBehaviour::think(){ 00069 //Clear the pheromone list 00070 _pheros->clear(); 00071 00072 //Get the visual context 00073 VisualContext * visu = getVisualContext(); 00074 00075 //The map containing the score for each movement 00076 map<move_command, int> map_scores; 00077 map<move_command, int>::iterator it_map_scores, end_map_scores; 00078 00079 //The best score and movement 00080 int best_score = -INFINITE; 00081 move_command best_move = MOVECMD_NOMOVE; 00082 00083 //For ennemies 00084 bool found = false; 00085 list<WorshiperInfo> winfos; 00086 list<WorshiperInfo>::iterator it_winfos, end_winfos; 00087 00088 //For movements 00089 MoveIterator it_move, end_move = visu->endMove(); 00090 00091 //Foreach movement, we evaluate its score 00092 for(it_move = visu->beginMove(); it_move != end_move; ++it_move){ 00093 if(*it_move != MOVECMD_NOMOVE && visu->legal(it_move) && visu->reachable(it_move)){ 00094 00095 //Zero initialization 00096 map_scores[*it_move] = 0; 00097 00098 //If there is food 00099 if(visu->haveFood(it_move)){ 00100 00101 //If I'm greedy (max value) 00102 if(_code->getGreedy() == ((1 << NB_BITS_GREEDY) - 1)){ 00103 map_scores[*it_move] += BONUS_GREEDY; 00104 } else if(_code->getGreedy() == 0){ //Else if I'm anorexic 00105 map_scores[*it_move] += MALUS_ANOREXIC; 00106 } else if(getFood() > (NOT_HUNGRY_FACTOR * getCapacity())){ //If I have enough food I don't go 00107 map_scores[*it_move] += MALUS_NOT_HUNGRY; 00108 } 00109 } 00110 00111 //If there are ennemies.. 00112 winfos = visu->getWorshipers(it_move); 00113 found = false; 00114 if(!winfos.empty()){ 00115 end_winfos = winfos.end(); 00116 for(it_winfos = winfos.begin(); !found && it_winfos != end_winfos; ++it_winfos){ 00117 found = it_winfos->isEnnemy(); 00118 } 00119 } 00120 --it_winfos; 00121 00122 if(found){ 00123 00124 //If I'm aggressive (max value), I want to go ! 00125 if(_code->getAggressiveness() == ((1 << NB_BITS_AGGRESSIVENESS) - 1)){ 00126 map_scores[*it_move] += BONUS_AGGRESSIVE; 00127 } else if(_code->getAggressiveness() == 0){ //I'm a coward ! 00128 map_scores[*it_move] += MALUS_COWARD; 00129 } 00130 00131 //If I'm reasonable and if the ennemy is taller than me, I run away ! 00132 if(_code->getReasonable() == ((1 << NB_BITS_REASONABLE) - 1)){ 00133 if(it_winfos->getSize() > getSize()){ 00134 map_scores[*it_move] += MALUS_REASONABLE; 00135 } 00136 } 00137 } 00138 } 00139 } 00140 00141 //I find the maximum value 00142 end_map_scores = map_scores.end(); 00143 for(it_map_scores = map_scores.begin(); it_map_scores != end_map_scores; ++it_map_scores){ 00144 if(it_map_scores->second > best_score){ 00145 best_score = it_map_scores->second; 00146 best_move = it_map_scores->first; 00147 } 00148 } 00149 00150 //And I make my decision 00151 _action = best_move; 00152 00153 }