src/hcode/btech/mech.los.c File Reference

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/file.h>
#include "mech.h"
#include "p.map.obj.h"
#include "p.mech.sensor.h"
#include "p.mech.los.h"
#include "p.mech.utils.h"

Include dependency graph for mech.los.c:

Go to the source code of this file.

Functions

float ActualElevation (MAP *map, int x, int y, MECH *mech)
int TraceLOS (MAP *map, int ax, int ay, int bx, int by, lostrace_info **result)
int CalculateLOSFlag (MECH *mech, MECH *target, MAP *map, int x, int y, int ff, float hexRange)
int AddTerrainMod (MECH *mech, MECH *target, MAP *map, float hexRange, int wAmmoMode)
int InLineOfSight_NB (MECH *mech, MECH *target, int x, int y, float hexRange)
int InLineOfSight (MECH *mech, MECH *target, int x, int y, float hexRange)
void mech_losemit (dbref player, MECH *mech, char *buffer)


Function Documentation

float ActualElevation ( MAP map,
int  x,
int  y,
MECH mech 
)

Definition at line 35 of file mech.los.c.

References CLASS_DS, CLASS_MECH, Elevation, Fallen, IsDS, MechDugIn, MechMove, MechType, MechZ, and MOVE_NONE.

Referenced by CalculateLOSFlag().

00036 {
00037 
00038         if(!map)
00039                 return 0.0;
00040         if(!mech)
00041                 return (float) (Elevation(map, x, y) + 0.1);
00042         if(MechType(mech) == CLASS_MECH && !Fallen(mech))
00043                 return (float) MechZ(mech) + 1.5;
00044         else if(MechMove(mech) == MOVE_NONE)
00045                 return (float) MechZ(mech) + 1.5;
00046         else if(IsDS(mech))
00047                 return (float) MechZ(mech) + 2.5 + (MechType(mech) ==
00048                                                                                         CLASS_DS ? 0 : 2);
00049         if(MechDugIn(mech))
00050                 return (float) MechZ(mech) + 0.1;
00051         return (float) MechZ(mech) + 0.5;
00052 }

int AddTerrainMod ( MECH mech,
MECH target,
MAP map,
float  hexRange,
int  wAmmoMode 
)

Definition at line 282 of file mech.los.c.

References MECHLOSFLAG_PARTIAL, MechStatus, MechToMech_LOSFlag, PARTIAL_COVER, and Sensor_ToHitBonus().

Referenced by FindNormalBTH(), and FireSpot().

00284 {
00285         /* Possibly do a quickie check only */
00286         if(mech && target) {
00287                 if(MechToMech_LOSFlag(map, mech, target) & MECHLOSFLAG_PARTIAL)
00288                         MechStatus(target) |= PARTIAL_COVER;
00289                 else
00290                         MechStatus(target) &= ~PARTIAL_COVER;
00291 
00292                 return Sensor_ToHitBonus(mech, target,
00293                                                                  MechToMech_LOSFlag(map, mech, target),
00294                                                                  map->maplight, hexRange, wAmmoMode);
00295         }
00296         return 0;
00297 }

int CalculateLOSFlag ( MECH mech,
MECH target,
MAP map,
int  x,
int  y,
int  ff,
float  hexRange 
)

Definition at line 60 of file mech.los.c.

References AA_TECH, ActualElevation(), BOUNDED(), BRIDGE, CLASS_MECH, Elevation, Fallen, FIRE, GetRTerrain, GetTerrain, HEAVY_FOREST, HIGHWATER, ICE, InWater, IsWater, LIGHT_FOREST, MAP::map_height, MAP::map_width, MAP::maxvis, MECHLOSFLAG_BLOCK, MECHLOSFLAG_FIRE, MECHLOSFLAG_MNTN, MECHLOSFLAG_PARTIAL, MECHLOSFLAG_SEEC2, MECHLOSFLAG_SEEN, MECHLOSFLAG_SMOKE, MECHLOSFLAG_WATER, MECHLOSFLAG_WOOD, MECHLOSMAX_WATER, MECHLOSMAX_WOOD, MechMove, MechRTerrain, MechSpecials, MechType, MechX, MechY, MechZ, MOUNTAINS, MOVE_HOVER, SMOKE, TraceLOS(), WATER, WaterBeast, and lostrace_info::y.

