home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Exec 1 / CD_Magazyn_EXEC_nr_1.iso / Gry / battalion.lha / Battalion / source / battalion.c < prev    next >
C/C++ Source or Header  |  1999-12-23  |  192KB  |  5,893 lines

  1. /****************************************************************/
  2. /* code copyright 1995-1996 Andrew Johnson - ALL RIGHTS RESERVED*/
  3. /*                          ajohnson@eecs.uic.edu               */
  4. /*                                                              */
  5. /*                      Electronic Visualization Lab (M/C 154)  */
  6. /*                      University of Illinois at Chicago       */
  7. /*                      851 South Morgan St. Room 1120 SEO      */
  8. /*                      Chicago, IL 60607-7053                  */
  9. /*                                                              */
  10. /*                      (312) 996-3002     (312) 413-7585 FAX   */
  11. /***********************************************************************/
  12. /* battalion.c  v 1.4                                                  */
  13. /* main routines for battalion                                         */
  14. /***********************************************************************/
  15. /*                                                */
  16. /* code within '#ifdef SOLARIS' by Johan Hagman   */
  17. /*                                                */
  18. /**************************************************/
  19.  
  20. #include "battalion.h"
  21.  
  22. #ifdef MACVERSION
  23.  
  24. #define ROADFILE "DATA:road.data"
  25. #define TREEFILE "DATA:tree.data"
  26. #define TANKFILE "DATA:tank.data"
  27.  
  28. #include "tkmacglobals.h"
  29.  
  30. void setPlayerName(char *);
  31. drawGrow(void);
  32.  
  33. #else
  34.  
  35. #ifndef AMIGAVERSION
  36. #define DATADIR  "./battalion.data"
  37. #else
  38. #define DATADIR  "battalion.data"
  39. #endif
  40. #define ROADFILE "DATA/road.data"
  41. #define TREEFILE "DATA/tree.data"
  42. #define TANKFILE "DATA/tank.data"
  43.  
  44. #endif
  45.  
  46.  
  47. /*****************/
  48. /* network stuff */
  49. /*****************/
  50.  
  51. int buildingBoomSoFarCounter;
  52. int buildingBoomSoFar[800];
  53.  
  54. int buildingBoomThisFrameCounter;
  55. int buildingBoomThisFrame[20];
  56. int currentTankNumber;
  57.  
  58.  
  59. /*********/
  60. /* times */
  61. /*********/
  62.  
  63. time_t beg, now;
  64. time_t timePaused, time3d, timeSound, timeMusic, timeDetail;
  65.  
  66. /**************/
  67. /* indicators */
  68. /**************/
  69.  
  70. int frames;
  71.  
  72. int moreThanOne;
  73.  
  74. int viewW,  viewH;
  75.  
  76. int alone;
  77. int oldview,  view;
  78. int showOptions;
  79. int paused;
  80. int noSound;
  81. int no3D;
  82. int mode3D;
  83. int mode;
  84. int backdrop;
  85. int itsChristmas;
  86. int mapHeight;
  87. int lod;
  88.  
  89. /* it would be nice to dynamically get these ... */
  90. int XMAXSCREEN = 1280;
  91.  
  92. #ifdef SOLARIS
  93.  int YMAXSCREEN = 1024;
  94. #else
  95.  int YMAXSCREEN = 1040;
  96. #endif
  97.  
  98. /************/
  99. /* counters */
  100. /************/
  101.  
  102. int killtanks, killmtanks, killhelos;
  103. int killCHHs, killmechags,  killheros,
  104. killfighters, killplanes, killlaunchers;
  105.  
  106. int mainCounter;
  107. int totalCounter;
  108. int firingDelay;
  109. int arrivalTime;
  110. int showframes; /* also used to filter out repetitive sounds */
  111. float accuracy;
  112.  
  113. int treeID;
  114.  
  115. /****************/
  116. /* window stuff */
  117. /****************/
  118.  
  119. long windowOriginX, windowOriginY, windowSizeX, windowSizeY;
  120. long monitorType;
  121. long windowWide, windowTall, windowLeft, windowTop;
  122. GLuint viewL, viewR;
  123. long zmax;
  124. int doBigClear;
  125.  
  126. float lastTankY, lastTankTheta, lastTankRad;
  127.  
  128. int pointerGrab;
  129.  
  130. /*********/
  131. /* lists */
  132. /*********/
  133.  
  134. struct road * roadSystem;
  135. struct projectile * projectFlight;
  136. struct boom * projectboom;
  137. struct tank * tanklist;
  138. struct tank * slaglist;
  139. struct tree * treelist;
  140.  
  141. /*********/
  142. /* files */
  143. /*********/
  144.  
  145. char dataPath[MAXPATH];
  146. char fullPath[MAXPATH];
  147. char scorefullPath[MAXPATH];
  148.  
  149. /*****************/
  150. /* monster stuff */
  151. /*****************/
  152.  
  153. struct monsterInfo Googelon;
  154. float offsetX; /* needed global to bank flutter */
  155. struct targetInfo * targets;
  156.  
  157.  
  158. /*********************/
  159. /* battlefield stuff */
  160. /*********************/
  161.  
  162. float globalxshift, globalzshift;
  163.  
  164. GLfloat xrot, xsaverot, yrot, ysaverot;
  165.  
  166. struct tree allTreesOnPlane[MAXTREESONPLANE];
  167. struct tree * allTreesOnPlanePtrs[MAXTREESONPLANE];
  168.  
  169. /* needed for the targets to blow up trees off the player's plane */
  170. int numTreesEverywhere;
  171. struct tree allTreesEverywhere[MAXTREESONPLANE];
  172. struct tree * allTreesEverywherePtrs[MAXTREESONPLANE];
  173.  
  174. int numTreesOnPlane;
  175.  
  176. struct fireType fires[MAXFIRESONPLANE];
  177. int flameCount;
  178.  
  179. struct tank * allTanks2OnPlane[MAXTANKSONPLANE];
  180. struct tank allTanksOnPlane[MAXTANKSONPLANE];
  181. int numTanksOnPlane;
  182.  
  183. int frameCount;
  184. int outFrameCount;
  185. time_t frameTime;
  186.  
  187. GLuint monsterLookat;
  188. GLuint overviewLookat;
  189.     
  190. int Gfor, Gbak, Gturn;
  191.  
  192. float textLineWidth;
  193.  
  194. struct timeval startTime, endTime;
  195.  
  196. /*
  197. #ifdef MACVERSION
  198.  
  199.         double macStart, macEnd;
  200.         
  201. #endif
  202. */
  203.  
  204. char playerName[16];
  205. char playerHome[256];
  206.  
  207. struct score G[3];
  208. struct score F[3];
  209. struct score V[3];
  210. struct score T[3];
  211. int multipleHighScores;
  212.  
  213. struct projectile * tproj,  *deadproj;
  214. struct boom * tboom, *deadboom;
  215.  
  216. void * arena;
  217. void * sharedmem;
  218.  
  219. int sizeBoom;
  220. int sizeTank;
  221. int sizeProjectile;
  222.  
  223. int netUp;
  224. int client;
  225.  
  226. int biggestTankNumberSent;
  227.  
  228.  
  229. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  230.  
  231. void goToHighDetail()
  232.     {
  233.     glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
  234.     glEnable(GL_DEPTH_TEST);
  235.     }
  236.     
  237. void goToLowDetail()
  238.     {
  239.     glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
  240.     glDisable(GL_DEPTH_TEST);
  241.     }
  242.  
  243. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  244.  
  245. void updateScores(char * scorefullPath, int monster, int monsterScore, int mode, char * playerName)
  246.     {
  247.     char thaName[MAXSTRING];
  248.     FILE * hiScoreFile;
  249.     char garbage;
  250.     struct score * currentOne;
  251.     int c;
  252.     int position;
  253.     int current;
  254.  
  255.     if (mode == DEMOMODE)
  256.         strcpy(thaName, "demo");
  257.     else
  258.         strcpy(thaName, playerName);
  259.     
  260.     hiScoreFile = fopen(scorefullPath, "r");
  261.     
  262.     if (hiScoreFile != NULL)
  263.         {
  264.         for(c=0;c<3;c++)
  265.             fscanf(hiScoreFile, "%d%c%s", &(G[c].number), &garbage, G[c].name);    
  266.         for(c=0;c<3;c++)
  267.             fscanf(hiScoreFile, "%d%c%s", &(V[c].number), &garbage, V[c].name);
  268.         for(c=0;c<3;c++)
  269.             fscanf(hiScoreFile, "%d%c%s", &(F[c].number), &garbage, F[c].name);
  270.         for(c=0;c<3;c++)
  271.             fscanf(hiScoreFile, "%d%c%s", &(T[c].number), &garbage, T[c].name);
  272.         
  273.         fclose(hiScoreFile);
  274.         
  275.         switch (monster){
  276.             case GOOGELON:      currentOne = G;
  277.                                 break;
  278.                                 
  279.             case TECHS:         currentOne = T;
  280.                                 break;
  281.                                 
  282.             case VAPOUR:        currentOne = V;
  283.                                 break;
  284.                                 
  285.             case FLUTTER:       currentOne = F;
  286.                                 break;                          
  287.             } 
  288.     
  289.         /* where does the new score belong */
  290.         /***********************************/
  291.     
  292.         if (monsterScore > currentOne[0].number)
  293.             position = 0;
  294.             
  295.         else if (monsterScore > currentOne[1].number)
  296.             position = 1;
  297.             
  298.         else if (monsterScore > currentOne[2].number)
  299.             position = 2;
  300.     
  301.             
  302.         if (multipleHighScores)
  303.             {
  304.             switch (position) {
  305.                 case 0: currentOne[2].number = currentOne[1].number;
  306.                         strcpy(currentOne[2].name, currentOne[1].name);
  307.                         
  308.                         currentOne[1].number = currentOne[0].number;
  309.                         strcpy(currentOne[1].name, currentOne[0].name);
  310.                         
  311.                         currentOne[0].number = monsterScore;
  312.                         strcpy(currentOne[0].name, thaName);
  313.                         break;
  314.                         
  315.                 case 1: currentOne[2].number = currentOne[1].number;
  316.                         strcpy(currentOne[2].name, currentOne[1].name);
  317.                         
  318.                         currentOne[1].number = monsterScore;
  319.                         strcpy(currentOne[1].name, thaName);
  320.                         break;
  321.                         
  322.                 case 2: currentOne[2].number = monsterScore;
  323.                         strcpy(currentOne[2].name, thaName);
  324.                         break;
  325.                 }
  326.             }
  327.         else
  328.             {
  329.             /* does the player currently have a score for this monster */
  330.             /***********************************************************/
  331.         
  332.             current = -1;
  333.             
  334.             if (same(thaName, currentOne[0].name))
  335.                 current = 0;            
  336.             else if(same(thaName, currentOne[1].name))
  337.                 current =  1;           
  338.             else if (same(thaName, currentOne[2].name))
  339.                 current =  2;
  340.  
  341.             switch (position) {
  342.                 case 0: switch (current)
  343.                             {
  344.                             case 0:     currentOne[0].number = monsterScore;
  345.                                         strcpy(currentOne[0].name, thaName);
  346.                                         break;
  347.                             
  348.                             case 1:     currentOne[1].number = currentOne[0].number;
  349.                                         strcpy(currentOne[1].name, currentOne[0].name);
  350.                                         
  351.                                         currentOne[0].number = monsterScore;
  352.                                         strcpy(currentOne[0].name, thaName);
  353.                                         break;
  354.     
  355.                             case -1:    
  356.                             case 2:     currentOne[2].number = currentOne[1].number;
  357.                                         strcpy(currentOne[2].name, currentOne[1].name);
  358.                                         
  359.                                         currentOne[1].number = currentOne[0].number;
  360.                                         strcpy(currentOne[1].name, currentOne[0].name);
  361.                         
  362.                                         currentOne[0].number = monsterScore;
  363.                                         strcpy(currentOne[0].name, thaName);
  364.                                         break;
  365.                             }
  366.                             
  367.                             
  368.                         break;
  369.                         
  370.                 case 1: switch (current)
  371.                             {
  372.                             case 0:     break;
  373.                             
  374.                             case 1:     currentOne[1].number = monsterScore;
  375.                                         strcpy(currentOne[1].name, thaName);
  376.                                         break;
  377.     
  378.                             case -1:
  379.                             case 2:     currentOne[2].number = currentOne[1].number;
  380.                                         strcpy(currentOne[2].name, currentOne[1].name);
  381.                         
  382.                                         currentOne[1].number = monsterScore;
  383.                                         strcpy(currentOne[1].name, thaName);
  384.                                         break;
  385.                             }
  386.                             
  387.                             
  388.                         break;
  389.                         
  390.                 case 2: switch (current)
  391.                             {
  392.                             case 0:     break;
  393.                             
  394.                             case 1:     break;
  395.                             
  396.                             case -1:
  397.                             case 2:     currentOne[2].number = monsterScore;
  398.                                         strcpy(currentOne[2].name, thaName);
  399.                                         break;
  400.                             }
  401.                 
  402.                         break;
  403.                 }
  404.             }
  405.     
  406.         hiScoreFile = fopen(scorefullPath, "w");
  407.     
  408.         for(c=0;c<3;c++)
  409.             fprintf(hiScoreFile, "%d%c%s\n", G[c].number, ' ', G[c].name);    
  410.         for(c=0;c<3;c++)
  411.             fprintf(hiScoreFile, "%d%c%s\n", V[c].number, ' ', V[c].name);    
  412.         for(c=0;c<3;c++)
  413.             fprintf(hiScoreFile, "%d%c%s\n", F[c].number, ' ', F[c].name);    
  414.         for(c=0;c<3;c++)
  415.             fprintf(hiScoreFile, "%d%c%s\n", T[c].number, ' ', T[c].name);    
  416.         
  417.         fclose(hiScoreFile);
  418.         }
  419.     }
  420.  
  421.  
  422. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  423.  
  424. void quickTanks()
  425.     {
  426.     struct tank *temptank;
  427.  
  428.     /**********************************************************/
  429.     /* copy all vehicles everywhere into quick-access array   */
  430.     /**********************************************************/
  431.   
  432.     numTanksOnPlane = 0;
  433.     for(temptank = tanklist->next;(temptank != NULL);temptank = temptank->next)
  434.         {
  435.             allTanks2OnPlane[numTanksOnPlane] = temptank;
  436.             allTanksOnPlane[numTanksOnPlane] = *temptank;
  437.             numTanksOnPlane += 1;
  438.             if (numTanksOnPlane >= MAXTANKSONPLANE)
  439.                 {
  440.                 showError("Too many tanks on plane");
  441.                 numTanksOnPlane -= 1;
  442.                 }
  443.         }
  444.         
  445.     for(temptank = slaglist->next;(temptank != NULL);temptank = temptank->next)
  446.         {
  447.             allTanks2OnPlane[numTanksOnPlane] = temptank;
  448.             allTanksOnPlane[numTanksOnPlane] = *temptank;
  449.             numTanksOnPlane += 1;
  450.             if (numTanksOnPlane >= MAXTANKSONPLANE)
  451.                 {
  452.                 showError("Too Many Tanks on Plane");
  453.                 numTanksOnPlane -= 1;
  454.                 }
  455.         }
  456.  
  457.     }
  458.  
  459. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  460. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  461. /* determine whether a vehicle is blocked                        */
  462. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  463.      
  464. int checkForBlock(struct tank * ttank, float rad, float theta, float y)
  465.     {
  466.     register int tankCounter;
  467.  
  468.     struct tank* ttank2;
  469.     struct tree * temptree;
  470.     struct targetInfo * temptarget;
  471.     float tankInRad, tankOutRad;
  472.     float treeInRad, treeOutRad;
  473.     float raddy;
  474.     float angle;
  475.     float targx,  targz;
  476.     float rad2;
  477.     float angDiff;
  478.     int useTarg;
  479.     int blocked;
  480.     
  481.     tankInRad   = rad + 0.2;
  482.     tankOutRad  = rad - 0.8;
  483.     treeInRad   = rad + 0.3;
  484.     treeOutRad  = rad - 1.2;
  485.  
  486.  
  487.     blocked = 0;
  488.     
  489.     /**********************************************/
  490.     /* is the vehicle blocked by another vehicle? */
  491.     /**********************************************/
  492.  
  493.     tankCounter = 0;
  494.     while ((tankCounter < numTanksOnPlane) && (!blocked))
  495.         {
  496.         ttank2 = allTanks2OnPlane[tankCounter];
  497.         rad2 = ttank2->rad;
  498.         
  499.         if ((ttank->goforit == ttank2->goforit) &&
  500.             (tankInRad >= rad2)  &&          /* check radius */
  501.             (tankOutRad <= rad2) &&
  502.             (ttank2 != ttank)    &&                 /* not same tank */
  503.             (fabs(theta - ttank2->theta) < 0.22) &&   /* check angle */
  504.             (fabs(ttank2->y - y) <= 0.6)            /* check altitude */
  505.             )
  506.                 blocked = 1;
  507.  
  508.         tankCounter += 1;
  509.         }
  510.  
  511.     /**********************************************************/
  512.     /* is the vehicle blocked by a structure (tree,building)? */
  513.     /**********************************************************/
  514.     
  515.     useTarg = 0;
  516.     for(temptarget = targets->next; temptarget != NULL; temptarget = temptarget->next)
  517.         if (&(temptarget->monster) == ttank->goforit)
  518.             {
  519.             targx = temptarget->x;
  520.             targz = temptarget->z;
  521.             useTarg = 1;
  522.             }
  523.  
  524.         for(temptree = treelist->next;(temptree != NULL) && (!blocked); temptree = temptree->next)
  525.             {
  526.             if (useTarg) /* radius to the target */
  527.                 {
  528.                 raddy = sqrt((temptree->x - targx) * (temptree->x - targx) + (temptree->z - targz) * (temptree->z - targz));
  529.                 }
  530.             else
  531.                 {
  532.                 raddy = temptree->rad; /* radius and theta to the player's monster */
  533.                 }
  534.     
  535.             if ((treeInRad >= raddy) && (treeOutRad <= raddy) && (y <= (temptree->height + 0.5)))
  536.                 {
  537.                 if (useTarg) /* theta to the target */
  538.                     {
  539.                     angle = computeAngle(temptree->z, targz, temptree->x, targx);
  540.                     }
  541.                 else
  542.                     {
  543.                     angle = temptree->theta;
  544.                     }
  545.         
  546.                 if (angle < 0)
  547.                     angle += TWOPI;
  548.                 else if (angle >= TWOPI)
  549.                     angle -= TWOPI;
  550.                 
  551.                 if (theta < 0)
  552.                     theta += TWOPI;
  553.                 else if (theta >= TWOPI)
  554.                     theta -= TWOPI;
  555.             
  556.                 angDiff = theta - angle;
  557.             
  558.                 if ((fabs(angDiff) < 0.31) || (fabs(angDiff + TWOPI) < 0.31) ||
  559.                     (fabs(angDiff - TWOPI) < 0.31))
  560.                     blocked = 1;
  561.                 }
  562.             }
  563.         
  564.     return (blocked);
  565.     }
  566.  
  567. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  568. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  569. /* increase monster's score based on kill                        */
  570. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  571.  
  572. void addScore(int tank, struct monsterInfo * m)
  573.     { 
  574.     switch(tank){
  575.         case TANK:      killtanks += 1;
  576.                         if (m!= NULL)
  577.                             m->monsterScore += 5;
  578.                         break;
  579.  
  580.         case LAUNCHER:  killlaunchers += 1;
  581.                         if (m!= NULL)
  582.                             m->monsterScore += 10;
  583.                         break;
  584.                         
  585.         case MASERTANK: killmtanks += 1;
  586.                         if (m!= NULL)
  587.                             m->monsterScore += 15;
  588.                         break;
  589.                         
  590.         case HELO:      killhelos += 1;
  591.                         if (m!= NULL)
  592.                             m->monsterScore += 8;
  593.                         break;
  594.                         
  595.         case MECHAG:    killmechags += 1;
  596.                         break;
  597.                         
  598.         case CHH:       killCHHs += 1;
  599.                         break;
  600.                         
  601.         case HERO:      killheros += 1;
  602.                         break;
  603.                         
  604.         case AIRPLANE:  killplanes += 1;
  605.                         if (m!= NULL)
  606.                             m->monsterScore += 25;
  607.                         break;
  608.  
  609.         case FIGHTER:   killfighters += 1;
  610.                         if (m!= NULL)
  611.                             m->monsterScore += 20;
  612.                         break;
  613.                         
  614.         case BUILDING:  if (m!= NULL)
  615.                             m->monsterScore += 50;
  616.                         break;
  617.                         
  618.         case PARTIALM:  if (m!= NULL)
  619.                             m->monsterScore += 4;
  620.                         break;
  621.  
  622.         case PARTIALH:  if (m!= NULL)
  623.                             m->monsterScore += 5;
  624.                         break;
  625.  
  626.         case PARTIALC:  if (m!= NULL)
  627.                             m->monsterScore += 3;
  628.                         break;
  629.  
  630.         case MONSTER:   if (m!= NULL)
  631.                             m->monsterScore += 1;
  632.                         break;
  633.                         
  634.         default:        showError("Bogus Score! (addScore)");
  635.                         break;
  636.         }
  637.     }       
  638.  
  639. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  640. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  641. /* add a new explosion                                           */
  642. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  643.  
  644. void addBoom(float x,  float y,  float z, struct monsterInfo* m)
  645.     {
  646.     struct boom * tempboom2;
  647.     struct boom tempboom;
  648.     
  649.     tempboom2 = (struct boom *) amalloc(sizeBoom, arena);
  650.  
  651.     if (tempboom2 != NULL)
  652.         {
  653.         tempboom.mine   = m;
  654.         tempboom.count  = 1;
  655.         tempboom.x      = x;
  656.         
  657.         if (y >= PLANEY)
  658.             tempboom.y = y;
  659.         else
  660.             tempboom.y = PLANEY;
  661.             
  662.         tempboom.z          = z;
  663.         tempboom.next       = projectboom->next;
  664.         *tempboom2          = tempboom;
  665.         projectboom->next   = tempboom2;
  666.         }
  667.     }
  668.  
  669. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  670. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  671. /* add a new projectile                                          */
  672. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  673.  
  674. void addProjectile( float x,  float y,  float z, int type, 
  675.                     float xv,  float yv,  float zv, float accuracy, struct monsterInfo * m)
  676.     {
  677.     struct projectile * temp;
  678.     struct projectile tempProj;
  679.  
  680.  
  681.     switch(type){
  682.         case PROJTANK:      doSound(TANKFIRE);
  683.                             break;
  684.                         
  685.         case PROJROCKET:    doSound(HELOROCKET);
  686.                             break;
  687.                         
  688.         case PROJTECHS:
  689.         case PROJHERO:      doSound(TECHSHOOT);
  690.                             break;
  691.                     
  692.         }       
  693.  
  694.     temp = (struct projectile *) amalloc(sizeProjectile, arena);
  695.  
  696.     if (temp != NULL)
  697.         {
  698.         tempProj.count = 0;
  699.         
  700.         tempProj.mine = m;
  701.         
  702.         tempProj.x = x;
  703.         tempProj.y = y;
  704.         tempProj.z = z;
  705.             
  706.         tempProj.type = (char) type;
  707.             
  708.         tempProj.xv = xv;
  709.         tempProj.yv = yv;
  710.         tempProj.zv = zv;
  711.         
  712.         if (accuracy != 0)
  713.             {
  714.             tempProj.xv += randy(5.0)/accuracy;
  715.             tempProj.yv += randy(5.0)/accuracy;
  716.             tempProj.zv += randy(5.0)/accuracy;
  717.             }
  718.             
  719.  
  720.         tempProj.next = projectFlight->next;
  721.         *temp = tempProj;
  722.         projectFlight->next = temp;
  723.         }
  724.     }               
  725.             
  726. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  727. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  728. /* update all projectiles on the battlefield                     */
  729. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  730.  
  731. void updateProjectiles()
  732.     {
  733.     float px, py, pz;
  734.     float qx, qy, qz;
  735.     float floor, ceiling;
  736.     int i, dead;
  737.     int inPlay, monsterHit, groundHit;
  738.     struct targetInfo * temptarget;
  739.     struct monsterInfo thaMonster;
  740.     float monsterX, monsterZ;
  741.     
  742.     struct projectile * pproj, *killer, *temp;
  743.     
  744.     int tankCounter, treeCounter;
  745.     float maxX, maxZ, minX, minZ;
  746.  
  747.     maxX = maxZ = minX = minZ = 0;
  748.  
  749.     /******************************************************************************/
  750.     /* figure out the range of valid shells bounded by all monsters + PLANESIZE   */
  751.     /******************************************************************************/
  752.  
  753.     for(temptarget = targets->next; temptarget != NULL; temptarget = temptarget->next)
  754.         {
  755.         if (temptarget->x > maxX)
  756.             maxX = temptarget->x;
  757.         if (temptarget->x < minX)
  758.             minX = temptarget->x;
  759.         if (temptarget->z > maxZ)
  760.             maxZ = temptarget->z;
  761.         if (temptarget->z < minZ)
  762.             minZ = temptarget->z;
  763.         }
  764.  
  765.     maxX += (PLANESIZE+1);
  766.     maxZ += (PLANESIZE+1);
  767.     minX -= (PLANESIZE+1);
  768.     minZ -= (PLANESIZE+1);
  769.  
  770.     /**********************************/
  771.     /* process each shell in turn     */
  772.     /**********************************/
  773.  
  774.     floor   = PLANEY + 0.1;
  775.     ceiling = PLANEY + 10;
  776.  
  777.     flameCount = 0;
  778.      
  779.     temp = projectFlight;
  780.     while (temp->next != NULL)
  781.         {
  782.         dead = 0;
  783.         
  784.         pproj = temp->next;
  785.         
  786.         pproj->count += 1;
  787.         
  788.         if (pproj->count > ARMCOUNT)
  789.             pproj->count = ARMCOUNT;
  790.  
  791.         /**********************************/
  792.         /* is projectile still in play?   */
  793.         /**********************************/
  794.  
  795.         px = fabs(pproj->x);
  796.         py = pproj->y;
  797.         pz = fabs(pproj->z);
  798.  
  799.         qx = pproj->x;
  800.         qy = pproj->y;
  801.         qz = pproj->z;
  802.                   
  803.         monsterHit = 0;
  804.  
  805.         /**************************************************/
  806.         /* did the projectile hit the player's monster?   */
  807.         /**************************************************/
  808.  
  809.         if ((pproj->type != PROJWATER) && (pproj->type != PROJFIRE) && (pproj->type != PROJSCAR))
  810.             {
  811.             if ((Googelon.monsterIsDead != 1) &&
  812.                 (px <= Googelon.width) && (pz <= Googelon.width) &&
  813.                 (py <= Googelon.height) && (py >= Googelon.bottom))    
  814.                     {
  815.                     if ((pproj->type != PROJTECHS) || ((pproj->type == PROJTECHS) && (pproj->mine != &Googelon)))
  816.                         {
  817.                         Googelon.energyRemaining -= BLASTPOINTS;
  818.                         monsterHit = 1;
  819.                         
  820.     /*
  821.                         if (pproj->mine != NULL)
  822.                             pproj->mine->monsterScore += 1;
  823.     */
  824.                         }
  825.                     }
  826.     
  827.             /********************************************/
  828.             /* did the projectile hit another target?   */
  829.             /********************************************/
  830.     
  831.             for(temptarget = targets->next;temptarget != NULL;temptarget = temptarget->next)
  832.                 {
  833.                 thaMonster = temptarget->monster;
  834.                 monsterX = temptarget->x;
  835.                 monsterZ = temptarget->z;
  836.                 
  837.                 if ( (thaMonster.monsterIsDead != 1) &&
  838.                     (qx <= (monsterX+thaMonster.width)) && (qz <= (monsterZ+thaMonster.width)) &&
  839.                     (qx >= (monsterX-thaMonster.width)) && (qz >= (monsterZ-thaMonster.width)) &&
  840.                     (qy <= thaMonster.height) && (qy >= thaMonster.bottom))    
  841.                         {
  842.                         if ((pproj->type != PROJTECHS) || ((pproj->type == PROJTECHS) && (pproj->mine != &(temptarget->monster))))
  843.                             {
  844.                             temptarget->monster.energyRemaining -= BLASTPOINTS;
  845.                             monsterHit = 1;
  846.         
  847.     /*
  848.                             if (pproj->mine != NULL)
  849.                                 pproj->mine->monsterScore += 1;
  850.     */
  851.                             }
  852.                         }
  853.                 }
  854.             }    
  855.  
  856.         if (!monsterHit && (py > floor) && (py < ceiling) &&
  857.             (px > minX) && (pz > minZ) && (px < maxX) && (pz < maxZ))
  858.             inPlay = 1;
  859.         else
  860.             inPlay = 0;
  861.  
  862.         if ((px <= PLANESIZE) && (pz <= PLANESIZE) && (py <= floor) &&
  863.             (pproj->type != PROJWATER) && (pproj->type != PROJSCAR))
  864.             groundHit = 1;
  865.         else
  866.             groundHit = 0;
  867.            
  868.         if (monsterHit || groundHit)
  869.             addBoom(pproj->x, pproj->y, pproj->z, pproj->mine);
  870.             
  871.  
  872.         if (!inPlay)
  873.             dead = 1;
  874.                                 
  875.         if (inPlay)
  876.             {   
  877.             /**********************************/
  878.             /* update projectile position     */
  879.             /**********************************/
  880.  
  881.             px = pproj->x += pproj->xv;
  882.             py = pproj->y += pproj->yv;
  883.             pz = pproj->z += pproj->zv;
  884.             
  885.             if (pproj->y < PLANEY)
  886.                 py = pproj->y = PLANEY;
  887.  
  888.             /*****************************/
  889.             /* update all the flames     */
  890.             /*****************************/
  891.  
  892.             if (pproj->type == PROJFIRE)
  893.                 {
  894.                 for (i=0;i<2;i++)
  895.                     {
  896.                     fires[flameCount].x         = pproj->x + randy(0.15);
  897.                     fires[flameCount].z         = pproj->z + randy(0.15);
  898.                     if (lod == 0) {
  899.                         fires[flameCount].xwid   = 0.07 + randy(0.06);
  900.                         fires[flameCount].zwid   = 0.07 + randy(0.06);
  901.                         fires[flameCount].height = 0.15 + randy(0.15);
  902.                     } else {
  903.                         fires[flameCount].xwid   = 0.1 + randy(0.07);
  904.                         fires[flameCount].zwid   = 0.1 + randy(0.07);
  905.                         fires[flameCount].height = 0.2 + randy(0.15);
  906.                     }
  907.                     do
  908.                         fires[flameCount].col   = 0.9 + randy(0.25);
  909.                     while (fires[flameCount].col > 1);
  910.                     
  911.                     flameCount += 1;
  912.                     if (flameCount >= MAXFIRESONPLANE)
  913.                         {
  914.                         showError("Too many fires on plane");
  915.                         flameCount -= 1;
  916.                         }
  917.                     }
  918.                 }
  919.  
  920.             /**********************************/
  921.             /* shells affected by gravity     */
  922.             /**********************************/
  923.  
  924.             if ((pproj->type == PROJTANK) || (pproj->type == PROJWATER))
  925.                 pproj->yv -= GRAVITY;
  926.  
  927.             /**********************************/
  928.             /* check for a tank hit           */
  929.             /**********************************/
  930.                     
  931.             if ((pproj->type != PROJSCAR) && (pproj->type != PROJWATER)
  932.                 && ((pproj->count >= ARMCOUNT) || (pproj->type == PROJTECHS) || (pproj->type == PROJFIRE)))
  933.                 {
  934.                 tankCounter = 0;
  935.                 while (tankCounter < numTanksOnPlane)
  936.                     {
  937.                     if (tankHit(&(allTanksOnPlane[tankCounter]), px, py, pz))
  938.                         {
  939.                         addBoom(px, py, pz, pproj->mine);
  940.                         dead = 1;
  941.                         }
  942.                     tankCounter += 1;
  943.                     }
  944.                 }
  945.                 
  946.             /**********************************/
  947.             /* check for a tree hit           */
  948.             /**********************************/
  949.             
  950.             if ((pproj->type != PROJSCAR) && (pproj->type != PROJWATER))
  951.                 {
  952.                 treeCounter = 0;
  953.  
  954.                 while (treeCounter < numTreesEverywhere)
  955.                     {
  956.                     if ((fabs(allTreesEverywhere[treeCounter].x - px) < TREEBLASTR) &&
  957.                         (fabs(allTreesEverywhere[treeCounter].z - pz) < TREEBLASTR) &&
  958.                         (fabs(allTreesEverywhere[treeCounter].y + allTreesEverywhere[treeCounter].height - py) < TREEBLASTHEIGHTR)
  959.                         )
  960.                             {
  961.                             addBoom(px, py, pz, pproj->mine);
  962.                             dead = 1;
  963.                         
  964.                             if ((pproj->type == PROJTECHS) || (pproj->type == PROJFIRE) || (pproj->type == PROJHERO))
  965.                                 {
  966.                                 if (allTreesEverywherePtrs[treeCounter]->intact && (allTreesEverywherePtrs[treeCounter]->type == 1)) 
  967.                                     addScore(BUILDING, pproj->mine);
  968.  
  969.                                 allTreesEverywherePtrs[treeCounter]->intact = 0;
  970.                                 }
  971.                             
  972.                             if (((pproj->type == PROJTANK) || (pproj->type == PROJROCKET)) && (allTreesEverywhere[treeCounter].type == 0))
  973.                                 allTreesEverywherePtrs[treeCounter]->intact = 0;
  974.                     
  975.                             }
  976.                     treeCounter += 1;
  977.                     }               
  978.                 }               
  979.             }
  980.  
  981.         /************************************/
  982.         /* if projectile is dead, remove it */
  983.         /************************************/
  984.  
  985.         if (dead)
  986.             {
  987.             killer = temp->next;
  988.             temp->next = temp->next->next;
  989.             afree(killer, arena);   
  990.             }
  991.         else
  992.             temp = temp->next;
  993.         }
  994.     }
  995.  
  996. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  997. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  998. /* update the state of all the structures                        */
  999. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1000.  
  1001. void updatetrees(struct tree * allTrees, int itsChristmas)
  1002.     {
  1003.     struct tree *temptree, *ttree;
  1004.     float x, y, z;
  1005.     float Vplane;
  1006.     int i, j, k, jmax, l;
  1007.     int dead;
  1008.  
  1009.     buildingBoomThisFrameCounter = 0;
  1010.  
  1011.     Vplane = sqrt(GRAVITY * 1.5) * 0.7071;
  1012.   
  1013.     ttree = allTrees;
  1014.   
  1015.     while (ttree->next != NULL)
  1016.         {
  1017.         dead = 0;
  1018.         temptree = ttree->next;
  1019.  
  1020.         x = temptree->x;
  1021.         y = temptree->y;
  1022.         z = temptree->z;
  1023.         
  1024.         temptree->rad = sqrt(x * x + z * z);
  1025.  
  1026.         temptree->theta = computeAngle(z, 0, x, 0);
  1027.  
  1028.  
  1029.         /*****************************/
  1030.         /* update special structures */
  1031.         /*****************************/
  1032.  
  1033.         if (temptree->type == 1)
  1034.             {
  1035.             /***********************/
  1036.             /* hero beam-in effect */
  1037.             /***********************/
  1038.  
  1039.             if (temptree->treeshape == 33)
  1040.                 {
  1041.                 temptree->deathCount += 1;
  1042.                 if (temptree->deathCount >= 20)
  1043.                     temptree->intact = 0;
  1044.                 }
  1045.  
  1046.             /************/
  1047.             /* fountain */
  1048.             /************/
  1049.  
  1050.             if ((temptree->treeshape == 29) && (temptree->intact) && (!itsChristmas))
  1051.                 {
  1052.                 addProjectile(x, PLANEY+0.6, z, PROJWATER,
  1053.                           2*randy(0.005), .05, 2*randy(0.005), 0, NULL);
  1054.                 }
  1055.  
  1056.             /****************/
  1057.             /* power towers */
  1058.             /****************/
  1059.  
  1060.             if ((temptree->treeshape == 3) && !(temptree->intact))
  1061.                 {
  1062.                 temptree->deathCount += 1;
  1063.             
  1064.                 if (temptree->death2 == -1)
  1065.                     {
  1066.                     doSound(CRASH);
  1067.         
  1068.                     buildingBoomThisFrame[buildingBoomThisFrameCounter++] = temptree->number;
  1069.                     buildingBoomSoFar[buildingBoomSoFarCounter++] = temptree->number;
  1070.  
  1071.                     temptree->death2 = rand() % 360;
  1072.                     temptree->height = -0.4;
  1073.                     }
  1074.             
  1075.                 if (temptree->deathCount > 40)
  1076.                     temptree->deathCount = 40;
  1077.                 }
  1078.             }
  1079.             
  1080.         /**********************************************/
  1081.         /* buildings / trees disappearing / exploding */
  1082.         /**********************************************/
  1083.             
  1084.         if (!(temptree->intact) && (((temptree->type == 1) && (temptree->treeshape != 3)) || (temptree->type == 0)))
  1085.             {
  1086.             doSound(CRASH);
  1087.             dead = 1;
  1088.  
  1089.             buildingBoomThisFrame[buildingBoomThisFrameCounter++] = temptree->number;
  1090.             buildingBoomSoFar[buildingBoomSoFarCounter++] = temptree->number;
  1091.  
  1092.             switch(temptree->treeshape)
  1093.                 {
  1094.                 case    1:
  1095.                 case    11:
  1096.                 case    14:
  1097.                 case    22:
  1098.                 case    23:
  1099.                 case    24: jmax = 5;
  1100.                             break;
  1101.                 case    33: jmax = 0;
  1102.                             break;
  1103.                 default:    jmax = 3;
  1104.                             break;
  1105.                 }
  1106.             
  1107.  
  1108.             /**********************/
  1109.             /* structures explode */
  1110.             /**********************/
  1111.  
  1112.             if (temptree->type == 1) 
  1113.                 {
  1114.                 for (i=-1; i<2; i++)
  1115.                     for (j=0; j<jmax; j++)
  1116.                         for (k=-1; k<2; k++)
  1117.                             if ((rand() % 100) < 50)
  1118.                                 {           
  1119.                                 addProjectile( x + i * 0.2, y + (j * 0.2) + 0.1, z + k * 0.2, PROJTANK, 
  1120.                                     sin(randy(PI)) * Vplane, Vplane, cos(randy(PI)) * Vplane, 75, NULL);
  1121.                                 }
  1122.                                 
  1123.                 if (temptree->treeshape == 9)  /* add water into water tower */
  1124.                     {
  1125.                     for(l=0;l<30;l++)
  1126.                         addProjectile(x, PLANEY+1, z, PROJWATER,
  1127.                           2*randy(0.02), randy(0.05), 2*randy(0.02), 0, NULL);
  1128.                     }
  1129.                 }
  1130.                 
  1131.     
  1132.             addProjectile( x - 0.2,  PLANEY + 0.14,  z + 0.2, PROJFIRE, 0,  -0.0005,  0, 10000, NULL);
  1133.             addProjectile( x + 0.2,  PLANEY + 0.14,  z + 0.2, PROJFIRE, 0,  -0.0005,  0, 10000, NULL);
  1134.             addProjectile( x      ,  PLANEY + 0.14,  z - 0.2, PROJFIRE, 0,  -0.0005,  0, 10000, NULL);
  1135.             }
  1136.         
  1137.         if (dead)
  1138.             {
  1139.             ttree->next = temptree->next;
  1140.             afree(temptree, arena);
  1141.             }
  1142.         else
  1143.             ttree = ttree->next;
  1144.         }       
  1145.     }       
  1146. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1147. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1148. /* update all of the vehicles                                    */
  1149. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1150.  
  1151. void updateTanks(struct tank * allTanks, float width, float height,
  1152.                 float bottom, int dead, int monster, 
  1153.                 struct tank* slag, float accuracy, int firingDelay, 
  1154.                 int mainCounter, struct monsterInfo * m, struct targetInfo * targets)
  1155.     {
  1156.     float xv,  yv,  zv;
  1157.     float Vplane, angle;
  1158.     int blocked, maserOn;
  1159.     struct tank *killertank,  *ttank, *temptank;
  1160.     float energyLoss;
  1161.     float tankx,  tankz;
  1162.     int tanktype;
  1163.     
  1164.     float rad;
  1165.     float radToNearestTarget;
  1166.     struct targetInfo * nearestTarget;
  1167.  
  1168.     int aircraft;
  1169.     struct targetInfo * temptarget;
  1170.     struct monsterInfo * nearestMonster;
  1171.     
  1172.     float centerX,  centerZ;
  1173.     float nearAngle;
  1174.     
  1175.     
  1176.     int targetCounter, targetc;
  1177.     float targetxs[MAXTARGETS+1];
  1178.     float targetzs[MAXTARGETS+1];
  1179.     struct targetInfo * targetinfs[MAXTARGETS+1];
  1180.  
  1181.     /****************************************/
  1182.     /* move targets into quick access array */
  1183.     /****************************************/
  1184.  
  1185.     targetCounter = 0;
  1186.     for(temptarget = targets->next;temptarget != NULL;temptarget = temptarget->next)
  1187.         {
  1188.         targetxs[targetCounter]     = temptarget->x;
  1189.         targetzs[targetCounter]     = temptarget->z;
  1190.         targetinfs[targetCounter]   = temptarget;
  1191.         targetCounter++;
  1192.         }
  1193.     
  1194.     centerX     = 0;
  1195.     centerZ     = 0;
  1196.     
  1197.     maserOn     = 0;
  1198.     energyLoss  = 0;
  1199.  
  1200.     temptank    = allTanks;
  1201.  
  1202.     while(temptank->next != NULL)
  1203.         {
  1204.         ttank = temptank->next;
  1205.         ttank->count -= 1;
  1206.  
  1207.         tankx = ttank->x;
  1208.         tankz = ttank->z;
  1209.         tanktype = ttank->type;
  1210.  
  1211.         radToNearestTarget = 10000;
  1212.         nearestTarget = NULL;
  1213.  
  1214.         /************************************************/
  1215.         /* need to compute radius to the nearest target */
  1216.         /************************************************/
  1217.                 
  1218.         for(targetc = 0; targetc < targetCounter; targetc++)
  1219.             {
  1220.             rad = sqrt((tankx-targetxs[targetc]) * (tankx-targetxs[targetc]) + (tankz-targetzs[targetc]) * (tankz-targetzs[targetc]));
  1221.             if (rad < radToNearestTarget)
  1222.                 {
  1223.                 radToNearestTarget  = rad;
  1224.                 nearestTarget       = targetinfs[targetc];
  1225.                 nearestMonster      = &(nearestTarget->monster);
  1226.                 centerX             = nearestTarget->x;
  1227.                 centerZ             = nearestTarget->z;
  1228.                 }
  1229.             }
  1230.  
  1231.         /**********************************************/
  1232.         /* need to compute radius to player's monster */
  1233.         /**********************************************/
  1234.  
  1235.         rad = sqrt(tankx * tankx + tankz * tankz);
  1236.  
  1237.         if (rad < radToNearestTarget)
  1238.             {
  1239.             radToNearestTarget  = rad;
  1240.             nearestTarget       = NULL;
  1241.             nearestMonster      = m;
  1242.             centerX             = 0;
  1243.             centerZ             = 0;
  1244.             }
  1245.  
  1246.  
  1247.         ttank->rad = radToNearestTarget;
  1248.         ttank->goforit = nearestMonster;
  1249.  
  1250.  
  1251.         if (tanktype == MECHAG) /* mechaG shoots 5X as fast*/
  1252.             ttank->count -= 4;
  1253.  
  1254.         if (tanktype == CHH) /* 009CHH shoots 2X as fast*/
  1255.             ttank->count -= 1;
  1256.  
  1257.  
  1258.  
  1259.         if (ttank->z == 0)
  1260.             ttank->z = NEARZERO; 
  1261.  
  1262.         angle = computeAngle(tankz, centerZ, tankx, centerX);
  1263.  
  1264.         /**************************/
  1265.         /* deal with the aircraft */
  1266.         /**************************/
  1267.  
  1268.         if ((tanktype == AIRPLANE) || (tanktype == FIGHTER))
  1269.             aircraft = 1;
  1270.         else
  1271.             aircraft = 0;
  1272.             
  1273.         if ((!aircraft) || (aircraft && (ttank->rad > (PLANESIZE*2.5))))
  1274.             {
  1275.             nearAngle = angle;
  1276.             if (fabs(ttank->theta - (angle + TWOPI)) < fabs(ttank->theta - nearAngle))
  1277.                 nearAngle = angle + TWOPI;
  1278.             if (fabs(ttank->theta - (angle - TWOPI)) < fabs(ttank->theta - nearAngle))
  1279.                 nearAngle = angle - TWOPI;
  1280.                 
  1281.             ttank->theta = 0.8 * ttank->theta + 0.2 * nearAngle;
  1282.  
  1283.             if (ttank->theta < 0)
  1284.                 ttank->theta += TWOPI;
  1285.             else if (ttank->theta >= TWOPI)
  1286.                 ttank->theta -= TWOPI;
  1287.             }
  1288.  
  1289.  
  1290.         if (aircraft && (ttank->rad > (PLANESIZE*2.5)))
  1291.             ttank->count = 0;
  1292.             
  1293.             
  1294.         if ((tanktype == MASERTANK) || (tanktype == CHH) || (tanktype == MECHAG))
  1295.             {
  1296.             ttank->rand1 = randy(0.025);
  1297.             ttank->rand2 = randy(0.025);
  1298.             ttank->rand3 = randy(0.025);
  1299.             }
  1300.  
  1301.         /**********************************/    
  1302.         /* move vehicle                   */
  1303.         /**********************************/
  1304.  
  1305.         if ((ttank->rad > ttank->finalR) || (tanktype == AIRPLANE) || (tanktype == FIGHTER))
  1306.             {
  1307.  
  1308.             /**********************************/
  1309.             /* check for obstacles            */
  1310.             /**********************************/
  1311.  
  1312.             if ((tanktype == AIRPLANE) || (tanktype == FIGHTER))
  1313.                 blocked = 0;
  1314.             else
  1315.                 blocked = checkForBlock(ttank, ttank->rad,  ttank->theta,  ttank->y);
  1316.  
  1317.             if (!blocked)
  1318.                 {
  1319.                 Vplane = ttank->speed;
  1320.             
  1321.                 ttank->walking += 1;
  1322.             
  1323.                 ttank->zv = cos(ttank->theta) * Vplane;
  1324.                 ttank->xv = sin(ttank->theta) * Vplane;
  1325.  
  1326.                 ttank->x += ttank->xv;
  1327.                 ttank->z += ttank->zv;
  1328.                 }
  1329.             }
  1330.  
  1331.         if ((!dead) && (nearestMonster->monsterIsDead != 1) && (ttank->rad <= ttank->range) && (ttank->rad >= ttank->minrange))
  1332.         {
  1333.         /**********************************/
  1334.         /* mechaGoogelon firing           */
  1335.         /**********************************/
  1336.  
  1337.         if ((tanktype == MECHAG))
  1338.             {
  1339.             if ((ttank->count <= 0) && ((rand() % 5) == 0) && (nearestMonster->monsterIsDead != 1))
  1340.                 {                   
  1341.                 xv = - (ttank->x-centerX) / 12;
  1342.                 yv = ((height - bottom) * 0.5 + bottom - ttank->y) / 12;            
  1343.                 zv = - (ttank->z-centerZ) / 12;
  1344.         
  1345.                 addProjectile( ttank->x, ttank->y, ttank->z, PROJROCKET, 
  1346.                     xv, yv, zv, accuracy*0.33, NULL);
  1347.                 
  1348.                 ttank->count = firingDelay;
  1349.                 }
  1350.  
  1351.             if ((ttank->count <= 0) && (ttank->maserCount <= 0) && ((rand() % 10) == 0))
  1352.                 {
  1353.                 ttank->maserCount = 10 + (rand() % 5);
  1354.                 ttank->count = firingDelay;
  1355.                 }
  1356.             if ((ttank->maserCount > 0) && (ttank->rad <= ttank->range))
  1357.                 {
  1358.                 maserOn = 1;
  1359.                 ttank->maserCount -= 1;
  1360.                 
  1361.                 nearestMonster->energyRemaining -= 0.5;
  1362.                 }                                       
  1363.             }
  1364.  
  1365.         /**********************************/
  1366.         /* 009 CHH firing                 */
  1367.         /**********************************/
  1368.  
  1369.         if ((tanktype == CHH))
  1370.             {
  1371.             if ((ttank->count <= 0) && ((rand() % 5) == 0))
  1372.                 {
  1373.                 xv = - (ttank->x-centerX) / 12;
  1374.                 yv = ((height - bottom) * 0.5 + bottom - ttank->y) / 12;            
  1375.                 zv = - (ttank->z-centerZ) / 12;
  1376.         
  1377.                 addProjectile( ttank->x, ttank->y, ttank->z, PROJROCKET, 
  1378.                     xv, yv, zv, accuracy*0.5, NULL);
  1379.                 
  1380.                 ttank->count = firingDelay;
  1381.                 }
  1382.                 
  1383.             if ((ttank->count <= 0) && (ttank->maserCount <= 0) && ((rand() % 10) == 0))
  1384.                 {
  1385.                 ttank->maserCount = 10 + (rand() % 5);
  1386.                 ttank->count = firingDelay;
  1387.                 }
  1388.             if ((ttank->maserCount > 0) && (ttank->rad <= ttank->range))
  1389.                 {
  1390.                 maserOn = 1;
  1391.                 ttank->maserCount -= 1;                 
  1392.  
  1393.                 nearestMonster->energyRemaining -= 0.5;
  1394.                 }                       
  1395.             }
  1396.                     
  1397.         /**********************************/
  1398.         /* tank firing shell              */
  1399.         /**********************************/
  1400.  
  1401.         if ((tanktype == TANK) && (ttank->count <= 0) && ((rand() % 5) == 0))
  1402.             {
  1403.             ttank->count = firingDelay;
  1404.             
  1405.             if (monster == FLUTTER)
  1406.                 Vplane = sqrt(GRAVITY * ttank->rad) * 0.8071;
  1407.             else
  1408.                 Vplane = sqrt(GRAVITY * ttank->rad) * 0.7071;
  1409.             
  1410.             xv = sin(ttank->theta) * Vplane;
  1411.             zv = cos(ttank->theta) * Vplane;
  1412.  
  1413.             addProjectile( ttank->x, ttank->y + 0.15, ttank->z, PROJTANK, 
  1414.                 xv, Vplane, zv, accuracy, NULL);
  1415.             }
  1416.  
  1417.         /************************************/
  1418.         /* airplane 'dropping' bomb         */
  1419.         /************************************/
  1420.  
  1421.         if ((tanktype == AIRPLANE) && (mainCounter % 2))
  1422.             {                   
  1423.             addProjectile(ttank->x, ttank->y-0.1, ttank->z, PROJTANK,  0, 0, 0,  0, NULL);  
  1424.             }
  1425.  
  1426.         /************************************/
  1427.         /* fighter launchine missile        */
  1428.         /************************************/
  1429.  
  1430.         if ((tanktype == FIGHTER) && (ttank->count <= 0))
  1431.             {                   
  1432.             ttank->count = 1000; /* way bug number */
  1433.  
  1434.             xv = - (ttank->x-centerX) / 15;
  1435.             yv = ((height - bottom) * 0.5 + bottom - ttank->y) / 15;        
  1436.             zv = - (ttank->z-centerZ) / 15;
  1437.  
  1438.             addProjectile(ttank->x, ttank->y-0.1, ttank->z, PROJROCKET, xv, yv, zv, accuracy * 0.75, NULL);  
  1439.             addProjectile(ttank->x, ttank->y-0.1, ttank->z, PROJROCKET, xv, yv, zv, accuracy * 0.75, NULL);  
  1440.             addProjectile(ttank->x, ttank->y-0.1, ttank->z, PROJROCKET, xv, yv, zv, accuracy * 0.75, NULL);  
  1441.             addProjectile(ttank->x, ttank->y-0.1, ttank->z, PROJROCKET, xv, yv, zv, accuracy * 0.75, NULL);  
  1442.             }
  1443.         
  1444.         /**********************************/
  1445.         /* helo firing rocket             */
  1446.         /**********************************/
  1447.  
  1448.         if ((tanktype == HELO) && (ttank->count <= 0) && ((rand() % 5) == 0))
  1449.             {
  1450.             ttank->count = firingDelay;
  1451.  
  1452.             xv = - (ttank->x-centerX) / 15;
  1453.             yv = ((height - bottom) * 0.5 + bottom - ttank->y) / 15;        
  1454.             zv = - (ttank->z-centerZ) / 15;
  1455.  
  1456.             addProjectile( ttank->x, ttank->y-0.15, ttank->z, PROJROCKET, 
  1457.                 xv, yv, zv, accuracy*2, NULL);
  1458.             }
  1459.  
  1460.         /**********************************/
  1461.         /* launcher firing rocket         */
  1462.         /**********************************/
  1463.  
  1464.         if ((tanktype == LAUNCHER) && (ttank->count <= 0) && ((rand() % 5) == 0))
  1465.             {
  1466.             ttank->count = firingDelay/3;
  1467.  
  1468.             yv = ((height - bottom) * 0.5 + bottom - ttank->y) / 15;        
  1469.  
  1470.             xv = - (ttank->x-centerX) / 15;
  1471.             zv = - (ttank->z-centerZ) / 15;
  1472.  
  1473.             addProjectile( ttank->x, ttank->y+0.2, ttank->z, PROJROCKET, 
  1474.                 xv, yv, zv, accuracy*0.4, NULL);
  1475.             }
  1476.  
  1477.         /**********************************/
  1478.         /* hero firing maser / shells     */
  1479.         /**********************************/
  1480.  
  1481.         if ( (tanktype == HERO))
  1482.             {
  1483.             if ((ttank->count <= 0) && (ttank->maserCount <= 0) && ((rand() % 5) == 0))
  1484.                 {
  1485.                 ttank->maserCount = 40;
  1486.                 }
  1487.  
  1488.             if (ttank->maserCount > 0)
  1489.                 {
  1490.                 ttank->maserCount -= 1;
  1491.                 if (ttank->maserCount == 0)
  1492.                     ttank->count = firingDelay;
  1493.                         
  1494.                 if ((ttank->maserCount > 10) && (ttank->maserCount < 30) && (ttank->subtype == 1))
  1495.                     {
  1496.                     maserOn = 1;
  1497.  
  1498.                     nearestMonster->energyRemaining -= 0.5;
  1499.                     }
  1500.                     
  1501.                 if ((ttank->maserCount > 10) && (ttank->maserCount < 30) && (ttank->subtype == 0))
  1502.                     {
  1503.                     xv = - (ttank->x-centerX) / 15;
  1504.                     yv = ((height - bottom) *0.5 + bottom - ttank->y) / 15;         
  1505.                     zv = - (ttank->z-centerZ) / 15;
  1506.  
  1507.                     addProjectile(ttank->x, ttank->y + 0.5, ttank->z, PROJHERO, xv, yv, zv, accuracy, NULL);
  1508.                     addProjectile(ttank->x, ttank->y + 0.5, ttank->z, PROJHERO, xv, yv, zv, accuracy, NULL);
  1509.                     }
  1510.                 }
  1511.             }       
  1512.    
  1513.         /**********************************/
  1514.         /* tank firing maser              */
  1515.         /**********************************/
  1516.  
  1517.         if (tanktype == MASERTANK)
  1518.             {
  1519.             if (!client)
  1520.                 {
  1521.                 if ((ttank->count <= 0) && (ttank->maserCount <= 0) && ((rand() % 5) == 0))
  1522.                     {
  1523.                     ttank->maserCount = 20 + (rand() % 5);
  1524.                     }
  1525.                 }
  1526.                 
  1527.             if (ttank->maserCount > 0)
  1528.                 {           
  1529.                 maserOn = 1;
  1530.                 ttank->maserCount -= 1;
  1531.                 if (ttank->maserCount == 0)
  1532.                     ttank->count = firingDelay;
  1533.                         
  1534.                 nearestMonster->energyRemaining -= 0.3;
  1535.                 }
  1536.             }       
  1537.         }
  1538.                     
  1539.         /**********************************/
  1540.         /* tank being crushed             */
  1541.         /**********************************/
  1542.  
  1543.         if ((ttank->x <= (centerX+width)) && (ttank->z <= (centerZ+width)) &&
  1544.             (ttank->x >= (centerX-width)) && (ttank->z >= (centerZ-width)) &&
  1545.             (ttank->y <= height) && (ttank->y >= bottom) && (!dead))
  1546.             {
  1547.             nearestMonster->energyRemaining -= 0.75;
  1548.  
  1549.             ttank->damage -= 1;
  1550.  
  1551.             switch (tanktype)
  1552.                 {
  1553.                 case TANK:
  1554.                 case LAUNCHER:
  1555.                 case MASERTANK:
  1556.                 case AIRPLANE:
  1557.                 case FIGHTER:
  1558.                 case HELO:          addScore(tanktype, nearestMonster);
  1559.                                     break;
  1560.                                     
  1561.                 case MECHAG:        addScore(PARTIALM, nearestMonster);
  1562.                                     break;
  1563.                                     
  1564.                 case CHH:           addScore(PARTIALC, nearestMonster);
  1565.                                     break;
  1566.                                     
  1567.                 case HERO:          addScore(PARTIALH, nearestMonster);
  1568.                                     break;
  1569.                 }
  1570.             }
  1571.  
  1572.         /**********************************/
  1573.         /* tank is dead                   */
  1574.         /**********************************/
  1575.             
  1576.         if (ttank->damage <= 0)
  1577.             {
  1578.             addBoom(ttank->x, ttank->y, ttank->z, NULL);
  1579.                 
  1580.             killertank = temptank->next;
  1581.             temptank->next = temptank->next->next;
  1582.  
  1583.             switch (ttank->type)
  1584.                 {
  1585.                 case MECHAG:
  1586.                 case CHH:
  1587.                 case HERO:          addScore(ttank->type, NULL);
  1588.                 }
  1589.  
  1590.             if ((ttank->damage <= -99) || (tanktype == MECHAG) || (tanktype == CHH) || (tanktype == HERO) ||
  1591.                 (tanktype == AIRPLANE) || (tanktype == FIGHTER))
  1592.                 {
  1593.                 killertank->next = slag->next;
  1594.                 slag->next = killertank;
  1595.                 killertank->count = 1;
  1596.                 }
  1597.             else
  1598.                 {
  1599.                 afree(killertank, arena); 
  1600.  
  1601.                 } 
  1602.             }
  1603.         else 
  1604.             if (ttank->rad > 20 * PLANESIZE)
  1605.                 {
  1606.                 killertank = temptank->next;
  1607.                 temptank->next = temptank->next->next;
  1608.                 afree(killertank, arena);  
  1609.  
  1610.                 }
  1611.             else
  1612.                 temptank = temptank->next;
  1613.         }   
  1614.  
  1615.     /**********************************************************/
  1616.     /* if some vehicle is firing a maser then do maser sound  */
  1617.     /**********************************************************/
  1618.         
  1619.     if (maserOn)
  1620.         doSound(TANKMASER);
  1621.     else
  1622.         soundKiller(TANKMASER);
  1623.     }
  1624.  
  1625. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1626. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1627. /* update all the vehicles in the process of dying               */
  1628. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1629.  
  1630. void updateSlagTanks(struct tank * allSlags)
  1631.     {
  1632.     int i, j, k;
  1633.     float x, y, z;
  1634.     float zv,  xv;
  1635.     float Vplane;
  1636.     int dead;
  1637.     struct tank *killertank, *ttank, *temptank;
  1638.     int boom1,  boom2;
  1639.     
  1640.     temptank = allSlags;
  1641.     
  1642.     while(temptank->next != NULL)
  1643.         {
  1644.         ttank = temptank->next;
  1645.         
  1646.         ttank->count += 1;
  1647.         
  1648.         dead = 0;
  1649.  
  1650.         if (ttank->z == 0)
  1651.             ttank->z = NEARZERO;
  1652.  
  1653.         if (((ttank->type == HELO) || (ttank->type == CHH)) && (ttank->y <= PLANEY+0.1))
  1654.             {
  1655.             addBoom(ttank->x, PLANEY, ttank->z, NULL);
  1656.             dead = 1;
  1657.             }
  1658.  
  1659.         if (((ttank->type == HELO) || (ttank->type == CHH) || (ttank->type == AIRPLANE) || (ttank->type == FIGHTER)) && (ttank->y > PLANEY))
  1660.             {
  1661.             ttank->y -= 0.04;
  1662.             }
  1663.                     
  1664.         if ((ttank->type == AIRPLANE) || (ttank->type == FIGHTER))
  1665.             {
  1666.             ttank->x += sin(ttank->theta) * TANKV;
  1667.             ttank->z += cos(ttank->theta) * TANKV;
  1668.  
  1669.             if (ttank->count > 5)
  1670.                 dead = 1;
  1671.             }
  1672.             
  1673.             
  1674.         if ((ttank->type != HELO) && (ttank->type != CHH) && (ttank->type != AIRPLANE)
  1675.         && (ttank->type != FIGHTER) && (ttank->count >= 40))
  1676.             {
  1677.             dead = 1;
  1678.             }
  1679.             
  1680.         x = ttank->x;
  1681.         y = ttank->y;
  1682.         z = ttank->z;
  1683.             
  1684.         if (ttank->count % 2)
  1685.             {
  1686.             switch(ttank->type){
  1687.                 case MECHAG:    addBoom(x + randy(0.15), y + (rand() % 1000) / 1000.0 - 0.4, 
  1688.                                 z + randy(0.15), NULL);
  1689.                                 break;
  1690.                 case AIRPLANE:
  1691.                 case FIGHTER:
  1692.                 case CHH:       addBoom(x + randy(0.25), y + randy(0.25), z + randy(0.25), NULL);
  1693.                                 break;
  1694.                 }
  1695.             }
  1696.  
  1697.                     
  1698.         if (((ttank->type == AIRPLANE) || (ttank->type == FIGHTER)) && (ttank->count >= 5))
  1699.             {
  1700.             Vplane = sqrt(GRAVITY * 1.5) * 0.7071;
  1701.                         
  1702.                 for (i=-1;i<2;i++)
  1703.                     for (j=-1;j<2;j++)
  1704.                         for (k=-1;k<2;k++)
  1705.                             {
  1706.                             if ((rand() % 100) < 30)
  1707.                                 {
  1708.                                 zv = cos((rand() % 100) * 0.0628) * Vplane;
  1709.                                 xv = sin((rand() % 100) * 0.0628) * Vplane;
  1710.         
  1711.                                 addProjectile(x+i*0.2, y+(j*0.3), z+k*0.2, PROJTANK, 
  1712.                                             xv,  Vplane,  zv, 75, NULL);
  1713.                                 }
  1714.                             }
  1715.             }
  1716.  
  1717.         if ((ttank->type == HERO) && (ttank->count >= 40))
  1718.             {
  1719.             Vplane = sqrt(GRAVITY * 1.5) * 0.7071;
  1720.             
  1721.                 for (i=-1;i<2;i++)
  1722.                     for (j=-1;j<2;j++)
  1723.                         for (k=-1;k<2;k++)
  1724.                             {
  1725.                             zv = cos((rand() % 100) * 0.0628) * Vplane;
  1726.                             xv = sin((rand() % 100) * 0.0628) * Vplane;
  1727.         
  1728.                             if (ttank->subtype == 1)
  1729.                                 {
  1730.                                 boom1 = rand() % 3;
  1731.                                 boom2 = rand() % 3;
  1732.                                 }
  1733.                             else
  1734.                                 {
  1735.                                 boom1 = PROJTANK;
  1736.                                 boom2 = PROJHERO;
  1737.                                 }
  1738.                             
  1739.                             addProjectile(x+i*0.2, y+(j*0.3)+0.1, z+k*0.2, boom1, 
  1740.                                             xv,  Vplane,  zv, 75, NULL);
  1741.                             zv = cos(rand()%100*0.0628) * Vplane;
  1742.                             xv = sin(rand()%100*0.0628) * Vplane;
  1743.         
  1744.                             addProjectile(x+i*0.2, y+(j*0.3)+0.1, z+k*0.2, boom2, 
  1745.                                             xv,  Vplane,  zv, 75, NULL);
  1746.                             }
  1747.             }
  1748.  
  1749.         if ((ttank->type == MECHAG) && (ttank->count >= 40))
  1750.             {
  1751.             Vplane = sqrt(GRAVITY * 1.5) * 1.4;
  1752.             
  1753.                 for (i=-1;i<2;i++)
  1754.                     for (j=-1;j<2;j++)
  1755.                         for (k=-1;k<2;k++)
  1756.                             {
  1757.                             zv = cos((rand() % 100) * 0.0628) * Vplane;
  1758.                             xv = sin((rand() % 100) * 0.0628) * Vplane;
  1759.         
  1760.                             addProjectile(x+i*0.2, y+(j*0.3)+.1, z+k*0.2, PROJTANK, xv, Vplane, zv, 75, NULL);
  1761.                             }
  1762.             }
  1763.  
  1764.         if (dead)
  1765.             {
  1766.             killertank = temptank->next;
  1767.             temptank->next = temptank->next->next;
  1768.             afree(killertank, arena);
  1769.             }
  1770.         else
  1771.             temptank = temptank->next;
  1772.         }
  1773.     }
  1774.  
  1775. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1776. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1777. /* a new military vehicle is entering the game                   */
  1778. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  1779.  
  1780. void addNewTank(struct targetInfo * targets, float startx, float startz, int starttype, struct tank * tanklist, 
  1781.                 struct tree * treelist, int mainCounter, int firingDelay, struct monsterInfo * G)
  1782.     {
  1783.     float amount,amount2;
  1784.     float xabs,zabs;
  1785.     int attempts;
  1786.     int type,  side;
  1787.     int blocked;
  1788.     int howManyOfEach;
  1789.     float minX, minZ, maxX, maxZ;
  1790.     float ttankx, ttankz;
  1791.     struct targetInfo * temptarget;
  1792.     char newtype;
  1793.  
  1794.     struct targetInfo * nearestTarget;
  1795.     float radToNearestTarget;
  1796.     struct monsterInfo * nearestMonster;
  1797.     float centerX, centerZ;
  1798.     float rad;
  1799.     
  1800.     struct tank * temptank,  *ttank;
  1801.     struct tree * temptree;
  1802.         
  1803.     /*********************************/
  1804.     /* decide on type of vehicle     */
  1805.     /*********************************/
  1806.  
  1807. /* disable the adding of vehicles in networked games */
  1808.  
  1809. if (netUp || client)
  1810.     return;
  1811.  
  1812.  
  1813. if ((starttype != -1) && (netUp || client))
  1814.     return;
  1815.     
  1816.     type = rand() % 100;
  1817.  
  1818. if (netUp)
  1819.     {
  1820.     if (type > 50)
  1821.         newtype = MASERTANK;
  1822.     }
  1823. else
  1824.     {
  1825.     if ((type < 28) && (mainCounter  > 750))
  1826.         newtype = MASERTANK;
  1827.     else if ((type >= 28) && (type < 45))
  1828.         newtype = HELO;
  1829.     else if ((type >= 45) && (type < 60))
  1830.         newtype = LAUNCHER;
  1831.     else if ((type >= 60) && (type < 65) && (mainCounter  > 1000))
  1832.         newtype = AIRPLANE;
  1833.     else if ((type >= 65) && (type < 70) && (mainCounter  > 750))
  1834.         newtype = FIGHTER;
  1835.     else if ((type >= 90) && (type < 92) && (mainCounter  > 3000))
  1836.         newtype = HERO;
  1837.     else if ((type >= 92) && (type < 97) && (mainCounter  > 2000))
  1838.         newtype = CHH;
  1839.     else if ((type >= 97) && (mainCounter  > 1250))
  1840.         newtype = MECHAG;
  1841.     else
  1842.         newtype = TANK;
  1843.     }
  1844.     
  1845. if ((!netUp) || (newtype == MASERTANK))
  1846. {
  1847.     /***************************************************************/
  1848.     /* ensure max of 1 bomber, 2 mechagoogelons, 2 heros on screen */
  1849.     /***************************************************************/
  1850.             
  1851.     howManyOfEach = 0;
  1852.  
  1853.     if ((newtype == AIRPLANE) || (newtype == FIGHTER) || (newtype == MECHAG) || (newtype == HERO))
  1854.         {
  1855.         for(ttank = tanklist->next; ttank != NULL; ttank = ttank->next)
  1856.             if (ttank->type == newtype)
  1857.                 howManyOfEach += 1;
  1858.                         
  1859.         if ((((newtype == AIRPLANE) || (newtype == FIGHTER))  && (howManyOfEach >= 1))
  1860.         || ((newtype != AIRPLANE) && (newtype != FIGHTER) && (howManyOfEach >= 2)))
  1861.             newtype = TANK;
  1862.         }
  1863.  
  1864.     /************************************/
  1865.     /* choose where vehicle will appear */
  1866.     /************************************/
  1867.  
  1868.     maxX = 0;
  1869.     maxZ = 0;
  1870.     minX = 0;
  1871.     minZ = 0;
  1872.  
  1873.  
  1874.     for(temptarget = targets->next;temptarget != NULL;temptarget = temptarget->next)
  1875.         {
  1876.         if (temptarget->x > maxX)
  1877.             maxX = temptarget->x;
  1878.         if (temptarget->x < minX)
  1879.             minX = temptarget->x;
  1880.         if (temptarget->z > maxZ)
  1881.             maxZ = temptarget->z;
  1882.         if (temptarget->z < minZ)
  1883.             minZ = temptarget->z;
  1884.         }
  1885.  
  1886.         maxX += (PLANESIZE+1);
  1887.         maxZ += (PLANESIZE+1);
  1888.         minX -= (PLANESIZE+1);
  1889.         minZ -= (PLANESIZE+1);
  1890.  
  1891.         if (fabs(maxX) > fabs(minX))
  1892.             xabs = fabs(maxX);
  1893.         else
  1894.             xabs = fabs(minX);
  1895.  
  1896.  
  1897.         if (fabs(maxZ) > fabs(minZ))
  1898.             zabs = fabs(maxZ);
  1899.         else
  1900.             zabs = fabs(minZ);
  1901.  
  1902.  
  1903.     blocked = 1;
  1904.     attempts = 0;
  1905.  
  1906.     temptank = (struct tank *) amalloc(sizeTank, arena);
  1907.     
  1908.     if (temptank != NULL)
  1909.         {
  1910.         while ((blocked) && (attempts < 1000))
  1911.             {
  1912.             attempts += 1;
  1913.             side = rand() % 4; 
  1914.             amount = randy(xabs);
  1915.             amount2 = randy(zabs);
  1916.         
  1917.             switch(side)
  1918.                 {
  1919.                 case 0: temptank->x = amount;
  1920.                         temptank->z = minZ;
  1921.                         break;
  1922.  
  1923.                 case 1: temptank->z = amount2;
  1924.                         temptank->x = minX;
  1925.                         break;
  1926.  
  1927.                 case 2: temptank->x = amount;
  1928.                         temptank->z = maxZ;
  1929.                         break;
  1930.  
  1931.                 case 3: temptank->z = amount2;
  1932.                         temptank->x = maxX;
  1933.                         break;
  1934.                 }
  1935.         
  1936.             temptank->y = PLANEY;
  1937.             
  1938.             if (newtype == HERO)
  1939.                 {
  1940.                 temptank->x /= (2+randy(0.5));
  1941.                 temptank->z /= (2+randy(0.5));              
  1942.                 }
  1943.         
  1944.             /***********************/
  1945.             /* check for obstacles */
  1946.             /***********************/
  1947.  
  1948.             ttankx = temptank->x;
  1949.             ttankz = temptank->z;
  1950.  
  1951.             /************************************************/
  1952.             /* need to compute radius to the nearest target */
  1953.             /************************************************/
  1954.  
  1955.             radToNearestTarget = 10000;
  1956.             nearestTarget = NULL;
  1957.                 
  1958.             for(temptarget = targets->next; temptarget != NULL; temptarget = temptarget->next)
  1959.                 {
  1960.                 rad = sqrt((ttankx - temptarget->x) * (ttankx - temptarget->x) + (ttankz - temptarget->z) * (ttankz - temptarget->z));
  1961.                 if (rad < radToNearestTarget)
  1962.                     {
  1963.                     radToNearestTarget  = rad;
  1964.                     nearestTarget       = temptarget;
  1965.                     nearestMonster      = &(nearestTarget->monster);
  1966.                     centerX             = nearestTarget->x;
  1967.                     centerZ             = nearestTarget->z;
  1968.                     }
  1969.                 }
  1970.     
  1971.             /**********************************************/
  1972.             /* need to compute radius to player's monster */
  1973.             /**********************************************/
  1974.     
  1975.             rad = sqrt(ttankx * ttankx + ttankz * ttankz);
  1976.     
  1977.             if (rad < radToNearestTarget)
  1978.                 {
  1979.                 radToNearestTarget  = rad;
  1980.                 nearestTarget       = NULL;
  1981.                 nearestMonster      = G;
  1982.                 centerX             = 0;
  1983.                 centerZ             = 0;
  1984.                 }
  1985.     
  1986.     
  1987.             temptank->rad = radToNearestTarget;
  1988.             temptank->goforit = nearestMonster;
  1989.     
  1990.             temptank->theta = computeAngle(ttankz, centerZ, ttankx, centerX);
  1991.     
  1992.             blocked = checkForBlock(temptank, temptank->rad, temptank->theta, temptank->y);
  1993.             
  1994.             if (rad > 2 * PLANESIZE)
  1995.                 blocked = 1;
  1996.         }
  1997.  
  1998.         temptank->goforit = NULL;
  1999.         
  2000.  
  2001.         /**************************************/
  2002.         /* set up specific vehicle attributes */
  2003.         /**************************************/
  2004.  
  2005.         if (attempts >= 1500)
  2006.             {
  2007.             showError("Nowhere to put a new vehicle");
  2008.             afree(temptank, arena);
  2009.             }
  2010.         else
  2011.             {
  2012.             temptank->finalR = (rand() % 1000) * 0.002 + 1.0;
  2013.             temptank->type = newtype;
  2014.             
  2015.             if (starttype != -1)
  2016.                 {
  2017.                 temptank->type = (char) starttype;
  2018.                 temptank->x = startx;
  2019.                 temptank->z = startz;
  2020.                 }
  2021.  
  2022.             temptank->count = firingDelay;
  2023.             temptank->maserCount = 0;
  2024.             temptank->walking = 0;
  2025.  
  2026.             temptank->number = currentTankNumber++;
  2027.             
  2028.             temptank->subtype = (char) (rand() % 2);
  2029.  
  2030.             switch (temptank->type)
  2031.                 {
  2032.                 case TANK:          temptank->range     = 6;
  2033.                                     temptank->damage    = 1;
  2034.                                     temptank->minrange  = 0.5;
  2035.                                     temptank->speed     = TANKV;
  2036.                                     break;
  2037.                                     
  2038.                 case LAUNCHER:      temptank->range     = 4;
  2039.                                     temptank->damage    = 1;
  2040.                                     temptank->minrange  = 0.5;
  2041.                                     temptank->speed     = 0.8 * TANKV;
  2042.                                     temptank->count     = firingDelay/3;
  2043.                                     break;
  2044.  
  2045.                 case MASERTANK:     temptank->range     = 3;
  2046.                                     temptank->damage    = 1;
  2047.                                     temptank->minrange  = 0.5;
  2048.                                     temptank->speed     = 1.2 * TANKV;
  2049.                                     break;
  2050.  
  2051.                 case HELO:          temptank->range     = 4;
  2052.                                     temptank->y         = PLANEY + 1.0 + randy(0.2);
  2053.                                     temptank->damage    = 1;
  2054.                                     temptank->minrange  = 0.5;
  2055.                                     temptank->speed     = 1.5 * TANKV;
  2056.                                     break;
  2057.                                     
  2058.                 case MECHAG:        temptank->range     = 4.5;
  2059.                                     temptank->y         = PLANEY +0.4;
  2060.                                     temptank->damage    = 50;
  2061.                                     temptank->minrange  = 0.5;
  2062.                                     temptank->speed     = TANKV;
  2063.                                     break;
  2064.                                     
  2065.                 case CHH:           temptank->range     = 4.5;
  2066.                                     temptank->y         = PLANEY + 1.0 + randy(0.2);
  2067.                                     temptank->damage    = 20;
  2068.                                     temptank->minrange  = 0.5;
  2069.                                     temptank->speed     = 1.2 * TANKV;
  2070.                                     break;
  2071.                                     
  2072.                 case HERO:          temptank->range     = 4;
  2073.                                     temptank->y         = PLANEY +0.58;
  2074.                                     temptank->damage    = 100;
  2075.                                     temptank->minrange  = 0.5;
  2076.                                     temptank->speed     = TANKV;
  2077.                                     
  2078.                                     temptree = (struct tree *) amalloc(sizeof(struct tree), arena);
  2079.                                     if (temptree != NULL)
  2080.                                         {
  2081.                                         temptree->x             = temptank->x;
  2082.                                         temptree->z             = temptank->z; 
  2083.                                         temptree->type          = 1;
  2084.                                         temptree->treeshape     = 33;
  2085.                                         temptree->y             = PLANEY;
  2086.                                         temptree->deathCount    = 0;        
  2087.                                         temptree->death2        = -1;       
  2088.                                         temptree->intact        = 1;        
  2089.                                         temptree->height        = buildingHeight(temptree->type, temptree->treeshape);
  2090.  
  2091.                                         temptree->next          = treelist->next;
  2092.                                         treelist->next          = temptree;
  2093.                                         }
  2094.                                     break;
  2095.                                     
  2096.                 case AIRPLANE:      temptank->range     = 1.5;
  2097.                                     temptank->y         = PLANEY +2.5 + randy(0.25);
  2098.                                     temptank->damage    = 1;
  2099.                                     temptank->minrange  = 0.0;
  2100.                                     temptank->speed     = 4 * TANKV;
  2101.                                     temptank->finalR    = -1;
  2102.                                     break;
  2103.  
  2104.                 case FIGHTER:       temptank->range     = 5;
  2105.                                     temptank->y         = PLANEY + 2.0 + randy(0.2);
  2106.                                     temptank->damage    = 1;
  2107.                                     temptank->minrange  = 4.5;
  2108.                                     temptank->speed     = 6 * TANKV;
  2109.                                     temptank->finalR    = -1;
  2110.                                     temptank->count = 0;
  2111.                                     break;
  2112.  
  2113.                 default:        showError("Bogus Vehicle Type! (addNewTank)");
  2114.                                 break;
  2115.                 }
  2116.              
  2117.             temptank->next = tanklist->next;
  2118.             tanklist->next = temptank;
  2119.             }
  2120.         }
  2121. }
  2122.     }
  2123.  
  2124. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2125. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2126. /* update all of the explosions                                  */
  2127. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2128.  
  2129. void updateBooms(struct boom * allBooms, struct tank * tanklist)
  2130.     {
  2131.     struct boom * bboom,  * killerb, *tempboom;   
  2132.     struct tank *temptank;
  2133.     int tanktype;
  2134.     
  2135.     tempboom = allBooms;
  2136.     
  2137.     while (tempboom->next != NULL)
  2138.         {
  2139.         bboom = tempboom->next;
  2140.         bboom->count += 1;
  2141.         
  2142.         /***********************/
  2143.         /* make some noise     */
  2144.         /***********************/
  2145.  
  2146.         if ((bboom->count == 2))
  2147.             doSound(EXPLOSION);
  2148.  
  2149.         /**********************************/
  2150.         /* check for another tank hit     */
  2151.         /**********************************/
  2152.  
  2153.         if ((bboom->count == 4))
  2154.             {    
  2155.             for(temptank = tanklist; temptank->next != NULL; temptank = temptank->next)
  2156.                 if (tankHit(temptank->next, bboom->x, bboom->y, bboom->z))
  2157.                     {
  2158.                     tanktype                = temptank->next->type;
  2159.                     temptank->next->damage -= 1;
  2160.                     switch (tanktype)
  2161.                         {
  2162.                         case TANK:
  2163.                         case LAUNCHER:
  2164.                         case MASERTANK:
  2165.                         case AIRPLANE:
  2166.                         case FIGHTER:
  2167.                         case HELO:          addScore(tanktype, bboom->mine);
  2168.                                             break;
  2169.                                             
  2170.                         case MECHAG:        addScore(PARTIALM, bboom->mine);
  2171.                                             break;
  2172.                                             
  2173.                         case CHH:           addScore(PARTIALC, bboom->mine);
  2174.                                             break;
  2175.                                             
  2176.                         case HERO:          addScore(PARTIALH, bboom->mine);
  2177.                                             break;
  2178.                         }
  2179.                     }
  2180.             }
  2181.  
  2182.         /*******************/
  2183.         /* remove boom     */
  2184.         /*******************/
  2185.             
  2186.         if (bboom->count >= 7)
  2187.             {
  2188.             killerb = tempboom->next;
  2189.             tempboom->next = tempboom->next->next;
  2190.             afree(killerb, arena);
  2191.             }
  2192.         else
  2193.             tempboom = tempboom->next;
  2194.         }
  2195.     }
  2196.  
  2197. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2198.  
  2199. void buildHillPart(struct tree unitHill, int shape, float x, float z)
  2200.     {
  2201.     struct tree * temptree;
  2202.  
  2203.     temptree = (struct tree *) amalloc(sizeof(struct tree), arena);
  2204.  
  2205.     if (temptree != NULL)
  2206.         {
  2207.         *temptree = unitHill;               
  2208.         temptree->treeshape = shape;
  2209.         temptree->x         = x;
  2210.         temptree->z         = z;
  2211.         temptree->height    = buildingHeight(temptree->type, temptree->treeshape);
  2212.         temptree->number    = treeID++;
  2213.     
  2214.         temptree->next      = treelist->next;
  2215.         treelist->next      = temptree;
  2216.         }
  2217.     }
  2218.  
  2219.  
  2220. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2221. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2222. /* reset everything for a new game                               */
  2223. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2224.  
  2225. void setPlayConditions()
  2226.     {
  2227.     struct boom * tempboom,  *tempboom2;
  2228.     struct tank * ttank,  *temptank;
  2229.     struct tree * ttree,  *temptree;
  2230.     struct projectile * killer,  *temp;
  2231.     struct targetInfo * ttarget, *temptarg;
  2232.  
  2233.     float x, z;
  2234.     FILE * roadFile;
  2235.     int type, shape;
  2236.     int buildingNumber;
  2237.  
  2238.     struct tree unitHill;
  2239.  
  2240.     unitHill.type           = 3;
  2241.     unitHill.y              = PLANEY;
  2242.     unitHill.deathCount     = 0;
  2243.     unitHill.death2         = -1;
  2244.     unitHill.intact         = 1;                
  2245.     
  2246.     moreThanOne = 0;
  2247.  
  2248. #ifndef MACVERSION
  2249.     setUnconnected();
  2250. #endif    
  2251.     /******************************/
  2252.     /* reset all the linked lists */
  2253.     /******************************/
  2254.  
  2255.     temptank = tanklist;
  2256.     while(temptank != NULL)
  2257.             {
  2258.             ttank = temptank;
  2259.             temptank= temptank->next;
  2260.             afree(ttank, arena);
  2261.             }
  2262.     
  2263.     tempboom = projectboom;
  2264.     while (tempboom != NULL)
  2265.             {
  2266.             tempboom2 = tempboom;
  2267.             tempboom = tempboom->next;
  2268.             afree(tempboom2, arena);
  2269.             }
  2270.  
  2271.     temp = projectFlight;
  2272.     while (temp != NULL)
  2273.             {
  2274.             killer = temp;
  2275.             temp = temp->next;
  2276.             afree(killer, arena);
  2277.             }
  2278.  
  2279.     temptank = slaglist;
  2280.     while(temptank != NULL)
  2281.             {
  2282.             ttank = temptank;
  2283.             temptank = temptank->next;
  2284.             afree(ttank, arena);
  2285.             }
  2286.  
  2287.     temptree = treelist;
  2288.     while(temptree != NULL)
  2289.             {
  2290.             ttree = temptree;
  2291.             temptree = temptree->next;
  2292.             afree(ttree, arena);
  2293.             }
  2294.  
  2295.     temptarg = targets;
  2296.     while(temptarg != NULL)
  2297.             {
  2298.             ttarget = temptarg;
  2299.             temptarg= temptarg->next;
  2300.             afree(ttarget, arena);
  2301.             }
  2302.  
  2303.  
  2304.     /******************************/
  2305.     /* set up the dummy head nodes*/
  2306.     /******************************/
  2307.  
  2308.     projectFlight = (struct projectile *) amalloc(sizeProjectile, arena);
  2309.     projectFlight->next = NULL;
  2310.  
  2311.     projectboom = (struct boom *) amalloc(sizeBoom, arena);
  2312.     projectboom->next = NULL;
  2313.  
  2314.     tanklist = (struct tank *) amalloc(sizeTank, arena);
  2315.     tanklist->next = NULL;
  2316.  
  2317.     slaglist = (struct tank *) amalloc(sizeTank, arena);
  2318.     slaglist->next = NULL;
  2319.  
  2320.     treelist = (struct tree *) amalloc(sizeof(struct tree), arena);
  2321.     treelist->next = NULL;
  2322.  
  2323.     targets = (struct targetInfo *) amalloc(sizeof(struct targetInfo), arena);
  2324.     targets->next = NULL;
  2325.  
  2326.     /************************************************************/
  2327.     /* read in data file of structures (trees, buildings, etc.) */
  2328.     /************************************************************/
  2329.  
  2330.     strcpy(fullPath, dataPath);
  2331.     strcat(fullPath, TREEFILE);
  2332.     roadFile = fopen(fullPath, "r");
  2333.     
  2334.     treeID = 0;
  2335.     
  2336.     if (roadFile == NULL)
  2337.         showError("Could not load in tree.data\n");
  2338.     else
  2339.         {
  2340.         do
  2341.             {
  2342.             temptree = (struct tree *) amalloc(sizeof(struct tree), arena);
  2343.             if (temptree != NULL)
  2344.                 {
  2345.                 fscanf(roadFile,  "%f %f %d %d ", &x, &z, &type, &shape);
  2346.                 
  2347.                 temptree->x                 = x;
  2348.                 temptree->z                 = z;
  2349.                 temptree->type              = (char) type;
  2350.                 temptree->treeshape         = (char) shape;
  2351.                 temptree->y                 = PLANEY;
  2352.                 temptree->deathCount        = 0;
  2353.                 temptree->death2            = -1;
  2354.                 temptree->intact            = 1;                
  2355.                 temptree->height            = buildingHeight(temptree->type, temptree->treeshape);
  2356.                 temptree->number            = treeID++;
  2357.  
  2358.                 if ((type == 1) && (shape == 31))
  2359.                     addNewTank(targets, x, z, 1, tanklist, treelist, mainCounter, firingDelay, &Googelon);
  2360.                 if ((type == 1) && (shape == 32))
  2361.                     addNewTank(targets, x, z, 2, tanklist, treelist, mainCounter, firingDelay, &Googelon);
  2362.  
  2363.                 if ((type == 3) && (shape == 13))
  2364.                     {
  2365.                     /* create all the parts of the unit-hill */
  2366.  
  2367.                     buildHillPart(unitHill, 0, x,     z);
  2368.                     buildHillPart(unitHill, 2, x-0.6, z);
  2369.                     buildHillPart(unitHill, 1, x,     z+0.6);
  2370.                     buildHillPart(unitHill, 4, x+0.6, z);
  2371.                     buildHillPart(unitHill, 3, x,     z-0.6);
  2372.  
  2373.                     buildHillPart(unitHill, 7, x-0.6, z-0.6);
  2374.                     buildHillPart(unitHill, 5, x+0.6, z+0.6);
  2375.                     buildHillPart(unitHill, 8, x+0.6, z-0.6);
  2376.  
  2377.                     *temptree = unitHill;                   
  2378.                     temptree->treeshape     = 6;
  2379.                     temptree->x             = x-0.6;
  2380.                     temptree->z             = z+0.6;
  2381.                     temptree->height        = buildingHeight(temptree->type, temptree->treeshape);
  2382.                     }
  2383.                 
  2384.                 temptree->next      = treelist->next;
  2385.                 treelist->next      = temptree;
  2386.                 }
  2387.             }
  2388.         while (x || z || type || shape);
  2389.         
  2390.         treelist->next = treelist->next->next;
  2391.         afree(temptree, arena);
  2392.  
  2393.         /**************************************************************************/
  2394.         /* eliminate all trees that have been destroyed already in a network game */
  2395.         /**************************************************************************/
  2396.  
  2397.         if (netUp)
  2398.             for (temptree = treelist->next; temptree != NULL; temptree = temptree->next)
  2399.                 for(buildingNumber=0; buildingNumber< buildingBoomSoFarCounter; buildingNumber++)
  2400.                     if (temptree->number == buildingBoomSoFar[buildingNumber])
  2401.                         temptree->intact = 0;
  2402.         
  2403.         fclose(roadFile);
  2404.         }
  2405.     
  2406.     /***********************************************/
  2407.     /* read in data file of prepositioned vehicles */
  2408.     /***********************************************/
  2409.  
  2410.     if (!netUp && !client)
  2411.         {
  2412.         strcpy(fullPath, dataPath);
  2413.         strcat(fullPath, TANKFILE);
  2414.         roadFile = fopen(fullPath, "r");
  2415.       
  2416.         if (roadFile == NULL)
  2417.             showError("Could not load in tank.data\n");
  2418.         else
  2419.             {
  2420.             do  {
  2421.                 fscanf(roadFile,  "%f %f %d", &x, &z, &type);
  2422.                 
  2423.                 if (x || z || type)
  2424.                     addNewTank(targets, x, z, type, tanklist, treelist, mainCounter, firingDelay, &Googelon);
  2425.                 }
  2426.             while (x || z || type);
  2427.             
  2428.             fclose(roadFile);
  2429.             }
  2430.         }
  2431.     
  2432.     /*********************************/
  2433.     /* reset general game parmeters  */
  2434.     /*********************************/
  2435.  
  2436.     accuracy                = STARTACCURACY;
  2437.     arrivalTime             = ARRIVALRATE;
  2438.     firingDelay             = STARTFIRINGDELAY;
  2439.     mainCounter             = 0;
  2440.  
  2441.     killtanks = killmtanks = killhelos = 0;
  2442.     killCHHs = killheros = killmechags = 0;
  2443.     killlaunchers = killfighters = killplanes = 0;
  2444.  
  2445.     xrot = xsaverot         = 300;
  2446.     yrot = ysaverot         = 0;
  2447.     
  2448.     globalxshift            = 0;
  2449.     globalzshift            = 0;
  2450.  
  2451.     if (!netUp && !client)
  2452.         buildingBoomSoFarCounter = 0;
  2453.  
  2454.     Googelon = resetMonsterParameters(Googelon);
  2455.     
  2456.  
  2457. /***********************************************************
  2458.  code to print out the state of the shared memory arena 
  2459.  
  2460.         {
  2461.         struct mallinfo mi;
  2462.         
  2463.         mi = amallinfo(arena);
  2464.         fprintf(stderr, "--------------------------------------------------------------------------------\n");
  2465.         fprintf(stderr, "%8d %8d %8d %8d %8d %8d %8d %8d %8d -start\n", 
  2466.             mi.arena, mi.ordblks, mi.smblks, mi.hblkhd,  mi.hblks, 
  2467.             mi.usmblks, mi.fsmblks, mi.uordblks, mi.fordblks);
  2468.         fprintf(stderr, "--------------------------------------------------------------------------------\n");
  2469.         fflush(stderr);
  2470.         }
  2471.         
  2472. ***********************************************************/
  2473. }
  2474.  
  2475.     
  2476. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2477.  
  2478. void addRandomTarget()
  2479.     {
  2480.     struct monsterInfo newMonster;
  2481.     struct targetInfo * nother,  * temp;
  2482.     int i, j, k;
  2483.     float Vplane;
  2484.  
  2485.     /**************************************/
  2486.     /* is there room for another monster? */
  2487.     /**************************************/
  2488.  
  2489.     for (i=0, temp=targets->next; temp != NULL; i++,temp=temp->next);
  2490.     
  2491.     if (i < MAXTARGETS)
  2492.         {
  2493.         moreThanOne = 1;
  2494.     
  2495.         /******************************/
  2496.         /* generate a random monster  */
  2497.         /******************************/
  2498.     
  2499.         newMonster.monster = rand() % 4;
  2500.     
  2501.         /************************************/
  2502.         /* reset general monster parmeters  */
  2503.         /************************************/
  2504.     
  2505.         newMonster = resetMonsterParameters(newMonster);
  2506.         
  2507.         newMonster.energyRemaining = MAXLIFE / 2;       
  2508.     
  2509.         nother = (struct targetInfo *) amalloc(sizeof(struct targetInfo), arena);
  2510.         
  2511.         if (nother != NULL)
  2512.             {
  2513.             nother->monster = newMonster;
  2514.  
  2515.             /********************************************/
  2516.             /* declare this is not a networked monster  */
  2517.             /********************************************/
  2518.             
  2519.             nother->net_clientFrom = COMPUTER_MONSTER;
  2520.          
  2521.             do
  2522.                 nother->x = rand() % (PLANESIZE-1);
  2523.             while (fabs(nother->x) < 2);
  2524.             
  2525.             do
  2526.                 nother->z = rand() % (PLANESIZE-1);
  2527.             while (fabs(nother->z) < 2);
  2528.          
  2529.             nother->next    = targets->next;
  2530.             targets->next   = nother;
  2531.             
  2532.             Vplane = sqrt(GRAVITY * 1.5) * 0.7071;
  2533.             
  2534.             for (i=-1;i<2;i++)
  2535.                 for (j=0;j<3;j++)
  2536.                     for (k=-1;k<2;k++)
  2537.                             if ((rand() % 100) < 75)
  2538.                                 {
  2539.                                 addProjectile( nother->x+i*.35, (newMonster.height * 0.5 + newMonster.bottom * 0.5)+(j*.35), nother->z+k*.35, 2, 
  2540.                                     sin(randy(PI)) * Vplane, Vplane, cos(randy(PI)) * Vplane, 75, &(nother->monster));
  2541.                                 addProjectile( nother->x+i*.35, (newMonster.height * 0.5 + newMonster.bottom * 0.5)+(j*.35), nother->z+k*.35, 2, 
  2542.                                     sin(randy(PI)) * Vplane, Vplane, cos(randy(PI)) * Vplane, 75, &(nother->monster));
  2543.                                 }
  2544.             }
  2545.         }
  2546.  
  2547.     }
  2548.  
  2549. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2550.  
  2551. void newPlayerName(char * newName)
  2552.         {
  2553.         sscanf(newName,"%s",playerName);
  2554.         }
  2555.  
  2556. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2557. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2558. /* initialize everything at the start of battalion               */
  2559. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  2560.  
  2561. void initialization()
  2562.     {
  2563.     struct passwd *passwd;
  2564.     struct tm* theTime;
  2565.     FILE * roadFile;
  2566.     FILE * hiScoreFile;
  2567.     float garb1, garb2;
  2568.     int i, garb3;
  2569.     GLint gdtmp;
  2570.     GLint tmp[4];
  2571.     GLenum type;    
  2572.     char textBuffer[80];
  2573.     char * dataPtr;
  2574.     char * playerPointer;
  2575.     char scoredataPath[MAXPATH];
  2576.     char garbage;
  2577.     
  2578.  
  2579.     /******************************/
  2580.     /* set up sone network stuff  */
  2581.     /******************************/
  2582.  
  2583. #ifndef MACVERSION
  2584.  
  2585.     setHostAddr("");
  2586.     setPortNumber(DEFAULT_PORT);
  2587.  
  2588.     setUnconnected();
  2589. #endif
  2590.  
  2591.     netUp                           = 0;
  2592.     client                          = 0;
  2593.  
  2594.     buildingBoomSoFarCounter        = 0;    
  2595.     buildingBoomThisFrameCounter    = 0;
  2596.     currentTankNumber               = 1;
  2597.     biggestTankNumberSent           = 0;
  2598.     
  2599.     totalCounter                    = 0;
  2600.  
  2601.     /************************************/
  2602.     /* set up memory arena              */
  2603.     /************************************/
  2604.  
  2605. #ifdef SGIVERSION
  2606.  
  2607.     sharedmem = calloc(1, ARENASIZE);
  2608.     arena = acreate(sharedmem, ARENASIZE, 0, NULL, NULL); 
  2609.     amallopt(M_FREEHD, 1, arena);
  2610.     amallopt(M_CLRONFREE, 0, arena);
  2611.     amallopt(M_MXFAST, 16, arena);
  2612.  
  2613. #endif
  2614.  
  2615.     sizeBoom        = sizeof(struct boom);
  2616.     sizeTank        = sizeof(struct tank);
  2617.     sizeProjectile  = sizeof(struct projectile);
  2618.  
  2619.     /************************************/
  2620.     /* set up the window                */
  2621.     /************************************/
  2622.   
  2623.     /* TK_INDIRECT gives me a 50% boost in speed! on a an indy */
  2624.     
  2625.     /* removing the depth buffer from this line has no effect */
  2626.     /* switching to TK_SINGLE almost works in Vector graphics mode - BIG speedup there */
  2627.  
  2628.     type = TK_INDIRECT | TK_DOUBLE /* TK_SINGLE*/ | TK_RGB| TK_DEPTH;
  2629.     tkInitDisplayMode(type);
  2630.  
  2631. #ifdef MESAVERSION
  2632.     tkInitPosition(-1, -1, 352, 275);
  2633. #else
  2634.     tkInitPosition(-1, -1, 640, 500);
  2635. #endif
  2636.  
  2637. #ifdef MESA_TK_VERSION
  2638.     tkIdleFunc(id);
  2639.     tkExposeFunc(reshape);
  2640.     tkReshapeFunc(reshape);
  2641.     tkKeyDownFunc(processKey);
  2642. #ifdef AMIGAVERSION
  2643.     tkKeyUpFunc(processKeyRelease);
  2644. #endif
  2645.     tkMouseDownFunc(MouseDown);
  2646.     tkMouseUpFunc(MouseUp);
  2647. #endif
  2648.  
  2649.     if (tkInitWindow("battalion") == GL_FALSE)
  2650.         {
  2651.         fprintf(stderr, "could not open a window\n");
  2652.         exit(1);
  2653.         }
  2654.  
  2655.     pointerGrab = 0;
  2656.  
  2657.     /************************************/
  2658.     /* get information on the player    */
  2659.     /************************************/
  2660.  
  2661.     strcpy(playerName, "Anonymous");
  2662.  
  2663. #ifdef AMIGAVERSION
  2664.     if (!(playerPointer = getenv("USER")))
  2665.         playerPointer = getenv("LOGNAME");
  2666. #else
  2667.     playerPointer = cuserid(NULL);
  2668.     if (playerPointer == NULL)
  2669.         playerPointer = getlogin();
  2670. #endif
  2671.  
  2672.     if (playerPointer != NULL)
  2673.         /*strcpy(playerName, playerPointer);*/
  2674.         
  2675.         /* this ensures the player name is a single word */
  2676.         sscanf(playerPointer,"%s",playerName);
  2677.         if (strlen(playerName) > 9)
  2678.                 playerName[9] = 0;
  2679.  
  2680. #if defined(MACVERSION) || defined(AMIGAVERSION)
  2681.     playerHome[0] = '\0';
  2682. #ifdef MACVERSION
  2683.     setPlayerName(playerName);
  2684. #endif
  2685. #else
  2686.  
  2687.     passwd = getpwuid(getuid());
  2688.     if (passwd != NULL && passwd->pw_dir != NULL && *(passwd->pw_dir) != '\0')
  2689.         {
  2690.         strcpy(playerHome, passwd->pw_dir);
  2691.         playerHome[strlen(playerHome)] = '\0';
  2692.         }
  2693.     else
  2694.         {
  2695.         playerHome[0] = '\0';
  2696.         }
  2697. #endif
  2698.  
  2699.     /************************************/
  2700.     /* set up the graphics              */
  2701.     /************************************/
  2702.  
  2703.     /* if line widths are integral Mesa chokes in a large window */
  2704.     glLineWidth(1.01);
  2705.  
  2706.     glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST); 
  2707.     glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST); 
  2708.     glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST); 
  2709.  
  2710.     glFogi(GL_FOG_MODE,  GL_LINEAR);
  2711.     
  2712.     glDisable(GL_POINT_SMOOTH);
  2713.     glDisable(GL_LINE_SMOOTH);
  2714.     glDisable(GL_POLYGON_SMOOTH);
  2715.  
  2716.     glDisable(GL_ALPHA_TEST);
  2717.     glDisable(GL_AUTO_NORMAL);
  2718.     glDisable(GL_BLEND);
  2719.     glDisable(GL_COLOR_MATERIAL);
  2720.     glDisable(GL_LIGHTING);
  2721.     glDisable(GL_LINE_STIPPLE);
  2722.     glDisable(GL_NORMALIZE);
  2723.     glDisable(GL_POLYGON_STIPPLE);
  2724.  
  2725.     glDisable(GL_FOG);
  2726.     
  2727.     glCullFace(GL_BACK);
  2728.     glEnable(GL_CULL_FACE);
  2729.  
  2730.  
  2731. /* this helps zbuffering in mesa */
  2732.  
  2733. #ifdef MESAVERSION
  2734.     glDepthRange(0,1);
  2735.     glDepthFunc(GL_LEQUAL);
  2736. #endif
  2737.  
  2738.  
  2739.     glPointSize(2);
  2740.     goToHighDetail();
  2741.     
  2742.     glMatrixMode(GL_MODELVIEW);
  2743.  
  2744.  
  2745.     glClearDepth(1);
  2746.     glClearColor(0, 0, 0, 1);
  2747.     
  2748.     glBlendFunc(GL_SRC_ALPHA,  GL_ONE_MINUS_SRC_ALPHA);
  2749.  
  2750.     glDrawBuffer(GL_BACK); 
  2751.     
  2752.      /**************************/
  2753.     /* stereo stuff           */
  2754.     /**************************/
  2755.  
  2756.         /* OGLXXX
  2757.          * getsize not supported -- See Window Manager
  2758.          * getsize(&windowSizeX, &windowSizeY);
  2759.          */
  2760.  
  2761.         /* OGLXXX
  2762.          * getorigin not supported -- See Window Manager
  2763.          * getorigin(&windowOriginX, &windowOriginY);
  2764.          */
  2765.  
  2766.         glGetIntegerv(GL_VIEWPORT, tmp);
  2767.         viewL=tmp[0];
  2768.         viewR=tmp[0]+tmp[2]-1;
  2769.    
  2770.         /* OGLXXX
  2771.          * getmonitor not supported
  2772.          * getmonitor()
  2773.          */
  2774.     monitorType = 0; /*THIS IS BAD*/
  2775.  
  2776.  
  2777.     monsterLookat =  makeMonsterLookat();
  2778.     overviewLookat =  makeOverviewLookat();
  2779.    
  2780.     /*************************/
  2781.     /* initialize indicators */
  2782.     /*************************/
  2783.     
  2784.     alone           = 0;
  2785.     noSound         = 0;
  2786.     turnSoundOff();
  2787.     turnMusicOff();
  2788.     no3D            = 0;
  2789.     mode3D          = 0;
  2790.     doBigClear      = 0;
  2791.     showOptions     = 0;
  2792.     backdrop        = 0;
  2793.     showframes      = 0;
  2794.     paused          = 0;
  2795.  
  2796. #ifdef MESAVERSION
  2797.     lod             = 0;
  2798. #else
  2799.     lod             = 1;
  2800. #endif
  2801.  
  2802. #ifdef DETAIL
  2803.     lod             = DETAIL;
  2804. #endif
  2805.  
  2806.     mode            = DEMOMODE;
  2807.     view            = OMNISCIENTVIEW;
  2808.     oldview         = 99;
  2809.     
  2810.     timePaused      = 0;
  2811.     time3d          = 0;
  2812.     timeSound       = 0;
  2813.     timeMusic       = 0;
  2814.     timeDetail      = 0;
  2815.     
  2816.     mapHeight       = 35;
  2817.  
  2818.     /************************************/
  2819.     /* initialize all the linked lists  */
  2820.     /************************************/
  2821.  
  2822.     projectFlight   = NULL;
  2823.     projectboom     = NULL;
  2824.     tanklist        = NULL;
  2825.     slaglist        = NULL;
  2826.     treelist        = NULL;
  2827.  
  2828.     roadSystem      = NULL;
  2829.     
  2830.     initSounds();
  2831.  
  2832.     /************************************/
  2833.     /* get the current date/time        */
  2834.     /************************************/
  2835.  
  2836.     beg = time(NULL);
  2837.     theTime = localtime(&beg);
  2838.  
  2839.     /*************************************/
  2840.     /* if its xmas use the xmas graphics */
  2841.     /*************************************/
  2842.     
  2843.     if ((theTime->tm_mday == 25) && (theTime->tm_mon == 11))
  2844.         itsChristmas = 1;
  2845.     else
  2846.         itsChristmas = 0;
  2847.  
  2848.    
  2849.     /**************************************/
  2850.     /* initialize random number generator */
  2851.     /**************************************/
  2852.  
  2853.     srand( (unsigned) beg);
  2854.  
  2855.      
  2856.     /************************************/
  2857.     /* check graphics hardware          */
  2858.     /************************************/
  2859.     
  2860.     glGetIntegerv(GL_DEPTH_BITS, &gdtmp);
  2861.     if (gdtmp == GL_FALSE)
  2862.         showError("Z-buffer not available on this machine");
  2863.  
  2864.     glGetIntegerv(GL_RED_BITS, &gdtmp);
  2865.     if (gdtmp == GL_FALSE)
  2866.         showError("Double buffered RGB not available on this machine");
  2867.  
  2868.     glGetIntegerv(GL_STEREO, &gdtmp);
  2869.     if (gdtmp == GL_FALSE)
  2870.         no3D = 1;
  2871.  
  2872.     /********************************************/
  2873.     /* find where all the data files are stored */
  2874.     /********************************************/
  2875.  
  2876.     roadFile = NULL;
  2877.  
  2878. #ifdef MACVERSION
  2879.         strcpy(dataPath, ":battalion.data:");
  2880.         strcpy(fullPath, dataPath);
  2881.         strcat(fullPath, "battalion.sho");
  2882.         roadFile = fopen(fullPath, "rb");       
  2883. #else
  2884.  
  2885.     dataPtr = getenv("BATTALIONDATADIR");
  2886.     if (dataPtr != NULL)
  2887.         {
  2888.         strcpy(dataPath, dataPtr);
  2889.         
  2890.         if (dataPath[strlen(dataPath)-1] != '/')
  2891.             strcat(dataPath, "/");
  2892.  
  2893.         strcpy(fullPath, dataPath);
  2894.         strcat(fullPath, "battalion.sho");
  2895.         roadFile = fopen(fullPath, "rb");
  2896.         }
  2897. #endif
  2898.         
  2899.     if (roadFile != NULL)
  2900.         {
  2901.         fclose(roadFile);
  2902.         }
  2903.     else
  2904.         {
  2905. /* since the Indizone version is missing Techs' sound we can't use this.
  2906.  
  2907.         roadFile = fopen("/usr/demos/IndiZone/.data/battalion/battalion.sho", "rb");
  2908.         if (roadFile != NULL)
  2909.             {
  2910.             strcpy(dataPath,  "/usr/demos/IndiZone/.data/battalion/");
  2911.             fclose(roadFile);
  2912.             }
  2913.         else
  2914. */
  2915.             {
  2916.             roadFile = fopen(DATADIR "/battalion.sho", "rb");
  2917.             if (roadFile != NULL)
  2918.                 {
  2919.                 strcpy(dataPath, DATADIR "/");
  2920.                 fclose(roadFile);
  2921.                 }
  2922.             else
  2923.                 showError("Could not find the data files\n");
  2924.             }
  2925.         }
  2926.           
  2927.     /************************************/
  2928.     /* build all the objects            */
  2929.     /************************************/
  2930.  
  2931.     makeObjects(dataPath);
  2932.  
  2933.     /************************************/
  2934.     /* read in data file of roads       */
  2935.     /************************************/
  2936.  
  2937.     strcpy(fullPath, dataPath);
  2938.         strcat(fullPath, ROADFILE);
  2939.  
  2940.     roadFile = fopen(fullPath, "r");
  2941.   
  2942.     if (roadFile == NULL)
  2943.         showError("Could not load in road.data\n");
  2944.     else
  2945.         {
  2946.  
  2947.         /* find out how many entries are in the road file */
  2948.  
  2949.         i = 0;
  2950.         do
  2951.             {
  2952.             fscanf(roadFile,  "%f %f %d", &garb1,  &garb2, &garb3);
  2953.             i += 1;
  2954.             }
  2955.         while (garb1 || garb2 || garb3);
  2956.         
  2957.         fclose(roadFile);
  2958.          
  2959.         roadSystem = (struct road *) acalloc(i, sizeof(struct road), arena);
  2960.         if (roadSystem == NULL)
  2961.             showError("Could not allocate array for road.data\n");
  2962.         else
  2963.             {
  2964.             roadSystem[i-1].type = NULLROAD;       
  2965.         
  2966.             roadFile = fopen(fullPath, "r");
  2967.             i = i - 2;
  2968.             for(; i >= 0; i--)
  2969.                 {
  2970.                 fscanf(roadFile,  "%f %f %d", &garb1,  &garb2, &garb3);
  2971.                 roadSystem[i].x = garb1;
  2972.                 roadSystem[i].y = garb2;
  2973.                 roadSystem[i].type = (char) garb3;
  2974.                 }
  2975.             fclose(roadFile);
  2976.             }
  2977.         }
  2978.  
  2979.     /***************************************/
  2980.     /* see if this machine can play sounds */
  2981.     /***************************************/
  2982.  
  2983.     checkSound(dataPath);
  2984.  
  2985.  
  2986.     /************************************/
  2987.     /* see if a high score file exists  */
  2988.     /* if not try and create one        */
  2989.     /************************************/
  2990.  
  2991.     multipleHighScores = 1;
  2992.     
  2993.     /* If BATTALIONSCOREUNIQUE is defined, only put the
  2994.        top entry for each user in the high score list.
  2995.      */
  2996.  
  2997.     if (getenv("BATTALIONSCOREUNIQUE"))
  2998.         {
  2999.         multipleHighScores = 0;
  3000.         }
  3001.  
  3002.     hiScoreFile = NULL;
  3003.  
  3004.     dataPtr = getenv("BATTALIONSCOREDIR");
  3005.     if (dataPtr != NULL)
  3006.         strcpy(scoredataPath, dataPtr);
  3007.     else
  3008. #ifndef AMIGAVERSION
  3009.         strcpy(scoredataPath, "/usr/tmp");
  3010. #else
  3011.         strcpy(scoredataPath, "RAM:T");
  3012. #endif
  3013.  
  3014.     if (scoredataPath[strlen(scoredataPath)-1] != '/')
  3015.         strcat(scoredataPath, "/");
  3016.     
  3017.     strcpy(scorefullPath, scoredataPath);
  3018.     
  3019. #ifdef MACVERSION
  3020. strcpy(scorefullPath,"");
  3021. #endif
  3022.     
  3023.     strcat(scorefullPath, "battalion_hiscore");
  3024.     hiScoreFile = fopen(scorefullPath, "r");
  3025.  
  3026.     if (hiScoreFile == NULL)
  3027.         {
  3028.         hiScoreFile = fopen(scorefullPath, "w");
  3029.         
  3030.         if (hiScoreFile == NULL)
  3031.             {
  3032.             sprintf(textBuffer, "Couldn't create high score file: %s", scorefullPath);
  3033.             showError(textBuffer);
  3034.             }
  3035.         else
  3036.             {
  3037.             for(i=0;i<12;i++)
  3038.                 fprintf(hiScoreFile, "-1 -\n");
  3039.                 
  3040.             G[0].number = G[1].number = G[2].number = -1;
  3041.             F[0].number = F[1].number = F[2].number = -1;
  3042.             V[0].number = V[1].number = V[2].number = -1;
  3043.             T[0].number = T[1].number = T[2].number = -1;
  3044.  
  3045.             G[0].name[0] = G[1].name[0] = G[2].name[0] = 0;
  3046.             F[0].name[0] = F[1].name[0] = F[2].name[0] = 0;
  3047.             V[0].name[0] = V[1].name[0] = V[2].name[0] = 0;
  3048.             T[0].name[0] = T[1].name[0] = T[2].name[0] = 0;
  3049.             
  3050.             fclose(hiScoreFile);
  3051.  
  3052. # ifdef SOLARIS
  3053.  
  3054.             /* Make hiscore file read/writeable for everyone */
  3055.             if (chmod(scorefullPath, 0666))
  3056.                 {
  3057.                 sprintf(textBuffer, "Couldn't change permission of high score file: %s", hiScoreFile);      
  3058.                 showError(textBuffer);
  3059.                 }
  3060. # endif
  3061.             }
  3062.         }
  3063.     else
  3064.         {       
  3065.         fscanf(hiScoreFile, "%d%c%s", &(G[0].number), &garbage, G[0].name);
  3066.         fscanf(hiScoreFile, "%d%c%s", &(G[1].number), &garbage, G[1].name);
  3067.         fscanf(hiScoreFile, "%d%c%s", &(G[2].number), &garbage, G[2].name);
  3068.  
  3069.         fscanf(hiScoreFile, "%d%c%s", &(V[0].number), &garbage, V[0].name);
  3070.         fscanf(hiScoreFile, "%d%c%s", &(V[1].number), &garbage, V[1].name);
  3071.         fscanf(hiScoreFile, "%d%c%s", &(V[2].number), &garbage, V[2].name);
  3072.  
  3073.         fscanf(hiScoreFile, "%d%c%s", &(F[0].number), &garbage, F[0].name);
  3074.         fscanf(hiScoreFile, "%d%c%s", &(F[1].number), &garbage, F[1].name);
  3075.         fscanf(hiScoreFile, "%d%c%s", &(F[2].number), &garbage, F[2].name);
  3076.  
  3077.         fscanf(hiScoreFile, "%d%c%s", &(T[0].number), &garbage, T[0].name);
  3078.         fscanf(hiScoreFile, "%d%c%s", &(T[1].number), &garbage, T[1].name);
  3079.         fscanf(hiScoreFile, "%d%c%s", &(T[2].number), &garbage, T[2].name);
  3080.  
  3081.         fclose(hiScoreFile);
  3082.         }
  3083.  
  3084.  
  3085.     /************************************/
  3086.     /* pick a random monster to start   */
  3087.     /************************************/
  3088.  
  3089.     Googelon.monster = rand() % 4;
  3090.  
  3091.     }
  3092.  
  3093. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3094. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3095. /* go to 3d-video mode                                           */
  3096. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3097.  
  3098. void goto3d(void)
  3099.     {
  3100.     GLint gdtmp;
  3101.     
  3102.         /* OGLXXX
  3103.          * getsize not supported -- See Window Manager
  3104.          * getsize(&windowWide,  &windowTall);
  3105.          */
  3106.  
  3107.         /* OGLXXX
  3108.          * getorigin not supported -- See Window Manager
  3109.          * getorigin(&windowLeft,  &windowTop);
  3110.          */
  3111.  
  3112.         /* OGLXXX
  3113.          * getgdesc other posiblilties:
  3114.          *      glxGetConfig();
  3115.          *      glxGetCurrentContext();
  3116.          *      glxGetCurrentDrawable();
  3117.          * GLint gdtmp;
  3118.          */
  3119.     if ((glGetIntegerv(GL_STEREO, &gdtmp), gdtmp))
  3120.             {
  3121.         /* OGLXXX
  3122.          * setmonitor not supported
  3123.          * setmonitor(STR_RECT)
  3124.          */
  3125.  
  3126.         /* OGLXXX
  3127.          * getgdesc other posiblilties:
  3128.          *      glxGetConfig();
  3129.          *      glxGetCurrentContext();
  3130.          *      glxGetCurrentDrawable();
  3131.          * GLint gdtmp;
  3132.          * getgdesc other posiblilties:
  3133.          *      glxGetConfig();
  3134.          *      glxGetCurrentContext();
  3135.          *      glxGetCurrentDrawable();
  3136.          * GLint gdtmp;
  3137.          * see window manager
  3138.          * see window manager
  3139.          * prefposition not supported -- See Window Manager
  3140.          * prefposition(0, (glGetIntegerv(XXX_XPMAX, &gdtmp), gdtmp), 0, (glGetIntegerv(XXX_YPMAX, &gdtmp), gdtmp))
  3141.          */
  3142.  
  3143.             }
  3144.         /* OGLXXX
  3145.          * winconstraints not supported -- See Window Manager
  3146.          * winconstraints()
  3147.          */
  3148.         /* OGLXXX
  3149.          * setvaluator not supported -- See Events
  3150.          * setvaluator(MOUSEY, YMAXSTEREO/2, 0, YMAXSTEREO)
  3151.          */
  3152.  
  3153.     mode3D = 1;    
  3154.     doBigClear = 2; 
  3155.     }
  3156.        
  3157. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3158. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3159. /* go to 1d-video mode                                           */
  3160. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3161.  
  3162. void goto1d(void)
  3163.     {
  3164.     GLint gdtmp;
  3165.     
  3166.         /* OGLXXX
  3167.          * getgdesc other posiblilties:
  3168.          *      glxGetConfig();
  3169.          *      glxGetCurrentContext();
  3170.          *      glxGetCurrentDrawable();
  3171.          * GLint gdtmp;
  3172.          */
  3173.         if ((glGetIntegerv(GL_STEREO, &gdtmp), gdtmp))
  3174.         /* OGLXXX
  3175.          * setmonitor not supported
  3176.          * setmonitor((short) monitorType)
  3177.          */
  3178.  
  3179.         /* OGLXXX
  3180.          * winposition not supported -- See Window Manager
  3181.          * winposition(windowLeft, windowLeft + windowWide, windowTop, windowTop + windowTall)
  3182.          */
  3183.  
  3184.         /* OGLXXX
  3185.          * keepaspect not supported -- See Window Manager
  3186.          * keepaspect(1280, 1000)
  3187.          */
  3188.                             
  3189.         /* OGLXXX
  3190.          * winconstraints not supported -- See Window Manager
  3191.          * winconstraints()
  3192.          */
  3193.  
  3194.         /* OGLXXX
  3195.          * getgdesc other posiblilties:
  3196.          *      glxGetConfig();
  3197.          *      glxGetCurrentContext();
  3198.          *      glxGetCurrentDrawable();
  3199.          * GLint gdtmp;
  3200.          * see window manager
  3201.          * getvaluator not supported -- See Events
  3202.          * getvaluator(MOUSEY)
  3203.          * setvaluator not supported -- See Events
  3204.          * setvaluator(MOUSEY, (short) ???, 0, (short) (glGetIntegerv(XXX_YPMAX, &gdtmp), gdtmp))
  3205.          */
  3206.  
  3207.         mode3D = 0; 
  3208.     }
  3209.  
  3210.  
  3211. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3212. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3213. /* check the current location of the mouse in the window         */
  3214. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3215.  
  3216. void checkMouse()
  3217.     {
  3218.     int x, y;
  3219.     float offsetY;
  3220.  
  3221.     Googelon.monsterGo = Googelon.monsterBack = 0;
  3222.     
  3223.     if (Gfor)
  3224.         Googelon.monsterGo = 1;
  3225.  
  3226.     if (Gbak)
  3227.         Googelon.monsterBack = 1;
  3228.         
  3229.     if ((mode == PLAYMODE) && !paused)
  3230.         {
  3231.         tkGetMouseLoc(&x, &y);
  3232.                     
  3233.         offsetX = 2*(x / (float) viewW - 0.5);
  3234.         offsetY = 2*(y / (float) viewH - 0.5);
  3235.     
  3236.         
  3237.         if (offsetX > 1)
  3238.             offsetX = 1;
  3239.         else if (offsetX < -1)
  3240.             offsetX = -1;
  3241.     
  3242.         if (offsetY > 1)
  3243.             offsetY = 1;
  3244.         else if (offsetY < -1)
  3245.             offsetY = -1;
  3246.     
  3247.         if (fabs(offsetX) > 0.2)
  3248.             {
  3249.             Googelon.headHorzRotate -= (int) (offsetX * Googelon.xspeed);
  3250.             Googelon.monsterMoving = 1;
  3251.             }
  3252.             
  3253.         if (offsetY > 0.3)
  3254.             Googelon.monsterBack = 1;   
  3255.         else if (offsetY < -0.3)
  3256.             Googelon.monsterGo = 1;
  3257.         }
  3258.                 
  3259.         Gfor = 0;
  3260.         Gbak = 0;       
  3261.         Gturn = 0;
  3262.     }
  3263.  
  3264. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3265.     
  3266. GLenum mouseKey(int key, GLenum mask)
  3267.         {
  3268.         if ((mode == DEMOMODE) && (showOptions))
  3269.                 processKey(key,mask);
  3270.                 
  3271.         return GL_TRUE;
  3272.         }
  3273.  
  3274. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3275.     
  3276. GLenum MouseDown(int mouseX, int mouseY, GLenum button)
  3277.    {
  3278.     int xloc,yloc;
  3279.     
  3280.     xloc = mouseX;
  3281.     yloc = mouseY;
  3282.  
  3283.     if ((mode == PLAYMODE) && !paused && (button == TK_LEFTBUTTON))
  3284.  
  3285.         Googelon.beamOn = 1;
  3286.  
  3287.     return 0;
  3288.    }
  3289.  
  3290. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3291.  
  3292. GLenum MouseUp(int mouseX, int mouseY, GLenum button)
  3293.    {
  3294.     int xloc,yloc;
  3295.     
  3296.     xloc = mouseX;
  3297.     yloc = mouseY;
  3298.  
  3299.     if ((mode == PLAYMODE) && (button == TK_LEFTBUTTON))
  3300.         Googelon.beamOn = 0;
  3301.  
  3302.     return 0;
  3303.    }
  3304.    
  3305. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3306.  
  3307. void demoKeys(int key)
  3308.     {
  3309.     switch(key)
  3310.         {
  3311.         case TK_SPACE:  showOptions = 1;
  3312.                         break;
  3313.                         
  3314.         case TK_6:      mode = PLAYMODE;
  3315.                             showOptions = 0;
  3316.                             Googelon.monster = GOOGELON;
  3317.                             setPlayConditions();
  3318.                             break;
  3319.  
  3320.         case TK_7:      mode = PLAYMODE;
  3321.                             showOptions = 0;
  3322.                             Googelon.monster = TECHS;
  3323.                             setPlayConditions();
  3324.                             break;
  3325.  
  3326.         case TK_8:      mode = PLAYMODE;
  3327.                             showOptions = 0;
  3328.                             Googelon.monster = VAPOUR;
  3329.                             setPlayConditions();
  3330.                             break;
  3331.  
  3332.         case TK_9:      mode = PLAYMODE;
  3333.                             showOptions = 0;
  3334.                             Googelon.monster = FLUTTER;
  3335.                             setPlayConditions();
  3336.                             break;
  3337.                             
  3338.         }
  3339.     }
  3340.  
  3341. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3342.  
  3343. void doMonsterView()
  3344.         {
  3345.         view = MONSTERVIEW;
  3346.         
  3347. #ifdef MACVERSION
  3348.         updateMonsterMenu(imonsterview);
  3349. #endif
  3350.         }
  3351.  
  3352. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3353.  
  3354. void doOmniscientView()
  3355.         {
  3356.         view = OMNISCIENTVIEW;
  3357.         if (oldview != OMNISCIENTVIEW)
  3358.             {
  3359.             yrot = ysaverot;
  3360.             xrot = xsaverot;
  3361.             }
  3362.             
  3363. #ifdef MACVERSION
  3364.         updateMonsterMenu(ioverview);
  3365. #endif
  3366.         }
  3367.  
  3368. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3369.  
  3370. void doArmyView()
  3371.         {
  3372.         view = ARMYVIEW;
  3373.         
  3374. #ifdef MACVERSION
  3375.         updateMonsterMenu(iarmyview);
  3376. #endif
  3377.         }
  3378.  
  3379. void doMapView()
  3380.         {
  3381.         view = MAPVIEW;
  3382.         }
  3383.         
  3384. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3385.  
  3386. void playKeys(int key)
  3387.     {
  3388.     switch(key)
  3389.         {
  3390.         case TK_1:      doMonsterView();
  3391.                             break;
  3392.  
  3393.         case TK_2:      doOmniscientView();
  3394.                             break;
  3395.  
  3396.         case TK_3:      doArmyView();
  3397.                             break;
  3398.  
  3399.         case TK_4:      doMapView();
  3400.                             break;
  3401.  
  3402.         case TK_i:
  3403.         case TK_I:      xrot -= 8;
  3404.                             break;
  3405.                             
  3406.         case TK_j:
  3407.         case TK_J:      yrot += 8;
  3408.                             break;
  3409.                             
  3410.         case TK_k:
  3411.         case TK_K:      xrot += 8;
  3412.                             break;
  3413.                             
  3414.         case TK_l:
  3415.         case TK_L:      yrot -= 8;
  3416.                             break;
  3417.                             
  3418.         }
  3419.     }
  3420.  
  3421. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3422.  
  3423. void playNoPauseKeys(int key)
  3424.     {
  3425.     switch(key)
  3426.         {
  3427.         case TK_LEFT:   offsetX = -1/*-0.5*/;
  3428.                             Googelon.headHorzRotate -= (int) (offsetX * Googelon.xspeed);
  3429.                             Gturn = 1; 
  3430.                             break;
  3431.  
  3432.         case TK_RIGHT:  offsetX = 1/*0.5*/;
  3433.                             Googelon.headHorzRotate -= (int) (offsetX * Googelon.xspeed);
  3434.                             Gturn = 1;
  3435.                             break;
  3436.  
  3437.         case TK_UP:     Gfor = 1;
  3438.                             break;
  3439.  
  3440.         case TK_DOWN:   Gbak = 1;
  3441.                             break;
  3442.  
  3443.  
  3444.         case TK_a:
  3445.         case TK_A:      Googelon.headVertRotate += 15;
  3446.                             break;
  3447.  
  3448.         case TK_y:      /* for german keyboard */
  3449.         case TK_Y:
  3450.         case TK_z:
  3451.         case TK_Z:      Googelon.headVertRotate -= 15;
  3452.                             break;
  3453.         }
  3454.     }
  3455.  
  3456. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3457.  
  3458. GLenum processKey(int key, GLenum mask)
  3459.     {
  3460.     GLenum keyMask;
  3461.     
  3462.     keyMask = mask;
  3463.     
  3464.     if (mode == DEMOMODE)
  3465.         demoKeys(key);
  3466.             
  3467.     if ((mode == PLAYMODE) && !paused)
  3468.         playNoPauseKeys(key);
  3469.  
  3470.     if (mode == PLAYMODE)
  3471.          playKeys(key);
  3472.  
  3473.     switch(key)
  3474.         {
  3475.         case TK_CONTROL_L:
  3476. #ifndef MACVERSION
  3477.                             Googelon.beamOn = 1;
  3478. #else
  3479. /* temporary hack to get the control key to work on the mac since
  3480. I cant seem to get it to register a keyup for the control key */
  3481.                                 Googelon.beamOn = !     Googelon.beamOn;
  3482. #endif
  3483.                             break;
  3484.  
  3485.         case TK_p:
  3486.         case TK_P:          if (now > (timePaused+1))
  3487.                                 {
  3488.                                 paused = !paused;
  3489.                                 timePaused = now;
  3490.                                 }
  3491.                             break;
  3492.  
  3493.         case TK_m:
  3494.         case TK_M:          if (now > (timeMusic+1))
  3495.                                 {
  3496.                                 toggleMusic();
  3497.                                 timeMusic = now;
  3498.                                 }
  3499.                             break;
  3500.  
  3501.         case TK_s:
  3502.         case TK_S:          if (now > (timeSound+1))
  3503.                                 {
  3504.                                 toggleSound();
  3505.                                 timeSound = now;
  3506.                                 }
  3507.                             break;
  3508.  
  3509.         case TK_d:
  3510.         case TK_D:          if (now > (timeMusic+1))
  3511.                                 {
  3512.                                 lod++;
  3513.                                 if (lod > 2)
  3514.                                     lod = -1;
  3515.                                 timeDetail = now;
  3516.  
  3517. #ifdef MACVERSION                               
  3518.                                 switch (lod){
  3519.                                 case -1: updateDetailMenu(ivector); break;
  3520.                                 case  0: updateDetailMenu(ilowdetail); break;
  3521.                                 case  1: updateDetailMenu(imeddetail); break;
  3522.                                 case  2: updateDetailMenu(ihighdetail); break;
  3523.                                 }
  3524. #endif
  3525.                                 
  3526.                                 
  3527.                                  if (lod == -1)
  3528.                                     {
  3529.                                     goToLowDetail();
  3530.                                     }
  3531.                                 else
  3532.                                     {
  3533.                                     goToHighDetail();
  3534.                                     }
  3535.  
  3536.  
  3537.                                 }
  3538.                             break;
  3539.  
  3540. #ifdef SGIVERSION
  3541.         case TK_h:
  3542.         case TK_H:
  3543.                             if (mode3D)
  3544.                                 goto1d();
  3545.                             system("showcase -bfv battalion.data/battalion.sho");
  3546.                             break;
  3547. #endif
  3548.  
  3549.         case TK_g:
  3550.         case TK_G:      
  3551.         
  3552. #if !defined(MACVERSION) && !defined(AMIGAVERSION)
  3553.             if (pointerGrab)
  3554.                                 unGrabPointer();
  3555.                             else
  3556.                                 grabPointer();
  3557.                             pointerGrab = !pointerGrab;
  3558. #endif
  3559.                             break;
  3560.  
  3561.         case TK_q:
  3562.         case TK_Q:          if (mapHeight > 1)
  3563.                                 mapHeight -= 1;
  3564.                             break;
  3565.                             
  3566.         case TK_w:
  3567.         case TK_W:          if (mapHeight < 45)
  3568.                                 mapHeight += 1;
  3569.                             break;
  3570.  
  3571.         case TK_ESCAPE:     goto1d();
  3572. #if !defined(MACVERSION) && !defined(AMIGAVERSION)
  3573.                             if (pointerGrab)
  3574.                                 unGrabPointer();
  3575. #endif
  3576. #ifdef MESA_TK_VERSION
  3577.                             tkQuit();
  3578. #else
  3579.                             exit(0); 
  3580. #endif
  3581.         }
  3582.  
  3583.  
  3584.     return GL_TRUE;
  3585.     }
  3586.  
  3587. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3588. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3589. /* processKeyRelease                                             */
  3590. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3591.  
  3592. /* detects when the control key is released, to turn off the beam.
  3593. */
  3594.  
  3595. #ifndef AMIGAVERSION
  3596. GLenum processKeyRelease(int key)
  3597. #else
  3598. GLenum processKeyRelease(int key,GLenum mask)
  3599. #endif
  3600.     {
  3601. /* this seems to work on the 68K version but not the PPC version */
  3602.     
  3603.     if (key == TK_CONTROL_L)
  3604.         Googelon.beamOn = 0;
  3605.     return GL_TRUE;
  3606.     }
  3607.  
  3608.     
  3609. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3610. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3611. /* check the user's input                                        */
  3612. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3613. /*
  3614. void checkInput ()
  3615.     {
  3616.     int yes3D,  no3D,  yesDump;
  3617.     
  3618.     yes3D = no3D = yesDump = 0;
  3619.  
  3620.                         
  3621.  
  3622.                 case VKEY:      if (now > (time3d + 4))
  3623.                                     {
  3624.                                     if (mode3D)
  3625.                                         no3D = 1;
  3626.                                     else
  3627.                                         yes3D = 1;
  3628.                                     time3d = now;
  3629.                                     }
  3630.                                      do not put a qreset here! 
  3631.                                 break;
  3632.  
  3633.  
  3634.     if ((yes3D) && (!no3D))
  3635.         goto3d();
  3636.  
  3637.     if ((mode3D) && (no3D))
  3638.         goto1d();
  3639.         
  3640.     }
  3641. */
  3642.  
  3643. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3644. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3645. /* deal with a dead monster (not necessarily your monster)       */
  3646. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3647.  
  3648. void updateDeadMonster(float x, float z, struct monsterInfo * thaMonster)
  3649.     {
  3650.     float Vplane;
  3651.     int i, j, k;
  3652.  
  3653.     thaMonster->monsterIsDead = 1;
  3654.     
  3655.     if ((x==0) && (z==0)) /* its the player's monster that dies */
  3656.         view = OMNISCIENTVIEW;
  3657.     
  3658.     if (thaMonster->energyRemaining < 0)
  3659.         thaMonster->energyRemaining = 0;
  3660.  
  3661.     /************************/
  3662.     /* update dying monster */
  3663.     /************************/
  3664.  
  3665.     thaMonster->deadCount += 1;
  3666.     
  3667.     if (thaMonster->deadCount > 45)
  3668.         {
  3669.         thaMonster->deadCount = 45;
  3670.         thaMonster->timeDead += 1;
  3671.         }
  3672.     
  3673.     if (thaMonster->deadCount == 44)
  3674.         {
  3675.         if (thaMonster->monster != VAPOUR)
  3676.             {
  3677.             doSound(CRASH);
  3678.             }
  3679.             
  3680.         if (thaMonster->monster == FLUTTER)
  3681.             {
  3682.             addProjectile( x-0.2,  PLANEY+0.25,  z+0.2, 3, 0,  -0.001,  0, 10000, NULL);
  3683.             addProjectile( x+0.2,  PLANEY+0.25,  z+0.2, 3, 0,  -0.001,  0, 10000, NULL);
  3684.             addProjectile( x    ,  PLANEY+0.25,  z,     3, 0,  -0.001,  0, 10000, NULL);
  3685.             addProjectile( x-0.2,  PLANEY+0.25,  z-0.2, 3, 0,  -0.001,  0, 10000, NULL);
  3686.             addProjectile( x+0.2,  PLANEY+0.25,  z-0.2, 3, 0,  -0.001,  0, 10000, NULL);
  3687.             }
  3688.             
  3689.         if (thaMonster->monster == TECHS)
  3690.             {
  3691.             addProjectile( x-0.2,  PLANEY+0.2,  z+0.2, 3, 0,  -0.001,  0, 10000, NULL);
  3692.             addProjectile( x+0.2,  PLANEY+0.2,  z+0.2, 3, 0,  -0.001,  0, 10000, NULL);
  3693.             addProjectile( x    ,  PLANEY+0.2,  z,     3, 0,  -0.001,  0, 10000, NULL);
  3694.             addProjectile( x-0.2,  PLANEY+0.2,  z-0.2, 3, 0,  -0.001,  0, 10000, NULL);
  3695.             addProjectile( x+0.2,  PLANEY+0.2,  z-0.2, 3, 0,  -0.001,  0, 10000, NULL);
  3696.             
  3697.             Vplane = sqrt(GRAVITY * 1.5) * 0.7071;
  3698.             
  3699.                 for (i=-1;i<2;i++)
  3700.                     for (j=0;j<3;j++)
  3701.                         for (k=-1;k<2;k++)
  3702.                                 if ((rand() % 100) < 75)
  3703.                                     {
  3704.                                 addProjectile( x+i*.35, PLANEY+(j*.35)+.1, z+k*.35, 0, 
  3705.                                     sin(randy(PI)) * Vplane, Vplane, cos(randy(PI)) * Vplane, 75, NULL);
  3706.                                     }
  3707.             }
  3708.         }
  3709.     }
  3710.  
  3711. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3712. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3713. /* make the vapour 'vapourous'                                   */
  3714. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3715.  
  3716. void updateVapourLook(float a[MAXTRIBUTES][5], int monsterIsDead)
  3717.     {
  3718.     register int i, j;
  3719.     int again;
  3720.     
  3721.     for(i=0; i<MAXTRIBUTES; i++) /* needed not only for vapour - re options menu */
  3722.         {                   
  3723.         a[i][4] += 0.1;
  3724.                 
  3725.         if (a[i][4] >= 3.2)
  3726.             {
  3727.             a[i][4] = 0;                
  3728.             
  3729.             again = 1;
  3730.             while (again && !monsterIsDead)
  3731.                 {
  3732.                 a[i][0] =  randy(0.20);
  3733.                 a[i][1] =  PLANEY + 0.55 + randy(0.5);
  3734.                 a[i][2] =  randy(0.20);
  3735.                 
  3736.                 again = 0;
  3737.                 for(j=0; (j < MAXTRIBUTES) && !again; j++)
  3738.                     {
  3739.                     if ((i != j)
  3740.                         && (fabs(a[i][0] - a[j][0]) < 0.12)
  3741.                         && (fabs(a[i][1] - a[j][1]) < 0.12)
  3742.                         && (fabs(a[i][2] - a[j][2]) < 0.12))
  3743.                             again = 1;
  3744.                     }
  3745.                 }
  3746.             }
  3747.         a[i][3] = sin(a[i][4]) * 0.2;
  3748.         }
  3749.     }
  3750.  
  3751. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3752. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3753. /* update all of the other monsters currently in the game        */
  3754. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  3755.  
  3756. void updateTargets()
  3757.     {
  3758.     struct tree * temptree;
  3759.     struct tank * temptank;
  3760.     struct targetInfo * temptarget;
  3761.     struct targetInfo * temptarget2;
  3762.     struct monsterInfo  thaMonster;
  3763.     struct tree ttree;
  3764.     float mAngle, obsangle;
  3765.     float mRad, mAng;
  3766.     float tx, tz;
  3767.     float trad, rad;
  3768.     int blocked, nearAngle;
  3769.  
  3770.     for(temptarget = targets->next; temptarget != NULL; temptarget = temptarget->next)
  3771.         {
  3772.         thaMonster  = temptarget->monster;
  3773.         tx          = temptarget->x;
  3774.         tz          = temptarget->z;
  3775.  
  3776.     /************************************/
  3777.     /* deal with the networked monsters */
  3778.     /************************************/
  3779.     
  3780.     if (temptarget->net_clientFrom != COMPUTER_MONSTER)
  3781.         {
  3782.         thaMonster.energyRemaining      = temptarget->net_energyRemaining;
  3783.         thaMonster.beamOn               = temptarget->net_beamOn;
  3784.  
  3785.         nearAngle = temptarget->net_headHorzRotate;
  3786.         if (fabs(thaMonster.headHorzRotate - (temptarget->net_headHorzRotate + 3600)) < fabs(thaMonster.headHorzRotate - nearAngle))
  3787.             nearAngle = temptarget->net_headHorzRotate + 3600;
  3788.         if (fabs(thaMonster.headHorzRotate - (temptarget->net_headHorzRotate - 3600)) < fabs(thaMonster.headHorzRotate - nearAngle))
  3789.             nearAngle = temptarget->net_headHorzRotate - 3600;
  3790.  
  3791.         thaMonster.headHorzRotate       = 0.7 * thaMonster.headHorzRotate + 0.3 * nearAngle;
  3792.  
  3793.         thaMonster.headVertRotate       = 0.9 * thaMonster.headVertRotate + 0.1 * temptarget->net_headVertRotate;
  3794.         temptarget->x                   = 0.9 * temptarget->x + 0.1 * temptarget->net_x;
  3795.         temptarget->z                   = 0.9 * temptarget->z + 0.1 * temptarget->net_z;
  3796.  
  3797.         if (thaMonster.energyRemaining > 0)
  3798.             {
  3799.             thaMonster.rot1 = cos(thaMonster.moveCount) * 0.02;
  3800.             thaMonster.rot2 = sin(thaMonster.moveCount) * 0.05;
  3801.             }
  3802.         else
  3803.             {
  3804.             updateDeadMonster(temptarget->x, temptarget->z, &thaMonster);
  3805.             }
  3806.  
  3807.         thaMonster.monsterMoving = 1;
  3808.         thaMonster.moveCount += 1;
  3809.  
  3810.         updateVapourLook(thaMonster.a, thaMonster.monsterIsDead);
  3811.  
  3812.         /************************************************/
  3813.         /* update the weapons of the networked monsters */
  3814.         /************************************************/
  3815.  
  3816.         if (thaMonster.beamOn)
  3817.             switch (thaMonster.monster){
  3818.                 case GOOGELON:      updateBeam(&Googelon, targets, temptarget->x, temptarget->z, tanklist, allTreesEverywherePtrs,
  3819.                                             numTreesEverywhere, &thaMonster);
  3820.                                             
  3821.                                     thaMonster.energyRemaining -= 0.15;
  3822.                                     break;
  3823.                                     
  3824.                 case TECHS:         updateGun(temptarget->x, temptarget->z, thaMonster.headHorzRotate,
  3825.                                         thaMonster.headVertRotate, mainCounter, &(temptarget->monster));
  3826.                                     thaMonster.energyRemaining -= 0.09;
  3827.                                     break;
  3828.                                     
  3829.                 case VAPOUR:        updateVap(temptarget->x, temptarget->z, mainCounter, &(temptarget->monster));
  3830.                                     thaMonster.energyRemaining -= 0.1;
  3831.                                     break;
  3832.                                     
  3833.                 case FLUTTER:       updateBeam(&Googelon, targets, temptarget->x, temptarget->z, tanklist, allTreesEverywherePtrs,
  3834.                                             numTreesEverywhere, &thaMonster);
  3835.                                             
  3836.                                     thaMonster.energyRemaining -= 0.15;
  3837.                                     break;
  3838.                                     
  3839.                 default:            showError("Bogus Monster! (Update Targets)");
  3840.                                     break;
  3841.             } 
  3842.             
  3843.         temptarget->monster = thaMonster;
  3844.         }
  3845.     else
  3846.         {
  3847.         /**********************************************/
  3848.         /* deal with the computer controlled monsters */
  3849.         /**********************************************/
  3850.  
  3851.         if (thaMonster.monster == FLUTTER)
  3852.             {
  3853.             mRad = 1.2;
  3854.             mAng = 1.0;
  3855.             }
  3856.         else
  3857.             {
  3858.             mRad = 0.8;
  3859.             mAng = 0.8;
  3860.             }
  3861.         
  3862.         if (((thaMonster.monsterGo || thaMonster.monsterBack)) && (!thaMonster.monsterIsDead))
  3863.             {   
  3864.             thaMonster.monsterMoving = 1;
  3865.             
  3866.             thaMonster.energyRemaining -= thaMonster.moveCost; /* takes energy to move, not to turn */
  3867.             
  3868.             if (thaMonster.monsterGo)
  3869.                 mAngle = (thaMonster.headHorzRotate * BIG_DEG_TO_RAD);
  3870.             if (thaMonster.monsterBack)
  3871.                 mAngle = (thaMonster.headHorzRotate + 1800) * BIG_DEG_TO_RAD;
  3872.  
  3873.  
  3874.  
  3875.             blocked = 0;
  3876.             
  3877.             if (thaMonster.monster != VAPOUR)
  3878.                 {       
  3879.                 /****************************************************/
  3880.                 /* cant move through trees until they are destroyed */
  3881.                 /****************************************************/
  3882.         
  3883.                 temptree = treelist->next;
  3884.                 while ((temptree != NULL) && (!blocked))
  3885.                     {
  3886.                     ttree = *temptree;
  3887.  
  3888.                     trad = sqrt((ttree.x - tx) * (ttree.x - tx) + (ttree.z - tz) * (ttree.z - tz));
  3889.  
  3890.                     if (trad < mRad)
  3891.                         {
  3892.                         obsangle = computeAngle(ttree.z,  tz, ttree.x,  tx);
  3893.     
  3894.                         if (obsangle < 0)
  3895.                             obsangle += TWOPI;
  3896.                         
  3897.                         if ((fabs(mAngle + PI - obsangle) < mAng) || (fabs(mAngle - PI - obsangle) < mAng))
  3898.                                 {
  3899.                                 if (thaMonster.monster != FLUTTER)
  3900.                                     blocked = 1;
  3901.                                 else if ((buildingHeight(ttree.type, ttree.treeshape) > 0) ||
  3902.                                     ((ttree.type == 1) && (ttree.treeshape == 3) && (ttree.intact == 1)))
  3903.                                     blocked = 1;
  3904.                                 }
  3905.                         }
  3906.                         
  3907.                     temptree = temptree->next;
  3908.                     }
  3909.                     
  3910.                 /****************************************************/
  3911.                 /* cant move through tanks until they are destroyed */
  3912.                 /****************************************************/
  3913.         
  3914.                 temptank = tanklist->next;
  3915.                 while ((temptank != NULL) && !blocked)
  3916.                     {
  3917.  
  3918.                     trad = sqrt((temptank->x - tx) * (temptank->x - tx) + (temptank->z - tz) * (temptank->z - tz));
  3919.  
  3920.                     if (trad < thaMonster.width)
  3921.                         {
  3922.                         obsangle = computeAngle(temptank->z, tz, temptank->x, tx);
  3923.     
  3924.                         if (obsangle < 0)
  3925.                             obsangle += TWOPI;
  3926.                         
  3927.                         if ((fabs(mAngle + PI - obsangle) < .75) || (fabs(mAngle - PI - obsangle) < .75))
  3928.                             {
  3929.                             if ((temptank->y <= thaMonster.height) && (temptank->y >= thaMonster.bottom))
  3930.                                 blocked = 1;
  3931.                             if ((temptank->type == HERO) || (temptank->type == MECHAG))
  3932.                                 blocked = 1;
  3933.                             }
  3934.                         }
  3935.                         
  3936.                     temptank = temptank->next;
  3937.                     }
  3938.                 }
  3939.  
  3940.             /***********************************************************************************/
  3941.             /* cant move through other targets until they are destroyed or move out of the way */
  3942.             /***********************************************************************************/
  3943.     
  3944.             if (temptarget->monster.monster != VAPOUR)
  3945.                 {
  3946.                 temptarget2 = targets->next;
  3947.                 while ((temptarget2 != NULL) && (!blocked))
  3948.                     {
  3949.                     if ((temptarget2 != temptarget) && (temptarget2->monster.monster != VAPOUR))
  3950.                         {
  3951.                         rad = sqrt((temptarget2->x - tx) * (temptarget2->x - tx) + (temptarget2->z - tz) * (temptarget2->z - tz));
  3952.                         
  3953.                         if (rad < mRad)
  3954.                             {
  3955.                             obsangle = computeAngle(temptarget2->z, tz, temptarget2->x, tx);
  3956.             
  3957.                             if (obsangle < 0)
  3958.                                 obsangle += TWOPI;
  3959.                             
  3960.                             if ((fabs(mAngle + PI - obsangle) < mAng) || (fabs(mAngle - PI - obsangle) < mAng))
  3961.                                 blocked = 1;
  3962.                             }
  3963.                         }
  3964.                     temptarget2 = temptarget2->next;
  3965.                     }
  3966.             
  3967.                 /**************************************/
  3968.                 /* cant move through player's monster */
  3969.                 /**************************************/
  3970.         
  3971.                 rad = sqrt(tx * tx + tz * tz);
  3972.                 
  3973.                 if ((rad < mRad) && (Googelon.monster != VAPOUR))
  3974.                     {
  3975.                     obsangle = computeAngle(-temptarget->z, 0, -temptarget->x, 0);
  3976.                     
  3977.                     if (obsangle < 0)
  3978.                         obsangle += TWOPI;    
  3979.                     
  3980.                     if ((fabs(mAngle + PI - obsangle) < mAng) || (fabs(mAngle - PI - obsangle) < mAng))
  3981.                         blocked = 1;
  3982.                     }
  3983.                 }
  3984.  
  3985.             if (!blocked)
  3986.                 {
  3987.                 temptarget->z += cos(mAngle) * thaMonster.speed;
  3988.                 temptarget->x += sin(mAngle) * thaMonster.speed;
  3989.                 }
  3990.         }
  3991.  
  3992.         /**********************************/   
  3993.         /* update target Weapons          */
  3994.         /**********************************/
  3995.     
  3996.         if (thaMonster.beamOn)
  3997.             switch (thaMonster.monster){
  3998.                 case GOOGELON:      updateBeam(&Googelon, targets, temptarget->x, temptarget->z, tanklist, allTreesEverywherePtrs,
  3999.                                             numTreesEverywhere, &thaMonster);
  4000.                                             
  4001.                                     thaMonster.energyRemaining -= 0.15;
  4002.                                     break;
  4003.                                     
  4004.                 case TECHS:         updateGun(temptarget->x, temptarget->z, thaMonster.headHorzRotate,
  4005.                                         thaMonster.headVertRotate, mainCounter, &(temptarget->monster));
  4006.                                     thaMonster.energyRemaining -= 0.09;
  4007.                                     break;
  4008.                                     
  4009.                 case VAPOUR:        updateVap(temptarget->x, temptarget->z, mainCounter, &(temptarget->monster));
  4010.                                     thaMonster.energyRemaining -= 0.1;
  4011.                                     break;
  4012.                                     
  4013.                 case FLUTTER:       updateBeam(&Googelon, targets, temptarget->x, temptarget->z, tanklist, allTreesEverywherePtrs,
  4014.                                             numTreesEverywhere, &thaMonster);
  4015.                                             
  4016.                                     thaMonster.energyRemaining -= 0.15;
  4017.                                     break;
  4018.                                     
  4019.                 default:            showError("Bogus Monster! (Update Targets)");
  4020.                                     break;
  4021.             } 
  4022.  
  4023.         /********************************************/
  4024.         /* update the vapourness of a target vapour */
  4025.         /********************************************/
  4026.         
  4027.         if (thaMonster.monster == VAPOUR)
  4028.             updateVapourLook(thaMonster.a, thaMonster.monsterIsDead);
  4029.  
  4030.         /*****************/
  4031.         /* update energy */
  4032.         /*****************/
  4033.                 
  4034.         if (thaMonster.energyRemaining > 0)
  4035.             {
  4036.             thaMonster.energyRemaining += thaMonster.regenRate;
  4037.                     
  4038.             if (thaMonster.energyRemaining > MAXLIFE)
  4039.                 thaMonster.energyRemaining = MAXLIFE;
  4040.     
  4041.             thaMonster.rot1 = cos(thaMonster.moveCount) * 0.02;
  4042.             thaMonster.rot2 = sin(thaMonster.moveCount) * 0.05;
  4043.             }
  4044.         else
  4045.             {
  4046.             updateDeadMonster(temptarget->x, temptarget->z, &thaMonster);
  4047.             }
  4048.       
  4049.         if (thaMonster.monsterMoving)
  4050.             thaMonster.moveCount += 1;
  4051.  
  4052.             
  4053.         temptarget->monster = thaMonster;
  4054.         }
  4055.     }
  4056. }
  4057.     
  4058. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4059. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4060. /* update everything                                             */
  4061. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4062.  
  4063. void doUpdate()
  4064.     {
  4065.     struct boom * tempboom;
  4066.     struct tree * temptree;
  4067.     struct tank * temptank;
  4068.     struct targetInfo * temptarget;
  4069.     struct targetInfo * temptarg;
  4070.     struct projectile * temp;
  4071.     struct tree ttree;
  4072.     float rad;
  4073.     float mAngle, obsangle;
  4074.     float xv,  zv;
  4075.     float mRad, mAng;
  4076.     int blocked;
  4077.     
  4078.      
  4079.     /*************************************************/
  4080.     /* reclaim space from finished sounds            */
  4081.     /*************************************************/
  4082.     
  4083.    if (!noSound)
  4084.         {
  4085.         flushSounds();
  4086.  
  4087.         if (getMusicOn())
  4088.             doSound(MUSIC);
  4089.         else
  4090.             soundKiller(MUSIC);
  4091.         }
  4092.  
  4093.     /*************************************************/
  4094.     /* add another monster if the time is right      */
  4095.     /*************************************************/
  4096.  
  4097.     if ((!netUp) && (!client) && (!alone))
  4098.         {
  4099.         if (mode == DEMOMODE)
  4100.             {
  4101.             if ((mainCounter > 500) && ((mainCounter % 4000) ==  1500))
  4102.                 addRandomTarget();
  4103.             }
  4104.         else
  4105.             if ((mainCounter > 1000) && ((mainCounter % 9000) ==  8000))
  4106.                 addRandomTarget();
  4107.         }
  4108.         
  4109.     /*********************/
  4110.     /* add a new vehicle */
  4111.     /*********************/
  4112.  
  4113.     if (!client)
  4114.         {  
  4115.         if (((mainCounter % arrivalTime) == 0) && !Googelon.monsterIsDead)
  4116.             {
  4117.             addNewTank(targets, 0, 0, -1, tanklist, treelist, mainCounter, firingDelay, &Googelon);
  4118.             
  4119.             if ((mode == DEMOMODE) && !(rand() % 4) && (Googelon.moveCount >= 150))
  4120.                 view = (view + 1) % 3;
  4121.             }
  4122.         }
  4123.    
  4124.     /**********************************/
  4125.     /* monster on the move            */
  4126.     /**********************************/
  4127.  
  4128.     if (Googelon.monster == FLUTTER)
  4129.         {
  4130.         mRad = 1.2;
  4131.         mAng = 1.0;
  4132.         }
  4133.     else
  4134.         {
  4135.         mRad = 0.8;
  4136.         mAng = 0.8;
  4137.         }
  4138.   
  4139.     if (Googelon.monsterGo || Googelon.monsterBack)
  4140.         {       
  4141.         Googelon.monsterMoving = 1;
  4142.         
  4143.         Googelon.energyRemaining -= Googelon.moveCost; /* takes energy to move, not to turn */
  4144.         
  4145.         if (Googelon.monsterGo)
  4146.             mAngle = (Googelon.headHorzRotate * BIG_DEG_TO_RAD);
  4147.             
  4148.         if (Googelon.monsterBack)
  4149.             mAngle = (Googelon.headHorzRotate + 1800) * BIG_DEG_TO_RAD;
  4150.  
  4151.  
  4152.         blocked = 0;
  4153.         
  4154.         if (Googelon.monster != VAPOUR)
  4155.             {   
  4156.             /****************************************************/
  4157.             /* cant move through trees until they are destroyed */
  4158.             /****************************************************/
  4159.     
  4160.             temptree = treelist->next;
  4161.             while ((temptree != NULL) && (!blocked))
  4162.                 {
  4163.                 ttree = *temptree;
  4164.                 
  4165.                 if (ttree.rad < mRad)
  4166.                     {
  4167.                     obsangle = ttree.theta;
  4168.                     if (obsangle < 0)
  4169.                         obsangle += TWOPI;
  4170.                     
  4171.                     if ((fabs(mAngle + PI - obsangle) < mAng) || (fabs(mAngle - PI - obsangle) < mAng))
  4172.                         {
  4173.                         if (Googelon.monster != FLUTTER)
  4174.                             blocked = 1;
  4175.                         else if ((buildingHeight(ttree.type, ttree.treeshape) > 0) ||
  4176.                             ((ttree.type == 1) && (ttree.treeshape == 3) && (ttree.intact == 1)))
  4177.                             blocked = 1;
  4178.                         }
  4179.                     }
  4180.                     
  4181.                 temptree = temptree->next;
  4182.                 }
  4183.     
  4184.             /****************************************************/
  4185.             /* cant move through tanks until they are destroyed */
  4186.             /****************************************************/
  4187.     
  4188.             temptank = tanklist->next;
  4189.             while ((temptank != NULL) && !blocked)
  4190.                 {
  4191.                 if (temptank->rad < Googelon.width)
  4192.                     {
  4193.                     obsangle = temptank->theta;
  4194.                     if (obsangle < 0)
  4195.                         obsangle += TWOPI;
  4196.                     
  4197.                     if ((fabs(mAngle + PI - obsangle) < .75) || (fabs(mAngle - PI - obsangle) < .75))
  4198.                         {
  4199.                         if ((temptank->y <= Googelon.height) && (temptank->y >= Googelon.bottom))
  4200.                             blocked = 1;
  4201.                         if ((temptank->type == HERO) || (temptank->type == MECHAG))
  4202.                             blocked = 1;
  4203.                         }
  4204.                     }
  4205.                 temptank = temptank->next;
  4206.                 }
  4207.     
  4208.             /***********************************************************************************/
  4209.             /* cant move through other targets until they are destroyed or move out of the way */
  4210.             /***********************************************************************************/
  4211.     
  4212.             temptarget = targets->next;
  4213.             while ((temptarget != NULL) && (!blocked))
  4214.                 {
  4215.                 rad = sqrt(temptarget->x * temptarget->x + temptarget->z * temptarget->z);
  4216.     
  4217.                 if ((rad < mRad) && (temptarget->monster.monster != VAPOUR) && (temptarget->monster.monsterIsDead != 1))
  4218.                     {
  4219.                     obsangle = computeAngle(temptarget->z, 0, temptarget->x, 0);
  4220.                     
  4221.                     if (obsangle < 0)
  4222.                         obsangle += TWOPI;
  4223.                     
  4224.                     if ((fabs(mAngle + PI - obsangle) < mAng) || (fabs(mAngle - PI - obsangle) < mAng))
  4225.                             blocked = 1;
  4226.                     }
  4227.                     
  4228.                 temptarget = temptarget->next;
  4229.                 }
  4230.             }
  4231.  
  4232.         /***************************************/
  4233.         /* update position of everything else  */
  4234.         /***************************************/
  4235.         
  4236.         if (!blocked)
  4237.             {
  4238.             zv = cos(mAngle) * Googelon.speed;
  4239.             xv = sin(mAngle) * Googelon.speed;
  4240.  
  4241.             for(temptank = tanklist->next;temptank != NULL;temptank = temptank->next)
  4242.                 {
  4243.                 temptank->x -= xv;
  4244.                 temptank->z -= zv;
  4245.                 }
  4246.             for(tempboom = projectboom->next;tempboom != NULL;tempboom = tempboom->next)
  4247.                 {
  4248.                 tempboom->x -= xv;
  4249.                 tempboom->z -= zv;
  4250.                 }
  4251.             for(temp = projectFlight->next;temp != NULL;temp = temp->next)
  4252.                 {
  4253.                 temp->x -= xv;
  4254.                 temp->z -= zv;
  4255.                 }
  4256.             for(temptank = slaglist->next;temptank != NULL;temptank = temptank->next)
  4257.                 {
  4258.                 temptank->x -= xv;
  4259.                 temptank->z -= zv;
  4260.                 }
  4261.             for(temptree = treelist->next;temptree != NULL;temptree = temptree->next)
  4262.                 {
  4263.                 temptree->x -= xv;
  4264.                 temptree->z -= zv;
  4265.                 }
  4266.             for(temptarget = targets->next;temptarget != NULL;temptarget = temptarget->next)
  4267.                     {
  4268.                     temptarget->x -= xv;
  4269.                     temptarget->z -= zv;
  4270.  
  4271.                     temptarget->net_x -= xv;
  4272.                     temptarget->net_z -= zv;
  4273.                     }
  4274.                 
  4275.             globalxshift -= xv;
  4276.             globalzshift -= zv;
  4277.             }
  4278.         }
  4279.         
  4280.     /**********************/
  4281.     /* update structures  */
  4282.     /**********************/
  4283.  
  4284.     if (treelist->next != NULL)
  4285.         updatetrees(treelist, itsChristmas);
  4286.  
  4287.     /**********************************/
  4288.     /* isolate the trees on the plane */
  4289.     /*  must come after update trees  */
  4290.     /**********************************/
  4291.     
  4292.     numTreesOnPlane = 0;
  4293.     numTreesEverywhere = 0;
  4294.     
  4295.     for(temptree = treelist->next; temptree != NULL; temptree = temptree->next)
  4296.         {
  4297.         allTreesEverywhere[numTreesEverywhere]      = *temptree;
  4298.         allTreesEverywherePtrs[numTreesEverywhere]  = temptree;
  4299.         numTreesEverywhere += 1;
  4300.         
  4301.         if ((fabs(temptree->x) <= PLANESIZE) &&  (fabs(temptree->z) <= PLANESIZE))
  4302.             {
  4303.             allTreesOnPlane[numTreesOnPlane]        = *temptree;
  4304.             allTreesOnPlanePtrs[numTreesOnPlane]    = temptree;
  4305.             numTreesOnPlane += 1;
  4306.             
  4307.             if (numTreesOnPlane >= MAXTREESONPLANE)
  4308.                 {
  4309.                 showError("Too many trees on the plane");
  4310.                 numTreesOnPlane -= 1;
  4311.                 }
  4312.             }
  4313.         }
  4314.  
  4315.     /****************************/
  4316.     /* update all the targets   */
  4317.     /****************************/
  4318.  
  4319.     if (targets->next != NULL)
  4320.         updateTargets();
  4321.  
  4322.  
  4323.     /************************/
  4324.     /* update the vehicles  */
  4325.     /************************/
  4326.  
  4327.      if (tanklist->next != NULL)
  4328.         updateTanks(tanklist, Googelon.width, Googelon.height, Googelon.bottom,
  4329.             Googelon.monsterIsDead, Googelon.monster, slaglist, accuracy,
  4330.             firingDelay, mainCounter, &Googelon, targets);
  4331.  
  4332.  
  4333.     /****************************/
  4334.     /* update the slagging tank */
  4335.     /****************************/
  4336.     
  4337.     if (slaglist->next != NULL)
  4338.         updateSlagTanks(slaglist);
  4339.  
  4340.  
  4341.     /**************************/
  4342.     /* update the projectiles */
  4343.     /**************************/
  4344.  
  4345.     quickTanks();
  4346.         
  4347.     if (projectFlight->next != NULL)
  4348.         updateProjectiles();
  4349.  
  4350.  
  4351.     /**********************************/   
  4352.     /* update monster Weapons         */
  4353.     /**********************************/
  4354.  
  4355.     if (Googelon.beamOn)
  4356.         {
  4357.  
  4358. #ifndef MACVERSION
  4359.         turnBeamOnSinceLast();
  4360. #endif
  4361.         switch (Googelon.monster)
  4362.             {
  4363.             case GOOGELON:      updateBeam(&Googelon, targets, 0, 0, tanklist, allTreesOnPlanePtrs, numTreesOnPlane, &Googelon);
  4364.                                 Googelon.energyRemaining -= 0.15;
  4365.                                 break;
  4366.                                 
  4367.             case TECHS:         updateGun(0, 0, Googelon.headHorzRotate, Googelon.headVertRotate, mainCounter, &Googelon);
  4368.                                 Googelon.energyRemaining -= 0.09;
  4369.                                 break;
  4370.                                 
  4371.             case VAPOUR:        updateVap(0, 0, mainCounter, &Googelon);
  4372.                                 Googelon.energyRemaining -= 0.1;
  4373.                                 break;
  4374.                                 
  4375.             case FLUTTER:       updateBeam(&Googelon, targets,0, 0, tanklist, allTreesOnPlanePtrs, numTreesOnPlane, &Googelon);
  4376.                                 Googelon.energyRemaining -= 0.15;
  4377.                                 break;
  4378.                                 
  4379.             default:            showError("Bogus Monster! (doUpdate)");
  4380.                                 break;
  4381.             }
  4382.         } 
  4383.  
  4384.     /*************************/
  4385.     /* update the explosions */
  4386.     /*************************/
  4387.         
  4388.     if (projectboom->next != NULL)
  4389.         updateBooms(projectboom, tanklist);
  4390.         
  4391.         
  4392.     /***********************/
  4393.     /* update the monster  */
  4394.     /***********************/
  4395.  
  4396.     if (!Googelon.beamOn)
  4397.         soundKiller(MONSTERBEAM);
  4398.         
  4399.         
  4400.     /*********************************************************************/
  4401.     /* update the Vapour's particles (must do for all! re menu monsters  */
  4402.     /*********************************************************************/
  4403.         
  4404.     updateVapourLook(Googelon.a, Googelon.monsterIsDead);
  4405.  
  4406.  
  4407.     /****************************/
  4408.     /* update monster's energy  */
  4409.     /****************************/
  4410.  
  4411.     if (Googelon.energyRemaining > 0)
  4412.         {
  4413.         Googelon.energyRemaining += Googelon.regenRate;
  4414.                 
  4415.         if (Googelon.energyRemaining > MAXLIFE)
  4416.             Googelon.energyRemaining = MAXLIFE;
  4417.  
  4418.         Googelon.rot1 = cos(Googelon.moveCount) * 0.02;
  4419.         Googelon.rot2 = sin(Googelon.moveCount) * 0.05;
  4420.         }
  4421.     else
  4422.         {
  4423.         updateDeadMonster(0, 0, &Googelon);
  4424.         }
  4425.   
  4426.     if (Googelon.monsterMoving)
  4427.         Googelon.moveCount += 1;
  4428.  
  4429.     /*************************************/
  4430.     /* update the high-score list        */
  4431.     /*************************************/
  4432.  
  4433.    if (Googelon.monsterIsDead && (Googelon.deadCount == 1))
  4434.         updateScores(scorefullPath, Googelon.monster, Googelon.monsterScore, mode, playerName);
  4435.  
  4436.     /*********************************/
  4437.     /* deal with dead targets        */
  4438.     /*********************************/
  4439.  
  4440.     temptarget = targets;
  4441.     while(temptarget->next != NULL)
  4442.         {
  4443.             {
  4444.             if (temptarget->next->monster.timeDead > 250)
  4445.                 {
  4446.                 for(tboom=projectboom->next; tboom != NULL; tboom=tboom->next)
  4447.                     {
  4448.                     if (tboom->mine == &(temptarget->next->monster))
  4449.                         tboom->mine = NULL;
  4450.                     }
  4451.     
  4452.                 for(tproj=projectFlight->next; tproj != NULL; tproj=tproj->next)
  4453.                     {
  4454.                     if (tproj->mine == &(temptarget->next->monster))
  4455.                         tproj->mine = NULL;
  4456.                     }
  4457.     
  4458.                 temptarg = temptarget->next;
  4459.                 temptarget->next = temptarget->next->next;
  4460.     
  4461.                 if ((temptarg->monster.monster == FLUTTER) ||(temptarg->monster.monster == GOOGELON))
  4462.                     {
  4463.                     addProjectile( temptarg->x-0.2, PLANEY+0.25, temptarg->z+0.2, 3, 0, -0.003, 0, 10000, NULL);
  4464.                     addProjectile( temptarg->x+0.2, PLANEY+0.25, temptarg->z+0.2, 3, 0, -0.003, 0, 10000, NULL);
  4465.                     addProjectile( temptarg->x+0.2, PLANEY+0.25, temptarg->z-0.2, 3, 0, -0.003, 0, 10000, NULL);
  4466.                     addProjectile( temptarg->x-0.2, PLANEY+0.25, temptarg->z-0.2, 3, 0, -0.003, 0, 10000, NULL);
  4467.                     }
  4468.                     
  4469.                 afree(temptarg, arena);
  4470.                 }
  4471.             else
  4472.                 temptarget = temptarget->next;
  4473.             }
  4474.         }
  4475.  
  4476.    if ((mode == DEMOMODE) && (Googelon.timeDead > 400))
  4477.         {
  4478.         Googelon.monster = (Googelon.monster + 1) % 4;
  4479.         setPlayConditions();
  4480.         }
  4481.  
  4482.     /*************************************/
  4483.     /* vehicles arrive faster later on   */
  4484.     /*************************************/
  4485.   
  4486.     arrivalTime = (int) (ARRIVALRATE - (mainCounter * 0.0005));
  4487.     if (arrivalTime < 20)
  4488.         arrivalTime = 20;
  4489.  
  4490.     /*************************************/
  4491.     /* vehicles more accurate later on   */
  4492.     /*************************************/
  4493.  
  4494.     accuracy = (STARTACCURACY + (mainCounter * 0.002));
  4495.     if (accuracy > 500)
  4496.         accuracy = 500;
  4497.  
  4498.     /*************************************/
  4499.     /* vehicles fire faster later on     */
  4500.     /*************************************/
  4501.  
  4502.     firingDelay = (int) (STARTFIRINGDELAY - (mainCounter * 0.0005));
  4503.     if (firingDelay < 43)
  4504.         firingDelay = 43;
  4505.    
  4506.     }
  4507.  
  4508. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4509. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4510. /* view the scene from the monster's point of view               */
  4511. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4512.  
  4513. void goToMonsterView(int eyeball)
  4514.     {
  4515.     glMatrixMode(GL_PROJECTION);
  4516.     glLoadIdentity();
  4517.     gluPerspective(90,  1,   0.1,   15);
  4518.     glMatrixMode(GL_MODELVIEW);
  4519.     
  4520.     switch(eyeball){
  4521.         case 2: glCallList(monsterLookat);
  4522.                 break;
  4523.  
  4524.         case 0: gluLookAt(  0.015, PLANEY + 2.4, 0.1,  0.015, PLANEY, 1, 0,1, 0);
  4525.                 break;
  4526.  
  4527.         case 1: gluLookAt( -0.015, PLANEY + 2.4, 0.1, -0.015, PLANEY, 1, 0,1, 0);
  4528.                 break;
  4529.  
  4530.         }
  4531.  
  4532.     if (lod >= 2)
  4533.         {
  4534.         glFogi(GL_FOG_START,  MONSTERFOGSTART);
  4535.         glFogi(GL_FOG_END,  MONSTERFOGEND);
  4536.  
  4537.         glEnable(GL_FOG);                   
  4538.         }
  4539.  
  4540.     yrot = - (GLfloat) Googelon.headHorzRotate;
  4541.     xrot = 360;
  4542.     }
  4543.  
  4544. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4545. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4546. /* view teh scene from the most recently added military vehicle  */
  4547. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4548.  
  4549. void goToArmyView(int eyeball)
  4550.     {
  4551.     /*look throgh 0,0 to opposite side and assign the opposite to the
  4552.     OTHER one making 2 parallel lines! */
  4553.  
  4554.     glMatrixMode(GL_PROJECTION);
  4555.     glLoadIdentity();
  4556.     gluPerspective(60,  1,   0.1,   20);
  4557.     glMatrixMode(GL_MODELVIEW);
  4558.             
  4559.     switch(eyeball){
  4560.         case 2: gluLookAt(lastTankRad * sin(lastTankTheta), lastTankY,
  4561.                 lastTankRad*cos(lastTankTheta), 0, lastTankY, 0, 0,1,0);
  4562.                 break;
  4563.  
  4564.         case 0: gluLookAt(lastTankRad * sin(lastTankTheta + 0.002),
  4565.                 lastTankY, lastTankRad * cos(lastTankTheta + 0.002),
  4566.                 -lastTankRad * sin(lastTankTheta-0.002), lastTankY,
  4567.                 -lastTankRad * cos(lastTankTheta-0.002), 0,1,0);
  4568.                 break;
  4569.  
  4570.         case 1: gluLookAt(lastTankRad * sin(lastTankTheta - 0.002),
  4571.                 lastTankY, lastTankRad * cos(lastTankTheta - 0.002),
  4572.                 -lastTankRad*sin(lastTankTheta+0.002), lastTankY,
  4573.                 -lastTankRad * cos(lastTankTheta+0.002), 0,1,0);
  4574.                 break;
  4575.         }
  4576.  
  4577.     if (lod >= 2)
  4578.         {
  4579.         glFogi(GL_FOG_START,  ARMYFOGSTART);
  4580.         glFogi(GL_FOG_END,  ARMYFOGEND);
  4581.         glEnable(GL_FOG);                   
  4582.         }
  4583.     
  4584.     xrot = yrot = 0;
  4585.     }
  4586.  
  4587. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4588. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4589. /* view the scene from above                                     */
  4590. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4591.  
  4592. void goToMapView()
  4593.     {
  4594.                                  /* used to get overhead map of the town */
  4595.                                 /* also set plane size to 40 */
  4596.                                /* and eliminate prepositioned vehicles */
  4597.                               /* and hide motion dots */
  4598.     glMatrixMode(GL_PROJECTION);
  4599.     glLoadIdentity();
  4600.     glOrtho(mapHeight*viewW/viewH, -mapHeight*viewW/viewH, mapHeight,
  4601.            -mapHeight, 0.1, 50);
  4602.     glMatrixMode(GL_MODELVIEW);
  4603.         
  4604.     gluLookAt(0, mapHeight, 0, 0, PLANEY, 0,  0, 0, 1);
  4605.     xrot = yrot = 0;
  4606.     }
  4607.  
  4608. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4609. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4610. /* view the scene from omniscient 3rd person                     */
  4611. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4612.  
  4613. void goToOverView(int eyeball)
  4614.     {
  4615.     view = OMNISCIENTVIEW;
  4616.     
  4617.  
  4618.     glMatrixMode(GL_PROJECTION);
  4619.     glLoadIdentity();
  4620.     gluPerspective(60,  1,   0.1,   25);
  4621.     glMatrixMode(GL_MODELVIEW);
  4622.             
  4623.     switch(eyeball){
  4624.         case 2: glCallList(overviewLookat);
  4625.                 break;
  4626.  
  4627.         case 0: gluLookAt( 0.05,  0, 9,   0.05,  0, 0, 0,1,0);
  4628.                 break;
  4629.  
  4630.         case 1: gluLookAt(-0.05,  0, 9,  -0.05,  0, 0, 0,1,0);
  4631.                 break;
  4632.         }
  4633.         
  4634.     if (lod >= 2)
  4635.         {
  4636.         glFogi(GL_FOG_START,  OVERVIEWFOGSTART);
  4637.         glFogi(GL_FOG_END,  OVERVIEWFOGEND);
  4638.         glEnable(GL_FOG);                   
  4639.         }
  4640.     }
  4641.     
  4642. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4643. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4644. /* draw a given monster at a given location                      */
  4645. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4646.  
  4647. void drawAMonster(float x, struct monsterInfo monster, float z,
  4648.                         int isTarget, int view)
  4649.     {
  4650.  
  4651.     if ((fabs(x) <= PLANESIZE) && (fabs(z) <= PLANESIZE))
  4652.         {
  4653.         glPushMatrix();
  4654.             glTranslatef(x,  0,  z);
  4655.             switch(monster.monster){
  4656.                 case GOOGELON:  if (monster.energyRemaining <= 0)
  4657.                                     {
  4658.                                     glTranslatef(0, -monster.deadCount * 0.015, 0);
  4659.                                     glRotatef(-monster.deadCount * 2, 1,0,0);
  4660.                                     glRotatef(-monster.deadCount * 2, 0,1,0);       
  4661.                                     }
  4662.                                 if ((!isTarget) && (view == MONSTERVIEW))
  4663.                                     drawSimpleMonster(monster, mainCounter, itsChristmas, lod);
  4664.                                 else
  4665.                                     drawMonster(monster, mainCounter, itsChristmas, lod);
  4666.                                 break;
  4667.  
  4668.                 case VAPOUR:    drawVapour(monster, itsChristmas, lod);
  4669.                                 break;
  4670.                                 
  4671.                 case TECHS:     if (monster.energyRemaining <= 0)
  4672.                                     {
  4673.                                     glTranslatef(0, -monster.deadCount * 0.015, 0);
  4674.                                     glRotatef(-monster.deadCount * 2, 1,0,0);
  4675.                                     }
  4676.                                 if ((!isTarget) && (view == MONSTERVIEW))
  4677.                                     drawSimpleTechs(monster,lod);
  4678.                                 else
  4679.                                     drawTechs(monster,lod);
  4680.                                 break;
  4681.                                 
  4682.                 case FLUTTER:   if (monster.energyRemaining <= 0)
  4683.                                     {
  4684.                                     glTranslatef(0, -monster.deadCount * 0.025, 0);
  4685.                                     glRotatef(-monster.deadCount * 2.5, 0,1,0);
  4686.                                     }
  4687.                                 if (isTarget)
  4688.                                     drawFlutter(monster, mainCounter, itsChristmas,
  4689.                                             offsetX, OMNISCIENTVIEW, lod);
  4690.                                 else
  4691.                                     drawFlutter(monster, mainCounter, itsChristmas,
  4692.                                             offsetX, view, lod);
  4693.                                 
  4694.                                 break;
  4695.             }
  4696.         glPopMatrix();
  4697.         }
  4698.     }
  4699.  
  4700. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4701. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4702. /* draw everything                                               */
  4703. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4704.  
  4705. void doDrawing (int eyeball)
  4706.     {
  4707.     GLenum glErrorVal;
  4708.     GLint tmp[4];
  4709.     struct targetInfo * temptarget;
  4710.  
  4711.     /***********************/
  4712.     /* check for GL errors */
  4713.     /***********************/
  4714.  
  4715. /* mac 68K version giving a spurious error mesage here */
  4716.  
  4717.     glErrorVal = glGetError();
  4718. #ifndef MACVERSION
  4719.     if (glErrorVal != GL_NO_ERROR)
  4720.         showError((char *) gluErrorString(glErrorVal));
  4721. #endif
  4722.  
  4723.     /* if line widths are integral Mesa chokes in a large window */
  4724.  
  4725.     if (lod > -1)
  4726.         glLineWidth(2.01);
  4727.     else
  4728.         glLineWidth(1.01);
  4729.  
  4730.     if (lod >= 2)
  4731.         glShadeModel(GL_SMOOTH);
  4732.     else
  4733.         glShadeModel(GL_FLAT);
  4734.         
  4735.  
  4736.     /****************************************************************/
  4737.     /* MUST enable dithering or the 8-bit machines look REALLY ugly */
  4738.     /****************************************************************/
  4739.     
  4740.     glEnable(GL_DITHER);
  4741.  
  4742.  
  4743.     glPushMatrix();
  4744.  
  4745.     /**********************************/
  4746.     /* setting viewing location       */
  4747.     /**********************************/
  4748.  
  4749.     if (view == MONSTERVIEW)
  4750.         goToMonsterView(eyeball);
  4751.     else if ((view == ARMYVIEW) && (lastTankY > NOTANKONPLANE))
  4752.         goToArmyView(eyeball);
  4753.     else if (view == MAPVIEW)
  4754.         goToMapView();
  4755.     else /*view == OMNISCIENTVIEW */
  4756.         goToOverView(eyeball);      
  4757.  
  4758.     /***********************************/
  4759.     /* rotate and draw the battlefield */
  4760.     /***********************************/
  4761.  
  4762.     if (xrot != 0)
  4763.         glRotatef(0.1 * xrot, 1,0,0);
  4764.  
  4765.     if (yrot != 0)
  4766.         glRotatef(0.1 * yrot, 0,1,0);
  4767.  
  4768.     glDisable(GL_DEPTH_TEST);
  4769.  
  4770.     drawBattlefield(roadSystem, globalxshift, globalzshift, lod,
  4771.                 itsChristmas, view);
  4772.  
  4773.     if (lod != -1)   
  4774.         glEnable(GL_DEPTH_TEST);
  4775.  
  4776.     /**********************************/
  4777.     /* draw the slagging vehicles     */
  4778.     /**********************************/
  4779.     
  4780.     if (slaglist->next != NULL)
  4781.         drawSlagTanks(slaglist, mainCounter, lod);
  4782.  
  4783.  
  4784.     /******************************************************/
  4785.     /* draw the vehicles                                  */
  4786.     /* must come before draw structures for hero entrance */
  4787.     /******************************************************/
  4788.     
  4789.     if (tanklist->next != NULL)
  4790.         drawTanks(tanklist, mainCounter, Googelon, targets, lod,
  4791.                 view, viewW);
  4792.  
  4793.  
  4794.  
  4795.     /**********************************/
  4796.     /* draw all projectiles in flight */
  4797.     /**********************************/
  4798.  
  4799.     if (projectFlight->next != NULL)
  4800.         drawProjectiles(projectFlight, mainCounter, fires,
  4801.         flameCount, itsChristmas,lod);
  4802.  
  4803.  
  4804.  
  4805.     /********************/
  4806.     /* draw structures  */
  4807.     /********************/
  4808.  
  4809.     if (treelist->next != NULL)
  4810.         if (view == MAPVIEW)
  4811.             drawtrees(allTreesEverywhere, numTreesEverywhere, mainCounter,
  4812.                                 lod, itsChristmas, view);
  4813.         else
  4814.             drawtrees(allTreesOnPlane, numTreesOnPlane, mainCounter,
  4815.                                 lod, itsChristmas, view);
  4816.  
  4817.  
  4818.  
  4819.     /**********************************/   
  4820.     /* draw monsterBeam               */
  4821.     /**********************************/
  4822.  
  4823.     if ((Googelon.beamOn) && ((Googelon.monster == GOOGELON) ||
  4824.                               (Googelon.monster == FLUTTER)))
  4825.         drawBeam(0, 0, Googelon.headHorzRotate, Googelon.headVertRotate,
  4826.                         Googelon.monster, lod);
  4827.  
  4828.     for (temptarget = targets->next;temptarget != NULL;temptarget = temptarget->next)
  4829.         if ((temptarget->monster.beamOn) &&
  4830.                         ((temptarget->monster.monster == GOOGELON) ||
  4831.                          (temptarget->monster.monster == FLUTTER)))
  4832.             drawBeam(temptarget->x, temptarget->z,
  4833.                         temptarget->monster.headHorzRotate,
  4834.                         temptarget->monster.headVertRotate,
  4835.                         temptarget->monster.monster, lod);
  4836.  
  4837.  
  4838.  
  4839.     /*************************************************/
  4840.     /* draw explosions to be seen through the VAPOUR */
  4841.     /*************************************************/
  4842. /*I suppose technically if ANY monster on the field is the vapour this
  4843.  * should be done but that may be too costly 
  4844.  */
  4845.  
  4846.     if ((Googelon.monster == VAPOUR) && (projectboom->next != NULL))
  4847.         {
  4848.         if (lod == -1)
  4849.             {
  4850.             glPushAttrib(GL_POLYGON_BIT);
  4851.             glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); 
  4852.             drawBooms(projectboom, lod);
  4853.             glPopAttrib();
  4854.             }
  4855.         else
  4856.             drawBooms(projectboom, lod);
  4857.         }
  4858.  
  4859.  
  4860.  
  4861.     /**********************************/ 
  4862.     /* draw the targets               */
  4863.     /**********************************/
  4864.     
  4865.     for(temptarget = targets->next;temptarget != NULL;temptarget = temptarget->next)
  4866.         drawAMonster(temptarget->x, temptarget->monster, temptarget->z, 1,view);
  4867.  
  4868.  
  4869.     /**********************************/ 
  4870.     /* draw the player's monster      */
  4871.     /**********************************/
  4872.  
  4873.     drawAMonster(0, Googelon, 0, 0,view);
  4874.  
  4875.     /**********************************/
  4876.     /* draw explosions                */
  4877.     /*                                */
  4878.     /* explosions must be last so     */
  4879.     /* other things can be seen       */
  4880.     /* throught them                  */
  4881.     /**********************************/
  4882.  
  4883.     if (projectboom->next != NULL)
  4884.         {
  4885.         if (lod == -1)
  4886.             {
  4887.             glPushAttrib(GL_POLYGON_BIT);
  4888.             glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); 
  4889.             drawBooms(projectboom, lod);
  4890.             glPopAttrib();
  4891.             }
  4892.         else
  4893.             drawBooms(projectboom, lod);
  4894.         }
  4895.  
  4896.     glDisable(GL_FOG);
  4897.  
  4898.     glPopMatrix();
  4899.     
  4900.     if (!backdrop)
  4901.         {
  4902.         glGetIntegerv(GL_VIEWPORT, tmp);
  4903.         viewL = tmp[0];
  4904.         viewR = viewL+tmp[2] - 1;
  4905.  
  4906.         glPushMatrix();
  4907.     
  4908.         /**********************************/
  4909.         /* print the overlays             */
  4910.         /**********************************/
  4911.     
  4912.         glMatrixMode(GL_PROJECTION);
  4913.         glLoadIdentity();
  4914.         gluPerspective(60,  1,   0.1,   20);
  4915.         glMatrixMode(GL_MODELVIEW);
  4916.  
  4917.         switch(eyeball){
  4918.             case 2: glCallList(overviewLookat);
  4919.                     break;
  4920.             case 0: gluLookAt( 0.065, 0, 9,  0.065, 0, 0, 0,1,0);
  4921.                     break;
  4922.             case 1: gluLookAt(-0.065, 0, 9, -0.065, 0, 0, 0,1,0);
  4923.                     break;
  4924.             }
  4925.  
  4926.         textLineWidth = (viewR-viewL) / 300.0;
  4927.         if (textLineWidth < 1)
  4928.             textLineWidth = 1.01;
  4929.  
  4930.         if (lod == -1)
  4931.             textLineWidth = 1.01;
  4932.  
  4933.         /* if line widths are integral Mesa chokes in a large window */
  4934.         glLineWidth(textLineWidth);
  4935.  
  4936.         /* showText(Googelon.energyRemaining,  Googelon.monsterScore,
  4937.         (long) (viewR-viewL), paused);   */   
  4938.  
  4939.         showText(targets, Googelon.energyRemaining,  Googelon.monsterScore,
  4940.             showframes, paused, pointerGrab);
  4941.  
  4942.         if (mode == DEMOMODE)
  4943.             {
  4944.             if (!(Googelon.timeDead > 100) && !showOptions)
  4945.                 if (Googelon.moveCount < 150)
  4946.                     showScores(itsChristmas, G, V, T, F, Googelon, mainCounter, offsetX, lod);
  4947.                 else
  4948.                     showText2((long) (viewR-viewL), getSoundOn(), noSound, getMusicOn(),
  4949.                             mode3D, no3D, lod, paused, itsChristmas, pointerGrab);
  4950.     
  4951.             
  4952.             showText3(lod);
  4953.  
  4954.             if (showOptions)
  4955.                 doOptions(Googelon, (long) (viewR-viewL),  mainCounter, itsChristmas, offsetX, lod);
  4956.             else
  4957.                 showText4();        
  4958.     
  4959.             if ((Googelon.timeDead > 100) && !showOptions)
  4960.                 doSummary(Googelon.monster,  Googelon.timeDead,
  4961.                     (long) (viewR-viewL), killtanks, killmtanks, 
  4962.                     killhelos, killCHHs, killmechags, killheros,
  4963.                     killplanes, killlaunchers, killfighters,
  4964.                     mainCounter, lod, moreThanOne);     
  4965.             }
  4966.         
  4967.         glPopMatrix();
  4968.         }
  4969.  
  4970. /* part of test to see if single buffering can be used in vector mode
  4971. if (lod > -1 )
  4972. */
  4973.  
  4974.    tkSwapBuffers();
  4975.  
  4976. #ifdef MACVERSION
  4977.  
  4978. drawGrow();
  4979.  
  4980. #endif
  4981.     }
  4982.  
  4983.             
  4984. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4985. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4986. /* computer controlled monster for demo-mode                     */
  4987. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  4988.  
  4989. struct monsterInfo autopilot(float centerX, float centerZ, struct monsterInfo thaMonster)
  4990.     {
  4991.     struct tank * ttank;
  4992.     struct tree * ttree;
  4993.     
  4994.     struct enemy et, el, em, eh, ec, eg, ehe, ep, eb, ef, eall, einside;
  4995.         
  4996.     float alphaBig;
  4997.     float modHead;
  4998.     float y, ang, r, modR;
  4999.     int speed, speed2;
  5000.     int t;
  5001.     float rad;
  5002.     float tx, tz;
  5003.     float zdiff;
  5004.     float xdiff;
  5005.  
  5006.     t = -1;
  5007.  
  5008.     et.r = el.r = em.r = eh.r = ec.r = eg.r =
  5009.     ehe.r = ep.r = eb.r = ef.r = eall.r = BIGNUM;
  5010.  
  5011.     /*************************************/
  5012.     /* find nearest building to destroy  */
  5013.     /*************************************/
  5014.  
  5015.     for(ttree = treelist->next; ttree != NULL; ttree = ttree->next)
  5016.         if ((ttree->type == 1)  && (ttree->intact == 1))
  5017.             {
  5018.             zdiff = ttree->z-centerZ;
  5019.             xdiff = ttree->x-centerX;
  5020.             
  5021.             rad =  sqrt(xdiff * xdiff + zdiff * zdiff);
  5022.     
  5023.             if (rad < eb.r)
  5024.                 {
  5025.                 eb.r    = rad;
  5026.                 eb.y    = ttree->y;
  5027.                 eb.ang  = computeAngle(zdiff, 0, xdiff, 0);
  5028.                 }
  5029.             }
  5030.  
  5031.     /*********************************/
  5032.     /* find nearest military threat  */
  5033.     /*********************************/
  5034.         
  5035.     eall = eb;
  5036.     einside = eb;
  5037.     
  5038.     for(ttank = tanklist->next; ttank != NULL; ttank = ttank->next)
  5039.             {
  5040.             tx = ttank->x;
  5041.             tz = ttank->z;
  5042.             rad =  sqrt((tx-centerX) * (tx-centerX) + (tz-centerZ) * (tz-centerZ));
  5043.  
  5044.             if (rad < eall.r)
  5045.                 {
  5046.                 eall.r   = rad;
  5047.                 eall.y   = ttank->y;
  5048.                 eall.ang = computeAngle(tz, centerZ, tx, centerX);
  5049.                 }
  5050.  
  5051.             if ((rad < einside.r) && (fabs(tx) < fabs(centerX)) && (fabs(tz) < fabs(centerZ)))
  5052.                 {
  5053.                  einside.r   = rad;
  5054.                  einside.y   = ttank->y;
  5055.                  einside.ang = computeAngle(tz, centerZ, tx, centerX);
  5056.                 }
  5057.  
  5058.             if (rad <= PLANESIZE)
  5059.                 {
  5060.  
  5061.                 switch(ttank->type){
  5062.                         case TANK       :   if (rad < et.r)
  5063.                                                 {
  5064.                                                 et.r   = rad;
  5065.                                                 et.y   = ttank->y;
  5066.                                                 et.ang = computeAngle(tz, centerZ, tx, centerX);
  5067.                                                 }
  5068.                                             break;
  5069.  
  5070.                         case LAUNCHER   :   if (rad < el.r)
  5071.                                                 {
  5072.                                                 el.r   = rad;
  5073.                                                 el.y   = ttank->y;
  5074.                                                 el.ang = computeAngle(tz, centerZ, tx, centerX);
  5075.                                                 }
  5076.                                             break;
  5077.                                             
  5078.                         case MASERTANK  :   if (rad < em.r)
  5079.                                                 {
  5080.                                                 em.r   = rad;
  5081.                                                 em.y   = ttank->y;
  5082.                                                 em.ang = computeAngle(tz, centerZ, tx, centerX);
  5083.                                                 }
  5084.                                             break;
  5085.                                             
  5086.                         case HELO       :   if (rad < eh.r)
  5087.                                                 {
  5088.                                                 eh.r   = rad;
  5089.                                                 eh.y   = ttank->y;
  5090.                                                 eh.ang = computeAngle(tz, centerZ, tx, centerX);
  5091.                                                 }
  5092.                                             break;
  5093.                                             
  5094.                         case CHH        :   if (rad < ec.r)
  5095.                                                 {
  5096.                                                 ec.r   = rad;
  5097.                                                 ec.y   = ttank->y;
  5098.                                                 ec.ang = computeAngle(tz, centerZ, tx, centerX);
  5099.                                                 }
  5100.                                             break;
  5101.                                             
  5102.                         case MECHAG     :   if (rad < eg.r)
  5103.                                                 {
  5104.                                                 eg.r   = rad;
  5105.                                                 eg.y   = ttank->y + 0.5;
  5106.                                                 eg.ang = computeAngle(tz, centerZ, tx, centerX);
  5107.                                                 }
  5108.                                             break;
  5109.                                             
  5110.                         case HERO       :   if (rad < ehe.r)
  5111.                                                 {
  5112.                                                 ehe.r   = rad;
  5113.                                                 ehe.y   = ttank->y + 0.5;
  5114.                                                 ehe.ang = computeAngle(tz, centerZ, tx, centerX);
  5115.                                                 }
  5116.                                             break;
  5117.                                             
  5118.                         case AIRPLANE   :   if (rad < ep.r)
  5119.                                                 {
  5120.                                                 ep.r   = rad;
  5121.                                                 ep.y   = ttank->y + 0.5;
  5122.                                                 ep.ang = computeAngle(tz, centerZ, tx, centerX);
  5123.                                                 }
  5124.                                             break;
  5125.  
  5126.                         case FIGHTER    :   if (rad < ef.r)
  5127.                                                 {
  5128.                                                 ef.r   = rad;
  5129.                                                 ef.y   = ttank->y + 0.5;
  5130.                                                 ef.ang = computeAngle(tz, centerZ, tx, centerX);
  5131.                                                 }
  5132.                                             break;
  5133.                                             
  5134.                         default:            showError("Bogus Vehicle! (autopilot)");
  5135.                                             break;
  5136.                         }
  5137.  
  5138.                     }
  5139.  
  5140.                 }
  5141.  
  5142.     /****************************/
  5143.     /* choose target to attack  */
  5144.     /****************************/
  5145.                 
  5146.     if (ehe.r != BIGNUM)
  5147.             {
  5148.             r   = ehe.r;
  5149.             y   = ehe.y;
  5150.             ang = ehe.ang;
  5151.             t   = HERO;
  5152.             }    
  5153.     else if (eg.r != BIGNUM)
  5154.             {
  5155.             r   = eg.r;
  5156.             y   = eg.y;
  5157.             ang = eg.ang;
  5158.             t   = MECHAG;
  5159.             }    
  5160.     else if (ec.r != BIGNUM)
  5161.             {
  5162.             r   = ec.r;
  5163.             y   = ec.y;
  5164.             ang = ec.ang;
  5165.             t   = CHH;
  5166.             }    
  5167.     else if (em.r != BIGNUM)
  5168.             {
  5169.             r   = em.r;
  5170.             y   = em.y;
  5171.             ang = em.ang;
  5172.             t   = MASERTANK;
  5173.             }    
  5174.     else if (el.r != BIGNUM)
  5175.             {
  5176.             r   = el.r;
  5177.             y   = el.y;
  5178.             ang = el.ang;
  5179.             t   = LAUNCHER;
  5180.             }    
  5181.     else  if ((eb.r < et.r) && (eb.r < eh.r))
  5182.             {
  5183.             r   = eb.r;
  5184.             y   = eb.y + 0.5;
  5185.             ang = eb.ang;
  5186.             t   = HERO; /* building */
  5187.             }    
  5188.     else if (eh.r < et.r)
  5189.             {
  5190.             r   = eh.r;
  5191.             y   = eh.y;
  5192.             ang = eh.ang;
  5193.             t   = HELO;
  5194.             }    
  5195.     else  if ((ep.r < et.r) && (et.r != BIGNUM))
  5196.             {
  5197.             r   = ep.r;
  5198.             y   = ep.y;
  5199.             ang = ep.ang;
  5200.             t   = AIRPLANE;
  5201.             }    
  5202.     else  if ((ef.r < et.r) && (et.r != BIGNUM))
  5203.             {
  5204.             r   = ef.r;
  5205.             y   = ef.y;
  5206.             ang = ef.ang;
  5207.             t   = FIGHTER;
  5208.             }    
  5209.     else if (et.r < BIGNUM)
  5210.             {
  5211.             r   = et.r;
  5212.             y   = et.y;
  5213.             ang = et.ang;
  5214.             t   = TANK;
  5215.             }
  5216.     else if (einside.r < BIGNUM)
  5217.             {
  5218.             r   = einside.r;
  5219.             y   = einside.y;
  5220.             ang = einside.ang;
  5221.             t   = HERO;
  5222.             }
  5223.     else
  5224.             {
  5225.             r   = eall.r;
  5226.             y   = eall.y;
  5227.             ang = eall.ang;
  5228.             t   = HERO;
  5229.             }
  5230.  
  5231.     /*********************/
  5232.     /* move the monster  */
  5233.     /*********************/
  5234.  
  5235.     if (ang < 0)
  5236.         ang += TWOPI;
  5237.     
  5238.     modHead = (thaMonster.headHorzRotate+1800); 
  5239.     if (modHead > 3600)
  5240.         modHead -= 3600;
  5241.  
  5242.     speed = (int) (ang * RAD_TO_BIG_DEG - modHead);
  5243.     if (speed > 1800)
  5244.         speed -= 3600;
  5245.     else if (speed < - 1800)
  5246.         speed += 3600;
  5247.     
  5248.     speed = speed / 15;
  5249.     if (speed > 0.75 * thaMonster.xspeed)
  5250.         speed = (int) (0.75 * thaMonster.xspeed);
  5251.     if (speed < -0.75 * thaMonster.xspeed)
  5252.         speed = (int) (-0.75 * thaMonster.xspeed);
  5253.     
  5254.     thaMonster.headHorzRotate += speed;
  5255.     offsetX = 0.8*offsetX - 0.2*(speed * 0.05); /* used to bank flutter in demo mode*/
  5256.  
  5257.     if ((thaMonster.energyRemaining > 15) && (fabs(speed) < 6) && (r < 3.5))
  5258.         thaMonster.beamOn = 1;
  5259.  
  5260.     switch(thaMonster.monster){
  5261.         case GOOGELON:
  5262.         case TECHS:             
  5263.             if ((thaMonster.energyRemaining > 5) && (t != -1)  && (t != HERO) &&
  5264.                 (t != MECHAG) && ((fabs(speed) < 3) || (r < 1)))
  5265.                 thaMonster.monsterGo = 1;
  5266.  
  5267.             else if (((t == MECHAG)  || (t == HERO)) && (fabs(speed) < 5) && (r > 3))
  5268.                 thaMonster.monsterGo = 1;
  5269.  
  5270.             else if (((t == MECHAG)  || (t == HERO)) && (fabs(speed) < 5) && (r < .75))
  5271.                 thaMonster.monsterBack = 1;
  5272.             break;
  5273.             
  5274.         case VAPOUR:
  5275.             if (((t == MECHAG) || (t == CHH) || (t == HERO)) && (r < 0.2))
  5276.                 /*stay put on top of the enemy*/;
  5277.                 
  5278.             else if ((thaMonster.energyRemaining > 5) && ((fabs(speed) < 10) || (r < 4)))
  5279.                 thaMonster.monsterGo = 1;
  5280.             break;
  5281.                         
  5282.         case FLUTTER:
  5283.             if ((thaMonster.energyRemaining > 5) && (t != -1)  && (t != HERO) &&
  5284.                 (t != MECHAG) && ((fabs(speed) < 3) || (r < 1)))
  5285.                 thaMonster.monsterGo = 1;
  5286.             else if (((t == MECHAG) || (t == HERO)) && (fabs(speed) < 5) && (r > 3))
  5287.                 thaMonster.monsterGo = 1;
  5288.             else if (((t == MECHAG) || (t == HERO)) && (fabs(speed) < 5) && (r < .75))
  5289.                 thaMonster.monsterBack = 1;
  5290.             else if (!(((t == MECHAG) || (t == HERO)) && (fabs(speed) < 5) && (r < 1)))
  5291.                 thaMonster.monsterGo = 1;
  5292.             break;
  5293.     }
  5294.  
  5295.     /************************/
  5296.     /* tilt monster's head  */
  5297.     /************************/
  5298.  
  5299.     y = thaMonster.height - 0.1 - y;
  5300.              
  5301.     if (thaMonster.monsterGo)
  5302.         modR = r - 1.3;
  5303.     else
  5304.         modR = r - 0.6;
  5305.         
  5306.     if (modR <= 0)
  5307.         modR = NEARZERO;
  5308.  
  5309.     alphaBig = atan(y / modR) * RAD_TO_BIG_DEG;
  5310.     
  5311.     speed2 = (int) (fabs(alphaBig - thaMonster.headVertRotate))/15;
  5312.     
  5313.     if (alphaBig > thaMonster.headVertRotate)
  5314.         thaMonster.headVertRotate += speed2;
  5315.     else
  5316.         thaMonster.headVertRotate -= speed2;
  5317.  
  5318.     thaMonster.monsterMoving = 1;
  5319.     
  5320.     return(thaMonster);
  5321.     }
  5322.  
  5323. /**********************************/
  5324.  
  5325. void reshape( int width, int height )
  5326.     {
  5327.     viewW = width;
  5328.     viewH = height;
  5329.     glViewport(0, 0, width, height);
  5330.     }
  5331.  
  5332. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5333. /* doDisplay                                                     */
  5334. /*                                                               */
  5335. /* draw everything                                               */
  5336. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5337.  
  5338. static void doDisplay(void)
  5339.     {
  5340.  
  5341. /* part of test to see if single buffering can be used in vector mode
  5342. if (lod == -1)
  5343.     glDrawBuffer(GL_FRONT);
  5344. else
  5345.     glDrawBuffer(GL_BACK);
  5346. */
  5347.  
  5348.     if (!mode3D)
  5349.         {       
  5350.         /**********************************/
  5351.         /* draw in mono                   */
  5352.         /**********************************/
  5353.  
  5354.         if (lod == -1)
  5355.             glClear(GL_COLOR_BUFFER_BIT);
  5356.         else            
  5357.             glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
  5358.  
  5359.         doDrawing(2);
  5360.         }
  5361.     else
  5362.         {       
  5363.         short Height3d,  Width3d;
  5364.  
  5365.         /**********************************/
  5366.         /* draw in stereo                 */
  5367.         /**********************************/
  5368.  
  5369.         if (doBigClear)
  5370.             {
  5371.             glViewport(0,  0, XMAXSCREEN+1, YMAXSCREEN+1);
  5372.             glScissor(0,  0, XMAXSCREEN+1, YMAXSCREEN+1);
  5373.  
  5374.             glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
  5375.             doBigClear -= 1;
  5376.             }
  5377.  
  5378.         Height3d = (short) windowTall/4;
  5379.         Width3d = (short) windowWide/2;
  5380.  
  5381.         glViewport((short) (XMAXSCREEN/2 - Width3d),
  5382.             (short) (YMAXSTEREO/2 - Height3d),
  5383.             ( (short) (XMAXSCREEN/2 + Width3d))-((short) (XMAXSCREEN/2 - Width3d))+1, 
  5384.             ( (short) (YMAXSTEREO/2 + Height3d))-( (short) (YMAXSTEREO/2 - Height3d))+1);
  5385.             
  5386.         glScissor((short) (XMAXSCREEN/2 - Width3d),  (short) (YMAXSTEREO/2 - Height3d),
  5387.             ( (short) (XMAXSCREEN/2 + Width3d))-((short) (XMAXSCREEN/2 - Width3d))+1,
  5388.             ( (short) (YMAXSTEREO/2 + Height3d))-( (short) (YMAXSTEREO/2 - Height3d))+1);
  5389.  
  5390.         glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  5391.  
  5392.         doDrawing(0);
  5393.  
  5394.         glViewport((short) (XMAXSCREEN/2 - Width3d),
  5395.             (short) (YOFFSET+YMAXSTEREO/2 - Height3d),
  5396.             ( (short) (XMAXSCREEN/2 + Width3d))-((short) (XMAXSCREEN/2 - Width3d))+1, 
  5397.             ((short) (YOFFSET+YMAXSTEREO/2 + Height3d))-( (short) (YOFFSET+YMAXSTEREO/2 - Height3d))+1);
  5398.         
  5399.         glScissor((short) (XMAXSCREEN/2 - Width3d),  (short) (YOFFSET+YMAXSTEREO/2 - Height3d),
  5400.             ( (short) (XMAXSCREEN/2 + Width3d))-((short) (XMAXSCREEN/2 - Width3d))+1,
  5401.             ((short) (YOFFSET+YMAXSTEREO/2 + Height3d))-( (short) (YOFFSET+YMAXSTEREO/2 - Height3d))+1);
  5402.  
  5403.         glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  5404.  
  5405.         doDrawing(1);
  5406.         }
  5407.     }
  5408.  
  5409.  
  5410. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5411. /* id                                                            */
  5412. /*                                                               */
  5413. /* this is the idle function for the tk code. This is called if  */
  5414. /* there are no interrupts to process. This computes the status  */
  5415. /* for the next frame and then draws the next frame              */
  5416. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5417.     
  5418. void id()
  5419.     {
  5420.     struct tank * ttank;
  5421.     struct targetInfo * temptarget;
  5422.  
  5423. #ifdef MACVERSION
  5424. if (mode == DEMOMODE)
  5425.         disableViewMenu();
  5426. else
  5427.         enableViewMenu();
  5428. #endif
  5429.  
  5430.     if (targets->next != NULL)
  5431.         {
  5432.         for(temptarget = targets->next; temptarget != NULL; temptarget = temptarget->next)
  5433.             {
  5434.             temptarget->monster.monsterMoving   = 0;
  5435.             temptarget->monster.monsterGo       = 0;
  5436.             temptarget->monster.monsterBack     = 0;
  5437.             
  5438.             temptarget->monster.beamOn          = 0;
  5439.             }
  5440.         }
  5441.                 
  5442.     if (mode == DEMOMODE)
  5443.         {
  5444.         Googelon.beamOn = 0;
  5445.         }
  5446.  
  5447.     Googelon.monsterMoving = 0;
  5448.  
  5449.     if (Gturn)
  5450.         Googelon.monsterMoving = 1;
  5451.  
  5452.     checkMouse();
  5453.  
  5454.     /**************************************/
  5455.     /* update the frames / second counter */
  5456.     /**************************************/
  5457.  
  5458.     now = time(NULL);
  5459.     if (now != beg)
  5460.         {
  5461.         showframes  = frames;
  5462.         frames      = 0;
  5463.         beg         = now;
  5464.         }       
  5465.     frames += 1;
  5466.  
  5467.  
  5468.     totalCounter += 1;
  5469.  
  5470.     if (!paused)
  5471.         mainCounter += 1;
  5472.  
  5473.  
  5474.     if (Googelon.monsterIsDead)
  5475.         mode = DEMOMODE;
  5476.  
  5477.     oldview = view;
  5478.  
  5479.     if (view == MONSTERVIEW) /* must be before view change!!!!*/
  5480.         yrot = (GLfloat) -Googelon.headHorzRotate;
  5481.     else if (view == OMNISCIENTVIEW)
  5482.         {
  5483.         ysaverot = yrot;
  5484.         xsaverot = xrot;
  5485.         }
  5486.  
  5487.     if ((mode == DEMOMODE) && !Googelon.monsterIsDead && !paused)
  5488.         Googelon = autopilot(0, 0, Googelon);
  5489.  
  5490.  
  5491.     for(temptarget = targets->next; temptarget != NULL; temptarget = temptarget->next)
  5492.         temptarget->monster = autopilot(temptarget->x, temptarget->z, temptarget->monster);
  5493.  
  5494.  
  5495.     /**********************************/
  5496.     /* update everything              */
  5497.     /**********************************/
  5498.     
  5499. #ifndef MACVERSION
  5500.     if (netUp)
  5501.         processNetwork(now, mainCounter, totalCounter, treelist,
  5502.                        tanklist, arena, Googelon, buildingBoomSoFarCounter, 
  5503.                        buildingBoomThisFrameCounter, buildingBoomSoFar,
  5504.                        buildingBoomThisFrame);
  5505.  
  5506.     if (client)
  5507.         processClient(now, mainCounter, totalCounter, treelist,
  5508.                       tanklist, arena, sizeTank, Googelon,
  5509.                       buildingBoomThisFrameCounter, buildingBoomThisFrame);
  5510. #endif
  5511.  
  5512.     if (!paused)
  5513.         doUpdate();
  5514.         
  5515. #ifdef SOLARIS
  5516.     else        /* sleep a while */
  5517.         {
  5518.         static struct timespec rqtp, rmtp;
  5519.         rqtp.tv_sec = 0;
  5520.         rqtp.tv_nsec = 500 * 1000000;   /* 500 ms delay */
  5521.         nanosleep(&rqtp, &rmtp);
  5522.         }
  5523. #endif
  5524. #ifdef SGIVERSION
  5525.     else
  5526.         sleep(1);
  5527. #endif
  5528.  
  5529.     /*************************************************/
  5530.     /* rotate the plane in demo mode omniscient view */
  5531.     /*************************************************/
  5532.     
  5533.     if ((view == OMNISCIENTVIEW) && (mode == DEMOMODE))
  5534.         {
  5535.         if (!paused)
  5536.             yrot += 10;
  5537.         xrot = 300;
  5538.         }
  5539.  
  5540.     /************************************************/
  5541.     /* find newest vehicle visible on the plane     */
  5542.     /************************************************/
  5543.  
  5544.     lastTankY = NOTANKONPLANE;
  5545.     lastTankTheta = lastTankRad = 0;
  5546.  
  5547.     for(ttank = tanklist->next; (ttank != NULL) && (lastTankY <= NOTANKONPLANE); ttank = ttank->next)
  5548.         if ((fabs(ttank->x) <= PLANESIZE) && (fabs(ttank->z) <= PLANESIZE) && (ttank->damage > 0)
  5549.             && (ttank->rad < 10))
  5550.             {
  5551.             lastTankY       = ttank->y + 0.4;
  5552.             lastTankTheta   = ttank->theta + PI;
  5553.             lastTankRad     = ttank->rad + 1.5;
  5554.             }
  5555.  
  5556.     /************************************************/
  5557.     /* ensure all monster variables are within range*/
  5558.     /************************************************/
  5559.  
  5560.     if (xrot > 600)
  5561.         xrot = 600;
  5562.     
  5563.     if (xrot < 0)
  5564.         xrot = 0;
  5565.         
  5566.     if (yrot < 0)
  5567.         yrot += 3600;
  5568.     
  5569.     if (yrot >= 3600)
  5570.         yrot -= 3600;
  5571.     
  5572.     if (Googelon.headHorzRotate < 0)
  5573.         Googelon.headHorzRotate += 3600;
  5574.  
  5575.     if (Googelon.headHorzRotate >= 3600)
  5576.         Googelon.headHorzRotate -= 3600;
  5577.         
  5578.     if (Googelon.headVertRotate < -400)
  5579.         Googelon.headVertRotate = -400;
  5580.  
  5581.     if (Googelon.headVertRotate > 400)
  5582.         Googelon.headVertRotate = 400;
  5583.  
  5584.     if (targets->next != NULL)
  5585.         {
  5586.         for(temptarget = targets->next; temptarget != NULL; temptarget = temptarget->next)
  5587.             {
  5588.             if (temptarget->monster.headHorzRotate < 0)
  5589.                 temptarget->monster.headHorzRotate += 3600;
  5590.         
  5591.             if (temptarget->monster.headHorzRotate >= 3600)
  5592.                 temptarget->monster.headHorzRotate -= 3600;
  5593.                 
  5594.             if (temptarget->monster.headVertRotate < -400)
  5595.                 temptarget->monster.headVertRotate = -400;
  5596.         
  5597.             if (temptarget->monster.headVertRotate > 400)
  5598.                 temptarget->monster.headVertRotate = 400;
  5599.             }
  5600.         }
  5601.                 
  5602.     /************************************************/
  5603.     /* draw everything                              */
  5604.     /************************************************/
  5605.  
  5606.     doDisplay();
  5607.  
  5608.     /***************************************************/
  5609.     /* limit the game to about 20fps for fast machines */
  5610.     /***************************************************/
  5611.  
  5612. #if defined SGIVERSION || defined SOLARIS
  5613.     gettimeofday(&endTime, NULL);
  5614.  
  5615.     while (((endTime.tv_sec - startTime.tv_sec) * 1000 + 
  5616.             (endTime.tv_usec - startTime.tv_usec) * 0.001) < 45)
  5617.         {
  5618. #ifdef SGIVERSION
  5619.         sginap(1);
  5620. # endif
  5621. # ifdef SOLARIS
  5622.         static struct timespec rqtp, rmtp;
  5623.  
  5624.         rqtp.tv_sec = 0;
  5625.         rqtp.tv_nsec = 2 * 1000000;     /* 2 ms delay */
  5626.         nanosleep(&rqtp, &rmtp);
  5627. # endif
  5628.         gettimeofday(&endTime, NULL);
  5629.         }
  5630. #endif
  5631.  
  5632. /*
  5633. #ifdef MACVERSION
  5634.  
  5635.  macEnd = tkNow();
  5636.  this works on 68K macs but the time never changes on a PPC (sigh)
  5637.  while((macEnd - macStart) < 45000)
  5638.         { 
  5639.         macEnd = tkNow();
  5640.         }
  5641.  
  5642. macStart = macEnd;
  5643.  
  5644. #endif
  5645. */
  5646.  
  5647. #ifdef AMIGA
  5648. #ifdef __PPC__
  5649.     GetSysTimePPC(&endTime);
  5650. #else
  5651.     #error "No M68k support"
  5652. #endif
  5653.     while (((endTime.tv_secs - startTime.tv_secs) * 1000 + 
  5654.             (endTime.tv_micro - startTime.tv_micro) * 0.001) < 45)
  5655.         {
  5656.         Delay(1);
  5657. #ifdef __PPC__
  5658.         GetSysTimePPC(&endTime);
  5659. #else
  5660.     #error "No M68k support"
  5661. #endif
  5662.         }
  5663. #endif
  5664.  
  5665.     startTime = endTime;
  5666.    }
  5667.  
  5668. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5669. /* showCommands                                                  */
  5670. /*                                                               */
  5671. /* print out the list of command line arguments                  */
  5672. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5673.  
  5674. #ifndef MACVERSION
  5675.  
  5676. void showCommands(char * progName)
  5677.     {
  5678.     fprintf (stderr, "\n\n");
  5679.  
  5680. #ifdef SOLARIS
  5681.     fprintf (stderr, "Usage: %s [-a] [-b] [-d level] [-m] [-s] [-help]\n", progName);
  5682. #else
  5683.     fprintf (stderr, "Usage: %s [-a] [-b] [-d level] [-m] [-s] [-c] [-h #] [-n] [-p #] [-help]\n", progName);
  5684. #endif
  5685.  
  5686.     fprintf (stderr, "  -a)lone        fight alone\n");
  5687.     fprintf (stderr, "  -b)ackdrop     hide the overlays\n");
  5688.     fprintf (stderr, "  -d)etail n     set level-of-detail from 0 (low) to 2 (high)\n");
  5689.     fprintf (stderr, "  -m)usic        initially turn on the music\n");
  5690.     fprintf (stderr, "  -s)ound        initially turn on the sound effects\n");
  5691.     fprintf (stderr, "  -help          show this list of command line options\n\n");
  5692.  
  5693. #ifdef SOLARIS
  5694.     fprintf (stderr, "Multiplayer options not yet supported:\n");
  5695. #else
  5696.      fprintf (stderr, "   Multiplayer options:\n");
  5697. #endif
  5698.  
  5699.     fprintf (stderr, "  -c)lient       declare yourself as a client in a net game\n");
  5700.     fprintf (stderr, "  -h)ost #       give the address of the host in a net game\n");
  5701.     fprintf (stderr, "  -n)etwork      declare yourself as a server in a net game\n");
  5702.     fprintf (stderr, "  -p)ort #       declare the port # being used in a net game\n");
  5703.  
  5704. #ifdef MESA_TK_VERSION
  5705.     tkQuit();
  5706. #else
  5707.     exit(1);
  5708. #endif
  5709.     }
  5710.     
  5711. #endif
  5712.  
  5713. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5714. /* checkArguments                                                */
  5715. /*                                                               */
  5716. /* change game settings based on the command line arguments      */
  5717. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5718.  
  5719. #ifndef MACVERSION
  5720.  
  5721. void checkArguments(int argc, char* argv[])
  5722. {
  5723.     register int argument;
  5724.     int port;
  5725.     char portName[40];
  5726.  
  5727.     for (argument=1;argument < argc;argument++)
  5728.         {
  5729.         if (((strcmp(argv[argument], "-sound") == 0) ||
  5730.             (strcmp(argv[argument], "-s") == 0) )&& !noSound)
  5731.             turnSoundOn();
  5732.  
  5733.         else if (((strcmp(argv[argument], "-music") == 0) ||
  5734.             (strcmp(argv[argument], "-m") == 0)) && !noSound)
  5735.             turnMusicOn();
  5736.  
  5737.         else if ((strcmp(argv[argument], "-alone") == 0) ||
  5738.             (strcmp(argv[argument], "-a") == 0))
  5739.             alone = 1;
  5740.  
  5741.         else if ((strcmp(argv[argument], "-detail") == 0) ||
  5742.                  (strcmp(argv[argument], "-d") == 0))
  5743.             {
  5744.             if ((argument + 1) < argc)
  5745.                 {
  5746.                 lod = atoi(argv[argument + 1]);
  5747.                 if (lod < 0 || lod > 2)
  5748.                     showCommands(argv[0]);
  5749.                 argument++;
  5750.                 }
  5751.             else
  5752.                 showCommands(argv[0]);
  5753.             }
  5754.  
  5755.         else if ((strcmp(argv[argument], "-network") == 0) ||
  5756.             (strcmp(argv[argument], "-net") == 0) ||
  5757.             (strcmp(argv[argument], "-n") == 0))
  5758.             netUp = 1;
  5759.  
  5760.         else if ((strcmp(argv[argument], "-backdrop") == 0) ||
  5761.             (strcmp(argv[argument], "-b") == 0))
  5762.             backdrop = 1;
  5763.             
  5764.         else if ((strcmp(argv[argument], "-client") == 0) ||
  5765.             (strcmp(argv[argument], "-c") == 0))
  5766.             client = 1;
  5767.  
  5768.         else if ((strcmp(argv[argument], "-host") == 0) ||
  5769.                  (strcmp(argv[argument], "-h") == 0))
  5770.             {
  5771.             if ((argument+1) < argc)
  5772.                 {
  5773.                 setHostAddr(argv[argument+1]);
  5774.                 argument++;
  5775.                 }
  5776.             else
  5777.                 showCommands(argv[0]);
  5778.             }
  5779.         else if ((strcmp(argv[argument], "-port") == 0) ||
  5780.                    (strcmp(argv[argument], "-p") == 0))
  5781.             {
  5782.             if ((argument+1) < argc)
  5783.                 {
  5784.                 strcpy(portName, argv[argument+1]);
  5785.                 sscanf(portName, "%d", &port);
  5786.                 setPortNumber(port);
  5787.                 argument++;
  5788.                 }
  5789.             else
  5790.                 showCommands(argv[0]);
  5791.             }
  5792.  
  5793.         else if ((strcmp(argv[argument], "-help") == 0))
  5794.                 {
  5795.                 showCommands(argv[0]);
  5796.                 }
  5797.         else
  5798.             {
  5799.             showCommands(argv[0]);
  5800.             }
  5801.         }
  5802. }
  5803.  
  5804. #endif
  5805.   
  5806. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5807. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5808. /* main                                                          */
  5809. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5810. /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
  5811.  
  5812. main (int argc, char*argv[])
  5813.     { 
  5814. #if defined SGIVERSION || defined SOLARIS
  5815.     
  5816.     gettimeofday(&startTime, NULL);
  5817.  
  5818. #endif
  5819.  
  5820. /*
  5821. #ifdef MACVERSION
  5822.  
  5823.         macStart = tkNow();
  5824.  
  5825. #endif
  5826. */
  5827.  
  5828. #ifdef AMIGAVERSION
  5829. #ifdef __PPC__
  5830.     GetSysTimePPC(&startTime);
  5831. #else
  5832.     #error "No M68k support"
  5833. #endif
  5834. #endif
  5835.  
  5836.     /******************/
  5837.     /* initialization */
  5838.     /******************/
  5839.  
  5840.     frames = 0;
  5841.     initialization();
  5842.  
  5843.     /********************************/
  5844.     /* check command line arguments */
  5845.     /********************************/
  5846.  
  5847. #ifndef MACVERSION
  5848.  
  5849.         checkArguments(argc, argv);
  5850.         
  5851. #endif
  5852.         
  5853.     /**********************************************/
  5854.     /* set starting conditions for chosen monster */
  5855.     /* (here so network options are used          */
  5856.     /**********************************************/
  5857.  
  5858.     setPlayConditions();
  5859.  
  5860.  
  5861.     /******************/
  5862.     /* set up network */
  5863.     /******************/
  5864.     
  5865. #ifndef MACVERSION
  5866.     if ((netUp == 1) && (client == 1))
  5867.         {
  5868.         showError("must be either a host or a client, not both");
  5869.         exit(1);
  5870.         }
  5871.     
  5872.     if (netUp)
  5873.         {
  5874.         netUp = setUpNetwork();
  5875.         }
  5876.  
  5877.     if (client)
  5878.         {
  5879.         client = setUpClient();
  5880.         }
  5881. #endif
  5882.  
  5883.  
  5884.     /****************/
  5885.     /* set it going */
  5886.     /****************/
  5887.  
  5888.     tkExec();
  5889.  
  5890. return 0;
  5891.  
  5892. }
  5893.