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

#include "mech.h"
#include "btmacros.h"
#include "mech.sensor.h"
#include "map.los.h"
#include "p.mech.utils.h"

Include dependency graph for map.los.c:

Go to the source code of this file.

Defines

#define INDEX2X(i)   ((i%(losmap.xsize))+(losmap.startx))
#define INDEX2Y(i)   ((i/(losmap.xsize))+(losmap.starty))
#define DEF_MINA(mech, sn)   (MechSeesTerrain(mech, sn) ? -20 : 1000)

Functions

int TraceLOS (MAP *map, int ax, int ay, int bx, int by, lostrace_info **result)
int LOSMap_Hex2Index (hexlosmap_info *losmap, int x, int y)
static float MechHeight (MECH *mech)
static void set_hexlosinfo (int x, int y, int flag)
static int hexlit (int x, int y)
static void set_sliteinfo (int x, int y, int flag)
static void set_hexlosall (int flag)
static int MechSeesThroughWoods (MECH *mech, MAP *map, int nwoods, int sensor)
static int MechSeesOverMountain (MECH *mech, MAP *map, int sensor)
static int MechSeesThroughWater (MECH *mech, MAP *map, int nwater, int sensor)
static int MechSeesRange (MECH *mech, MAP *map, int x, int y, int z, int sensor)
static int MechSLitesRange (MECH *mech, int x, int y, int z)
static int MechSeesTerrain (MECH *mech, int sn)
static void trace_slitelos (MAP *map, MECH *mech, int index, float start_height)
static void litemark_callback (MAP *map, int x, int y)
static void litemark_map (MAP *map)
static void trace_maphexlos (MAP *map, MECH *mech, int index, int tracew, float start_height)
hexlosmap_infoCalculateLOSMap (MAP *map, MECH *mech, int sx, int sy, int xsz, int ysz)

Variables

static hexlosmap_info losmap


Define Documentation

#define DEF_MINA ( mech,
sn   )     (MechSeesTerrain(mech, sn) ? -20 : 1000)

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

Referenced by trace_maphexlos().

#define INDEX2X (  )     ((i%(losmap.xsize))+(losmap.startx))

Definition at line 18 of file map.los.c.

Referenced by trace_maphexlos(), and trace_slitelos().

#define INDEX2Y (  )     ((i/(losmap.xsize))+(losmap.starty))

Definition at line 19 of file map.los.c.

Referenced by trace_maphexlos(), and trace_slitelos().


Function Documentation

hexlosmap_info* CalculateLOSMap ( MAP map,
MECH mech,
int  sx,
int  sy,
int  xsz,
int  ysz 
)

Definition at line 433 of file map.los.c.

References CLAIRVOYANT, CLASS_MECH, hexlosmap_info::flags, IsWater, litemark_map(), losmap, hexlosmap_info::map, MAPLOS_MAXX, MAPLOS_MAXY, MAPLOSHEX_NOLOS, MAPLOSHEX_SEE, MAPLOSHEX_SEEN, MechCritStatus, MechHeight(), MechMove, MechRTerrain, MechSeesTerrain(), MechType, MechZ, MOVE_HOVER, MECH::mynum, SendError, set_hexlosall(), hexlosmap_info::startx, hexlosmap_info::starty, tprintf(), trace_maphexlos(), WaterBeast, hexlosmap_info::xsize, and hexlosmap_info::ysize.

Referenced by sketch_tac_map().

