00001
00002
00003
00004
00005
00006
00007
00008
00009
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 }
00149
00150
00151
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
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
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
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
00224 wf->read(inputStream);
00225 area.push_back(wf);
00226 }
00227
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
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
00434
00435
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
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 }
00651
00652
00653
00654
00655
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
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