00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <math.h>
00023 #include "mapalgorithms.h"
00024 #include "typen.h"
00025 #include "vehicletype.h"
00026 #include "errors.h"
00027 #include "gamemap.h"
00028
00029
00030 tdrawgettempline :: tdrawgettempline ( int _freefields, GameMap* _gamemap )
00031 {
00032 gamemap = _gamemap;
00033 tempsum = 0;
00034 freefields = _freefields;
00035 num = 0;
00036 }
00037
00038 void tdrawgettempline :: putpix8 ( int x, int y )
00039 {
00040 if ( !gamemap->getField ( x, y ) )
00041 return;
00042
00043 if ( num >= freefields )
00044 tempsum += gamemap->getField ( x, y )->getjamming();
00045 num++;
00046
00047
00048
00049
00050
00051 }
00052
00053 int tdrawgettempline :: winkelcomp ( double w1, double w2 )
00054 {
00055 double pi = 3.141592654;
00056 double delta = w2 - w1;
00057 if ( delta > -0.0001 && delta < 0.0001 )
00058 return 0;
00059
00060 if ( delta > 0 ) {
00061 if ( delta <= pi )
00062 return 1;
00063 else
00064 return -1;
00065 }
00066
00067 if ( delta < 0 ) {
00068 if ( delta < -pi )
00069 return 1;
00070 else
00071 return -1;
00072 }
00073
00074 return 0;
00075 }
00076
00077
00078 int tdrawgettempline :: initialized = 0;
00079 double tdrawgettempline :: dirs[ sidenum ];
00080 double tdrawgettempline :: offset;
00081
00082 void tdrawgettempline :: init ( void )
00083 {
00084 if ( !initialized ) {
00085 offset = 0;
00086 sx = 10;
00087 sy = 10;
00088 int i;
00089
00090 for ( i = 0; i < sidenum; i++ ) {
00091 sx = 10;
00092 sy = 10;
00093 getnextfield ( sx, sy, i );
00094 dirs[i] = winkel ( 10, 10 );
00095 }
00096 offset = dirs[0];
00097
00098 for ( i = 0; i < sidenum; i++ ) {
00099 sx = 10;
00100 sy = 10;
00101 getnextfield ( sx, sy, i );
00102 dirs[i] = winkel ( 10, 10 );
00103 }
00104
00105 initialized = 1;
00106 }
00107 }
00108
00109
00110 double tdrawgettempline :: winkel ( int x, int y )
00111 {
00112 int xp2 = sx * fielddistx + (sy & 1) * fielddisthalfx;
00113 int yp2 = sy * fielddisty;
00114
00115 int xp1 = x * fielddistx + (y & 1) * fielddisthalfx;
00116 int yp1 = y * fielddisty;
00117
00118 int dx = xp2-xp1;
00119 int dy = yp2-yp1;
00120 double at = atan2 ( double(dy), double(dx) );
00121
00122 at -= offset;
00123 while ( at < 0 )
00124 at += 2 * 3.14159265;
00125
00126
00127 return at;
00128 }
00129
00130 #define checkvisibility
00131
00132 void tdrawgettempline :: start ( int x1, int y1, int x2, int y2 )
00133 {
00134 init();
00135
00136 sx = x2;
00137 sy = y2;
00138
00139 if ( y1 == y2 && x1 == x2 )
00140 return;
00141
00142 int x = x1;
00143 int y = y1;
00144
00145 double w = winkel ( x1, y1 );
00146
00147 int dir = -1;
00148 double mindiff = 10000;
00149 for ( int i = 0; i < sidenum; i++ ) {
00150 double nd = fabs ( dirs[i] - w );
00151 if ( nd < mindiff ) {
00152 dir = i;
00153 mindiff = nd;
00154 }
00155 }
00156
00157 #ifdef checkvisibility
00158 int ldist = beeline ( x1, y1, x2, y2 );
00159 #endif
00160
00161 int lastdir = winkelcomp ( w, dirs[dir] );
00162
00163
00164
00165
00166
00167
00168 getnextfield( x, y, dir );
00169 while ( x != x2 || y != y2 ) {
00170 #ifdef checkvisibility
00171 int ldist2 = beeline ( x, y, x2, y2 );
00172 if ( ldist2 > ldist ) {
00173 fatalError ( "inconsistency in tdrawgettempline :: start ; parameters are %d/%d ; %d/%d ", 1, x1, y1, x2, y2 );
00174 return;
00175 }
00176 #endif
00177
00178 putpix8 ( x, y );
00179 double w2 = winkel ( x, y );
00180
00181 if ( lastdir > 0 ) {
00182 if ( winkelcomp ( w2, w ) == 1 ) {
00183 dir--;
00184 lastdir = -1;
00185 }
00186 } else {
00187 if ( winkelcomp ( w2 , w ) == -1 ) {
00188 dir++;
00189 lastdir = 1;
00190 }
00191 }
00192 if ( dir < 0 )
00193 dir += sidenum;
00194
00195 if ( dir >= sidenum )
00196 dir = dir % sidenum;
00197
00198 getnextfield ( x, y, dir );
00199 }
00200 putpix8 ( x, y );
00201 }
00202
00203
00204
00205
00206
00207
00208 SearchFields :: SearchFields ( GameMap* _gamemap )
00209 {
00210 gamemap = _gamemap;
00211 cancelSearch = false;
00212 }
00213
00214 void SearchFields::initsearch( const MapCoordinate& startPosition, int _firstDistance, int _lastDistance )
00215 {
00216 cancelSearch = false;
00217 startPos = startPosition;
00218 firstDistance = _firstDistance;
00219 lastDistance = _lastDistance;
00220 }
00221
00222
00223
00224 void SearchFields::startsearch(void)
00225 {
00226 if ( cancelSearch )
00227 return;
00228
00229 int step;
00230
00231 if (firstDistance > lastDistance)
00232 step = -1;
00233 else
00234 step = 1;
00235
00236 dist = firstDistance;
00237
00238 do {
00239 MapCoordinate mc ( startPos.x, startPos.y - 2 * dist );
00240 if ( dist == 0 ) {
00241 if ((mc.x >= 0) && (mc.y >= 0) && (mc.x < gamemap->xsize) && (mc.y < gamemap->ysize))
00242 testfield( mc );
00243
00244 if ( cancelSearch )
00245 return;
00246
00247 } else {
00248 for ( int e = 0; e < 6; e++ ) {
00249 int dir = (e + 2) % sidenum;
00250 for ( int c = 0; c < dist; c++) {
00251 if ((mc.x >= 0) && (mc.y >= 0) && (mc.x < gamemap->xsize) && (mc.y < gamemap->ysize)) {
00252 testfield( mc );
00253 if ( cancelSearch )
00254 return;
00255 }
00256 getnextfield ( mc.x, mc.y, dir );
00257 }
00258
00259 }
00260 }
00261
00262 dist += step;
00263
00264 } while (!((dist - step == lastDistance) || cancelSearch));
00265 }
00266
00267
00268 class SearchFieldsIterator : public SearchFields {
00269 public:
00270 typedef FieldIterationFunctor MyFunctor;
00271 private:
00272 MyFunctor& myFunctor;
00273 protected:
00274 void testfield ( const MapCoordinate& pos ) {
00275 myFunctor(pos);
00276 };
00277 public:
00278 SearchFieldsIterator ( GameMap* _gamemap, MyFunctor& functor ) : SearchFields( _gamemap ), myFunctor( functor ) {};
00279
00280 };
00281
00282 void circularFieldIterator( GameMap* gamemap, const MapCoordinate& center, int startDist, int stopDist, FieldIterationFunctor functor )
00283 {
00284 SearchFieldsIterator searchFields( gamemap, functor );
00285 searchFields.initsearch( center, startDist, stopDist );
00286 searchFields.startsearch();
00287 }
00288
00289
00290 int ccmpheighchangemovedir[6] = {0, 1, 5, 2, 4, 3 };
00291
00292
00293 MapCoordinate3D getNeighbouringFieldCoordinate( const MapCoordinate3D& pos, int direc)
00294 {
00295 MapCoordinate3D mc = pos;
00296 getnextfield ( mc.x, mc.y, direc );
00297 return mc;
00298 }
00299
00300 MapCoordinate getNeighbouringFieldCoordinate( const MapCoordinate& pos, int direc)
00301 {
00302 MapCoordinate mc = pos;
00303 getnextfield ( mc.x, mc.y, direc );
00304 return mc;
00305 }
00306
00307
00308 void getnextfield(int& x,
00309 int& y,
00310 int direc)
00311 {
00312 switch (direc) {
00313
00314 case 0:
00315 y-=2 ;
00316 break;
00317
00318 case 1:
00319 if ((y & 1) == 1) x+=1;
00320 y-=1;
00321 break;
00322
00323 case 2:
00324 if ((y & 1) == 1) x+=1;
00325 y+=1;
00326 break;
00327
00328 case 3:
00329 y+=2;
00330 break;
00331
00332 case 4:
00333 if ((y & 1) == 0) x-=1;
00334 y+=1;
00335 break;
00336
00337 case 5:
00338 if ((y & 1) == 0) x-=1;
00339 y-=1;
00340 break;
00341
00342 }
00343 }
00344
00345
00346 int getdirection( const MapCoordinate& start, const MapCoordinate& dest )
00347 {
00348 return getdirection(start.x, start.y, dest.x, dest.y );
00349 }
00350
00351 int getdirection( int x1,
00352 int y1,
00353 int x2,
00354 int y2)
00355 {
00356 int a;
00357 int dx = (2 * x2 + (y2 & 1)) - (2 * x1 + (y1 & 1));
00358 int dy = y2 - y1;
00359
00360 if (dx < 0)
00361 if (dy < 0)
00362 a = 5;
00363 else
00364 a = 4;
00365 else
00366 if (dx > 0)
00367 if (dy < 0)
00368 a = 1;
00369 else
00370 a = 2;
00371 else
00372 if (dy < 0)
00373 a = 0;
00374 else
00375 if ( dy > 0 )
00376 a = 3;
00377 else
00378 a = -1;
00379 return a;
00380 }
00381
00382
00383 int beeline ( const Vehicle* a, const Vehicle* b )
00384 {
00385 return beeline ( a->xpos, a->ypos, b->xpos, b->ypos );
00386 }
00387
00388 int beeline ( const MapCoordinate& a, const MapCoordinate& b )
00389 {
00390 return beeline ( a.x, a.y, b.x, b.y );
00391 }
00392
00393
00394 int beeline ( int x1, int y1, int x2, int y2 )
00395 {
00396 int xdist = abs ( (x1 * 2 + (y1 & 1 )) - ( x2 * 2 + ( y2 & 1)) );
00397 int ydist = abs ( y2 - y1 );
00398 int num2;
00399 if ( ydist > xdist )
00400 num2 = (ydist - xdist) / 2 + xdist;
00401 else
00402 num2 = max ( xdist, ydist );
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 return minmalq*num2;
00414 }
00415
00416
00417 int square ( int i )
00418 {
00419 return i*i;
00420 }
00421
00422 inline float square ( float i )
00423 {
00424 return i*i;
00425 }
00426
00427
00428 WindMovement::WindMovement ( const Vehicle* vehicle )
00429 {
00430 for ( int i = 0; i < sidenum; i++ )
00431 wm[i] = 0;
00432
00433 int movement = 0;
00434 for ( int height = 4; height <= 6; height++ ){
00435 if ( vehicle->typ->movement[height] )
00436 if ( vehicle->typ->movement[height] > movement )
00437 movement = vehicle->typ->movement[height];
00438 }
00439
00440 if ( movement ) {
00441 int wmn[7];
00442
00443 int lastDir = 0;
00444
00445 float abswindspeed = float( vehicle->getMap()->weather.windSpeed) * maxwindspeed / 255;
00446
00447 for ( float direc = 0; direc < 360; direc++) {
00448 static const float pi = 3.14159265;
00449 float unitspeedx = movement * sin(direc/180*pi);
00450 float unitspeedy = movement * cos(direc/180*pi);
00451
00452 float angle = atan2( unitspeedx, unitspeedy + abswindspeed );
00453 if ( angle < 0 )
00454 angle += 2 * pi;
00455
00456 if ( angle >= 60 * float(lastDir) * (2*pi) / 360 ) {
00457 float absspeed = sqrt ( square ( unitspeedy + abswindspeed)+ square ( unitspeedx) );
00458 wmn[lastDir] = int( 10 - 10*movement/absspeed );
00459 ++lastDir;
00460 }
00461 }
00462
00463
00464 for ( int i = 0; i <= 3; i++ ) {
00465 wm[(i+vehicle->getMap()->weather.windDirection)%6] = wmn[i];
00466 if ( i > 0 )
00467 wm[(6-i+vehicle->getMap()->weather.windDirection)%6] = wmn[i];
00468 }
00469 }
00470 }
00471
00472
00473
00474 int WindMovement::getDist ( int dir )
00475 {
00476 assert( dir >= 0 && dir <= 5 );
00477 return wm[dir];
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488