Advanced Strategic Command
mapalgorithms.cpp
Go to the documentation of this file.
1 
5 /***************************************************************************
6  mapalgorithms.cpp - description
7  -------------------
8  begin : Thu Oct 5 2000
9  copyright : (C) 2000 by Martin Bickel
10  email : bickel@asc-hq.org
11  ***************************************************************************/
12 
13 /***************************************************************************
14  * *
15  * This program is free software; you can redistribute it and/or modify *
16  * it under the terms of the GNU General Public License as published by *
17  * the Free Software Foundation; either version 2 of the License, or *
18  * (at your option) any later version. *
19  * *
20  ***************************************************************************/
21 
22 #include <math.h>
23 #include "mapalgorithms.h"
24 #include "typen.h"
25 #include "vehicletype.h"
26 #include "errors.h"
27 #include "gamemap.h"
28 
29 tdrawgettempline :: tdrawgettempline ( int _freefields, GameMap* _gamemap )
30 {
31  gamemap = _gamemap;
32  tempsum = 0;
33  freefields = _freefields;
34  num = 0;
35 }
36 
37 void tdrawgettempline :: putpix8 ( int x, int y )
38 {
39  if ( !gamemap->getField ( x, y ) )
40  return;
41 
42  if ( num >= freefields )
43  tempsum += gamemap->getField ( x, y )->getjamming();
44  num++;
45  /*
46  getfield( x,y )->temp = 100;
47  displaymap();
48  cursor.gotoxy ( x , y );
49  */
50 }
51 
52 int tdrawgettempline :: winkelcomp ( double w1, double w2 )
53 {
54  double pi = 3.141592654;
55  double delta = w2 - w1;
56  if ( delta > -0.0001 && delta < 0.0001 )
57  return 0;
58 
59  if ( delta > 0 ) {
60  if ( delta <= pi )
61  return 1;
62  else
63  return -1;
64  }
65 
66  if ( delta < 0 ) {
67  if ( delta < -pi )
68  return 1;
69  else
70  return -1;
71  }
72 
73  return 0;
74 }
75 
76 
77 int tdrawgettempline :: initialized = 0;
78 double tdrawgettempline :: dirs[ sidenum ];
79 double tdrawgettempline :: offset;
80 
81 void tdrawgettempline :: init ( void )
82 {
83  if ( !initialized ) {
84  offset = 0;
85  sx = 10;
86  sy = 10;
87  int i;
88 
89  for ( i = 0; i < sidenum; i++ ) {
90  sx = 10;
91  sy = 10;
92  sx += getnextdx( i, sy );
93  sy += getnextdy( i );
94  dirs[i] = winkel ( 10, 10 );
95  }
96  offset = dirs[0];
97 
98  for ( i = 0; i < sidenum; i++ ) {
99  sx = 10;
100  sy = 10;
101  sx += getnextdx( i, sy );
102  sy += getnextdy( i );
103  dirs[i] = winkel ( 10, 10 );
104  }
105 
106  initialized = 1;
107  }
108 }
109 
110 
111 double tdrawgettempline :: winkel ( int x, int y )
112 {
113  int xp2 = sx * fielddistx + (sy & 1) * fielddisthalfx;
114  int yp2 = sy * fielddisty;
115 
116  int xp1 = x * fielddistx + (y & 1) * fielddisthalfx;
117  int yp1 = y * fielddisty;
118 
119  int dx = xp2-xp1;
120  int dy = yp2-yp1;
121  double at = atan2 ( double(dy), double(dx) );
122  // printf("%d / %d / %f \n", dx, dy, at);
123  at -= offset;
124  while ( at < 0 )
125  at += 2 * 3.14159265;
126 
127  // printf("%f \n", at);
128  return at;
129 }
130 
131 #define checkvisibility
132 
133 void tdrawgettempline :: start ( int x1, int y1, int x2, int y2 )
134 {
135  init();
136 
137  sx = x2;
138  sy = y2;
139 
140  if ( y1 == y2 && x1 == x2 )
141  return;
142 
143  int x = x1;
144  int y = y1;
145 
146  double w = winkel ( x1, y1 );
147 
148  int dir = -1;
149  double mindiff = 10000;
150  for ( int i = 0; i < sidenum; i++ ) {
151  double nd = fabs ( dirs[i] - w );
152  if ( nd < mindiff ) {
153  dir = i;
154  mindiff = nd;
155  }
156  }
157 
158 #ifdef checkvisibility
159  int ldist = beeline ( x1, y1, x2, y2 );
160 #endif
161 
162  int lastdir = winkelcomp ( w, dirs[dir] );
163  /*
164  if ( x1 == 18 && y1 == 24 && x2 == 18 && y2 == 9 ) {
165  printf("blurb");
166  }
167  */
168 
169  x += getnextdx( dir, y );
170  y += getnextdy( dir );
171  while ( x != x2 || y != y2 ) {
172 #ifdef checkvisibility
173  int ldist2 = beeline ( x, y, x2, y2 );
174  if ( ldist2 > ldist ) {
175  fatalError ( "inconsistency in tdrawgettempline :: start ; parameters are %d/%d ; %d/%d ", 1, x1, y1, x2, y2 );
176  return;
177  }
178 #endif
179 
180  putpix8 ( x, y );
181  double w2 = winkel ( x, y );
182  // printf("%f \n", w2);
183  if ( lastdir > 0 ) {
184  if ( winkelcomp ( w2, w ) == 1 ) {
185  dir--;
186  lastdir = -1;
187  }
188  } else {
189  if ( winkelcomp ( w2 , w ) == -1 ) {
190  dir++;
191  lastdir = 1;
192  }
193  }
194  if ( dir < 0 )
195  dir += sidenum;
196 
197  if ( dir >= sidenum )
198  dir = dir % sidenum;
199 
200  x += getnextdx( dir, y );
201  y += getnextdy( dir );
202  }
203  putpix8 ( x, y );
204 }
205 
206 
207 
208 
209 
210 
212 {
213  gamemap = _gamemap;
214  cancelSearch = false;
215 }
216 
217 void SearchFields::initsearch( const MapCoordinate& startPosition, int _firstDistance, int _lastDistance )
218 {
219  cancelSearch = false;
220  startPos = startPosition;
221  firstDistance = _firstDistance;
222  lastDistance = _lastDistance;
223 }
224 
225 
226 
228 {
229  if ( cancelSearch )
230  return;
231 
232  int step;
233 
235  step = -1;
236  else
237  step = 1;
238 
240 
241  do {
242  MapCoordinate mc ( startPos.x, startPos.y - 2 * dist );
243  if ( dist == 0 ) {
244  if ((mc.x >= 0) && (mc.y >= 0) && (mc.x < gamemap->xsize) && (mc.y < gamemap->ysize))
245  testfield( mc );
246 
247  if ( cancelSearch )
248  return;
249 
250  } else {
251  for ( int e = 0; e < 6; e++ ) {
252  int dir = (e + 2) % sidenum;
253  for ( int c = 0; c < dist; c++) {
254  if ((mc.x >= 0) && (mc.y >= 0) && (mc.x < gamemap->xsize) && (mc.y < gamemap->ysize)) {
255  testfield( mc );
256  if ( cancelSearch )
257  return;
258  }
259  mc.x += getnextdx( dir, mc.y );
260  mc.y += getnextdy( dir );
261  }
262 
263  }
264  }
265 
266  dist += step;
267 
268  } while (!((dist - step == lastDistance) || cancelSearch));
269 }
270 
271 
273  public:
275  private:
276  MyFunctor& myFunctor;
277  protected:
278  void testfield ( const MapCoordinate& pos ) {
279  myFunctor(pos);
280  };
281  public:
282  SearchFieldsIterator ( GameMap* _gamemap, MyFunctor& functor ) : SearchFields( _gamemap ), myFunctor( functor ) {};
283 
284 };
285 
286 void circularFieldIterator( GameMap* gamemap, const MapCoordinate& center, int startDist, int stopDist, FieldIterationFunctor functor )
287 {
288  SearchFieldsIterator searchFields( gamemap, functor );
289  searchFields.initsearch( center, startDist, stopDist );
290  searchFields.startsearch();
291 }
292 
293 
294 int ccmpheighchangemovedir[6] = {0, 1, 5, 2, 4, 3 };
295 
296 
298 {
299  MapCoordinate3D mc = pos;
300  mc.x += getnextdx( direc, mc.y );
301  mc.y += getnextdy( direc );
302  return mc;
303 }
304 
306 {
307  MapCoordinate mc = pos;
308  mc.x += getnextdx( direc, mc.y );
309  mc.y += getnextdy( direc );
310  return mc;
311 }
312 
313 int getdirection( const MapCoordinate& start, const MapCoordinate& dest )
314 {
315  return getdirection(start.x, start.y, dest.x, dest.y );
316 }
317 
318 int getdirection( int x1,
319  int y1,
320  int x2,
321  int y2)
322 {
323  int dy = y2 - y1;
324  int dx = x2 - x1;
325  if (dx < 0)
326  return (dy < 0) ? 5 : 4;
327  if (dx > 0)
328  return (dy < 0) ? 1 : 2;
329  // dx == 0
330  int dOdd = (y2 & 1) - (y1 & 1);
331  if (dOdd == -1)
332  return (dy < 0) ? 5 : 4;
333  if (dOdd == 1)
334  return (dy < 0) ? 1 : 2;
335  // dOdd == 0
336  return (dy < 0) ? 0 : (dy > 0) ? 3 : -1;
337 }
338 
339 
340 int beeline ( const Vehicle* a, const Vehicle* b )
341 {
342  return beeline ( a->xpos, a->ypos, b->xpos, b->ypos );
343 }
344 
345 int beeline ( const MapCoordinate& a, const MapCoordinate& b )
346 {
347  return beeline ( a.x, a.y, b.x, b.y );
348 }
349 
350 
351 int beeline ( int x1, int y1, int x2, int y2 )
352 {
353  int xdist = abs ( (x1 * 2 + (y1 & 1 )) - ( x2 * 2 + ( y2 & 1)) );
354  int ydist = abs ( y2 - y1 );
355  int num2;
356  if ( ydist > xdist )
357  num2 = (ydist - xdist) / 2 + xdist;
358  else
359  num2 = max ( xdist, ydist );
360 /*
361  int num = 0;
362  while ( x1 != x2 || y1 != y2 ) {
363  num++;
364  int direc = getdirection (x1, y1, x2, y2);
365  x1 += getnextdx ( direc, y1 );
366  y1 += getnextdy ( direc );
367  }
368 
369  if ( num != num2 )
370  printf("beeline inconsistent\n" );
371 */
372  return minmalq*num2;
373 }
374 
375 
376 inline int square ( int i )
377 {
378  return i*i;
379 }
380 
381 inline float square ( float i )
382 {
383  #ifdef __GNUC__
384  return __builtin_powif(i, 2);
385  #else
386  return pow(i, 2);
387  #endif
388 }
389 
390 
392 {
393  for ( int i = 0; i < sidenum; i++ )
394  wm[i] = 0;
395 
396  int movement = 0;
397  for ( int height = 4; height <= 6; height++ ){
398  if ( vehicle->typ->movement[height] )
399  if ( vehicle->typ->movement[height] > movement )
400  movement = vehicle->typ->movement[height];
401  }
402 
403  if ( movement ) {
404  int wmn[7];
405 
406  int lastDir = 0;
407 
408  float abswindspeed = float( vehicle->getMap()->weather.windSpeed) * maxwindspeed / 255;
409 
410  for ( float direc = 0; direc < 360; direc++) {
411  static const float pi = 3.14159265;
412  float unitspeedx = movement * sin(direc/180*pi);
413  float unitspeedy = movement * cos(direc/180*pi);
414 
415  float angle = atan2( unitspeedx, unitspeedy + abswindspeed );
416  if ( angle < 0 )
417  angle += 2 * pi;
418 
419  if ( angle >= 60 * float(lastDir) * (2*pi) / 360 ) {
420  float absspeed = sqrt ( square ( unitspeedy + abswindspeed)+ square ( unitspeedx) );
421  wmn[lastDir] = int( 10 - 10*movement/absspeed );
422  ++lastDir;
423  }
424  }
425 
426 
427  for ( int i = 0; i <= 3; i++ ) {
428  wm[(i+vehicle->getMap()->weather.windDirection)%6] = wmn[i];
429  if ( i > 0 )
430  wm[(6-i+vehicle->getMap()->weather.windDirection)%6] = wmn[i];
431  }
432  }
433 }
434 
435 
436 /*
437 Wenn Du Wind aus Westen hast und willst nach norden fliegen, dann darf der Flieger nicht Kurs auf Norden nehmen, denn dann wrde er abgetrieben. Er muss stattdessen etwas gegen den Wind fliegen.
438 
439 Diesen Winkel ermittel' ich durch plumpes ausprobieren, in WindMovement::WindMovement
440 
441 Solange die Sollrichtung der Einheitenbewegung und die WindRichtungen bereinstimmen, brauche ich nur den Fall fr 1 Windrichtung berechnen. Ich ermittel' dann fr die 6 Einheitenrichtungen den Malus. Fr andere Windrichtungen verschiebe ich einfach nur die Werte in die Tabelle (die letzten beiden Anweisungen in WindMovement), da das entscheidende ja nur der Winkelunterschied zwischen Wind- und Sollbewegungsrichtung ist.
442 */
443 
void testfield(const MapCoordinate &pos)
int ccmpheighchangemovedir[6]
The (base-) classes which are thrown as exceptions.
int xsize
the size of the map
Definition: gamemap.h:201
int winkelcomp(double w1, double w2)
void start(int x1, int y1, int x2, int y2)
struct GameMap::Weather weather
vector< int > movement
the distance a unit can travel each round. One value for each of the 8 levels of height ...
Definition: vehicletype.h:203
int beeline(const Vehicle *a, const Vehicle *b)
returns the distance between the units a and b
const int sidenum
the number of sides that a field has; is now fixed at 6;
Definition: typen.h:438
#define fielddisthalfx
Definition: typen.h:435
GameMap * gamemap
Definition: mapalgorithms.h:62
SearchFields(GameMap *_gamemap)
void initsearch(const MapCoordinate &startPosition, int _firstDistance, int _lastDistance)
Coordinate on the twodimensional map.
Definition: typen.h:202
Definition of THE central asc class: GameMap.
void circularFieldIterator(GameMap *gamemap, const MapCoordinate &center, int startDist, int stopDist, FieldIterationFunctor functor)
double winkel(int x, int y)
searches fields in hexagonal "circles" around a field and calls testfield for each field ...
Definition: mapalgorithms.h:28
const float pi
Definition: basegfx.cpp:551
int getnextdx(int dir, int y)
Definition: mapalgorithms.h:77
virtual void startsearch(void)
FieldIterationFunctor MyFunctor
MapCoordinate startPos
Definition: mapalgorithms.h:31
tdrawgettempline(int _freefields, GameMap *_gamemap)
int getnextdy(int dir)
Definition: mapalgorithms.h:80
int ysize
Definition: gamemap.h:201
#define fielddistx
Definition: typen.h:433
int xpos
the position on the map
Definition: vehicle.h:124
const VehicleType * typ
Definition: vehicle.h:83
SearchFieldsIterator(GameMap *_gamemap, MyFunctor &functor)
Coordinate on the map including height.
Definition: typen.h:238
int getjamming(void)
the radar jamming that is on this field
Definition: mapfield.cpp:537
virtual void testfield(const MapCoordinate &pos)=0
int square(int i)
GameMap * getMap() const
const T & max(const T &a, const T &b, const T &c)
Definition: misc.h:97
int ypos
Definition: vehicle.h:124
void fatalError(const ASCString &string)
int getdirection(const MapCoordinate &start, const MapCoordinate &dest)
virtual void putpix8(int x, int y)
GameMap * gamemap
Definition: mapalgorithms.h:30
WindMovement(const Vehicle *vehicle)
Loki::Functor< void, LOKI_TYPELIST_1(const MapCoordinate &) > FieldIterationFunctor
Definition: mapalgorithms.h:43
#define minmalq
Definition: typen.h:430
#define fielddisty
Definition: typen.h:434
const int maxwindspeed
Wind with its maximum strength of 255 is moving this distance per turn.
Definition: typen.h:501
MapCoordinate3D getNeighbouringFieldCoordinate(const MapCoordinate3D &pos, int direc)
returns the coordinate of the field that is adjecent to the given field in the direction of direc ...
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182
MapField * getField(int x, int y)
Definition: gamemap.h:465