00435 {
00436         int index, underterrain, bothworlds;
00437         float start_height;
00438 
00439         /* Some safeguarding on size */
00440 
00441         if(xsz > MAPLOS_MAXX || ysz > MAPLOS_MAXY) {
00442                 SendError(tprintf("xsize (%d vs %d) or ysize (%d vs %d) "
00443                                                   "to CalculateLOSMap too large, for mech #%d",
00444                                                   xsz, MAPLOS_MAXX, ysz, MAPLOS_MAXY, mech->mynum));
00445                 return NULL;
00446         }
00447 
00448         losmap.startx = sx;
00449         losmap.starty = sy;
00450         losmap.xsize = xsz;
00451         losmap.ysize = ysz;
00452         losmap.flags = 0;
00453         memset(losmap.map, 0, xsz * ysz);
00454 
00455         underterrain = MechZ(mech) <= -1;
00456         if(IsWater(MechRTerrain(mech))
00457            && ((MechType(mech) == CLASS_MECH && MechZ(mech) == -1)
00458                    || ((WaterBeast(mech) || MechMove(mech) == MOVE_HOVER)
00459                            && MechZ(mech) == 0))) {
00460                 bothworlds = 1;
00461         } else
00462                 bothworlds = 0;
00463 
00464         start_height = MechZ(mech) + MechHeight(mech);
00465 
00466         if(MechCritStatus(mech) & CLAIRVOYANT) {
00467                 set_hexlosall(MAPLOSHEX_SEE);
00468                 return &losmap;
00469         }
00470 
00471         if(!MechSeesTerrain(mech, 0) && !MechSeesTerrain(mech, 1)) {
00472                 set_hexlosall(MAPLOSHEX_NOLOS);
00473                 return &losmap;
00474         }
00475 
00476         /* In order for slites to properly light terrain, we have to mark the
00477          * losmap with all lit hexes first. Which means going over all 'mechs on
00478          * the map and tag all hexes that they light.
00479          */
00480 
00481         litemark_map(map);
00482 
00483         /* In order to do the most efficient lostracing, we make losmaps by
00484          * first tracing from the 'mech hex to the upper Y-row, the lower Y-row,
00485          * the leftmost X-row, the rightmost X-row, and then all hexes starting
00486          * at the upper left corner to make sure we have seen all hexes. (It is
00487          * entirely possible for a hex not to be visited yet, even if we traced
00488          * to every other hex.)
00489          */
00490 
00491         for(index = 0; index < xsz; index++) {
00492                 if(losmap.map[index] & MAPLOSHEX_SEEN)
00493                         continue;
00494                 trace_maphexlos(map, mech, index, underterrain || bothworlds,
00495                                                 start_height);
00496         }
00497         for(index = (ysz - 1) * xsz; index < ysz * xsz; index++) {
00498                 if(losmap.map[index] & MAPLOSHEX_SEEN)
00499                         continue;
00500                 trace_maphexlos(map, mech, index, underterrain || bothworlds,
00501                                                 start_height);
00502         }
00503         for(index = xsz; index < ysz * xsz; index += xsz) {
00504                 if(losmap.map[index] & MAPLOSHEX_SEEN)
00505                         continue;
00506                 trace_maphexlos(map, mech, index, underterrain || bothworlds,
00507                                                 start_height);
00508         }
00509         for(index = 2 * xsz - 1; index < ysz * xsz; index += xsz) {
00510                 if(losmap.map[index] & MAPLOSHEX_SEEN)
00511                         continue;
00512                 trace_maphexlos(map, mech, index, underterrain || bothworlds,
00513                                                 start_height);
00514         }
00515         for(index = 0; index < xsz * ysz; index++) {
00516                 if(losmap.map[index] & MAPLOSHEX_SEEN)
00517                         continue;
00518                 trace_maphexlos(map, mech, index, underterrain || bothworlds,
00519                                                 start_height);
00520         }
00521 
00522         return &losmap;
00523 }

static int hexlit ( int  x,
int  y 
) [static]

Definition at line 62 of file map.los.c.

References losmap, LOSMap_Hex2Index(), hexlosmap_info::map, MAPLOSHEX_LIT, hexlosmap_info::startx, hexlosmap_info::starty, hexlosmap_info::xsize, and hexlosmap_info::ysize.

Referenced by trace_maphexlos().