Referenced by InLineOfSight(), and update_LOSinfo().

00062 {
00063         int new_flag = (ff & (MECHLOSFLAG_SEEN)) + MECHLOSFLAG_SEEC2;
00064         int woods_count = 0;
00065         int water_count = 0;
00066         int height, i;
00067         int pos_x, pos_y;
00068         float pos_z, z_inc, end_z;
00069         int terrain;
00070         int dopartials = 0;
00071         int underwater, bothworlds, t_underwater, t_bothworlds;
00072         int uwatercount = 0, coordcount;
00073         lostrace_info *coords;
00074 
00075 #ifndef BT_PARTIAL
00076         float partial_z, p_z_inc;
00077 #endif
00078 
00079         /* A Hex target off the map? Don't bother */
00080         if(!target && ((x < 0 || y < 0 || x >= map->map_width ||
00081                                         y >= map->map_height)))
00082                 return new_flag + MECHLOSFLAG_BLOCK;
00083 
00084         /* Outside max sensor range in the worst case? Don't bother. */
00085         if(hexRange > (((MechSpecials(mech) & AA_TECH) || (target &&
00086                                                                                                            (MechSpecials(target) &
00087                                                                                                                 AA_TECH))) ? 180 :
00088                                    map->maxvis))
00089                 return new_flag + MECHLOSFLAG_BLOCK;
00090 
00091         /* We start at (MechX(mech), MechY(mech)) and wind up at (x,y) */
00092         pos_x = MechX(mech);
00093         pos_y = MechY(mech);
00094         pos_z = ActualElevation(map, pos_x, pos_y, mech);
00095         end_z = ActualElevation(map, x, y, target);
00096 
00097 /* Definition of 'both worlds': According to FASA, if a mech is half
00098    submerged, or a sub is surfaced, or any naval or hover is on top
00099    of the water, it can see in both the underwater and overwater 'worlds'.
00100    In other words, it'll never get a block from the water/air interface.
00101    Neither will anything get such a block against it. That's what the
00102    'both worlds' variables test for. */
00103 
00104         if(end_z > 10 && pos_z > 10)
00105                 return new_flag;
00106         bothworlds = IsWater(MechRTerrain(mech)) &&     /* Can we be in both worlds? */
00107                 (((MechType(mech) == CLASS_MECH) && (MechZ(mech) == -1)) ||
00108                  ((WaterBeast(mech)) && (MechZ(mech) == 0)) ||
00109                  ((MechMove(mech) == MOVE_HOVER) && (MechZ(mech) == 0)));
00110         underwater = InWater(mech) && (pos_z < 0.0);
00111 
00112         /* Ice hex targeting special case */
00113         if(!target && !underwater && GetRTerrain(map, x, y) == ICE)
00114                 end_z = 0.0;
00115 
00116         if(target) {
00117                 /* What about him? Both worlds? Or flat out underwater? */
00118                 t_bothworlds = IsWater(MechRTerrain(target)) &&
00119                         (((MechType(target) == CLASS_MECH) && (MechZ(target) == -1)) ||
00120                          ((WaterBeast(target)) && (MechZ(target) == 0)) ||
00121                          ((MechMove(target) == MOVE_HOVER) && (MechZ(target) == 0)));
00122 
00123                 t_underwater = InWater(target) && (end_z < 0.0);
00124         } else {
00125                 if(GetRTerrain(map, x, y) == ICE)
00126                         t_bothworlds = 1;
00127                 else
00128                         t_bothworlds = 0;
00129                 t_underwater = (end_z < 0.0);   /* Is the hex underwater? */
00130         }
00131 
00132         /* And now we look once more to make sure we aren't wasting our time */
00133         if(((underwater) && !(t_underwater)) ||
00134            ((t_underwater) && !(underwater))) {
00135                 return new_flag + MECHLOSFLAG_BLOCK;
00136         }
00137 
00138         /* Worth our time to mess with figuring partial cover? */
00139         if(target && mech)
00140                 dopartials = (MechType(target) == CLASS_MECH) && (!Fallen(target));
00141 
00142         /*Same hex is always LoS */
00143         if((x == pos_x) && (y == pos_y))
00144                 return new_flag;
00145 
00146         /* Special cases are out of the way, looks like we have to do actual work. */
00147         coordcount = TraceLOS(map, pos_x, pos_y, x, y, &coords);
00148         if(coordcount > 0) {
00149                 z_inc = (float) (end_z - pos_z) / coordcount;
00150         } else {
00151                 z_inc = 0;                              /* In theory, this should never happen. */
00152         }
00153 
00154 #ifndef BT_PARTIAL
00155         partial_z = 0;
00156         p_z_inc = (float) 1 / coordcount;
00157 #endif
00158 
00159         if(coordcount > 0) {            /* not in same hex ; in same hex, you see always */
00160                 for(i = 0; i < coordcount; i++) {
00161                         pos_z += z_inc;
00162 #ifndef BT_PARTIAL
00163                         partial_z += p_z_inc;
00164 #endif
00165                         if(coords[i].x < 0 || coords[i].x >= map->map_width ||
00166                            coords[i].y < 0 || coords[i].y >= map->map_height)
00167                                 continue;
00168                         /* Should be possible to see into water.. perhaps. But not
00169                            on vislight */
00170                         terrain = GetRTerrain(map, coords[i].x, coords[i].y);
00171                         /* get the current height */
00172                         height = Elevation(map, coords[i].x, coords[i].y);
00173 
00174 /* If you, persoanlly, are underwater, the only way you can see someone
00175    if if they are underwater or in both worlds AND your LoS passes thru
00176    nothing but water hexes AND your LoS doesn't go thru the sea floor */
00177                         if(underwater) {
00178 
00179 /* LoS hits sea floor */
00180                                 if(!(IsWater(terrain)) || (terrain != BRIDGE &&
00181                                                                                    height >= pos_z)) {
00182                                         new_flag |= MECHLOSFLAG_BLOCK;
00183                                         return new_flag;
00184                                 }
00185 
00186 /* LoS pops out of water, AND we're not tracing to half-submerged mech's head */
00187                                 if(!t_bothworlds && pos_z > 0.0) {
00188                                         new_flag |= MECHLOSFLAG_BLOCK;
00189                                         return new_flag;
00190                                 }
00191 
00192 /* uwatercount = # hexes LoS travel UNDERWATER */
00193                                 if(pos_z <= 0.0)
00194                                         uwatercount++;
00195                                 water_count++;
00196                         } else {                        /* Viewer is not underwater */
00197                                 /* keep track of how many wooded hexes we cross */
00198                                 if(pos_z < (height + 2)) {
00199                                         switch (GetTerrain(map, coords[i].x, coords[i].y)) {
00200                                         case SMOKE:
00201                                                 if(i < coordcount - 1)
00202                                                         new_flag |= MECHLOSFLAG_SMOKE;
00203                                                 break;
00204                                         case FIRE:
00205                                                 if(i < coordcount - 1)
00206                                                         new_flag |= MECHLOSFLAG_FIRE;
00207                                                 break;
00208                                         }
00209                                         switch (terrain) {
00210                                         case LIGHT_FOREST:
00211                                         case HEAVY_FOREST:
00212                                                 if(i < coordcount - 1)
00213                                                         woods_count += (terrain == LIGHT_FOREST) ? 1 : 2;
00214                                                 break;
00215                                         case HIGHWATER:
00216                                                 water_count++;
00217                                                 break;
00218                                         case ICE:
00219                                                 if(pos_z < -0.0) {
00220                                                         new_flag |= MECHLOSFLAG_BLOCK;
00221                                                         return new_flag;
00222                                                 }
00223                                                 water_count++;
00224                                                 break;
00225                                         case WATER:
00226 
00227 /* LoS goes INTO water and we're not tracing to a target in both worlds */
00228                                                 if(!bothworlds && (pos_z < 0.0)) {
00229                                                         new_flag |= MECHLOSFLAG_BLOCK;
00230                                                         return new_flag;
00231                                                 }
00232 
00233 /* Hexes in LoS that are phsyically underwater */
00234                                                 if(pos_z < 0.0)
00235                                                         uwatercount++;
00236                                                 water_count++;
00237                                                 break;
00238                                         case MOUNTAINS:
00239                                                 if(i < coordcount - 1)
00240                                                         new_flag |= MECHLOSFLAG_MNTN;
00241                                                 break;
00242                                         }
00243                                 }
00244                                 /* make this the new 'current hex' */
00245                                 if(height >= pos_z && terrain != BRIDGE) {
00246                                         new_flag |= MECHLOSFLAG_BLOCK;
00247                                         return new_flag;
00248                                 }
00249 #ifndef BT_PARTIAL
00250                                 else if(dopartials && height >= (pos_z - partial_z))
00251                                         new_flag |= MECHLOSFLAG_PARTIAL;
00252 #endif
00253                         }
00254                 }
00255         }
00256         /* Then, we check the hex before target hex */
00257 #ifdef BT_PARTIAL
00258         if(coordcount >= 2)
00259                 if(dopartials) {
00260                         if(MechZ(target) >= MechZ(mech) &&
00261                            (Elevation(map, coords[coordcount - 2].x,
00262                                                   coords[coordcount - 2].y) == (MechZ(target) + 1)))
00263                                 new_flag |= MECHLOSFLAG_PARTIAL;
00264                         if(MechZ(target) == -1 && MechRTerrain(target) == WATER)
00265                                 new_flag |= MECHLOSFLAG_PARTIAL;
00266                 }
00267 #endif
00268 
00269         water_count = BOUNDED(0, water_count, MECHLOSMAX_WATER - 1);
00270         woods_count = BOUNDED(0, woods_count, MECHLOSMAX_WOOD - 1);
00271         new_flag += MECHLOSFLAG_WOOD * woods_count;
00272         new_flag += MECHLOSFLAG_WATER * water_count;
00273 
00274 /* Block EM after 2, Vis/IR after 6 */
00275         if(uwatercount > 2)
00276                 new_flag |= MECHLOSFLAG_MNTN;
00277         if(uwatercount > 6)
00278                 new_flag |= MECHLOSFLAG_FIRE;
00279         return new_flag;
00280 }

