#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "mech.h"
#include "btmacros.h"
Include dependency graph for mech.lostracer.c:
Go to the source code of this file.
Defines | |
#define | DEG60 1.0471976 |
#define | DEG30 0.5235988 |
#define | ROOT3 1.7320508 |
#define | TRACESCALEMAP 1 |
#define | Store_Hex(store_x, store_y) |
#define | Store_BestOf(x1, y1, x2, y2) |
#define | LOS_MapCoordToRealCoord(x, y, cx, cy) |
Enumerations | |
enum | hexdir { N, NE, SE, S, SW, NW } |
Functions | |
static void | GetAdjHex (int currx, int curry, int nexthex, int *x, int *y) |
int | TraceLOS (MAP *map, int ax, int ay, int bx, int by, lostrace_info **result) |
#define DEG30 0.5235988 |
#define DEG60 1.0471976 |
Value:
do { cx = (float)x * ROOT3 / 2 * TRACESCALEMAP; \ cy = ((float)y - 0.5*(x%2))*TRACESCALEMAP;} while (0)
Definition at line 170 of file mech.lostracer.c.
Referenced by TraceLOS().
#define ROOT3 1.7320508 |
Definition at line 149 of file mech.lostracer.c.
#define Store_BestOf | ( | x1, | |||
y1, | |||||
x2, | |||||
y2 | ) |
Value:
if ( ((x1) < 0) || ((x1) >= map->map_width) || \ ((y1) < 0) || ((y1) >= map->map_height) ) \ { Store_Hex((x2), (y2)); } \ else if ( ((x2) < 0) || ((x2) >= map->map_width) || \ ((y2) < 0) || ((y2) >= map->map_height) ) \ { Store_Hex((x1), (y1)); }\ else if ((Elevation(map,(x1),(y1))) > (Elevation(map, (x2), (y2)))) \ { Store_Hex((x1),(y1)); } \ else { Store_Hex((x2),(y2)); }
Definition at line 159 of file mech.lostracer.c.
Referenced by TraceLOS().
#define Store_Hex | ( | store_x, | |||
store_y | ) |
Value:
do { found_coords[found_count].x = store_x; \ found_coords[found_count++].y = store_y; } \ while (0)
Definition at line 154 of file mech.lostracer.c.
Referenced by TraceLOS().
#define TRACESCALEMAP 1 |
enum hexdir |
static void GetAdjHex | ( | int | currx, | |
int | curry, | |||
int | nexthex, | |||
int * | x, | |||
int * | y | |||
) | [static] |
Definition at line 174 of file mech.lostracer.c.
References N, NE, NW, S, SE, and SW.
Referenced by TraceLOS().
00175 { 00176 switch (nexthex) { 00177 case N: 00178 *x = currx; 00179 *y = curry - 1; 00180 break; 00181 case NE: 00182 *x = currx + 1; 00183 *y = curry - (currx % 2); 00184 break; 00185 case SE: 00186 *x = currx + 1; 00187 *y = curry - (currx % 2) + 1; 00188 break; 00189 case S: 00190 *x = currx; 00191 *y = curry + 1; 00192 break; 00193 case SW: 00194 *x = currx - 1; 00195 *y = curry - (currx % 2) + 1; 00196 break; 00197 case NW: 00198 *x = currx - 1; 00199 *y = curry - (currx % 2); 00200 break; 00201 default: /* Mostly there to satisfy gcc */ 00202 fprintf(stderr, "XXX ARGH: TraceLos doesn't know where to go!\n"); 00203 *x = currx + 1; /* Just grab some values that aren't x/y */ 00204 *y = curry + 1; /* so we can break out of the loop */ 00205 } 00206 }
int TraceLOS | ( | MAP * | map, | |
int | ax, | |||
int | ay, | |||
int | bx, | |||
int | by, | |||
lostrace_info ** | result | |||
) |
Definition at line 208 of file mech.lostracer.c.
References DEG30, DEG60, GetAdjHex(), LOS_MapCoordToRealCoord, N, NW, ROOT3, Store_BestOf, Store_Hex, and TRACESCALEMAP.
00210 { 00211 00212 int i; /* Generic counter */ 00213 float acx, acy, bcx, bcy; /* endpoints CARTESIAN coords */ 00214 float currcx, currcy; /* current hex CARTESIAN coords */ 00215 int currx, curry; /* current hex being worked from */ 00216 int nextx, nexty; /* x & y coords of next hex */ 00217 int bestx = 0, besty = 0; /* best found so far */ 00218 int lastx, lasty; /* Holding place for final intervening hex */ 00219 int xmul, ymul; /* Used in 30/150/210/330 special case */ 00220 hexdir nexthex; /* potential next hex being examined */ 00221 float nextcx, nextcy; /* Next hex's CARTESIAN coords */ 00222 float slope; /* slope of line */ 00223 float uangle; /* angle of line (in STD CARTESIAN FORM!) */ 00224 float sinu; /* sin of -uangle */ 00225 float cosu; /* cos of same */ 00226 float liney; /* TRANSFORMED y coord of the line */ 00227 float tempangle; /* temporary uangle used for effrad calc */ 00228 float effrad; /* effective radius of hex */ 00229 float currdist; /* distance along line of current hex */ 00230 float nextdist; /* distance along the line of potential hex */ 00231 float bestdist; /* "best" (not furthest) distance tried */ 00232 float enddist; /* distance along at end of line */ 00233 static lostrace_info found_coords[4000]; 00234 int found_count = 0; 00235 00236 /* Before doing anything, let's check for special circumstances, this */ 00237 /* means vertical lines (which work using the current code, but depend */ 00238 /* on atan returning proper vaules for atan(-Inf) -- which is probably */ 00239 /* slow and may break on non-ANSI systems; and also lines at 30, 90 */ 00240 /* etc.. degrees which contain 'ties' between hexes. FASA rules here */ 00241 /* say that the 'best' hex for the defender (the one that breaks LOS, */ 00242 /* or gives a greater BTH penalty) should be used. */ 00243 00244 /* THE base case */ 00245 if((ax == bx) && (ay == by)) { 00246 Store_Hex(bx, by); 00247 *result = found_coords; 00248 return found_count; 00249 } 00250 /* Is it vertical? */ 00251 if(ax == bx) { 00252 if(ay > by) 00253 for(i = ay - 1; i > by; i--) 00254 Store_Hex(ax, i); 00255 else 00256 for(i = ay + 1; i < by; i++) 00257 Store_Hex(ax, i); 00258 Store_Hex(bx, by); 00259 *result = found_coords; 00260 return found_count; 00261 } 00262 00263 /* Does it lie along a 90 degree 'tie' direction? */ 00264 /* IF(even-number-of-cols apart AND same-y-coord) */ 00265 if(!((bx - ax) % 2) && ay == by) { 00266 currx = ax; 00267 i = bx > ax ? 1 : -1; 00268 while (currx != bx) { 00269 /* Do best of (currx+1,by-currx%2) */ 00270 /* or (currx+1,by-currx%2+1) */ 00271 Store_BestOf(currx + 1 * i, by - currx % 2, currx + 1 * i, 00272 by - currx % 2 + 1); 00273 00274 if(currx != bx) 00275 Store_Hex(currx + 2 * i, by); 00276 00277 currx += 2 * i; 00278 } 00279 00280 /* Store_Hex(bx,by); */ 00281 *result = found_coords; 00282 return found_count; 00283 } 00284 00285 /* Does it lie along a 30, 150, 210, 330 degree 'tie' direction? */ 00286 /* This expression is messy, but it just means that a hex is along */ 00287 /* 30 degrees if the y distance is (the integer part of) 3/2 */ 00288 /* times the x distance, plus 1 if the x difference is odd, AND */ 00289 /* the original hex was in an even column and heads in the +y */ 00290 /* direction, or odd and goes -y. It works, try it :) */ 00291 if(abs(by - ay) == 00292 (3 * abs(bx - ax) / 2) + abs((bx - ax) % 2) * abs((by < 00293 ay) ? (ax % 00294 2) : (1 - 00295 ax % 00296 2))) { 00297 00298 /* First get the x and y 'multipliers' -- either 1 or -1 */ 00299 /* they determine the direction of the movement */ 00300 if(bx > ax) 00301 if(by > ay) { 00302 xmul = 1; 00303 ymul = 1; 00304 } else { 00305 xmul = 1; 00306 ymul = -1; 00307 } else if(by > ay) { 00308 xmul = -1; 00309 ymul = 1; 00310 } else { 00311 xmul = -1; 00312 ymul = -1; 00313 } 00314 00315 currx = ax; 00316 curry = ay; 00317 while ((currx != bx) && (curry != by)) { 00318 00319 Store_BestOf(currx, curry + ymul, currx + xmul, 00320 ymul == 00321 1 ? curry + 1 - currx % 2 : curry - currx % 2); 00322 00323 curry += (ymul == 1) ? (2 - currx % 2) : (-1 - currx % 2); 00324 currx += xmul; 00325 00326 if(currx == bx && curry == by) 00327 continue; 00328 00329 Store_Hex(currx, curry); 00330 } 00331 Store_Hex(currx, curry); 00332 *result = found_coords; 00333 return found_count; 00334 } 00335 00336 /****************************************************************************/ 00337 00338 /**** OK, now we know it's not a special case ******************************/ 00339 00340 /****************************************************************************/ 00341 00342 /* First get the necessary constants set up */ 00343 00344 LOS_MapCoordToRealCoord(ax, ay, acx, acy); 00345 LOS_MapCoordToRealCoord(bx, by, bcx, bcy); 00346 00347 slope = (float) (acy - bcy) / (float) (acx - bcx); 00348 00349 uangle = -atan(slope); 00350 00351 sinu = sin(uangle); 00352 cosu = cos(uangle); 00353 00354 liney = acx * sinu + acy * cosu; /* we could just as */ 00355 /* correctly use bx, by */ 00356 00357 enddist = bcx * cosu - bcy * sinu; 00358 00359 tempangle = fabs(uangle); 00360 while (tempangle > DEG60) 00361 tempangle -= DEG60; 00362 effrad = cos(tempangle - DEG30) * TRACESCALEMAP / ROOT3; 00363 00364 /*****************************************************************/ 00365 00368 /*****************************************************************/ 00369 00370 currx = ax; 00371 curry = ay; 00372 LOS_MapCoordToRealCoord(currx, curry, currcx, currcy); 00373 currdist = currcx * cosu - currcy * sinu; 00374 bestdist = enddist; /* set this to the endpoint, the worst */ 00375 /* possible point to go to */ 00376 00377 while (!(currx == bx && curry == by)) { 00378 00379 for(nexthex = N; nexthex <= NW; nexthex++) { 00380 00381 GetAdjHex(currx, curry, nexthex, &nextx, &nexty); 00382 LOS_MapCoordToRealCoord(nextx, nexty, nextcx, nextcy); 00383 00384 /* Is it on the line? */ 00385 if(fabs((nextcx * sinu + nextcy * cosu) - liney) > effrad) 00386 continue; 00387 00388 /* Where is it? Find the transformed x coord */ 00389 nextdist = nextcx * cosu - nextcy * sinu; 00390 00391 /* is it forward of the current hex? */ 00392 if(fabs(enddist - nextdist) > fabs(enddist - currdist)) 00393 continue; 00394 00395 /* Is it better than what we have? */ 00396 if(fabs(enddist - nextdist) >= fabs(enddist - bestdist)) { 00397 bestdist = nextdist; 00398 bestx = nextx; 00399 besty = nexty; 00400 } 00401 } 00402 00403 if(bestx == bx && besty == by) { /* If we've found the last hex, record */ 00404 lastx = currx; /* the current hex as the last */ 00405 lasty = curry; /* intervening hex, save currx/y, */ 00406 currx = bestx; /* and jump to the end of the loop */ 00407 curry = besty; 00408 continue; 00409 } 00410 00411 /* ********************************************************* */ 00412 /* HERE is where you put the test code for intervening hexes */ 00413 /* ********************************************************* */ 00414 Store_Hex(bestx, besty); 00415 /* ********************************************************* */ 00416 00417 currx = bestx; /* Reset the curr hex for the next iteration */ 00418 curry = besty; 00419 currdist = bestdist; 00420 bestdist = enddist; /* reset to worst possible value */ 00421 00422 } 00423 00424 /* **************************************************** */ 00425 /* HERE is where you put the test code for the LAST hex */ 00426 /* **************************************************** */ 00427 Store_Hex(currx, curry); 00428 /* ********************************************************* */ 00429 *result = found_coords; 00430 return found_count; 00431 }