00063 {
00064         if(x < (losmap.startx) || x >= (losmap.startx) + (losmap.xsize) ||
00065            y < (losmap.starty) || y >= (losmap.starty) + (losmap.ysize)) {
00066                 return 0;
00067         }
00068 
00069         return (losmap.map[LOSMap_Hex2Index(&losmap, x, y)] & MAPLOSHEX_LIT);
00070 }

static void litemark_callback ( MAP map,
int  x,
int  y 
) [static]

Definition at line 260 of file map.los.c.

References MAPLOSHEX_LIT, and set_sliteinfo().

Referenced by litemark_map().

00261 {
00262         set_sliteinfo(x, y, MAPLOSHEX_LIT);
00263 }

static void litemark_map ( MAP map  )  [static]

Definition at line 265 of file map.los.c.

References FindObjectsData(), MAP::first_free, first_mapobj(), Jellied, litemark_callback(), losmap, MAPLOSHEX_LIT, MechHeight(), MechLites, MAP::mechsOnMap, MechX, MechY, MechZ, next_mapobj(), set_sliteinfo(), trace_slitelos(), TYPE_FIRE, visit_neighbor_hexes(), mapobj_struct::x, hexlosmap_info::xsize, mapobj_struct::y, and hexlosmap_info::ysize.

Referenced by CalculateLOSMap().

00266 {
00267         MECH *mech;
00268         int i;
00269         int index;
00270         mapobj *fire;
00271 
00272         for(fire = first_mapobj(map, TYPE_FIRE); fire; fire = next_mapobj(fire)) {
00273                 set_sliteinfo(fire->x, fire->y, MAPLOSHEX_LIT);
00274                 visit_neighbor_hexes(map, fire->x, fire->y, litemark_callback);
00275         }
00276 
00277         for(i = 0; i < map->first_free; i++) {
00278                 if(map->mechsOnMap[i] < 0)
00279                         continue;
00280                 mech = FindObjectsData(map->mechsOnMap[i]);
00281                 if(!mech)
00282                         continue;
00283 
00284                 if(Jellied(mech)) {
00285                         set_sliteinfo(MechX(mech), MechY(mech), MAPLOSHEX_LIT);
00286                         visit_neighbor_hexes(map, MechX(mech), MechY(mech),
00287                                                                  litemark_callback);
00288                 }
00289 
00290                 if(!MechLites(mech))
00291                         continue;
00292 
00293                 for(index = 0; index < losmap.xsize * losmap.ysize; index++) {
00294                         trace_slitelos(map, mech, index, MechZ(mech) + MechHeight(mech));
00295                 }
00296         }
00297 }

int LOSMap_Hex2Index ( hexlosmap_info losmap,
int  x,
int  y 
)

Definition at line 26 of file map.los.c.

References losmap, SendError, hexlosmap_info::startx, hexlosmap_info::starty, tprintf(), hexlosmap_info::xsize, and hexlosmap_info::ysize.

Referenced by hexlit(), set_hexlosinfo(), and set_sliteinfo().

00027 {
00028         if(x < losmap->startx || x > losmap->startx + losmap->xsize ||
00029            y < losmap->starty || y > losmap->starty + losmap->ysize) {
00030                 SendError(tprintf("LOSMap request from out of bounds hex: %d,%d",
00031                                                   x, y));
00032                 return 0;
00033         }
00034         return ((y - losmap->starty) * losmap->xsize) + (x - losmap->startx);
00035 }

static float MechHeight ( MECH mech  )  [static]

Definition at line 37 of file map.los.c.

References CLASS_DS, CLASS_MECH, CLASS_MW, CLASS_SPHEROID_DS, CLASS_VEH_NAVAL, Fallen, and MechType.

Referenced by CalculateLOSMap(), and litemark_map().

00038 {
00039         switch (MechType(mech)) {
00040         case CLASS_MECH:
00041                 return 0.2 + !Fallen(mech);
00042         case CLASS_SPHEROID_DS:
00043                 return 4.2;
00044         case CLASS_DS:
00045                 return 2.2;
00046         case CLASS_MW:
00047         case CLASS_VEH_NAVAL:
00048                 return 0.01;
00049         }
00050         return 0.2;
00051 }

