Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

weatherarea.cpp

Go to the documentation of this file.
00001 //
00002 // C++ Implementation: weatherarea
00003 //
00004 // Description:
00005 //
00006 //
00007 // Author: Kevin Hirschmann <hirsch@dhcppc0>, (C) 2004
00008 //
00009 // Copyright: See COPYING file that comes with this distribution
00010 //
00011 //
00012 #include <iostream>
00013 #include <ctime>
00014 #include "weatherarea.h"
00015 #include "geometry.h"
00016 IllegalValueException::IllegalValueException(const ASCString& msg):ASCmsgException(msg) {}
00017 
00018 IllegalValueException::~IllegalValueException() {}
00019 
00020 const char*  cdirections[WeatherSystem::WindDirNum] = {"North", "NorthEast", "SouthEast", "South", "SouthWest", "NorthWest" };
00021 
00022 
00023 void MapCoordinate::move(const Vector2D& v){
00024    x +=v.getXComponent();
00025    y +=v.getYComponent();
00026 }
00027 
00028 
00029 //***************************************************************************************************************************************
00030 Vector2D::Vector2D():xComponent(0), yComponent(0) {}
00031 
00032 Vector2D::Vector2D(int x, int y):xComponent(x), yComponent(y) {}
00033 
00034 Vector2D::~Vector2D() {}
00035 
00036 int Vector2D::getXComponent() const {
00037    return xComponent;
00038 }
00039 
00040 int Vector2D::getYComponent() const {
00041    return yComponent;
00042 }
00043 double Vector2D::getLength() const{
00044    return std::sqrt(std::pow(double(xComponent), 2) + std::pow(double(yComponent),2));
00045 }
00046 
00047 bool Vector2D::isZeroVector() const {
00048    return ((xComponent == 0) && (yComponent == 0));
00049 }
00050 
00051 
00052 //****************************************************************************************************************************************
00053 const int WeatherArea::MAXVALUE = 200;
00054 const int WeatherArea::MAXOFFSET = 100;
00055 WeatherArea::WeatherArea(GameMap* m, int xCenter, int yCenter, int w, int h, int d, FalloutType fallout, unsigned int sV, bool clustered): map(m), center(xCenter, yCenter), width(w), height(h), duration(d), ft(fallout), stepCount(0), seedValue(sV), verticalWindAccu(0), horizontalWindAccu(0), clustered(clustered) {
00056     WeatherField* wf;
00057     for(int i = 0; i < width * height; i++) {
00058         int x =  i % width;
00059         int y =  i / width;
00060         wf = new WeatherField(MapCoordinate(x + (center.x - width/2), y + (center.y - height/2)), this);
00061         area.push_back(wf);
00062     }
00063     createWeatherFields();
00064 }
00065 
00066 WeatherArea::WeatherArea(GameMap* m): map(m) {}
00067 
00068 
00069 WeatherArea::WeatherArea(GameMap* m, int xCenter, int yCenter, int r):map(m), center(xCenter, yCenter), width(r), height(r), radius(r) {}
00070 
00071 WeatherArea::~WeatherArea() {
00072     for(int i = 0; i < area.size(); i++) {
00073         delete area[i];
00074     }
00075 }
00076 
00077 
00078 void WeatherArea::createWeatherFields() {
00079     if(area.size()>0) {
00080         WeatherField* wf;
00081         srand(seedValue);
00082 
00083         wf = area[(width*height)/2];
00084         wf->setValue(MAXVALUE);
00085         wf = area[0];
00086         wf->setValue(createRandomValue(MAXVALUE));
00087         wf = area[width - 1];
00088         wf->setValue(createRandomValue(MAXVALUE));
00089         wf = area[width * height - 1];
00090         wf->setValue(createRandomValue(MAXVALUE));
00091         wf = area[(width * height - 1) - width];
00092         wf->setValue(createRandomValue(MAXVALUE));
00093         WeatherRect r = {0, width -1, width * height -1, (width * height) - width };
00094         step(r);
00095     }
00096 }
00097 
00098 
00099 GameMap* WeatherArea::getMap() const {
00100     return map;
00101 }
00102 
00103 
00104 void WeatherArea::setFalloutType(FalloutType fallout) {
00105     ft = fallout;
00106 }
00107 
00108 FalloutType WeatherArea::getFalloutType(int value) const {
00109 
00110     if((ft != map->weatherSystem->getDefaultFalloutType()) && (clustered)) {
00111       if(value < (MAXVALUE * 0.25)) {        
00112         if((ft != DRY) && (ft != LSNOW)){       
00113             return static_cast<FalloutType>(ft-1);
00114         }else{
00115           return map->weatherSystem->getDefaultFalloutType();
00116         }
00117       }
00118     }
00119     return ft;
00120 }
00121 
00122 int WeatherArea::getHeight() const{
00123   return height;
00124 }
00125 
00126 int WeatherArea::getWidth() const{
00127   return width;
00128 
00129 }
00130 
00131 void WeatherArea::updateMovementVector(unsigned int windspeed, Direction windDirection, double ratio) {
00132     if(windDirection == N) {
00133         verticalWindAccu += (-1 * ratio * windspeed);
00134     } else if(windDirection == NE) {
00135         verticalWindAccu += (-1 * ratio * windspeed);
00136         horizontalWindAccu += ratio * windspeed;
00137     } else if(windDirection == SE) {
00138         verticalWindAccu += (ratio * windspeed);
00139         horizontalWindAccu += ratio * windspeed;
00140     } else if(windDirection == S) {
00141         verticalWindAccu += (ratio * windspeed);
00142     } else if(windDirection == SW) {
00143         verticalWindAccu += (ratio * windspeed);
00144         horizontalWindAccu += -1 *ratio * windspeed;
00145     } else if(windDirection == NW) {
00146         verticalWindAccu += (-1 * ratio * windspeed);
00147         horizontalWindAccu += -1 *ratio * windspeed;
00148     } /*else if(windDirection == W) {
00149                 horizontalWindAccu += -1 *ratio * windspeed;
00150             } else if(windDirection == E) {
00151                 horizontalWindAccu += ratio * windspeed;
00152             }*/
00153     int vMove = static_cast<int>(verticalWindAccu);
00154     verticalWindAccu -= vMove;
00155     int hMove = static_cast<int>(horizontalWindAccu);
00156     horizontalWindAccu -= hMove;
00157     currentMovement = Vector2D(hMove,  2 * vMove);
00158 
00159 }
00160 
00161 
00162 void WeatherArea::update(WeatherSystem* wSystem, FieldSet& processedFields) {
00163     duration--;
00164     if(!currentMovement.isZeroVector()) {
00165         for(int i = 0; i < area.size(); i++) {
00166             WeatherField* wf = area[i];
00167             if(wf->isOnMap(map)) {
00168                 wf->reset(this->map, this, processedFields);
00169             }
00170         }
00171         center.move(currentMovement);
00172         //cout << "wa.update: center: " << center.getX() << ", " << center.getY() << endl;
00173     }
00174     for(int i = 0; i < area.size(); i++) {
00175         WeatherField* wf = area[i];
00176         wf->move(currentMovement);
00177         if(wf->isOnMap(map)) {
00178             wf->update(this, processedFields);
00179         }
00180     }
00181 }
00182 
00183 void WeatherArea::write (tnstream& outputStream) const {
00184     outputStream.writeInt(seedValue);
00185     outputStream.writeInt(duration);
00186     outputStream.writeInt(width);
00187     outputStream.writeInt(height);
00188     outputStream.writeInt(center.x);
00189     outputStream.writeInt(center.y);
00190     outputStream.writeFloat(verticalWindAccu);
00191     outputStream.writeFloat(horizontalWindAccu);
00192     /*Version 1*/
00193     outputStream.writeInt(currentMovement.getXComponent());
00194     outputStream.writeInt(currentMovement.getYComponent());
00195     outputStream.writeInt(ft);
00196     outputStream.writeInt ( area.size() );
00197     for ( WeatherFields::const_iterator i = area.begin(); i != area.end(); i++ ) {
00198     (*i)->write ( outputStream );
00199     }
00200     outputStream.writeInt(clustered);
00201 }
00202 
00203 void WeatherArea::read (tnstream& inputStream) {
00204     seedValue = inputStream.readInt();
00205     duration = inputStream.readInt();
00206     width = inputStream.readInt();
00207     height = inputStream.readInt();
00208     int x = inputStream.readInt();
00209     int y = inputStream.readInt();
00210     center = MapCoordinate(x, y);
00211     verticalWindAccu = inputStream.readFloat();
00212     horizontalWindAccu = inputStream.readFloat();
00213     /* Version 1*/
00214     int xmov = inputStream.readInt();
00215     int ymov = inputStream.readInt();
00216     currentMovement = Vector2D(xmov, ymov );
00217     ft = static_cast<FalloutType>(inputStream.readInt());
00218     int size = inputStream.readInt();
00219     for ( int i = 0; i < size; i++ ) {
00220         int x =  i % width;
00221         int y =  i / width;
00222         WeatherField* wf = new WeatherField(MapCoordinate(x + (center.x - width/2), y + (center.y - height/2)), this);
00223         /*WeatherField* newWf = new WeatherField(map);*/
00224         wf->read(inputStream);
00225         area.push_back(wf);
00226     }
00227     //createWeatherFields();
00228     clustered = inputStream.readInt();
00229 }
00230 
00231 Vector2D WeatherArea::getWindVector() const {
00232     return currentMovement;
00233 }
00234 
00235 FalloutType WeatherArea::getFalloutType() const {
00236     return ft;
00237 }
00238 
00239 void WeatherArea::placeArea() {
00240     FieldSet processedFields;
00241     for(int i = 0; i < area.size(); i++) {
00242         WeatherField* wf = area[i];
00243         if(wf->isOnMap(map)) {
00244             wf->update(this, processedFields);
00245         }
00246     }
00247 }
00248 
00249 void WeatherArea::removeArea(FieldSet& processedFields) {
00250     for(int i = 0; i < area.size(); i++) {
00251         WeatherField* wf = area[i];
00252         if(wf->isOnMap(map)) {
00253             wf->reset(this->map, this, processedFields);
00254         }
00255     }
00256 }
00257 
00258 int WeatherArea::getDuration() const {
00259     return duration;
00260 }
00261 
00262 void WeatherArea::setDuration(int d) {
00263     duration = d;
00264 }
00265 
00266 float WeatherArea::getHorizontalWindAccu() const{
00267   return horizontalWindAccu;
00268 }
00269 
00270 float WeatherArea::getVerticalWindAccu() const{
00271   return verticalWindAccu;
00272 }
00273 
00274 
00275 unsigned int WeatherArea::createRandomValue(int limit) {
00276     if(limit == 0) {
00277         return 1;
00278     }
00279     int random_integer = rand();
00280     return (random_integer % limit);
00281 }
00282 
00283 short WeatherArea::createAlgebraicSign() {
00284     int random_integer = rand();
00285     random_integer = random_integer % 2;
00286     if(random_integer == 0)
00287         return -1;
00288     else
00289         return 1;
00290 }
00291 
00292 int WeatherArea::calculateCurrentOffset(int currentOffset) {
00293     return  currentOffset / stepCount;
00294 }
00295 
00296 void WeatherArea::step(WeatherRect r) {
00297     //cout << "step" << endl;
00298     ++stepCount;
00299     int diamondPoint = calculateDiamondPoint(r.a, r.b, r.c, r.d);
00300     int f = calculateCornerPoint(r.a, r.b, diamondPoint);
00301     int g = calculateCornerPoint(r.b, r.c, diamondPoint);
00302     int h = calculateCornerPoint(r.d, r.c, diamondPoint);
00303     int i = calculateCornerPoint(r.a, r.d, diamondPoint);
00304 
00305 
00306     WeatherRect r1 ={r.a, f, diamondPoint, i};
00307     WeatherRect r2 ={f, r.b, g, diamondPoint};
00308     WeatherRect r3 ={diamondPoint, g, r.c, h};
00309     WeatherRect r4 ={i, diamondPoint, h, r.d};
00310 
00311     if((f - r.a > 1) || (diamondPoint - (f + width) > 1)) {
00312         step(r1);
00313     }
00314     if((r.b - f > 1) || (diamondPoint - (r.b + width -1) >1)) {
00315         step(r2);
00316     }
00317     if((g - diamondPoint > 1) || (r.c - (g + width ) > 1)) {
00318         step(r3);
00319     }
00320     if((diamondPoint -i > 1) || (r.d - (diamondPoint + width) > 1)) {
00321         step(r4);
00322     }
00323     --stepCount;
00324 }
00325 
00326 int WeatherArea::calculateDiamondPoint(int a, int b, int c, int d) {
00327     int xd = (b - a)/2;
00328     int diva = static_cast<int>(a / width);
00329     int divd = static_cast<int>(d / width);
00330     int diamondPoint = static_cast<int>((divd - diva)/2);
00331     diamondPoint *= width;
00332     diamondPoint = diamondPoint + xd + a;
00333 
00334     area[diamondPoint]->setValue(calculateDiamondPointValue(a, b, c, d));
00335     return diamondPoint;
00336 }
00337 
00338 int WeatherArea::calculateCornerPoint(int a, int b, int diamondPoint) {
00339     int x = 0;
00340     int y = 0;
00341     double xd = (b - a)/2;
00342     int cornerPoint = 0;
00343     int diva = static_cast<int>(a / width);
00344     int divb = static_cast<int>(b / width);
00345     if(diva == divb) {
00346         cornerPoint = a + (b - a)/2;
00347 
00348     } else {
00349         int diva = static_cast<int>(a / width);
00350         int divb = static_cast<int>(b / width);
00351         int yPos = (divb - diva)/2;
00352         cornerPoint = yPos * width + a;
00353 
00354     }
00355     area[cornerPoint]->setValue(calculateCornerPointValue(a, b, diamondPoint));
00356     return cornerPoint;
00357 }
00358 
00359 int WeatherArea::calculateCornerPointValue(int a, int b, int c) {
00360     int cornerValue = (area[a]->getValue() + area[b]->getValue() + area[c]->getValue()) / 3;
00361     cornerValue = cornerValue + static_cast<int>((createRandomValue(MAXOFFSET) * 1.3 * createAlgebraicSign()));
00362     if(cornerValue < 0) {
00363         cornerValue = 0;
00364     } else if(cornerValue>MAXVALUE) {
00365         cornerValue = MAXVALUE;
00366     }
00367     return cornerValue;
00368 }
00369 
00370 int WeatherArea::calculateDiamondPointValue(int a, int b, int c, int d) {
00371     int diamondValue = (area[a]->getValue() + area[b]->getValue() + area[c]->getValue() + area[c]->getValue()) / 4;
00372     diamondValue = diamondValue + static_cast<int>((createRandomValue(MAXOFFSET) * 1.3 * createAlgebraicSign()));
00373     if(diamondValue < 0) {
00374         diamondValue = 0;
00375     } else if(diamondValue > MAXVALUE) {
00376         diamondValue = MAXVALUE;
00377     }
00378     return diamondValue;
00379 
00380 }
00381 
00382 //******************************************************************************************************************************************
00383 
00384 WeatherField::WeatherField(GameMap* m):mapField(0), map(m) {}
00385 
00386 WeatherField::WeatherField(MapCoordinate mapPos, const WeatherArea* area):posInArea(mapPos), mapField(0) {
00387     if(isOnMap(area->getMap())) {
00388         mapField = area->getMap()->getField(posInArea.x, posInArea.y);
00389     }
00390     counter = 0;
00391 }
00392 
00393 WeatherField::~WeatherField() {}
00394 
00395 void WeatherField::move(const Vector2D& vector) {
00396     posInArea.move(vector.getXComponent(), vector.getYComponent());
00397 }
00398 
00399 void WeatherField::setMapField(tfield* field) {
00400     mapField = field;
00401 }
00402 
00403 bool WeatherField::isOnMap(const GameMap* map) const {
00404     if((posInArea.x>=0) && (posInArea.x < map->xsize)&&
00405             (posInArea.y>=0) && (posInArea.y < map->ysize))
00406     return true;
00407     else
00408         return false;
00409 
00410     }
00411 
00412 void WeatherField::reset(GameMap* m, const WeatherArea* area, FieldSet& processedFields) {
00413         if(processedFields.find(mapField)== processedFields.end()) {
00414             mapField->setweather(m->weatherSystem->getDefaultFalloutType());
00415             mapField->setparams();
00416         }
00417 }
00418 
00419 void WeatherField::update(const WeatherArea* area, FieldSet& processedFields) {    
00420     mapField = area->getMap()->getField(posInArea.x, posInArea.y);
00421     mapField->setweather(area->getFalloutType(value));
00422     mapField->setparams();
00423     processedFields.insert(mapField);
00424 }
00425 
00426 void WeatherField::write (tnstream& outputStream) const {    
00427     outputStream.writeInt(value);
00428 }
00429 
00430 void  WeatherField::read(tnstream& inputStream) {
00431 
00432     value = inputStream.readInt();
00433     //posInArea.set(x,y);
00434     // if(isOnMap(map))
00435     //    mapField = map->getField(x,y);
00436 }
00437 
00438 void WeatherField::setValue(int v) {
00439     value = v;
00440 }
00441 
00442 int WeatherField::getValue() {
00443     return value;
00444 }
00445 //******************************************************************************************************************************************
00446 
00447 int WeatherSystem::legacyWindSpeed = 0;
00448 int WeatherSystem::legacyWindDirection = 0;
00449 
00450 WeatherSystem::WeatherSystem(GameMap* map, int spawn, float ws2fr, unsigned int tInterval, WeatherSystemMode mode, FalloutType defaultFT):timeInterval(tInterval), windspeed2FieldRatio(ws2fr), areaSpawnAmount(spawn), maxForecast(5), gameMap(map), currentMode(mode), windspeed(0), globalWindDirection(S), lowerRandomSize(0.25), upperRandomSize(0.8), access2RandCount(0), defaultFallout(defaultFT), lowerRandomDuration(tInterval), upperRandomDuration(tInterval*3) {
00451     seedValue = time(0);
00452     seedValueIsSet = true;
00453     srand(static_cast<unsigned int>(seedValue));
00454 
00455     Percentages defaultFallOut;
00456     int sum = 0;
00457     for(int i = 0; i < FallOutNum - 1; i++) {
00458         int weight = 100 / FallOutNum;
00459         defaultFallOut.push_back(weight);
00460         sum += weight;
00461     }
00462     defaultFallOut.push_back(100 - sum);
00463     setLikelihoodFallOut(defaultFallOut);
00464 
00465     sum = 0;
00466     Percentages defaultWindDirections;
00467     for(int i = 0; i < WindDirNum - 1; i++) {
00468         int weight = (100 / WindDirNum);
00469         defaultWindDirections.push_back(weight);
00470         sum += weight;
00471     }
00472     defaultWindDirections.push_back(100 - sum);
00473     setLikelihoodWindDirection(defaultWindDirections);
00474 
00475     sum = 0;
00476     Percentages defaultWindSpeeds;
00477     for(int i = 0; i < WeatherSystem::WINDSPEEDDETAILLEVEL - 1 ; i++) {
00478         int weight = (100 / WINDSPEEDDETAILLEVEL);
00479         defaultWindSpeeds.push_back(weight);
00480         sum += weight;
00481     }
00482 
00483     defaultWindSpeeds.push_back(100 - sum);
00484     setLikelihoodWindSpeed(defaultWindSpeeds);
00485     map->newRound.connect(SigC::slot(*this, &WeatherSystem::update));
00486 }
00487 
00488 WeatherSystem::WeatherSystem(GameMap* map):gameMap(map) {
00489     map->newRound.connect(SigC::slot(*this, &WeatherSystem::update));
00490 
00491 
00492 }
00493 
00494 WeatherSystem::~WeatherSystem() {
00495     WeatherAreas::iterator it;
00496     for(it = weatherAreas.begin(); it!= weatherAreas.end(); it++) 
00497         delete it->second;
00498 
00499     weatherAreas.clear();
00500 }
00501 
00502 pair<GameTime, WeatherArea*> WeatherSystem::getNthWeatherArea(int n) const {
00503     int k = 0;
00504     WeatherAreas::const_iterator it;
00505     it = weatherAreas.begin();
00506     while(k<n) {
00507       ++it;
00508       ++k;
00509     }
00510     return *it;
00511 
00512 }
00513 
00514  const WeatherArea* WeatherSystem::getNthActiveWeatherArea(int n) const {
00515     int k = 0;
00516     WeatherAreaList::const_iterator it;
00517     it = activeWeatherAreas.begin();
00518     while(k<n) {
00519       ++it;
00520       ++k;
00521     }
00522     return *it;
00523 
00524 }
00525 
00526 
00527 const int WeatherSystem::getQueuedWeatherAreasSize() const {
00528     return weatherAreas.size();
00529 }
00530 
00531 void WeatherSystem::setSeedValueGeneration(bool setNew) {
00532     seedValueIsSet = !setNew;
00533 }
00534 void WeatherSystem::setLikelihoodFallOut(const Percentages& fol)
00535 throw (IllegalValueException) {
00536     int sum = 0;
00537     for(int i=0; i < fol.size();i++) {
00538         sum += fol[i];
00539     }
00540     if(sum != 100) {
00541         throw IllegalValueException("Total percentages for Fallouts not equal 100");
00542     }
00543     falloutPercentages.resize(fol.size());
00544     for(int i=0; i < fol.size();i++) {
00545         falloutPercentages[i] = fol[i];
00546     }
00547 }
00548 
00549 int WeatherSystem::getMaxForecast() const {
00550     return maxForecast;
00551 }
00552 
00553 void WeatherSystem::setLikelihoodWindDirection(const Percentages&  wd) throw (IllegalValueException) {
00554     int sum = 0;
00555     for(int i=0; i < wd.size();i++) {
00556         int value = wd[i];
00557         windDirPercentages.push_back(value);
00558         sum += value;
00559     }
00560     if(sum != 100) {
00561         throw IllegalValueException("Total percentages for WindDirections do not equal 100");
00562     }
00563 }
00564 
00565 void WeatherSystem::setLikelihoodWindSpeed(const Percentages&  ws) throw (IllegalValueException) {
00566     int sum = 0;
00567     for(int i=0; i < ws.size();i++) {
00568         int value = ws[i];
00569         windSpeedPercentages.push_back(value);
00570         sum += value;
00571     }
00572     if(sum != 100) {
00573         throw IllegalValueException("Total percentages for WindSpeed do not equal 100");
00574     }
00575 
00576 }
00577 
00578 void WeatherSystem::setRandomSizeBorders(float lower, float upper) {
00579 
00580     lowerRandomSize = lower;
00581     upperRandomSize = upper;
00582 }
00583 
00584 
00585 void WeatherSystem::setGlobalWind(unsigned int ws, Direction d) throw (IllegalValueException) {
00586     windspeed = ws;
00587     globalWindDirection = d;    
00588 }
00589 void WeatherSystem::setDefaultFallout(FalloutType newFalloutType){
00590   defaultFallout = newFalloutType;
00591 }
00592 
00593 void WeatherSystem::addWeatherArea(WeatherArea* area, GameTime time) {
00594     pair<GameTime, WeatherArea*>p(time, area);
00595     weatherAreas.insert(p);
00596 }
00597 
00598 void WeatherSystem::removeWeatherArea(GameTime time, WeatherArea* area) {
00599     WeatherAreas::iterator lower = weatherAreas.lower_bound(time);
00600     WeatherAreas::iterator upper = weatherAreas.upper_bound(time);
00601     while(lower != upper) {
00602         if(lower->second == area) {
00603             weatherAreas.erase(lower);
00604             delete area;
00605             return;
00606         }
00607         ++lower;
00608     }
00609 }
00610 
00611 
00612 Direction WeatherSystem::randomWindChange(int currentTurn, int delay) {
00613     int newWindDirection = createRandomValue(100);
00614     int newWindSpeed = createRandomValue(100);
00615     Direction newDirection;
00616     int sum = 0;
00617     for(int i = 0; i < windDirPercentages.size(); i++) {
00618         sum += windDirPercentages[i];
00619         if(newWindDirection <= sum) {
00620             newDirection = static_cast<Direction>(i);
00621             break;
00622         }
00623     }
00624     sum = 0;
00625     for(int i = 0; i < windSpeedPercentages.size(); i++) {
00626         sum += windSpeedPercentages[i];
00627         if(newWindSpeed <= sum) {
00628             newWindSpeed = i * (100 /WINDSPEEDDETAILLEVEL);
00629             break;
00630         }
00631     }
00632     addGlobalWindChange(newWindSpeed, newDirection, currentTurn + delay);
00633     return newDirection;
00634 }
00635 
00636 void WeatherSystem::randomWeatherChange(GameTime currentTime, Direction windDirection, int delay) {
00637     WeatherArea* newArea;
00638     int xpos;
00639     int ypos;
00640     int width = static_cast<int>(gameMap->xsize * createRandomValue(lowerRandomSize, upperRandomSize));
00641     int height = static_cast<int>(gameMap->ysize * createRandomValue(lowerRandomSize, upperRandomSize));
00642     //Determine where the new weatherfield is placed
00643     windDirection = getNthTurnWindDirection(currentTime.turn() + maxForecast, currentTime);
00644     if(windDirection == N) {
00645         ypos = gameMap->ysize;
00646         xpos = createRandomValue(gameMap->xsize);
00647     } else if(windDirection == S) {
00648         ypos = 0;
00649         xpos = createRandomValue(gameMap->xsize);
00650     }/* else if(windDirection == E) {
00651                 xpos = 0;
00652                 xpos = createRandomValue(gameMap->ysize);
00653             } else if(globalWindDirection == W) {
00654                 ypos = gameMap->xsize;
00655                 xpos = createRandomValue(gameMap->ysize);
00656             } */else {
00657         int sideDecision = createRandomValue(1);
00658         if(windDirection == NE) {
00659         if(sideDecision == 0) {
00660                 ypos = gameMap->ysize;
00661                 xpos = createRandomValue(gameMap->xsize);
00662             } else {
00663                 ypos = createRandomValue(gameMap->ysize);
00664                 xpos = 0;
00665             }
00666         } else if(windDirection == SE) {
00667         if(sideDecision == 0) {
00668                 ypos = 0;
00669                 xpos = createRandomValue(gameMap->xsize);
00670             } else {
00671                 ypos = createRandomValue(gameMap->ysize);
00672                 ;
00673                 xpos = 0;
00674             }
00675         } else if(windDirection == SW) {
00676         if(sideDecision == 0) {
00677                 ypos = 0;
00678                 xpos = createRandomValue(gameMap->xsize);
00679             } else {
00680                 ypos = createRandomValue(gameMap->ysize);
00681                 ;
00682                 xpos = gameMap->xsize;
00683             }
00684         } else if(windDirection == NW) {
00685         if(sideDecision == 0) {
00686                 ypos = gameMap->ysize;
00687                 xpos = createRandomValue(gameMap->xsize);
00688             } else {
00689                 ypos = createRandomValue(gameMap->ysize);
00690                 ;
00691                 xpos = gameMap->xsize;
00692             }
00693         }
00694     }
00695     FalloutType ft;
00696     int sum = 0;
00697     int newFallout = createRandomValue(100);
00698     for(int i = 0; i < falloutPercentages.size(); i++) {
00699         sum += falloutPercentages[i];
00700         if(newFallout <= sum) {
00701             ft = static_cast<FalloutType>(i);
00702             break;
00703         }
00704     }
00705     GameTime t;    
00706     t.set(currentTime.turn() + delay, currentTime.move());    
00707     newArea = new WeatherArea(gameMap, xpos, ypos, width, height, static_cast<unsigned int>(createRandomValue(lowerRandomDuration, upperRandomDuration)), ft, createRandomValue());
00708     //cout << "added area: " << ft << " turn: " << t.turn() << " expected dir: " << windDirection << endl;
00709     this->addWeatherArea(newArea, t);
00710 }
00711 
00712 WindData WeatherSystem::getWindDataOfTurn(int turn) const {
00713     WindData wData;
00714     wData.speed = this->windspeed;
00715     wData.direction = globalWindDirection;
00716 
00717     WindChanges::const_iterator itTr = windTriggers.find(turn);
00718     if(itTr != windTriggers.end()) {
00719     wData.speed = itTr->second.speed;
00720     wData.direction = itTr->second.direction;
00721     } else if(turn != gameMap->time.turn()) {
00722     wData = getWindDataOfTurn(--turn);
00723     }
00724     return wData;
00725 }
00726 
00727 
00728 void WeatherSystem::update() {
00729     GameTime currentTime = gameMap->time;
00730     GameTime startTime;
00731     startTime.set(1,0);
00732     Direction newDirection;
00733     if((currentMode == RANDOMMODE)  && ((currentTime.turn() % timeInterval == 0) || (currentTime.abstime == startTime.abstime))) {
00734         if(currentTime.abstime == startTime.abstime) {
00735             if(!isSeedValueSet()) {
00736                 setSeedValue();
00737             } else {
00738                 srand(seedValue);
00739             }
00740             newDirection = randomWindChange(currentTime.turn());
00741             for(int i=0; i < areaSpawnAmount; i++) {
00742                 randomWeatherChange(currentTime, newDirection);
00743             }
00744         } 
00745         newDirection = randomWindChange(currentTime.turn(), maxForecast);        
00746         for(int i=0; i < areaSpawnAmount; i++) {
00747             randomWeatherChange(currentTime, newDirection, maxForecast);
00748         }
00749     }
00750     WindChanges::iterator itTr = windTriggers.find(currentTime.turn());
00751     if(itTr != windTriggers.end()) {
00752         setGlobalWind(itTr->second.speed , itTr->second.direction );
00753         windTriggers.erase(itTr);
00754     }
00755     
00756     for(WeatherAreaList::iterator it = activeWeatherAreas.begin(); it != activeWeatherAreas.end(); it++) {
00757         if((*it)->getDuration()==0) {
00758             WeatherArea* area2Delete = *it;
00759             it = activeWeatherAreas.erase(it);
00760             area2Delete->removeArea(processedFields);
00761             delete area2Delete;
00762         }
00763     }
00764     
00765     for(WeatherAreaList::iterator it = activeWeatherAreas.begin(); it != activeWeatherAreas.end(); it++) {
00766         (*it)->updateMovementVector(windspeed, globalWindDirection, getWindspeed2FieldRatio());
00767         (*it)->update(this, processedFields);        
00768     }
00769     
00770     WeatherAreas::iterator medium = weatherAreas.lower_bound(currentTime);
00771     WeatherAreas::iterator upper = weatherAreas.upper_bound(currentTime);
00772     for(WeatherAreas::iterator it = medium; it != upper; it++) {
00773         activeWeatherAreas.push_back(it->second);
00774         it->second->placeArea();
00775         it->second->updateMovementVector(windspeed , globalWindDirection, getWindspeed2FieldRatio());
00776     }
00777 
00778     
00779     int amount = weatherAreas.erase(currentTime);            
00780     processedFields.clear();
00781 }
00782 
00783 
00784 void WeatherSystem::setSeedValue() {
00785     seedValue = time(0);
00786 
00787 }
00788 
00789 void WeatherSystem::skipRandomValue() const {
00790     unsigned int random_integer = rand();
00791 }
00792 
00793 
00794 unsigned int WeatherSystem::createRandomValue(unsigned int limit) {
00795     ++access2RandCount;
00796     unsigned int random_integer = rand();
00797     if(limit == 0) {
00798         limit = 1;
00799     }
00800     return (random_integer % limit);
00801 }
00802 
00803 float WeatherSystem::createRandomValue(float lowerLimit, float upperLimit) {
00804     ++access2RandCount;
00805     return (lowerLimit + (float)rand()/(float)RAND_MAX * (upperLimit - lowerLimit));
00806 
00807 }
00808 
00809 
00810 void WeatherSystem::addGlobalWindChange(int speed, Direction direction,  int turn) throw (IllegalValueException) {
00811     WindData data ={speed, direction};
00812     pair<int, WindData>p(turn, data);
00813     windTriggers.insert(p);
00814 }
00815 
00816 void WeatherSystem::removeWindChange(int turn, WindData data) {
00817     WindChanges::iterator windChange = windTriggers.find(turn);
00818     windTriggers.erase(windChange);
00819 }
00820 
00821 const int WeatherSystem::getQueuedWindChangesSize() const {
00822     return windTriggers.size();
00823 }
00824 
00825 
00826 pair<int, WindData> WeatherSystem::getNthWindChange(int n) const {
00827     int k = 0;
00828     WindChanges::const_iterator it;
00829     it = windTriggers.begin();
00830     while(k<n) {
00831     ++it;
00832     ++k;
00833     }
00834     return *it;
00835 }
00836 
00837 Direction WeatherSystem::getNthTurnWindDirection(int turn, GameTime currentTime) {
00838     Direction direction = globalWindDirection;
00839     GameTime t = currentTime;
00840     while((t.turn() < getQueuedWindChangesSize()) && (t.turn() < turn)) {
00841         WindChanges::iterator it = windTriggers.find(t.turn());
00842         WindData wd = it->second;
00843         direction = wd.direction;
00844         t.set(t.turn() + 1, t.move());
00845     }
00846 
00847     return direction;
00848 }
00849 
00850 const int WeatherSystem::getActiveWeatherAreasSize() const{
00851   return activeWeatherAreas.size();
00852 
00853 }
00854 
00855 void WeatherSystem::write(tnstream& outputStream) const {
00856     outputStream.writeInt(WEATHERVERSION);
00857     outputStream.writeFloat( seedValue );
00858     outputStream.writeInt(seedValueIsSet);
00859     outputStream.writeInt(access2RandCount);
00860     outputStream.writeInt( timeInterval );
00861     outputStream.writeInt(areaSpawnAmount);
00862     outputStream.writeInt(maxForecast);
00863     outputStream.writeInt(currentMode);
00864 
00865     outputStream.writeInt(defaultFallout);
00866     outputStream.writeInt(windspeed );
00867     outputStream.writeFloat( windspeed2FieldRatio );
00868     outputStream.writeInt(globalWindDirection );
00869 
00870     outputStream.writeFloat(lowerRandomSize);
00871     outputStream.writeFloat(upperRandomSize);
00872 
00873     outputStream.writeInt(lowerRandomDuration);
00874     outputStream.writeInt(upperRandomDuration);
00875 
00876     outputStream.writeInt(falloutPercentages.size());
00877     for (int i = 0; i < falloutPercentages.size(); i++ ) {
00878     outputStream.writeInt(falloutPercentages[i]);
00879     }
00880 
00881     outputStream.writeInt(windDirPercentages.size());
00882     for (int i  = 0; i < windDirPercentages.size(); i++ ) {
00883     outputStream.writeInt(windDirPercentages[i]);
00884     }
00885 
00886     outputStream.writeInt(windSpeedPercentages.size());
00887     for (int i = 0; i < windSpeedPercentages.size(); i++ ) {
00888     outputStream.writeInt(windSpeedPercentages[i]);
00889     }
00890 
00891     outputStream.writeInt(weatherAreas.size());
00892     for ( WeatherAreas::const_iterator i = weatherAreas.begin(); i != weatherAreas.end(); ++i ) {
00893     outputStream.writeInt(i->first.turn());
00894         outputStream.writeInt(i->first.move());
00895         i->second->write ( outputStream );
00896     }
00897 
00898     outputStream.writeInt(activeWeatherAreas.size());
00899     for ( WeatherAreaList::const_iterator i = activeWeatherAreas.begin(); i != activeWeatherAreas.end(); ++i ) {
00900     (*i)->write ( outputStream );
00901     }
00902 
00903     outputStream.writeInt(windTriggers.size());
00904     for ( WindChanges::const_iterator i = windTriggers.begin(); i != windTriggers.end(); ++i ) {
00905     outputStream.writeInt(i->first);
00906         outputStream.writeInt(i->second.speed);
00907         outputStream.writeInt(i->second.direction);
00908     }
00909 }
00910 
00911 void WeatherSystem::read (tnstream& inputStream) {
00912 
00913     int version = inputStream.readInt();
00914     seedValue = inputStream.readFloat();
00915     seedValueIsSet = inputStream.readInt();
00916     access2RandCount = inputStream.readInt();
00917     timeInterval = inputStream.readInt();
00918     areaSpawnAmount = inputStream.readInt();
00919     maxForecast = inputStream.readInt();
00920     currentMode  = static_cast<WeatherSystemMode>(inputStream.readInt());
00921 
00922     defaultFallout = static_cast<FalloutType>(inputStream.readInt());
00923     windspeed = inputStream.readInt();
00924     windspeed2FieldRatio = inputStream.readFloat();
00925     globalWindDirection = static_cast<Direction>(inputStream.readInt());
00926 
00927     lowerRandomSize = inputStream.readFloat();
00928     upperRandomSize = inputStream.readFloat();
00929 
00930     lowerRandomDuration = inputStream.readInt();
00931     upperRandomDuration = inputStream.readInt();
00932 
00933     int size = 0;
00934 
00935     size= inputStream.readInt();
00936     for(int i = 0; i < size; i++) {
00937         falloutPercentages.push_back(inputStream.readInt());
00938     }
00939 
00940     size= inputStream.readInt();
00941     for(int i = 0; i < size; i++) {
00942         windDirPercentages.push_back(inputStream.readInt());
00943     }
00944 
00945     size= inputStream.readInt();
00946     for(int i = 0; i < size; i++) {
00947         windSpeedPercentages.push_back(inputStream.readInt());
00948     }
00949 
00950     size= inputStream.readInt();
00951     for(int i = 0; i < size; i++) {
00952         int turn = inputStream.readInt();
00953         int move = inputStream.readInt();
00954         GameTime time;
00955         time.set(turn, move);
00956         WeatherArea* newArea = new WeatherArea(gameMap);
00957         newArea->read(inputStream);
00958         pair<GameTime, WeatherArea*>p(time, newArea);
00959         weatherAreas.insert(p);
00960     }
00961 
00962     size = inputStream.readInt();
00963     for(int i = 0; i < size; i++) {
00964         WeatherArea* newArea = new WeatherArea(gameMap);
00965         newArea->read(inputStream);
00966         activeWeatherAreas.push_back(newArea);
00967     }
00968 
00969     size = inputStream.readInt();
00970     for(int i = 0; i < size; i++) {
00971         int turn = inputStream.readInt();
00972         WindData data;
00973         data.speed = inputStream.readInt();
00974         data.direction = static_cast<Direction>(inputStream.readInt());
00975         pair<int, WindData>p(turn, data);
00976         windTriggers.insert(p);
00977     }
00978     srand(seedValue);
00979     for(int i = 0; i < access2RandCount; i++) {
00980         skipRandomValue();
00981 
00982     }
00983 }
00984 
00985 
00986 
00987 
00988 
00989 
00990 
00991 

Generated on Tue Jun 24 01:27:55 2008 for Advanced Strategic Command by  doxygen 1.4.2