home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / v / vol1n7.zip / TARGET.C < prev    next >
Text File  |  1992-10-10  |  9KB  |  259 lines

  1. /* TARGET.C - Targetting routines
  2.  
  3. Copyright (c) 1992 Timur Tabi 
  4. Copyright (c) 1992 Fasa Corporation 
  5.  
  6. The following trademarks are the property of Fasa Corporation:
  7. BattleTech, CityTech, AeroTech, MechWarrior, BattleMech, and 'Mech.
  8. The use of these trademarks should not be construed as a challenge to these marks.  
  9.  
  10. */
  11.  
  12. #define TARGET_C
  13. #define INCL_DOS
  14. #define INCL_GPIPRIMITIVES
  15. #define INCL_WINWINDOWMGR
  16. #include <os2.h>
  17. #include <math.h>
  18. #include <stdlib.h>
  19. #include "header.h"
  20. #include "target.h"
  21. #include "dialog.h"
  22.  
  23. void TgtInitialize(HWND hwnd) {
  24. /* Initializes variables that remain the same for all targetting functions.
  25.    Future enhancement: improve positioning algorithm of info box.
  26. */
  27.   target.fActive=FALSE;
  28.   target.hpsLine=WinGetPS(hwnd);
  29.   target.hpsHighlight=WinGetPS(hwnd);
  30.   target.hpsPath=WinGetPS(hwnd);
  31.   GpiSetColor(target.hpsLine,CLR_WHITE);
  32.   GpiSetMix(target.hpsLine,FM_XOR);
  33.   GpiSetColor(target.hpsPath,CLR_RED);
  34.   GpiSetMix(target.hpsPath,FM_XOR);
  35. }
  36.  
  37. void TgtShutdown(void) {
  38. /* This function releases the presentation-space handles when the program
  39.    terminates.
  40. */
  41.   WinReleasePS(target.hpsLine);
  42.   WinReleasePS(target.hpsHighlight);
  43.   WinReleasePS(target.hpsPath);
  44. }
  45.  
  46. void TgtStart(HEXINDEX hi) {
  47. /* This function activates the targetting mechanism.  It also spanws the thread that
  48.    performs the color cycling of the source hexagon
  49. */
  50.   target.fActive=TRUE;
  51.   target.hiStart=hi;
  52.   target.hiEnd=hi;
  53.   target.ptlStart=HexMidpoint(hi);
  54.   target.ptlEnd=target.ptlStart;
  55.  
  56.   DosCreateThread(&target.tid,HexHighlight,0UL,0UL,4096UL);
  57. }
  58.       
  59. int GetAngle(void) {
  60. /* Returns the angle of the trajectory from target.hiStart to target.hiEnd
  61. */
  62.   const double pi=3.1415926535897932384;                // Is this already declared anywhere?
  63.  
  64.   return (int) (atan2(target.ptlEnd.y-target.ptlStart.y,target.ptlEnd.x-target.ptlStart.x)*180.0/pi);
  65. }
  66.  
  67. int GetRange(void) {
  68. /* returns the range between target.hiStart and target.hiEnd
  69. */
  70.   int dx=target.hiEnd.c-target.hiStart.c;
  71.   int dy=target.hiEnd.r-target.hiStart.r;             // always even
  72.   int d=abs(dy)-abs(dx);                              // always even if d>0
  73.  
  74.   if (d <= 0)
  75.     return abs(dx);
  76.   else
  77.     return dx+d/2;
  78. }
  79.  
  80. BOOL Intersect(POINTL ptl1, POINTL ptl2) {
  81. /* This function retruns TRUE if the line segment from ptl1 to ptl2 intersects
  82.    with the targetting line.  Let s1 be the segment and let s2 be the targetting
  83.    line itself.  If we extend s1 to a line, then that
  84.    line is called l1.  Similarly, l2 is the line of s2.
  85.  
  86.    The math is quite simple.  Calculate the slopes of l1 and l2.
  87.    Find the x coordinate of the intersection of l1 and l2.  If the x coordinate
  88.    is between ptl1.x and ptl2.x, then the two seconds intersect.
  89.  
  90.    This function assumes that l1 and l2 do not _both_ have infinite slopes.
  91.  
  92.    Future enhancement: possible speed increase with matrix math
  93. */
  94.   float m,b;                                    // Slopes & intercepts
  95.   int x;                                        // Intersection x-coordinate
  96.   int dx;                                       // x-delta for l1
  97.   float f;                                      // Temp variable
  98.  
  99. // Is the targetting line vertical?
  100.   if (target.dx == 0)                                     
  101.     return (BOOL) BETWEEN(target.ptlStart.x,ptl1.x,ptl2.x);
  102.  
  103.   dx=ptl2.x-ptl1.x;
  104.   m=(float) (ptl2.y - ptl1.y) / dx;
  105.   b=ptl1.y-m*ptl1.x;
  106.             
  107.   f=(target.b-b) / (m-target.m);                // Calculate the floating-point first
  108.   x=(int) f;                                    //  To avoid round-off errors
  109.  
  110. // Now just test the intersection point
  111.   return (BOOL) ( BETWEEN(x,ptl1.x,ptl2.x) && BETWEEN(x,target.ptlStart.x,target.ptlEnd.x) );
  112. }
  113.  
  114. int NextHexSide(HEXINDEX hi, int iSide) {
  115. /* This function is used to find the intersection of hexagon hi with
  116.    the line described by ptl1 & ptl2.  It assumes that the line enters
  117.    the hexagon at side iSide.  It checks the next four sides until
  118.    it finds one that also intersects with the line.  If it can't find one,
  119.    then it assumes that the fifth (last) side must be the one.
  120.  
  121.    The first side (iSide == 0) is the at the lower-right side of the hexagon.
  122.  
  123.    Future enhancement: correction factor if targetting line is close to a vertex.
  124. */
  125.   int i;
  126.   POINTL ptl1, ptl2;
  127.  
  128.   for (i=0; i<4; i++) {
  129.     iSide=(++iSide) % 6;                       // Get the next side #
  130.     HexPointFromSide(hi,iSide,&ptl1,&ptl2);
  131.     if (Intersect(ptl1, ptl2)) return iSide;
  132.   }
  133.   return (iSide+1) % 6;                       // It has to be the last one
  134. }
  135.  
  136. void TgtInitPath(void) {
  137. /* This function is used to initialize the m, b, and dx fields of structure 'target'.
  138.    This makes sure that we don't waste any time calculating the targetting path.
  139. */
  140.   target.dx=target.ptlEnd.x-target.ptlStart.x;    // x-delta for targetting line
  141.  
  142.   if (target.dx != 0) {
  143.     target.m=(float) (target.ptlEnd.y - target.ptlStart.y) / target.dx;
  144.     target.b=target.ptlStart.y-target.m*target.ptlStart.x;
  145.   }
  146. }
  147.  
  148. void TgtShowPath(void) {
  149. /* This function a series of line segments that connect the midpoints of the
  150.    targetting path.  Since it uses the FM_XOR mix-mode, it erases the line
  151.    every other time it's called.  
  152.    Assumes that target.hiStart != target.hiEnd
  153.  
  154.    Future enhancement: support for vertex angles.
  155. */
  156.   HEXINDEX hi;
  157.   POINTL ptl;
  158.   int iSide;
  159.  
  160. // Draw the first segment
  161.   hi=target.hiStart;                                  // Start at the beginning
  162.   iSide=HexFirstSide(target.hiStart,target.hiEnd);    // Which way first?
  163.   if (iSide<0) return;                                // Don't draw a line if it's through a vertex
  164.   hi=target.hiStart;                                  // Start at the beginning
  165.   ptl=HexMidpoint(hi);                                
  166.   GpiMove(target.hpsPath,&ptl);                       
  167.  
  168.   hi=HexFromSide(hi,iSide);                           // Update to the next hex
  169.   ptl=HexMidpoint(hi);
  170.   GpiLine(target.hpsPath,&ptl);                       // Draw the first segment
  171.  
  172. // If there are any more segments, draw them too
  173. // Note: If hex1 connects to hex2 at side 'x', then hex2 connects to hex1 at side '3+x', modulo 6
  174.  
  175.   while (!HI_EQUAL(hi,target.hiEnd)) {
  176.     iSide=NextHexSide(hi,(3+iSide) % 6);
  177.     hi=HexFromSide(hi,iSide);
  178.     ptl=HexMidpoint(hi);
  179.     GpiLine(target.hpsPath,&ptl);
  180.     if (HI_EQUAL(hi,target.hiStart))        // Infinite loop?
  181.       return;                               //  Then get out of here!
  182.   }
  183. }
  184.  
  185. int GetVisibility(void) {
  186. /* Returns the visibility of the target hex, as seen from the source hex.
  187.    The current implementation is a far cry from the true calculations.
  188.  
  189.    Future enhancement: support for vertex angles.
  190. */
  191.   HEXINDEX hi;
  192.   int iVis,iSide;
  193.  
  194.   if (HI_EQUAL(target.hiStart,target.hiEnd)) return 0;  // Visibility in the same hex is always zero
  195.  
  196.   iSide=HexFirstSide(target.hiStart,target.hiEnd);
  197.   if (iSide<0) return -1;                               // We'll deal with this one later
  198.   hi=HexFromSide(target.hiStart,iSide);
  199.   hi=target.hiStart;
  200.   iVis=0;
  201.  
  202.   while (!HI_EQUAL(hi,target.hiEnd)) {
  203.     iSide=NextHexSide(hi,(3+iSide) % 6);
  204.     hi=HexFromSide(hi,iSide);
  205.     iVis+=HexTerrainVisibility(amap[hi.c][hi.r].iTerrain);
  206.     if (HI_EQUAL(hi,target.hiStart)) break;          // Inifinite loop? Get out of here!
  207.   }
  208.   return iVis;
  209. }
  210.  
  211. void TgtMove(HEXINDEX hi) {
  212. /* Performs all the necessary updates whenever the targetting line is moved.
  213.    Called every time target.fActive is TRUE, and a WM_MOUSEMOVE message is received.
  214.    First determines if the pointer has moved to a new hexagon.  If not, it
  215.    simply exists.
  216.    Otherwise, it erases the existing targetting line and targetting path, draws
  217.    the new ones, and updates the info box.
  218.  
  219.    Future enhancement: capturing the mouse.
  220. */
  221.   char sz[33];                                          // temp string
  222.  
  223. // If the target hex hasn't moved, just exit
  224.   if HI_EQUAL(target.hiEnd,hi) return;
  225.  
  226. // Erase any existing line
  227.   if (!HI_EQUAL(target.hiStart,target.hiEnd)) {  
  228.     GpiMove(target.hpsLine,&target.ptlStart);
  229.     GpiLine(target.hpsLine,&target.ptlEnd);
  230.     TgtShowPath();
  231.   }
  232.  
  233. // Set the new endpoint
  234.   target.ptlEnd=HexMidpoint(target.hiEnd=hi);
  235.   TgtInitPath();
  236.  
  237. // Draw the new line if it exists
  238.   if (!HI_EQUAL(target.hiStart,target.hiEnd)) {
  239.     GpiMove(target.hpsLine,&target.ptlStart);
  240.     GpiLine(target.hpsLine,&target.ptlEnd);
  241.     TgtShowPath();
  242.   }
  243.  
  244.   WinSetDlgItemText(hwndInfoBox,IDD_ANGLE,_itoa(GetAngle(),sz,10));
  245.   WinSetDlgItemText(hwndInfoBox,IDD_RANGE,_itoa(GetRange(),sz,10));
  246.   WinSetDlgItemText(hwndInfoBox,IDD_VISIBILITY,_itoa(GetVisibility(),sz,10));
  247. }
  248.  
  249. void TgtEnd(void) {
  250. /* Cancels the current targetting session
  251. */
  252.   target.fActive=FALSE;                           // Automatically terminates HexHighlight
  253.   if (!HI_EQUAL(target.hiStart,target.hiEnd)) {   // Erase the line if it exists
  254.     GpiMove(target.hpsLine,&target.ptlStart);
  255.     GpiLine(target.hpsLine,&target.ptlEnd);
  256.     TgtShowPath();
  257.   }
  258. }
  259.