int InLineOfSight ( MECH mech,
MECH target,
int  x,
int  y,
float  hexRange 
)

Definition at line 312 of file mech.los.c.

References CalculateLOSFlag(), CLAIRVOYANT, MAP::cloudbase, getMap(), InWeaponArc(), MAP::LOSinfo, MAP::map_height, MAP::map_width, MapCoordToRealCoord(), MECH::mapindex, MAP::maplight, MECH::mapnumber, MAP::mapvis, mech_notify(), MechCritStatus, MechFX, MechFY, MECHLOSFLAG_BLOCK, MECHLOSFLAG_SEEN, MECHLOSFLAG_SEESP, MECHLOSFLAG_SEESS, MECHPILOT, MechToMech_LOSFlag, MECH::mynum, SendError, Sensor_CanSee(), and tprintf().

Referenced by auto_radio_command_report(), DisplayTarget(), find_mech_in_hex(), findC3RangeWithNetwork(), FireSpot(), fun_btlosm2m(), InLineOfSight_NB(), mech_attachcables(), mech_bearing(), mech_c3_join_leave(), mech_c3i_join_leave(), mech_contacts(), mech_detachcables(), mech_embark(), mech_hide_event(), mech_jump(), mech_lock_event(), mech_pickup(), mech_radio(), mech_range(), mech_report(), mech_scan(), mech_settarget(), mech_spot(), mech_vector(), mech_view(), MechFireBroadcast(), MechLOSBroadcast(), MechLOSBroadcasti(), mechSeenByNetwork(), MechSeesHexF(), navigate_sketch_mechs(), parse_tacargs(), ScrambleInfraAndLiteAmp(), show_lrs_map(), showNetworkTargets(), and sketch_tac_mechs().