static int MechSeesOverMountain ( MECH mech,
MAP map,
int  sensor 
) [static]

Definition at line 106 of file map.los.c.

References SensorStruct::cansee_func, MECHLOSFLAG_MNTN, MechSensor, and sensors.

Referenced by trace_maphexlos().

00107 {
00108         int sn = MechSensor(mech)[sensor];
00109         int fake_losflag = MECHLOSFLAG_MNTN;
00110 
00111         return sensors[sn].cansee_func(mech, NULL, map, 1, fake_losflag);
00112 }

static int MechSeesRange ( MECH mech,
MAP map,
int  x,
int  y,
int  z,
int  sensor 
) [static]

Definition at line 123 of file map.los.c.

References FindRange(), hexlosmap_info::flags, FORWARDARC, InWeaponArc(), losmap, MapCoordToRealCoord(), MAP::maplight, MAPLOS_FLAG_SLITE, MAP::mapvis, SensorStruct::maxvis, MechFX, MechFY, MechFZ, MechSensor, sensors, TURRETARC, and ZSCALE.

Referenced by trace_maphexlos().

00125 {
00126         int sn = MechSensor(mech)[sensor];
00127         float fx, fy, range, maxvis = sensors[sn].maxvis;
00128 
00129         MapCoordToRealCoord(x, y, &fx, &fy);
00130         range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech),
00131                                           fx, fy, ZSCALE * z);
00132 
00133         /* XXX HACK: code duplication. this should be replaced with sensor
00134          * functions
00135          */
00136 
00137         if(sn < 2)                                      /* V or L sensors */
00138                 maxvis = map->mapvis;
00139         if(sn == 1 && map->maplight == 0)       /* L sensors in darkness */
00140                 maxvis *= 2;
00141 
00142         if(!sensors[sn].fullvision) {
00143                 int arc = InWeaponArc(mech, fx, fy);
00144 
00145                 if(!(arc & (FORWARDARC | TURRETARC))) {
00146                         if(MechSensor(mech)[0] == MechSensor(mech)[1])
00147                                 maxvis = (maxvis * 200 / 300);
00148                         else
00149                                 maxvis = 0;
00150                 }
00151         }
00152 
00153         if(sn == 0 && maxvis && range >= maxvis &&
00154            (losmap.flags & MAPLOS_FLAG_SLITE))
00155                 return -1;
00156 
00157         return range < maxvis;
00158 }

static int MechSeesTerrain ( MECH mech,
int  sn 
) [static]

Definition at line 176 of file map.los.c.

References MechSensor.

Referenced by CalculateLOSMap().

00177 {
00178         return MechSensor(mech)[sn] < 4;
00179 }

static int MechSeesThroughWater ( MECH mech,
MAP map,
int  nwater,
int  sensor 
) [static]

Definition at line 114 of file map.los.c.

References SensorStruct::cansee_func, MECHLOSFLAG_WATER, MechSensor, and sensors.

Referenced by trace_maphexlos().

00116 {
00117         int sn = MechSensor(mech)[sensor];
00118         int fake_losflag = nwater * MECHLOSFLAG_WATER;
00119 
00120         return sensors[sn].cansee_func(mech, NULL, map, 1, fake_losflag);
00121 }

static int MechSeesThroughWoods ( MECH mech,
MAP map,
int  nwoods,
int  sensor 
) [static]

Definition at line 96 of file map.los.c.

References SensorStruct::cansee_func, MECHLOSFLAG_WOOD, MechSensor, and sensors.

Referenced by trace_maphexlos().

00098 {
00099         int sn = MechSensor(mech)[sensor];
00100         int fake_losflag = nwoods * MECHLOSFLAG_WOOD;
00101         int res = sensors[sn].cansee_func(mech, NULL, map, 1, fake_losflag);
00102 
00103         return res;
00104 }

static int MechSLitesRange ( MECH mech,
int  x,
int  y,
int  z 
) [static]

