00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "World.h"
00026
00027 #include <GL/glut.h>
00028 #include <list>
00029 #include <utility>
00030
00031 #include "Constants.h"
00032 #include "Random.h"
00033
00034 #include "WallCell.h"
00035 #include "ColonyCell.h"
00036 #include "EmptyCell.h"
00037 #include "CorridorCell.h"
00038 #include "InfiniteFood.h"
00039 #include "RenewableFood.h"
00040 #include "GodsGiftFood.h"
00041 #include "CorpseFood.h"
00042
00043 #include "NorthMove.h"
00044 #include "SouthMove.h"
00045 #include "EastMove.h"
00046 #include "WestMove.h"
00047 #include "NorthEastMove.h"
00048 #include "NorthWestMove.h"
00049 #include "SouthEastMove.h"
00050 #include "SouthWestMove.h"
00051 #include "NoMove.h"
00052
00053 #include "Colony.h"
00054 #include "Worshiper.h"
00055 #include "VisualContext.h"
00056 #include "UntilVictoryFight.h"
00057 #include "HeuristicReplication.h"
00058 #include "GeneticReplication.h"
00059
00060 void World::addNewWorshipers() {
00061 std::list<ColonyCell*>::iterator it, begin, end;
00062 std::list<Worshiper*> *worshipers = NULL;
00063 Worshiper *w = NULL;
00064
00065
00066 for(int i = 0; i < _colonies.size(); i++) {
00067
00068 worshipers = _colonies[i]->getNewWorshipers();
00069 if(worshipers != NULL) {
00070 _colonies[i]->getCellIterators(begin, end);
00071
00072 while(! worshipers->empty()) {
00073 for(it = begin; it != end && ! worshipers->empty(); ++it) {
00074
00075 w = worshipers->front();
00076 if(w != NULL) {
00077
00078 w->setVisualContext(
00079 new VisualContext(this, (*it)->getHeight(), (*it)->getWidth()));
00080
00081 (*it)->addWorshiper(w);
00082 }
00083
00084 worshipers->pop_front();
00085 }
00086 }
00087 }
00088 }
00089 }
00090
00091 void World::addPheromone(Cell *cell, Worshiper *w) {
00092 std::list<Pheromone*>::iterator it, end;
00093 std::list<Pheromone*> *pheromones = NULL;
00094
00095
00096 pheromones = w->getPheromones();
00097 if(pheromones != NULL) {
00098 end = pheromones->end();
00099
00100 for(it = pheromones->begin(); it != end; ++it) {
00101 cell->addPheromone(*it);
00102 }
00103 }
00104 }
00105
00106 void World::addCommand(Worshiper *w, unsigned int i, unsigned int j) {
00107 std::pair<unsigned int, unsigned int> coord;
00108
00109
00110 coord = _move->getAbsCoords(w->getAction(), i, j);
00111
00112
00113 if((coord.first != i || coord.second != j) &&
00114 coord.first > 0 && coord.first < _height - 1 &&
00115 coord.second > 0 && coord.second < _width - 1 &&
00116 getCell(coord.first, coord.second)->reachable(w)) {
00117
00118 coord_t c = {coord.first, coord.second, i, j};
00119 _commandes[w] = c;
00120 }
00121 }
00122
00123 void World::makeCommand() {
00124 std::map<Worshiper*, coord_t>::iterator it, end;
00125 VisualContext *view = NULL;
00126
00127
00128 end = _commandes.end();
00129 for(it = _commandes.begin(); it != end; ++it) {
00130
00131 if(getCell(it->second.i, it->second.j)->addWorshiper(it->first)) {
00132
00133 view = it->first->getVisualContext();
00134 if(view != NULL) {
00135 view->_i = it->second.i;
00136 view->_j = it->second.j;
00137 }
00138
00139 getCell(it->second.old_i, it->second.old_j)->removeWorshiper(it->first);
00140 }
00141 }
00142
00143 _commandes.clear();
00144 }
00145
00146 Cell* World::fight(Cell *cell) {
00147 ReachableCell *next = NULL;
00148 ColonyCell *colony = NULL;
00149 CorpseFood *dead = NULL;
00150 unsigned int food;
00151
00152
00153 food = _fightStrategy->resolve(cell);
00154
00155 if(food > 0) {
00156 if(dynamic_cast<CorpseFood*>(cell)) {
00157
00158 cell->addFood(food);
00159 } else {
00160
00161
00162 next = dynamic_cast<ReachableCell*>(cell);
00163
00164 if(colony = dynamic_cast<ColonyCell*>(cell)) {
00165
00166 colony->getColony()->incrementFood(food);
00167 } else if(next) {
00168
00169 dead = new CorpseFood(food);
00170 if(dead != NULL) {
00171
00172 dead->push(next);
00173
00174 cell = dead;
00175 }
00176 }
00177 }
00178 }
00179
00180 return cell;
00181 }
00182
00183 void World::feed(Cell *cell) {
00184 std::list<Worshiper*> *worshipers = NULL;
00185 std::list<Worshiper*>::iterator it, end;
00186 unsigned int nb_people, ratio;
00187 unsigned int needed, consumed;
00188 unsigned int food;
00189 bool full;
00190
00191
00192 worshipers = cell->getPeople();
00193
00194 food = cell->getFood();
00195
00196 if(food > 0 && worshipers != NULL && (nb_people = worshipers->size()) > 0) {
00197
00198
00199 full = false;
00200
00201 while(food > 0 && ! full) {
00202
00203
00204 full = true;
00205
00206 ratio = (unsigned int) (food / nb_people) + 1;
00207
00208 end = worshipers->end();
00209 for(it = worshipers->begin(); food > 0 && it != end; ++it) {
00210
00211 needed = (*it)->getCapacity() - (*it)->getFood();
00212
00213 full = !(full && needed > ratio);
00214
00215 needed = (needed > ratio ? ratio : needed);
00216
00217 consumed = cell->subFood(needed);
00218
00219 food = cell->getFood();
00220
00221 (*it)->setFood((*it)->getFood() + consumed);
00222 }
00223 }
00224 }
00225
00226 end = worshipers->end();
00227 for(it = worshipers->begin(); it != end; ++it) {
00228 if(! (*it)->subFood()) {
00229
00230
00231 delete (*it);
00232 cell->removeWorshiper(*it);
00233 --it;
00234 }
00235 }
00236 }
00237
00238 World::World(unsigned int width, unsigned int height, unsigned int nb_colonies):
00239 _width(width), _height(height), _colonies(nb_colonies) {
00240 unsigned int max;
00241 int i, j, n = 0;
00242
00243
00244 for(int i = 0; i < nb_colonies; i++){
00245 _colonies[i] = new Colony(MAX_FOOD_CAPACITY * 30, new GeneticReplication);
00246 }
00247
00248 _map = new Cell*[_width * _height];
00249 for(i = 0; i < _height; i++) {
00250 for(j = 0; j < _width; j++) {
00251 if(i == 0 || i == _height - 1 || j == 0 || j == _width - 1) {
00252
00253 getCell(i, j) = new WallCell;
00254 } else {
00255
00256
00257
00258
00259
00260
00261
00262
00263 switch(Random::value() % 10) {
00264 case 0:
00265 getCell(i, j) = new ColonyCell(_colonies[n++ % _colonies.size()], i, j);
00266 break;
00267 case 1:
00268
00269
00270 max = (Random::value() % MAX_FOOD_CAPACITY) + 1;
00271 getCell(i, j) = new RenewableFood(max, (Random::value() % max) + 1);
00272 break;
00273 case 2:
00274
00275 getCell(i, j) = new InfiniteFood((Random::value() % MAX_FOOD_CAPACITY) + 1);
00276 break;
00277 case 3:
00278
00279 getCell(i, j) = new CorridorCell((Random::value() % CORRIDOR_SIZE_MAX) + 1);
00280 break;
00281 case 4:
00282 getCell(i, j) = new WallCell;
00283 break;
00284 default:
00285 getCell(i, j) = new EmptyCell;
00286 }
00287 }
00288 }
00289 }
00290 delete getCell(7, 7);
00291 getCell(7, 7) = new ColonyCell(_colonies[0], 7, 7);
00292 delete getCell(8, 8);
00293 getCell(8, 8) = new ColonyCell(_colonies[1], 8, 8);
00294
00295 _fightStrategy = new UntilVictoryFight;
00296
00297
00298 _move = new NoMove(
00299 new NorthMove(
00300 new SouthMove(
00301 new WestMove(
00302 new EastMove(
00303 new NorthWestMove(
00304 new NorthEastMove(
00305 new SouthEastMove(
00306 new SouthWestMove(NULL)
00307 )
00308 )
00309 )
00310 )
00311 )
00312 )
00313 )
00314 );
00315 }
00316
00317 World::~World() {
00318 int i;
00319
00320 for(i = 0; i < _width * _height; i++) {
00321 delete _map[i];
00322 }
00323 delete[] _map;
00324 delete _fightStrategy;
00325 delete _move;
00326 }
00327
00328 unsigned int World::getWidth() {
00329 return _width;
00330 }
00331
00332 unsigned int World::getHeight() {
00333 return _height;
00334 }
00335
00336 Move* World::getMove() const {
00337 return _move;
00338 }
00339
00340 void World::addGodsGift(unsigned int i, unsigned int j) {
00341 ReachableCell *next = NULL;
00342 GodsGiftFood *gift = NULL;
00343 Cell *cell = NULL;
00344
00345 cell = getCell(i, j);
00346 next = dynamic_cast<ReachableCell*>(cell);
00347
00348 if(next && ! dynamic_cast<ColonyCell*>(cell)) {
00349 gift = new GodsGiftFood(GODS_GIFT_FOOD_VALUE);
00350 if(gift != NULL) {
00351
00352 gift->push(next);
00353
00354 getCell(i, j) = gift;
00355 }
00356 }
00357 }
00358
00359 void World::iteration() {
00360 std::list<Worshiper*> *worshipers = NULL;
00361 std::list<Worshiper*>::iterator it, end;
00362 Cell *cell = NULL;
00363 unsigned int i, j;
00364
00365
00366 addNewWorshipers();
00367
00368 for(i = 1; i < _height - 1; i++) {
00369 for(j = 1; j < _width - 1; j++) {
00370 cell = getCell(i, j);
00371
00372 worshipers = cell->getPeople();
00373 if(worshipers != NULL) {
00374 end = worshipers->end();
00375 for(it = worshipers->begin(); it != end; ++it) {
00376
00377 (*it)->think();
00378
00379 addPheromone(cell, *it);
00380
00381 addCommand(*it, i, j);
00382 }
00383 }
00384 }
00385 }
00386
00387 makeCommand();
00388
00389 for(i = 1; i < _height - 1; i++) {
00390 for(j = 1; j < _width - 1; j++) {
00391 cell = getCell(i, j);
00392
00393 if(cell->getPeople() != NULL) {
00394
00395
00396
00397
00398 getCell(i, j) = cell = fight(cell);
00399
00400 feed(cell);
00401
00402 getCell(i, j) = cell->makeActions();
00403 }
00404 }
00405 }
00406 }
00407
00408 void World::draw() {
00409 int i, j;
00410
00411 glMatrixMode(GL_MODELVIEW);
00412
00413 for(i = 0; i < _height; i++) {
00414 for(j = 0; j < _width; j++) {
00415
00416 getCell(i, j)->draw();
00417 glTranslatef(CELL_SIZE, 0.0, 0.0);
00418 }
00419 glTranslatef(- (GLfloat) CELL_SIZE * _width, 0.0, CELL_SIZE);
00420 }
00421 }