00313 {
00314         MAP *map;
00315         float x1, y1;
00316         int arc;
00317         int losflag;
00318 
00319         map = getMap(mech->mapindex);
00320         if(!map) {
00321                 mech_notify(mech, MECHPILOT,
00322                                         "You are on an invalid map! Map index reset!");
00323                 SendError(tprintf("InLineOfSight:invalid map:Mech %d  Index %d",
00324                                                   mech->mynum, mech->mapindex));
00325                 mech->mapindex = -1;
00326                 return 0;
00327         }
00328         if(x < 0 || y < 0 || y >= map->map_height || x >= map->map_width) {
00329                 SendError(tprintf("x:%d y:%d out of bounds for #%d (LOS check)", x,
00330                                                   y, mech ? mech->mynum : -1));
00331         }
00332 
00333         /* Possibly do a quickie check only */
00334         if(MechCritStatus(mech) & CLAIRVOYANT)
00335                 return 1;
00336 
00337         if(target) {
00338                 x1 = MechFX(target);
00339                 y1 = MechFY(target);
00340         } else
00341                 MapCoordToRealCoord(x, y, &x1, &y1);
00342         arc = InWeaponArc(mech, x1, y1);
00343 
00344         if(mech && target) {
00345 #ifndef ADVANCED_LOS
00346                 losflag = MechToMech_LOSFlag(map, mech, target);
00347                 if(Sensor_CanSee(mech, target, &losflag, arc, hexRange, map->mapvis,
00348                                                  map->maplight, map->cloudbase)) {
00349                         map->LOSinfo[mech->mapnumber][target->mapnumber] |=
00350                                 (MECHLOSFLAG_SEEN | MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS);
00351                         return 1;
00352                 } else {
00353                         map->LOSinfo[mech->mapnumber][target->mapnumber] &=
00354                                 ~(MECHLOSFLAG_SEEN | MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS);
00355                         return 0;
00356                 }
00357 #else
00358                 if(MechToMech_LOSFlag(map, mech, target) & (MECHLOSFLAG_SEESP |
00359                                                                                                         MECHLOSFLAG_SEESS))
00360                         return MechToMech_LOSFlag(map, mech, target) &
00361                                 (MECHLOSFLAG_SEESP | MECHLOSFLAG_SEESS | MECHLOSFLAG_BLOCK);
00362 #endif
00363                 return 0;
00364         }
00365         losflag = CalculateLOSFlag(mech, NULL, map, x, y, 0, hexRange);
00366         return Sensor_CanSee(mech, NULL, &losflag, arc, hexRange, map->mapvis,
00367                                                  map->maplight, map->cloudbase);
00368 }