Definition at line 160 of file map.los.c.

References FindRange(), FORWARDARC, InWeaponArc(), MapCoordToRealCoord(), MechFX, MechFY, MechFZ, TURRETARC, and ZSCALE.

Referenced by trace_slitelos().

00161 {
00162         float fx, fy, range;
00163         int arc, maxvis = 60;
00164 
00165         MapCoordToRealCoord(x, y, &fx, &fy);
00166         arc = InWeaponArc(mech, fx, fy);
00167         if(!(arc & (FORWARDARC | TURRETARC))) {
00168                 return 0;
00169         }
00170 
00171         range = FindRange(MechFX(mech), MechFY(mech), MechFZ(mech),
00172                                           fx, fy, ZSCALE * z);
00173         return range < maxvis;
00174 }

static void set_hexlosall ( int  flag  )  [static]

Definition at line 87 of file map.los.c.

References losmap, hexlosmap_info::map, MAPLOSHEX_SEEN, hexlosmap_info::xsize, and hexlosmap_info::ysize.

Referenced by CalculateLOSMap().

00088 {
00089         memset(&(losmap.map), flag | MAPLOSHEX_SEEN, losmap.xsize * losmap.ysize);
00090 }

static void set_hexlosinfo ( int  x,
int  y,
int  flag 
) [static]

Definition at line 53 of file map.los.c.

References losmap, LOSMap_Hex2Index(), hexlosmap_info::map, MAPLOSHEX_SEEN, hexlosmap_info::startx, hexlosmap_info::starty, hexlosmap_info::xsize, and hexlosmap_info::ysize.

Referenced by trace_maphexlos().

00054 {
00055         if(x < (losmap.startx) || x >= (losmap.startx) + (losmap.xsize) ||
00056            y < (losmap.starty) || y >= (losmap.starty) + (losmap.ysize)) {
00057                 return;
00058         }
00059         losmap.map[LOSMap_Hex2Index(&losmap, x, y)] |= (flag | MAPLOSHEX_SEEN);
00060 }

static void set_sliteinfo ( int  x,
int  y,
int  flag 
) [static]

Definition at line 72 of file map.los.c.

References hexlosmap_info::flags, losmap, LOSMap_Hex2Index(), hexlosmap_info::map, MAPLOS_FLAG_SLITE, hexlosmap_info::startx, hexlosmap_info::starty, hexlosmap_info::xsize, and hexlosmap_info::ysize.

Referenced by litemark_callback(), litemark_map(), and trace_slitelos().

00073 {
00074         if(x < (losmap.startx) || x >= (losmap.startx) + (losmap.xsize) ||
00075            y < (losmap.starty) || y >= (losmap.starty) + (losmap.ysize)) {
00076                 return;
00077         }
00078         losmap.flags |= MAPLOS_FLAG_SLITE;
00079         losmap.map[LOSMap_Hex2Index(&losmap, x, y)] |= flag;
00080 }

static void trace_maphexlos ( MAP map,
MECH mech,
int  index,
int  tracew,
float  start_height 
) [static]

Definition at line 301 of file map.los.c.

References DEF_MINA, Elevation, GetRTerrain, HEAVY_FOREST, hexlit(), INDEX2X, INDEX2Y, LIGHT_FOREST, MAPLOSHEX_NOLOS, MAPLOSHEX_SEE, MAPLOSHEX_SEETERRAIN, MAX_SENSORS, MechSeesOverMountain(), MechSeesRange(), MechSeesThroughWater(), MechSeesThroughWoods(), MechX, MechY, MOUNTAINS, NUMSENSORS, set_hexlosinfo(), TraceLOS(), WATER, watercount, lostrace_info::x, and lostrace_info::y.

Referenced by CalculateLOSMap().

