Advanced Strategic Command
weatherarea.cpp
Go to the documentation of this file.
1 //
2 // C++ Implementation: weatherarea
3 //
4 // Description:
5 //
6 //
7 // Author: Kevin Hirschmann <hirsch@dhcppc0>, (C) 2004
8 //
9 // Copyright: See COPYING file that comes with this distribution
10 //
11 //
12 #include <iostream>
13 #include <ctime>
14 #include "weatherarea.h"
15 #include "geometry.h"
17 
19 
20 const char* cdirections[WeatherSystem::WindDirNum] = {"North", "NorthEast", "SouthEast", "South", "SouthWest", "NorthWest" };
21 
22 
23 void MapCoordinate::move(const Vector2D& v){
24  x +=v.getXComponent();
25  y +=v.getYComponent();
26 }
27 
28 
29 //***************************************************************************************************************************************
30 Vector2D::Vector2D():xComponent(0), yComponent(0) {}
31 
32 Vector2D::Vector2D(int x, int y):xComponent(x), yComponent(y) {}
33 
35 
37  return xComponent;
38 }
39 
41  return yComponent;
42 }
43 double Vector2D::getLength() const{
44  return std::sqrt(std::pow(double(xComponent), 2) + std::pow(double(yComponent),2));
45 }
46 
47 bool Vector2D::isZeroVector() const {
48  return ((xComponent == 0) && (yComponent == 0));
49 }
50 
51 
52 //****************************************************************************************************************************************
53 const int WeatherArea::MAXVALUE = 200;
54 const int WeatherArea::MAXOFFSET = 100;
55 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) {
56  WeatherField* wf;
57  for(int i = 0; i < width * height; i++) {
58  int x = i % width;
59  int y = i / width;
60  wf = new WeatherField(MapCoordinate(x + (center.x - width/2), y + (center.y - height/2)), this);
61  area.push_back(wf);
62  }
63  createWeatherFields();
64 }
65 
66 WeatherArea::WeatherArea(GameMap* m): map(m) {}
67 
68 
69 WeatherArea::WeatherArea(GameMap* m, int xCenter, int yCenter, int r):map(m), center(xCenter, yCenter), width(r), height(r), radius(r) {}
70 
72  for(int i = 0; i < area.size(); i++) {
73  delete area[i];
74  }
75 }
76 
77 
78 void WeatherArea::createWeatherFields() {
79  if(area.size()>0) {
80  WeatherField* wf;
81  srand(seedValue);
82 
83  wf = area[(width*height)/2];
84  wf->setValue(MAXVALUE);
85  wf = area[0];
86  wf->setValue(createRandomValue(MAXVALUE));
87  wf = area[width - 1];
88  wf->setValue(createRandomValue(MAXVALUE));
89  wf = area[width * height - 1];
90  wf->setValue(createRandomValue(MAXVALUE));
91  wf = area[(width * height - 1) - width];
92  wf->setValue(createRandomValue(MAXVALUE));
93  WeatherRect r = {0, width -1, width * height -1, (width * height) - width };
94  step(r);
95  }
96 }
97 
98 
100  return map;
101 }
102 
103 
105  ft = fallout;
106 }
107 
109 
110  if((ft != map->weatherSystem->getDefaultFalloutType()) && (clustered)) {
111  if(value < (MAXVALUE * 0.25)) {
112  if((ft != DRY) && (ft != LSNOW)){
113  return static_cast<FalloutType>(ft-1);
114  }else{
115  return map->weatherSystem->getDefaultFalloutType();
116  }
117  }
118  }
119  return ft;
120 }
121 
123  return height;
124 }
125 
127  return width;
128 
129 }
130 
131 void WeatherArea::updateMovementVector(unsigned int windspeed, Direction windDirection, double ratio) {
132  if(windDirection == N) {
133  verticalWindAccu += (-1 * ratio * windspeed);
134  } else if(windDirection == NE) {
135  verticalWindAccu += (-1 * ratio * windspeed);
136  horizontalWindAccu += ratio * windspeed;
137  } else if(windDirection == SE) {
138  verticalWindAccu += (ratio * windspeed);
139  horizontalWindAccu += ratio * windspeed;
140  } else if(windDirection == S) {
141  verticalWindAccu += (ratio * windspeed);
142  } else if(windDirection == SW) {
143  verticalWindAccu += (ratio * windspeed);
144  horizontalWindAccu += -1 *ratio * windspeed;
145  } else if(windDirection == NW) {
146  verticalWindAccu += (-1 * ratio * windspeed);
147  horizontalWindAccu += -1 *ratio * windspeed;
148  } /*else if(windDirection == W) {
149  horizontalWindAccu += -1 *ratio * windspeed;
150  } else if(windDirection == E) {
151  horizontalWindAccu += ratio * windspeed;
152  }*/
153  int vMove = static_cast<int>(verticalWindAccu);
154  verticalWindAccu -= vMove;
155  int hMove = static_cast<int>(horizontalWindAccu);
156  horizontalWindAccu -= hMove;
157  currentMovement = Vector2D(hMove, 2 * vMove);
158 
159 }
160 
161 
162 void WeatherArea::update(WeatherSystem* wSystem, FieldSet& processedFields) {
163  duration--;
164  if(!currentMovement.isZeroVector()) {
165  for(int i = 0; i < area.size(); i++) {
166  WeatherField* wf = area[i];
167  if(wf->isOnMap(map)) {
168  wf->reset(this->map, this, processedFields);
169  }
170  }
171  center.move(currentMovement);
172  //cout << "wa.update: center: " << center.getX() << ", " << center.getY() << endl;
173  }
174  for(int i = 0; i < area.size(); i++) {
175  WeatherField* wf = area[i];
176  wf->move(currentMovement);
177  if(wf->isOnMap(map)) {
178  wf->update(this, processedFields);
179  }
180  }
181 }
182 
183 void WeatherArea::write (tnstream& outputStream) const {
184  outputStream.writeInt(seedValue);
185  outputStream.writeInt(duration);
186  outputStream.writeInt(width);
187  outputStream.writeInt(height);
188  outputStream.writeInt(center.x);
189  outputStream.writeInt(center.y);
190  outputStream.writeFloat(verticalWindAccu);
191  outputStream.writeFloat(horizontalWindAccu);
192  /*Version 1*/
193  outputStream.writeInt(currentMovement.getXComponent());
194  outputStream.writeInt(currentMovement.getYComponent());
195  outputStream.writeInt(ft);
196  outputStream.writeInt ( area.size() );
197  for ( WeatherFields::const_iterator i = area.begin(); i != area.end(); i++ ) {
198  (*i)->write ( outputStream );
199  }
200  outputStream.writeInt(clustered);
201 }
202 
203 void WeatherArea::read (tnstream& inputStream) {
204  seedValue = inputStream.readInt();
205  duration = inputStream.readInt();
206  width = inputStream.readInt();
207  height = inputStream.readInt();
208  int x = inputStream.readInt();
209  int y = inputStream.readInt();
210  center = MapCoordinate(x, y);
211  verticalWindAccu = inputStream.readFloat();
212  horizontalWindAccu = inputStream.readFloat();
213  /* Version 1*/
214  int xmov = inputStream.readInt();
215  int ymov = inputStream.readInt();
216  currentMovement = Vector2D(xmov, ymov );
217  ft = static_cast<FalloutType>(inputStream.readInt());
218  int size = inputStream.readInt();
219  for ( int i = 0; i < size; i++ ) {
220  int x = i % width;
221  int y = i / width;
222  WeatherField* wf = new WeatherField(MapCoordinate(x + (center.x - width/2), y + (center.y - height/2)), this);
223  /*WeatherField* newWf = new WeatherField(map);*/
224  wf->read(inputStream);
225  area.push_back(wf);
226  }
227  //createWeatherFields();
228  clustered = inputStream.readInt();
229 }
230 
232  return currentMovement;
233 }
234 
236  return ft;
237 }
238 
240  FieldSet processedFields;
241  for(int i = 0; i < area.size(); i++) {
242  WeatherField* wf = area[i];
243  if(wf->isOnMap(map)) {
244  wf->update(this, processedFields);
245  }
246  }
247 }
248 
249 void WeatherArea::removeArea(FieldSet& processedFields) {
250  for(int i = 0; i < area.size(); i++) {
251  WeatherField* wf = area[i];
252  if(wf->isOnMap(map)) {
253  wf->reset(this->map, this, processedFields);
254  }
255  }
256 }
257 
259  return duration;
260 }
261 
263  duration = d;
264 }
265 
267  return horizontalWindAccu;
268 }
269 
271  return verticalWindAccu;
272 }
273 
274 
275 unsigned int WeatherArea::createRandomValue(int limit) {
276  if(limit == 0) {
277  return 1;
278  }
279  int random_integer = rand();
280  return (random_integer % limit);
281 }
282 
283 short WeatherArea::createAlgebraicSign() {
284  int random_integer = rand();
285  random_integer = random_integer % 2;
286  if(random_integer == 0)
287  return -1;
288  else
289  return 1;
290 }
291 
292 int WeatherArea::calculateCurrentOffset(int currentOffset) {
293  return currentOffset / stepCount;
294 }
295 
296 void WeatherArea::step(WeatherRect r) {
297  //cout << "step" << endl;
298  ++stepCount;
299  int diamondPoint = calculateDiamondPoint(r.a, r.b, r.c, r.d);
300  int f = calculateCornerPoint(r.a, r.b, diamondPoint);
301  int g = calculateCornerPoint(r.b, r.c, diamondPoint);
302  int h = calculateCornerPoint(r.d, r.c, diamondPoint);
303  int i = calculateCornerPoint(r.a, r.d, diamondPoint);
304 
305 
306  WeatherRect r1 ={r.a, f, diamondPoint, i};
307  WeatherRect r2 ={f, r.b, g, diamondPoint};
308  WeatherRect r3 ={diamondPoint, g, r.c, h};
309  WeatherRect r4 ={i, diamondPoint, h, r.d};
310 
311  if((f - r.a > 1) || (diamondPoint - (f + width) > 1)) {
312  step(r1);
313  }
314  if((r.b - f > 1) || (diamondPoint - (r.b + width -1) >1)) {
315  step(r2);
316  }
317  if((g - diamondPoint > 1) || (r.c - (g + width ) > 1)) {
318  step(r3);
319  }
320  if((diamondPoint -i > 1) || (r.d - (diamondPoint + width) > 1)) {
321  step(r4);
322  }
323  --stepCount;
324 }
325 
326 int WeatherArea::calculateDiamondPoint(int a, int b, int c, int d) {
327  int xd = (b - a)/2;
328  int diva = static_cast<int>(a / width);
329  int divd = static_cast<int>(d / width);
330  int diamondPoint = static_cast<int>((divd - diva)/2);
331  diamondPoint *= width;
332  diamondPoint = diamondPoint + xd + a;
333 
334  area[diamondPoint]->setValue(calculateDiamondPointValue(a, b, c, d));
335  return diamondPoint;
336 }
337 
338 int WeatherArea::calculateCornerPoint(int a, int b, int diamondPoint) {
339  int x = 0;
340  int y = 0;
341  double xd = (b - a)/2;
342  int cornerPoint = 0;
343  int diva = static_cast<int>(a / width);
344  int divb = static_cast<int>(b / width);
345  if(diva == divb) {
346  cornerPoint = a + (b - a)/2;
347 
348  } else {
349  int diva = static_cast<int>(a / width);
350  int divb = static_cast<int>(b / width);
351  int yPos = (divb - diva)/2;
352  cornerPoint = yPos * width + a;
353 
354  }
355  area[cornerPoint]->setValue(calculateCornerPointValue(a, b, diamondPoint));
356  return cornerPoint;
357 }
358 
359 int WeatherArea::calculateCornerPointValue(int a, int b, int c) {
360  int cornerValue = (area[a]->getValue() + area[b]->getValue() + area[c]->getValue()) / 3;
361  cornerValue = cornerValue + static_cast<int>((createRandomValue(MAXOFFSET) * 1.3 * createAlgebraicSign()));
362  if(cornerValue < 0) {
363  cornerValue = 0;
364  } else if(cornerValue>MAXVALUE) {
365  cornerValue = MAXVALUE;
366  }
367  return cornerValue;
368 }
369 
370 int WeatherArea::calculateDiamondPointValue(int a, int b, int c, int d) {
371  int diamondValue = (area[a]->getValue() + area[b]->getValue() + area[c]->getValue() + area[c]->getValue()) / 4;
372  diamondValue = diamondValue + static_cast<int>((createRandomValue(MAXOFFSET) * 1.3 * createAlgebraicSign()));
373  if(diamondValue < 0) {
374  diamondValue = 0;
375  } else if(diamondValue > MAXVALUE) {
376  diamondValue = MAXVALUE;
377  }
378  return diamondValue;
379 
380 }
381 
382 //******************************************************************************************************************************************
383 
384 WeatherField::WeatherField(GameMap* m):mapField(0), map(m) {}
385 
386 WeatherField::WeatherField(MapCoordinate mapPos, const WeatherArea* area):posInArea(mapPos), mapField(0) {
387  if(isOnMap(area->getMap())) {
388  mapField = area->getMap()->getField(posInArea.x, posInArea.y);
389  }
390  counter = 0;
391 }
392 
394 
395 void WeatherField::move(const Vector2D& vector) {
396  posInArea.move(vector.getXComponent(), vector.getYComponent());
397 }
398 
399 void WeatherField::setMapField(MapField* field) {
400  mapField = field;
401 }
402 
403 bool WeatherField::isOnMap(const GameMap* map) const {
404  if((posInArea.x>=0) && (posInArea.x < map->xsize)&&
405  (posInArea.y>=0) && (posInArea.y < map->ysize))
406  return true;
407  else
408  return false;
409 
410  }
411 
412 void WeatherField::reset(GameMap* m, const WeatherArea* area, FieldSet& processedFields) {
413  if(processedFields.find(mapField)== processedFields.end()) {
414  mapField->setweather(m->weatherSystem->getDefaultFalloutType());
415  mapField->setparams();
416  }
417 }
418 
419 void WeatherField::update(const WeatherArea* area, FieldSet& processedFields) {
420  mapField = area->getMap()->getField(posInArea.x, posInArea.y);
421  mapField->setweather(area->getFalloutType(value));
422  mapField->setparams();
423  processedFields.insert(mapField);
424 }
425 
426 void WeatherField::write (tnstream& outputStream) const {
427  outputStream.writeInt(value);
428 }
429 
430 void WeatherField::read(tnstream& inputStream) {
431 
432  value = inputStream.readInt();
433  //posInArea.set(x,y);
434  // if(isOnMap(map))
435  // mapField = map->getField(x,y);
436 }
437 
439  value = v;
440 }
441 
443  return value;
444 }
445 //******************************************************************************************************************************************
446 
449 
450 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) {
451  seedValue = time(0);
452  seedValueIsSet = true;
453  srand(static_cast<unsigned int>(seedValue));
454 
455  Percentages defaultFallOut;
456  int sum = 0;
457  for(int i = 0; i < FallOutNum - 1; i++) {
458  int weight = 100 / FallOutNum;
459  defaultFallOut.push_back(weight);
460  sum += weight;
461  }
462  defaultFallOut.push_back(100 - sum);
463  setLikelihoodFallOut(defaultFallOut);
464 
465  sum = 0;
466  Percentages defaultWindDirections;
467  for(int i = 0; i < WindDirNum - 1; i++) {
468  int weight = (100 / WindDirNum);
469  defaultWindDirections.push_back(weight);
470  sum += weight;
471  }
472  defaultWindDirections.push_back(100 - sum);
473  setLikelihoodWindDirection(defaultWindDirections);
474 
475  sum = 0;
476  Percentages defaultWindSpeeds;
477  for(int i = 0; i < WeatherSystem::WINDSPEEDDETAILLEVEL - 1 ; i++) {
478  int weight = (100 / WINDSPEEDDETAILLEVEL);
479  defaultWindSpeeds.push_back(weight);
480  sum += weight;
481  }
482 
483  defaultWindSpeeds.push_back(100 - sum);
484  setLikelihoodWindSpeed(defaultWindSpeeds);
485  map->newRound.connect(sigc::mem_fun(*this, &WeatherSystem::update));
486 }
487 
488 WeatherSystem::WeatherSystem(GameMap* map):gameMap(map) {
489  map->newRound.connect(sigc::mem_fun(*this, &WeatherSystem::update));
490 
491 
492 }
493 
495  WeatherAreas::iterator it;
496  for(it = weatherAreas.begin(); it!= weatherAreas.end(); it++)
497  delete it->second;
498 
499  weatherAreas.clear();
500 }
501 
502 pair<GameTime, WeatherArea*> WeatherSystem::getNthWeatherArea(int n) const {
503  int k = 0;
504  WeatherAreas::const_iterator it;
505  it = weatherAreas.begin();
506  while(k<n) {
507  ++it;
508  ++k;
509  }
510  return *it;
511 
512 }
513 
515  int k = 0;
516  WeatherAreaList::const_iterator it;
517  it = activeWeatherAreas.begin();
518  while(k<n) {
519  ++it;
520  ++k;
521  }
522  return *it;
523 
524 }
525 
526 
528  return weatherAreas.size();
529 }
530 
532  seedValueIsSet = !setNew;
533 }
535 throw (IllegalValueException) {
536  int sum = 0;
537  for(int i=0; i < fol.size();i++) {
538  sum += fol[i];
539  }
540  if(sum != 100) {
541  throw IllegalValueException("Total percentages for Fallouts not equal 100");
542  }
543  falloutPercentages.resize(fol.size());
544  for(int i=0; i < fol.size();i++) {
545  falloutPercentages[i] = fol[i];
546  }
547 }
548 
550  return maxForecast;
551 }
552 
554  int sum = 0;
555  for(int i=0; i < wd.size();i++) {
556  int value = wd[i];
557  windDirPercentages.push_back(value);
558  sum += value;
559  }
560  if(sum != 100) {
561  throw IllegalValueException("Total percentages for WindDirections do not equal 100");
562  }
563 }
564 
566  int sum = 0;
567  for(int i=0; i < ws.size();i++) {
568  int value = ws[i];
569  windSpeedPercentages.push_back(value);
570  sum += value;
571  }
572  if(sum != 100) {
573  throw IllegalValueException("Total percentages for WindSpeed do not equal 100");
574  }
575 
576 }
577 
578 void WeatherSystem::setRandomSizeBorders(float lower, float upper) {
579 
580  lowerRandomSize = lower;
581  upperRandomSize = upper;
582 }
583 
584 
586  windspeed = ws;
587  globalWindDirection = d;
588 }
590  defaultFallout = newFalloutType;
591 }
592 
594  pair<GameTime, WeatherArea*>p(time, area);
595  weatherAreas.insert(p);
596 }
597 
599  WeatherAreas::iterator lower = weatherAreas.lower_bound(time);
600  WeatherAreas::iterator upper = weatherAreas.upper_bound(time);
601  while(lower != upper) {
602  if(lower->second == area) {
603  weatherAreas.erase(lower);
604  delete area;
605  return;
606  }
607  ++lower;
608  }
609 }
610 
611 
612 Direction WeatherSystem::randomWindChange(int currentTurn, int delay) {
613  int newWindDirection = createRandomValue(100);
614  int newWindSpeed = createRandomValue(100);
615  Direction newDirection;
616  int sum = 0;
617  for(int i = 0; i < windDirPercentages.size(); i++) {
618  sum += windDirPercentages[i];
619  if(newWindDirection <= sum) {
620  newDirection = static_cast<Direction>(i);
621  break;
622  }
623  }
624  sum = 0;
625  for(int i = 0; i < windSpeedPercentages.size(); i++) {
626  sum += windSpeedPercentages[i];
627  if(newWindSpeed <= sum) {
628  newWindSpeed = i * (100 /WINDSPEEDDETAILLEVEL);
629  break;
630  }
631  }
632  addGlobalWindChange(newWindSpeed, newDirection, currentTurn + delay);
633  return newDirection;
634 }
635 
636 void WeatherSystem::randomWeatherChange(GameTime currentTime, Direction windDirection, int delay) {
637  WeatherArea* newArea;
638  int xpos;
639  int ypos;
640  int width = static_cast<int>(gameMap->xsize * createRandomValue(lowerRandomSize, upperRandomSize));
641  int height = static_cast<int>(gameMap->ysize * createRandomValue(lowerRandomSize, upperRandomSize));
642  //Determine where the new weatherfield is placed
643  windDirection = getNthTurnWindDirection(currentTime.turn() + maxForecast, currentTime);
644  if(windDirection == N) {
645  ypos = gameMap->ysize;
646  xpos = createRandomValue(gameMap->xsize);
647  } else if(windDirection == S) {
648  ypos = 0;
649  xpos = createRandomValue(gameMap->xsize);
650  }/* else if(windDirection == E) {
651  xpos = 0;
652  xpos = createRandomValue(gameMap->ysize);
653  } else if(globalWindDirection == W) {
654  ypos = gameMap->xsize;
655  xpos = createRandomValue(gameMap->ysize);
656  } */else {
657  int sideDecision = createRandomValue(1);
658  if(windDirection == NE) {
659  if(sideDecision == 0) {
660  ypos = gameMap->ysize;
661  xpos = createRandomValue(gameMap->xsize);
662  } else {
663  ypos = createRandomValue(gameMap->ysize);
664  xpos = 0;
665  }
666  } else if(windDirection == SE) {
667  if(sideDecision == 0) {
668  ypos = 0;
669  xpos = createRandomValue(gameMap->xsize);
670  } else {
671  ypos = createRandomValue(gameMap->ysize);
672  ;
673  xpos = 0;
674  }
675  } else if(windDirection == SW) {
676  if(sideDecision == 0) {
677  ypos = 0;
678  xpos = createRandomValue(gameMap->xsize);
679  } else {
680  ypos = createRandomValue(gameMap->ysize);
681  ;
682  xpos = gameMap->xsize;
683  }
684  } else if(windDirection == NW) {
685  if(sideDecision == 0) {
686  ypos = gameMap->ysize;
687  xpos = createRandomValue(gameMap->xsize);
688  } else {
689  ypos = createRandomValue(gameMap->ysize);
690  ;
691  xpos = gameMap->xsize;
692  }
693  }
694  }
695  FalloutType ft;
696  int sum = 0;
697  int newFallout = createRandomValue(100);
698  for(int i = 0; i < falloutPercentages.size(); i++) {
699  sum += falloutPercentages[i];
700  if(newFallout <= sum) {
701  ft = static_cast<FalloutType>(i);
702  break;
703  }
704  }
705  GameTime t;
706  t.set(currentTime.turn() + delay, currentTime.move());
707  newArea = new WeatherArea(gameMap, xpos, ypos, width, height, static_cast<unsigned int>(createRandomValue(lowerRandomDuration, upperRandomDuration)), ft, createRandomValue());
708  //cout << "added area: " << ft << " turn: " << t.turn() << " expected dir: " << windDirection << endl;
709  this->addWeatherArea(newArea, t);
710 }
711 
713  WindData wData;
714  wData.speed = this->windspeed;
715  wData.direction = globalWindDirection;
716 
717  WindChanges::const_iterator itTr = windTriggers.find(turn);
718  if(itTr != windTriggers.end()) {
719  wData.speed = itTr->second.speed;
720  wData.direction = itTr->second.direction;
721  } else if(turn != gameMap->time.turn()) {
722  wData = getWindDataOfTurn(--turn);
723  }
724  return wData;
725 }
726 
727 
729  GameTime currentTime = gameMap->time;
730  GameTime startTime;
731  startTime.set(1,0);
732  Direction newDirection;
733  if((currentMode == RANDOMMODE) && ((currentTime.turn() % timeInterval == 0) || (currentTime.abstime == startTime.abstime))) {
734  if(currentTime.abstime == startTime.abstime) {
735  if(!isSeedValueSet()) {
736  setSeedValue();
737  } else {
738  srand(seedValue);
739  }
740  newDirection = randomWindChange(currentTime.turn());
741  for(int i=0; i < areaSpawnAmount; i++) {
742  randomWeatherChange(currentTime, newDirection);
743  }
744  }
745  newDirection = randomWindChange(currentTime.turn(), maxForecast);
746  for(int i=0; i < areaSpawnAmount; i++) {
747  randomWeatherChange(currentTime, newDirection, maxForecast);
748  }
749  }
750  WindChanges::iterator itTr = windTriggers.find(currentTime.turn());
751  if(itTr != windTriggers.end()) {
752  setGlobalWind(itTr->second.speed , itTr->second.direction );
753  windTriggers.erase(itTr);
754  }
755 
756  for(WeatherAreaList::iterator it = activeWeatherAreas.begin(); it != activeWeatherAreas.end(); it++) {
757  if((*it)->getDuration()==0) {
758  WeatherArea* area2Delete = *it;
759  it = activeWeatherAreas.erase(it);
760  area2Delete->removeArea(processedFields);
761  delete area2Delete;
762  }
763  }
764 
765  for(WeatherAreaList::iterator it = activeWeatherAreas.begin(); it != activeWeatherAreas.end(); it++) {
766  (*it)->updateMovementVector(windspeed, globalWindDirection, getWindspeed2FieldRatio());
767  (*it)->update(this, processedFields);
768  }
769 
770  WeatherAreas::iterator medium = weatherAreas.lower_bound(currentTime);
771  WeatherAreas::iterator upper = weatherAreas.upper_bound(currentTime);
772  for(WeatherAreas::iterator it = medium; it != upper; it++) {
773  activeWeatherAreas.push_back(it->second);
774  it->second->placeArea();
775  it->second->updateMovementVector(windspeed , globalWindDirection, getWindspeed2FieldRatio());
776  }
777 
778 
779  int amount = weatherAreas.erase(currentTime);
780  processedFields.clear();
781 }
782 
783 
785  seedValue = time(0);
786 
787 }
788 
790  unsigned int random_integer = rand();
791 }
792 
793 
794 unsigned int WeatherSystem::createRandomValue(unsigned int limit) {
795  ++access2RandCount;
796  unsigned int random_integer = rand();
797  if(limit == 0) {
798  limit = 1;
799  }
800  return (random_integer % limit);
801 }
802 
803 float WeatherSystem::createRandomValue(float lowerLimit, float upperLimit) {
804  ++access2RandCount;
805  return (lowerLimit + (float)rand()/(float)RAND_MAX * (upperLimit - lowerLimit));
806 
807 }
808 
809 
810 void WeatherSystem::addGlobalWindChange(int speed, Direction direction, int turn) throw (IllegalValueException) {
811  WindData data ={speed, direction};
812  pair<int, WindData>p(turn, data);
813  windTriggers.insert(p);
814 }
815 
817  WindChanges::iterator windChange = windTriggers.find(turn);
818  windTriggers.erase(windChange);
819 }
820 
822  return windTriggers.size();
823 }
824 
825 
826 pair<int, WindData> WeatherSystem::getNthWindChange(int n) const {
827  int k = 0;
828  WindChanges::const_iterator it;
829  it = windTriggers.begin();
830  while(k<n) {
831  ++it;
832  ++k;
833  }
834  return *it;
835 }
836 
837 Direction WeatherSystem::getNthTurnWindDirection(int turn, GameTime currentTime) {
838  Direction direction = globalWindDirection;
839  GameTime t = currentTime;
840  while((t.turn() < getQueuedWindChangesSize()) && (t.turn() < turn)) {
841  WindChanges::iterator it = windTriggers.find(t.turn());
842  WindData wd = it->second;
843  direction = wd.direction;
844  t.set(t.turn() + 1, t.move());
845  }
846 
847  return direction;
848 }
849 
851  return activeWeatherAreas.size();
852 
853 }
854 
855 void WeatherSystem::write(tnstream& outputStream) const {
856  outputStream.writeInt(WEATHERVERSION);
857  outputStream.writeFloat( seedValue );
858  outputStream.writeInt(seedValueIsSet);
859  outputStream.writeInt(access2RandCount);
860  outputStream.writeInt( timeInterval );
861  outputStream.writeInt(areaSpawnAmount);
862  outputStream.writeInt(maxForecast);
863  outputStream.writeInt(currentMode);
864 
865  outputStream.writeInt(defaultFallout);
866  outputStream.writeInt(windspeed );
867  outputStream.writeFloat( windspeed2FieldRatio );
868  outputStream.writeInt(globalWindDirection );
869 
870  outputStream.writeFloat(lowerRandomSize);
871  outputStream.writeFloat(upperRandomSize);
872 
873  outputStream.writeInt(lowerRandomDuration);
874  outputStream.writeInt(upperRandomDuration);
875 
876  outputStream.writeInt(falloutPercentages.size());
877  for (int i = 0; i < falloutPercentages.size(); i++ ) {
878  outputStream.writeInt(falloutPercentages[i]);
879  }
880 
881  outputStream.writeInt(windDirPercentages.size());
882  for (int i = 0; i < windDirPercentages.size(); i++ ) {
883  outputStream.writeInt(windDirPercentages[i]);
884  }
885 
886  outputStream.writeInt(windSpeedPercentages.size());
887  for (int i = 0; i < windSpeedPercentages.size(); i++ ) {
888  outputStream.writeInt(windSpeedPercentages[i]);
889  }
890 
891  outputStream.writeInt(weatherAreas.size());
892  for ( WeatherAreas::const_iterator i = weatherAreas.begin(); i != weatherAreas.end(); ++i ) {
893  outputStream.writeInt(i->first.turn());
894  outputStream.writeInt(i->first.move());
895  i->second->write ( outputStream );
896  }
897 
898  outputStream.writeInt(activeWeatherAreas.size());
899  for ( WeatherAreaList::const_iterator i = activeWeatherAreas.begin(); i != activeWeatherAreas.end(); ++i ) {
900  (*i)->write ( outputStream );
901  }
902 
903  outputStream.writeInt(windTriggers.size());
904  for ( WindChanges::const_iterator i = windTriggers.begin(); i != windTriggers.end(); ++i ) {
905  outputStream.writeInt(i->first);
906  outputStream.writeInt(i->second.speed);
907  outputStream.writeInt(i->second.direction);
908  }
909 }
910 
911 void WeatherSystem::read (tnstream& inputStream) {
912 
913  int version = inputStream.readInt();
914  seedValue = inputStream.readFloat();
915  seedValueIsSet = inputStream.readInt();
916  access2RandCount = inputStream.readInt();
917  timeInterval = inputStream.readInt();
918  areaSpawnAmount = inputStream.readInt();
919  maxForecast = inputStream.readInt();
920  currentMode = static_cast<WeatherSystemMode>(inputStream.readInt());
921 
922  defaultFallout = static_cast<FalloutType>(inputStream.readInt());
923  windspeed = inputStream.readInt();
924  windspeed2FieldRatio = inputStream.readFloat();
925  globalWindDirection = static_cast<Direction>(inputStream.readInt());
926 
927  lowerRandomSize = inputStream.readFloat();
928  upperRandomSize = inputStream.readFloat();
929 
930  lowerRandomDuration = inputStream.readInt();
931  upperRandomDuration = inputStream.readInt();
932 
933  int size = 0;
934 
935  size= inputStream.readInt();
936  for(int i = 0; i < size; i++) {
937  falloutPercentages.push_back(inputStream.readInt());
938  }
939 
940  size= inputStream.readInt();
941  for(int i = 0; i < size; i++) {
942  windDirPercentages.push_back(inputStream.readInt());
943  }
944 
945  size= inputStream.readInt();
946  for(int i = 0; i < size; i++) {
947  windSpeedPercentages.push_back(inputStream.readInt());
948  }
949 
950  size= inputStream.readInt();
951  for(int i = 0; i < size; i++) {
952  int turn = inputStream.readInt();
953  int move = inputStream.readInt();
954  GameTime time;
955  time.set(turn, move);
956  WeatherArea* newArea = new WeatherArea(gameMap);
957  newArea->read(inputStream);
958  pair<GameTime, WeatherArea*>p(time, newArea);
959  weatherAreas.insert(p);
960  }
961 
962  size = inputStream.readInt();
963  for(int i = 0; i < size; i++) {
964  WeatherArea* newArea = new WeatherArea(gameMap);
965  newArea->read(inputStream);
966  activeWeatherAreas.push_back(newArea);
967  }
968 
969  size = inputStream.readInt();
970  for(int i = 0; i < size; i++) {
971  int turn = inputStream.readInt();
972  WindData data;
973  data.speed = inputStream.readInt();
974  data.direction = static_cast<Direction>(inputStream.readInt());
975  pair<int, WindData>p(turn, data);
976  windTriggers.insert(p);
977  }
978  srand(seedValue);
979  for(int i = 0; i < access2RandCount; i++) {
980  skipRandomValue();
981 
982  }
983 }
984 
985 
986 
987 
988 
989 
990 
991 
the time in ASC, measured in turns and moves
Definition: typen.h:178
void removeWindChange(int time, WindData)
void setLikelihoodWindSpeed(const Percentages &wd)
int xsize
the size of the map
Definition: gamemap.h:201
virtual void writeInt(int i)
Writes a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is p...
Definition: basestrm.cpp:363
float getWindspeed2FieldRatio() const
Definition: weatherarea.h:377
static int legacyWindSpeed
Definition: weatherarea.h:292
void setSeedValueGeneration(bool setNew)
int getDuration() const
unsigned int createRandomValue(int limit)
void updateMovementVector(unsigned int speed, Direction windDirection, double ratio)
void read(tnstream &inputStream)
void move(Vehicle *veh, const MapCoordinate &dest)
Definition: weatherarea.h:86
int abstime
Definition: typen.h:183
virtual int readInt(void)
Reads a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is pe...
Definition: basestrm.cpp:284
const WeatherArea * getNthActiveWeatherArea(int n) const
void setGlobalWind(unsigned int speed, Direction direction)
int getHeight() const
int turn() const
Definition: typen.h:181
int getMaxForecast() const
static const int WindDirNum
Definition: weatherarea.h:285
void write(tnstream &outputStream) const
static int legacyWindDirection
Definition: weatherarea.h:293
Definition: weatherarea.h:87
void update(const WeatherArea *, FieldSet &processedFields)
void read(tnstream &inputStream)
~Vector2D()
Destructor.
Definition: weatherarea.cpp:34
void removeArea(FieldSet &processedFields)
void addGlobalWindChange(int speed, Direction direction, int time)
bool isZeroVector() const
Checks if the vector is the zero-vector.
Definition: weatherarea.cpp:47
float getHorizontalWindAccu() const
void setRandomSizeBorders(float lower, float upper)
The interface for all kinds of IO stream.
a single field of the map
Definition: mapfield.h:26
void placeArea()
const int getActiveWeatherAreasSize() const
void setValue(int v)
Direction direction
Definition: weatherarea.h:105
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
WindData getWindDataOfTurn(int turn) const
Definition: weatherarea.h:90
FalloutType
Definition: weatherarea.h:94
Vector2D getWindVector() const
int move() const
Definition: typen.h:180
virtual float readFloat(void)
Reads a flaot variable.
Definition: basestrm.cpp:328
void setDuration(int duration)
int getXComponent() const
Retrieves the xComponent of the Vector.
Definition: weatherarea.cpp:36
WeatherSystemMode
Definition: weatherarea.h:209
float getVerticalWindAccu() const
void removeWeatherArea(GameTime time, WeatherArea *area)
int getWidth() const
void move(const Vector2D &vector)
Coordinate on the twodimensional map.
Definition: typen.h:202
void addWeatherArea(WeatherArea *area, GameTime time)
GameMap * getMap() const
Definition: weatherarea.cpp:99
const int getQueuedWindChangesSize() const
void setparams(ObjectRemovalStrategy *objectRemovalStrategy)
recalculates the terrain properties, movemalus etc from the terraintype and the objects,
Definition: mapfield.cpp:605
vector< int > Percentages
Definition: weatherarea.h:121
void setLikelihoodWindDirection(const Percentages &wd)
void write(tnstream &outputStream) const
unsigned int speed
Definition: weatherarea.h:104
Definition: weatherarea.h:88
void reset(GameMap *m, const WeatherArea *, FieldSet &processedFields)
const int getQueuedWeatherAreasSize() const
A Vector2D is a line (without a defined start point) in a 2 dimensional space and is deccribed by its...
Definition: weatherarea.h:33
void update(WeatherSystem *wSystem, FieldSet &processedFields)
WeatherField(GameMap *map)
Vector2D()
Default constructor.
Definition: weatherarea.cpp:30
pair< int, WindData > getNthWindChange(int n) const
int ysize
Definition: gamemap.h:201
FalloutType getFalloutType() const
IllegalValueException(const ASCString &msg)
Definition: weatherarea.cpp:16
void write(tnstream &outputStream) const
virtual void writeFloat(float f)
Write a floating point variable.
Definition: basestrm.cpp:385
bool isOnMap(const GameMap *map) const
Direction
Definition: weatherarea.h:84
Definition: weatherarea.h:85
void skipRandomValue() const
MapCoordinate posInArea
Definition: weatherarea.h:236
void setDefaultFallout(FalloutType newFalloutType)
int getYComponent() const
Retrieves the yComponent of the Vector.
Definition: weatherarea.cpp:40
multiset< MapField * > FieldSet
Definition: weatherarea.h:114
void read(tnstream &inputStream)
pair< GameTime, WeatherArea * > getNthWeatherArea(int n) const
sigc::signal< void > newRound
called when a new round starts (after switching from player 7 to player 0 )
Definition: gamemap.h:508
const char * cdirections[WeatherSystem::WindDirNum]
Definition: weatherarea.cpp:20
void setSeedValue()
void move(int width, int height)
Definition: typen.cpp:299
void setFalloutType(FalloutType fallout)
Definition: weatherarea.h:89
double getLength() const
Calculates the length of the vector (Pythagoras)
Definition: weatherarea.cpp:43
void setLikelihoodFallOut(const Percentages &fol)
static const int FallOutNum
Definition: weatherarea.h:284
GameTime time
the time in the game, mesured in a turns and moves
Definition: gamemap.h:235
static const int WINDSPEEDDETAILLEVEL
Definition: weatherarea.h:286
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182
void set(int turn, int move)
Definition: typen.h:183
bool isSeedValueSet()
Definition: weatherarea.h:339
MapField * getField(int x, int y)
Definition: gamemap.h:465