int InLineOfSight_NB ( MECH mech,
MECH target,
int  x,
int  y,
float  hexRange 
)

Definition at line 299 of file mech.los.c.

References InLineOfSight(), and MECHLOSFLAG_BLOCK.

Referenced by checkTAG(), FindBSuitTarget(), fun_bthexlos(), fun_btid2db(), fun_btlosm2m(), GetMechToMechID(), mech_charge(), mech_contacts(), mech_report(), mech_scan(), mech_tag(), mech_view(), mechSeenByNetwork(), PhysicalAttack(), showNetworkTargets(), and SwarmHitTarget().

00300 {
00301         int i;
00302 
00303         if(mech == target)
00304                 return 1;
00305 
00306         i = InLineOfSight(mech, target, x, y, hexRange);
00307         if(i & MECHLOSFLAG_BLOCK)
00308                 return 0;
00309         return i;
00310 }

void mech_losemit ( dbref  player,
MECH mech,
char *  buffer 
)

Definition at line 370 of file mech.los.c.

References cch, MECH_USUALSP, MechLOSBroadcast(), and notify.

00371 {
00372         cch(MECH_USUALSP);
00373         MechLOSBroadcast(mech, buffer);
00374         notify(player, "Broadcast done.");
00375 }

int TraceLOS ( MAP map,
int  ax,
int  ay,
int  bx,
int  by,
lostrace_info **  result 
)

Definition at line 208 of file mech.lostracer.c.

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 }


Generated on Mon May 28 04:25:36 2007 for BattletechMUX by  doxygen 1.4.7