00303 {
00304         int trace_water[MAX_SENSORS] = { tracew, tracew };
00305         float minangle[MAX_SENSORS] = { DEF_MINA(mech, 0), DEF_MINA(mech, 1) };
00306         float blockangle[MAX_SENSORS] = { DEF_MINA(mech, 0), DEF_MINA(mech, 1) };
00307         int woodcount[MAX_SENSORS] = { 0, 0 };
00308         int watercount[MAX_SENSORS] = { 0, 0 };
00309         lostrace_info *trace_coords;
00310         int trace_range = 0;
00311 
00312         int trace_coordnum = TraceLOS(map, MechX(mech), MechY(mech),
00313                                                                   INDEX2X(index), INDEX2Y(index),
00314                                                                   &trace_coords);
00315 
00316         for(; trace_range < trace_coordnum; trace_range++) {
00317                 int seestate;
00318                 int trace_x = trace_coords[trace_range].x;
00319                 int trace_y = trace_coords[trace_range].y;
00320                 int trace_height = Elevation(map, trace_x, trace_y);
00321 
00322                 float trace_a = (trace_height - start_height) / (trace_range + 1);
00323                 float trace_ba =
00324                         ((trace_height + 2 - start_height)) / (trace_range + 1);
00325                 int trace_terrain = GetRTerrain(map, trace_x, trace_y);
00326                 int nsensor, newwoods;
00327 
00328                 for(nsensor = 0; nsensor < NUMSENSORS(mech); nsensor++) {
00329 
00330                         /* If the current hex and all its terrain ('blockangle') lies
00331                          * below our minimum angle of sight, we won't see it at all;
00332                          * jump straight ahead to the water/mountain checks. This check
00333                          * is made first, because it is the cheapest check and the
00334                          * general mechanism to signal 'no more visibility on this line
00335                          * of sight' is to set trace_ba to an impossible angle.
00336                          */
00337 
00338                         if(trace_ba < minangle[nsensor]) {
00339                                 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS);
00340                                 goto hexinfluence;
00341 
00342                         }
00343 
00344                         /* Then we check for range. */
00345                         seestate = MechSeesRange(mech, map, trace_x, trace_y,
00346                                                                          trace_height, nsensor);
00347 
00348                         if(seestate == 0) {
00349                                 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS);
00350                                 minangle[nsensor] = blockangle[nsensor] = 1000;
00351                                 goto hexinfluence;
00352                         }
00353 
00354                         /* Count the number of woods. */
00355                         newwoods = 0;
00356                         switch (trace_terrain) {
00357                         case HEAVY_FOREST:
00358                                 newwoods++;
00359                                 /* FALLTHROUGH */
00360                         case LIGHT_FOREST:
00361                                 newwoods++;
00362                                 /* Because we aren't in water, we stop tracing below water */
00363                                 trace_water[nsensor] = 0;
00364                                 break;
00365                         }
00366 
00367                         if(!newwoods) {
00368 
00369                                 if(trace_a < minangle[nsensor] || (seestate < 0 &&
00370                                                                                                    !hexlit(trace_x,
00371                                                                                                                    trace_y))) {
00372                                         set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS);
00373                                 } else {
00374                                         set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_SEE);
00375                                         blockangle[nsensor] = minangle[nsensor] = trace_a;
00376                                         woodcount[nsensor] = 0;
00377                                 }
00378                                 goto hexinfluence;
00379                         }
00380 
00381                         if(blockangle[nsensor] < trace_a) {
00382                                 minangle[nsensor] = trace_a;
00383                                 blockangle[nsensor] = trace_ba;
00384                                 woodcount[nsensor] = newwoods;
00385                         } else if(!MechSeesThroughWoods(mech, map, woodcount[nsensor] +
00386                                                                                         newwoods, nsensor)) {
00387                                 if(trace_ba >= blockangle[nsensor]) {
00388                                         minangle[nsensor] = blockangle[nsensor];
00389                                         blockangle[nsensor] = trace_ba;
00390                                         woodcount[nsensor] = newwoods;
00391                                 } else
00392                                         minangle[nsensor] = trace_ba;
00393                         } else {
00394                                 minangle[nsensor] = trace_a;
00395                                 woodcount[nsensor] += newwoods;
00396                         }
00397 
00398                         if(trace_terrain == WATER) {
00399                                 if(trace_water[nsensor])
00400                                         watercount[nsensor]++;
00401                                 if(!trace_water[nsensor] ||
00402                                    !MechSeesThroughWater(mech, map, watercount[nsensor],
00403                                                                                  nsensor)) {
00404                                         if(seestate < 0 && !hexlit(trace_x, trace_y))
00405                                                 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS);
00406                                         else
00407                                                 set_hexlosinfo(trace_x, trace_y,
00408                                                                            MAPLOSHEX_SEETERRAIN);
00409                                 }
00410                         } else if(seestate < 0 && !hexlit(trace_x, trace_y))
00411                                 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS);
00412                         else
00413                                 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_SEE);
00414 
00415                   hexinfluence:
00416                         if(trace_terrain == WATER &&
00417                            !MechSeesThroughWater(mech, map, 1, nsensor)) {
00418                                 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS);
00419                                 minangle[nsensor] = blockangle[nsensor] = 1000;
00420                                 continue;
00421                         }
00422                         trace_water[nsensor] = 0;
00423                         if(trace_terrain == MOUNTAINS &&
00424                            !MechSeesOverMountain(mech, map, nsensor)) {
00425                                 set_hexlosinfo(trace_x, trace_y, MAPLOSHEX_NOLOS);
00426                                 minangle[nsensor] = blockangle[nsensor] = 1000;
00427                                 continue;
00428                         }
00429                 }
00430         }
00431 }

static void trace_slitelos ( MAP map,
MECH mech,
int  index,
float  start_height 
) [static]

Definition at line 223 of file map.los.c.

References Elevation, GetTerrain, HEAVY_FOREST, INDEX2X, INDEX2Y, LIGHT_FOREST, MAPLOSHEX_LIT, MAX, MechSLitesRange(), MechX, MechY, set_sliteinfo(), SMOKE, TraceLOS(), x, and lostrace_info::y.

Referenced by litemark_map().

00225 {
00226         float minangle = -20;
00227         lostrace_info *trace_coords;
00228         int trace_range = 0;
00229         int trace_x, trace_y, trace_height;
00230         float trace_a;
00231         int trace_coordnum = TraceLOS(map, MechX(mech), MechY(mech),
00232                                                                   INDEX2X(index), INDEX2Y(index),
00233                                                                   &trace_coords);
00234 
00235         for(; trace_range < trace_coordnum; trace_range++) {
00236                 trace_x = trace_coords[trace_range].x;
00237                 trace_y = trace_coords[trace_range].y;
00238 
00239                 trace_height = MAX(0, Elevation(map, trace_x, trace_y));
00240 
00241                 if(!MechSLitesRange(mech, trace_x, trace_y, trace_height))
00242                         return;
00243 
00244                 trace_a = (trace_height - start_height) / (trace_range + 1);
00245                 switch (GetTerrain(map, trace_x, trace_y)) {
00246                 case HEAVY_FOREST:
00247                 case LIGHT_FOREST:
00248                 case SMOKE:
00249                         trace_a += 2;
00250                 }
00251 
00252                 if(trace_a < minangle)
00253                         continue;
00254 
00255                 set_sliteinfo(trace_x, trace_y, MAPLOSHEX_LIT);
00256                 minangle = trace_a;
00257         }
00258 }

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

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

Referenced by CalculateLOSFlag(), trace_maphexlos(), and trace_slitelos().

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 }


Variable Documentation

hexlosmap_info losmap [static]

Definition at line 24 of file map.los.c.

Referenced by CalculateLOSMap(), get_lrshexstr(), hexlit(), litemark_map(), LOSMap_Hex2Index(), MechSeesRange(), set_hexlosall(), set_hexlosinfo(), set_sliteinfo(), show_lrs_map(), and sketch_tac_map().


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