home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / xgalaga-2_0_tar.gz / xgalaga-2_0_tar / xgalaga-2.0 / main.c < prev    next >
C/C++ Source or Header  |  1998-04-30  |  34KB  |  1,163 lines

  1. /* Copyright (c) 1998 Joe Rumsey (mrogre@mediaone.net) */
  2. #include "copyright.h"
  3. /*
  4.  * main.c for XGalaga
  5.  * Copyright (c) 1995 Joe Rumsey
  6.  */
  7. #include "copyright.h"
  8. #include <config.h>
  9.  
  10. #define IM_A_BIG_FAT_CHEATER
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #ifdef HAVE_SYS_TIME_H
  15. #include <sys/time.h>
  16. #endif
  17. #ifdef HAVE_UNISTD_H
  18. # include <unistd.h>
  19. #endif
  20. #include "libsprite/Wlib.h"
  21. #include "data.h"
  22. #include "images.h"
  23. #include "defs.h"
  24. #include "struct.h"
  25. #include "paths.h"
  26. #include "proto.h"
  27. #include "sound.h"
  28.  
  29. struct torp torps[MAXTORPS];
  30. struct star stars[NUMSTARS];
  31. struct torp *first_etorp=0;
  32.  
  33. static int convoyx = 0, convoymove = 1;
  34. static int livecount = 0;
  35. static int starspeed = 1;
  36. static int attacking = 0, maxattacking, entering=0;
  37. static int maxetorps = 5, numetorps=0;
  38. static int pldead = 0;
  39. static int plflash = 50;
  40.  
  41. #define convoy_x_pos(i) (convoyx+(20 * (i - 10 * (i/10))))
  42. #define convoy_y_pos(i) (20 + (20*(i/10)))
  43.  
  44. static int moves[16][2] = {
  45.     0,-4,
  46.     1,-4,
  47.     3,-3,
  48.     4,-1,
  49.     4,0,
  50.     4,1,
  51.     3,3,
  52.     1,4,
  53.     0,4,
  54.     -1,4,
  55.     -3,3,
  56.     -4,1,
  57.     -4,0,
  58.     -4,-1,
  59.     -3,-3,
  60.     -1,-4
  61. };
  62.  
  63. void
  64. xgal_exit(int v)
  65. {
  66.     /*    W_AutoRepeatOn();*/
  67. #ifdef SOUND
  68.     kill_sound();
  69. #endif
  70.     /*    sleep(1);*/ /* Without this, the auto-repeat request fails on my machine... */
  71.     exit(v);
  72. }
  73.  
  74.  
  75. static void print_usage()
  76. {
  77.     printf("\
  78. XGalaga v%s\n\
  79. Copyright (c) 1995-1998 Joe Rumsey\n\
  80. <mrogre@mediaone.net>\n\
  81. Command line options:\n\
  82. -scores              Prints out the high score files and exits\n\
  83. -display <display>   Set your display\n\
  84. -mouse               Use mouse control (same as 'm' at the title screen)\n\
  85. -keyboard            Use keyboard control (same as 'k')\n%s\
  86. -b                   turn buffered mode off, use this if it runs\n\
  87. too slowly.  Will cause flicker, maybe lots,\n\
  88. maybe only a little.\n\
  89. \n\
  90. This game is now free software, under the GPL\n\
  91. \n\
  92. Basic instructions:\n\
  93. It's Galaga, you know how to play Galaga, stop bothering me.\n\
  94. (Ship follows the mouse, button fires.  Auto-fire by holding it\n\
  95. down, so no-one accuses me of breaking their mouse!)\n\
  96. \n\
  97. Keyboard commands:\n\
  98. \n\
  99. p - pauses\n\
  100. q - end this game\n\
  101. b - Toggle buffering (flicker vs. speed.)\n\
  102. o - Toggle OR mode.  Don't use this, it sucks.\n", VERSION,
  103. #ifdef SOUND
  104.            "  -nosound             Turn sound OFF\n"
  105. #else
  106.            ""
  107. #endif
  108.            );
  109. }
  110.  
  111. /*------------------stars-----------------*/
  112. static void init_stars()
  113. {
  114.     int i;
  115.  
  116.     for(i=0;i<NUMSTARS;i++) {
  117.         stars[i].x = random()%WINWIDTH;
  118.         stars[i].y = random()%WINHEIGHT;
  119.         stars[i].speed = (random()%3)+1;
  120.         switch(random()%5) {
  121.         case 0:
  122.             stars[i].color = W_White;
  123.             break;
  124.         case 1:
  125.             stars[i].color = W_Green;
  126.             break;
  127.         case 2:
  128.             stars[i].color = W_Cyan;
  129.             break;
  130.         case 3:
  131.             stars[i].color = W_Red;
  132.             break;
  133.         default:
  134.             stars[i].color = W_Yellow;
  135.             break;
  136.         }
  137.     }
  138. }
  139.  
  140. static int drewlevel = 0;
  141.  
  142. static void undo_stars()
  143. {
  144.     int i;
  145.     
  146.     for(i=0;i<NUMSTARS;i++) {
  147.         W_DrawPoint(baseWin, stars[i].x, stars[i].y, W_Black);
  148.     }
  149.     if(drewlevel) {
  150.         W_ClearArea(baseWin, WINWIDTH/2 - (W_StringWidth("LEVEL 000", W_BigFont)/2), WINHEIGHT/2-W_BigTextheight/2,
  151.                     10*W_BigTextwidth, W_BigTextheight);
  152.         drewlevel = 0;
  153.     }
  154. }
  155.  
  156. static void do_stars()
  157. {
  158.     int i;
  159.     
  160.     for(i=0;i<NUMSTARS;i++) {
  161.         if(!paused)
  162.             stars[i].y+=stars[i].speed*((starspeed < 20) ? ABS(starspeed) : 20);
  163.         if(stars[i].y >= WINHEIGHT) {
  164.             stars[i].y-=WINHEIGHT+starspeed;
  165.             stars[i].x = random() % WINWIDTH;
  166.             switch(random()%5) {
  167.             case 0:
  168.                 stars[i].color = W_White;
  169.                 break;
  170.             case 1:
  171.                 stars[i].color = W_Green;
  172.                 break;
  173.             case 2:
  174.                 stars[i].color = W_Cyan;
  175.                 break;
  176.             case 3:
  177.                 stars[i].color = W_Red;
  178.                 break;
  179.             default:
  180.                 stars[i].color = W_Yellow;
  181.                 break;
  182.             }
  183.         }
  184.         W_DrawPoint(baseWin, stars[i].x, stars[i].y, stars[i].color);
  185.     }
  186.     if(starspeed != 1) {
  187.         char buf[20];
  188.     
  189.         drewlevel = 1;
  190.         sprintf(buf, "LEVEL %d", level+1);
  191.         W_MaskText(baseWin, WINWIDTH/2 - (W_StringWidth(buf, W_BigFont)/2), WINHEIGHT/2-W_BigTextheight/2,
  192.                    W_Red, buf, strlen(buf), W_BigFont);
  193.     }
  194. }
  195.  
  196. /*-------------------aliens---------------*/
  197.  
  198. static void delete_etorps()
  199. {
  200.     struct torp *tmp;
  201.  
  202.     while(first_etorp) {
  203.         tmp = first_etorp->next;
  204.         free(first_etorp);
  205.         first_etorp = tmp;
  206.     }
  207. }
  208.  
  209. static void init_aliens(int level)
  210. {
  211.     int i;
  212.  
  213.     convoyx=0;
  214.     convoymove = 1;
  215.  
  216.     maxattacking = 1 + (level*2);
  217.     if(maxattacking > 30)
  218.         maxattacking = 30;
  219.     attacking = 0;
  220.     maxetorps = 10 + (level*5);
  221.     numetorps = 0;
  222.  
  223.     delete_etorps();
  224.     metaLevel = 1;
  225.     if(read_level(level) <= 0)
  226.     {
  227.     fprintf(stderr, "Error reading level %d\n", level);
  228.     exit(0);
  229.     }
  230.  
  231.     for(i=0;i<MAXALIENS;i++) {
  232.  
  233.         livecount++;
  234.         new_alien(level, i, &aliens[i]);
  235.     }
  236.  
  237.     printf("%d,%d", get_dir(7,1), get_duration(7,1));
  238.  
  239.     for(i=0;i<MAXTORPS;i++)
  240.         torps[i].alive = 0;
  241. }
  242.  
  243.     
  244. static void undo_aliens()
  245. {
  246.     int i;
  247.  
  248.     for(i=0;i<MAXALIENS;i++) {
  249.         if(aliens[i].alive)
  250.             W_ClearArea(baseWin, 
  251.                         aliens[i].x-(aliens[i].shape->width/2), 
  252.                         aliens[i].y-(aliens[i].shape->height/2),
  253.                         aliens[i].shape->width, aliens[i].shape->height);
  254.         if(aliens[i].dying) {
  255.             aliens[i].alive = 0;
  256.             aliens[i].dying=0;
  257.         }
  258.     }
  259. }
  260.  
  261. static void
  262. do_escort(int i)
  263. {
  264.     int fs = aliens[i].escorting;
  265.     
  266.     if(!aliens[fs].alive) {
  267.         aliens[i].escorting = -1;
  268.     } else if(aliens[fs].dir >= 0) {
  269.         aliens[i].dir = aliens[fs].dir;
  270.     } else {
  271.         aliens[i].x = 20 * (i - 10 * (i/10)) + convoyx + convoymove;
  272.         aliens[i].y = -10;
  273.         aliens[i].dir = -2;
  274.         aliens[i].path = -1;
  275.         aliens[i].steer = 2;
  276.         aliens[i].escorting = -1;
  277.     }
  278. }
  279.  
  280. static void
  281. do_convoy(int i)
  282. {
  283.     aliens[i].x += convoymove;
  284.     if((entering == 0) &&
  285.        (attacking < maxattacking) && 
  286.        ((livecount < maxattacking) || 
  287.         ((random()%10000) < (level + 2 *(48-(livecount)))))) {
  288.         switch(random()%2) {
  289.         case 0:
  290.             path_dir(P_PEELLEFT, 0, &aliens[i].dir, &aliens[i].steer);
  291.             aliens[i].path = P_PEELLEFT;
  292.             break;
  293.         case 1:
  294.             path_dir(P_PEELRIGHT, 0, &aliens[i].dir, &aliens[i].steer);
  295.             aliens[i].path = P_PEELRIGHT;
  296.             break;
  297.         }
  298.         aliens[i].path_pos = 0;
  299.         attacking++;
  300.         if(i<10) { /* Flagship, grab escorts */
  301.             int e;
  302.             for(e=i+9;e<i+12;e++) {
  303.                 if(aliens[e].alive && aliens[e].dir == -1) {
  304.                     aliens[e].escorting = i;
  305.                 }
  306.             }
  307.         }
  308.     }
  309. }
  310.  
  311. static void new_etorp(int x, int y, int xs, int ys)
  312. {
  313.     struct torp *t;
  314.  
  315.     t = malloc(sizeof(struct torp));
  316.     t->next = first_etorp;
  317.     if(t->next)
  318.         t->next->prev = t;
  319.     t->prev = 0;
  320.     first_etorp = t;
  321.  
  322.     t->x = x;
  323.     t->y = y;
  324.     t->xspeed = xs;
  325.     t->yspeed = ys;
  326.     t->alive = 1;
  327.     t->frame = 0;
  328.     numetorps++;
  329. }
  330.  
  331. static void do_enter(int i)
  332. {
  333.     int diffx, diffy;
  334.     int tc;
  335.  
  336.     if(aliens[i].enterdelay) {
  337.         aliens[i].enterdelay--;
  338.         return;
  339.     }
  340.  
  341.     if(aliens[i].path >= 0) {
  342.         aliens[i].x += moves[aliens[i].dir][0] + metaLevel * moves[aliens[i].dir][0]/2;
  343.         aliens[i].y += moves[aliens[i].dir][1] + metaLevel * moves[aliens[i].dir][1]/2;
  344.     
  345.         aliens[i].steer--;
  346.         if(aliens[i].steer <= 0) {
  347.             aliens[i].path_pos++;
  348.             enter_path_dir(aliens[i].path, aliens[i].path_pos, &aliens[i].dir, &aliens[i].steer);
  349.         if(metaLevel > 1)
  350.         aliens[i].steer = aliens[i].steer / (1 + ((metaLevel - 1) * .5));
  351.         /*aliens[i].steer -= ((metaLevel - 1) * (aliens[i].steer / 3));*/
  352.  
  353.             if(aliens[i].dir < 0) {
  354.                 aliens[i].path = -1;
  355.             }
  356.         }
  357.         tc = TORPCHANCE - level/2 - weapon*5;
  358.         if(tc < 35) tc = 35;
  359.         if(numetorps < maxetorps && (!(random()%tc))) {
  360.             int xs, ys;
  361.         
  362.             /* could aim better, not sure it should! */
  363.         
  364.             if(aliens[i].x > plx + 200) {
  365.                 xs = -3;
  366.             } else if(aliens[i].x > plx + 100) {
  367.                 xs = -2;
  368.             } else if(aliens[i].x < plx - 200) {
  369.                 xs = 3;
  370.             } else if(aliens[i].x < plx - 100) {
  371.                 xs = 2;
  372.             } else {
  373.                 xs = 0;
  374.             }
  375.             ys = (ETORPSPEED+level/5) - ABS(xs);
  376.             new_etorp(aliens[i].x, aliens[i].y, xs, ys);
  377.         }
  378.     } else {
  379.         diffx = ABS(convoy_x_pos(i) - aliens[i].x);
  380.         diffy = ABS(convoy_y_pos(i) - aliens[i].y);
  381.         if(diffy< 4 + (metaLevel * 2)) {
  382.             aliens[i].y = convoy_y_pos(i);
  383.             if(diffx < 4 + (metaLevel * 2)) {
  384.                 aliens[i].x = convoy_x_pos(i);
  385.                 aliens[i].dir = -1;
  386.                 aliens[i].entering = 0;
  387.                 return;
  388.             }
  389.             aliens[i].dir = 0;
  390.             if(convoy_x_pos(i) > aliens[i].x)
  391.                 aliens[i].dir = 4;
  392.             else
  393.                 aliens[i].dir = 12;
  394.         } else {
  395.         if(convoy_y_pos(i) < aliens[i].y) {
  396.         if(diffx < 4 + (metaLevel * 2)) {
  397.             aliens[i].x = convoy_x_pos(i);
  398.             aliens[i].dir = 0;
  399.         } else {
  400.             if(convoy_x_pos(i) > aliens[i].x)
  401.             aliens[i].dir = 2;
  402.             else
  403.             aliens[i].dir = 14;
  404.         }
  405.         } else {
  406.         if(diffx < 4 + (metaLevel * 2)) {
  407.             aliens[i].x = convoy_x_pos(i);
  408.             aliens[i].dir = 8;
  409.         } else {
  410.             if(convoy_x_pos(i) > aliens[i].x)
  411.             aliens[i].dir = 6;
  412.             else
  413.             aliens[i].dir = 10;
  414.         }
  415.         }
  416.         }
  417.         aliens[i].x += moves[aliens[i].dir][0] + metaLevel * moves[aliens[i].dir][0]/2;
  418.         aliens[i].y += moves[aliens[i].dir][1] + metaLevel * moves[aliens[i].dir][1]/2;
  419.     }
  420. }
  421.  
  422. static void do_aliens()
  423. {
  424.     int i, j;
  425.     int tc;
  426.  
  427.     if(!paused) {
  428.         convoyx += convoymove;
  429.         if(convoyx <= 0) {
  430.             convoyx=0;
  431.             convoymove = -convoymove;
  432.         } else if(convoyx >= WINWIDTH/2) {
  433.             convoyx = WINWIDTH/2;
  434.             convoymove = -convoymove;
  435.         }
  436.     }
  437.     
  438.     livecount=0; attacking = 0;
  439.     for(i=0, livecount=0, entering=0; i < MAXALIENS; i++) {
  440.         if(aliens[i].alive) {
  441.             livecount++;
  442.             if(aliens[i].dir >= 0 && aliens[i].escorting < 0 && !(aliens[i].entering))
  443.                 attacking++;
  444.             if(aliens[i].entering)
  445.                 entering++;
  446.         }
  447.     }
  448.  
  449.     for(i=0; i < MAXALIENS; i++) {
  450.         if(aliens[i].alive) {
  451.             if(!paused) {
  452.                 if(aliens[i].escorting >= 0) {
  453.                     do_escort(i);
  454.                 }
  455.  
  456.                 if(aliens[i].entering) {
  457.                     do_enter(i);
  458.                 } else if(aliens[i].dir == -1) {
  459.                     do_convoy(i);
  460.                 } else if(aliens[i].dir == -2) {
  461.                     aliens[i].x += convoymove;
  462.                     aliens[i].y+=2;
  463.                     if(aliens[i].y >= 20 + (20*(i/10))) {
  464.                         aliens[i].y = 20 + (20*(i/10));
  465.                         aliens[i].dir = -1;
  466.                     }
  467.                 } else {
  468.                     aliens[i].x += moves[aliens[i].dir][0];
  469.                     aliens[i].y += moves[aliens[i].dir][1];
  470.                     if(aliens[i].x > WINWIDTH+20)
  471.                         aliens[i].x = -20;
  472.                     else if(aliens[i].x < -20)
  473.                         aliens[i].x = WINWIDTH+20;
  474.             
  475.                     if(aliens[i].y > WINHEIGHT) {
  476.                         aliens[i].x = 20 * (i - 10 * (i/10)) + convoyx + convoymove;
  477.                         aliens[i].y = -30;
  478.                         aliens[i].dir = -2;
  479.                         aliens[i].path = -1;
  480.                         aliens[i].steer = 2;
  481.                         aliens[i].escorting = -1;
  482.                         attacking--;
  483.                         if(i < 10) {
  484.                             for(j=i+9;j<i+12;j++)
  485.                                 aliens[j].escorting = -1;
  486.                         }
  487.                     } else if(aliens[i].y < 0) {
  488.                         aliens[i].dir = 8;
  489.                     }
  490.             
  491.                     if(aliens[i].escorting < 0) {
  492.                         aliens[i].steer--;
  493.                         if(aliens[i].steer <= 0) {
  494.                             if(aliens[i].path >= 0) {
  495.                                 int lastdir=aliens[i].dir;
  496.                 
  497.                                 aliens[i].path_pos++;
  498.                                 path_dir(aliens[i].path, aliens[i].path_pos, &aliens[i].dir, &aliens[i].steer);
  499.                                 if(aliens[i].dir < 0) {
  500.                                     aliens[i].dir = lastdir;
  501.                                 newpath:
  502.                                     switch(random()%8) {
  503.                                     case 0:
  504.                                         start_path(P_LOOP, &aliens[i]);
  505.                                         break;
  506.                                     case 1:
  507.                                         start_path(P_SWOOP1, &aliens[i]);
  508.                                         break;
  509.                                     case 2:
  510.                                         start_path(P_SWOOP2, &aliens[i]);
  511.                                         break;
  512.                                     case 3:
  513.                                         start_path(P_ZIGZAG, &aliens[i]);
  514.                                         break;
  515.                                     case 4:
  516.                                         start_path(P_LOOP2, &aliens[i]);
  517.                                         break;
  518.                                     case 5:
  519.                                         start_path(P_SPIN, &aliens[i]);
  520.                                         break;
  521.                                     case 6:
  522.                                         start_path(P_LEFTDIAG, &aliens[i]);
  523.                                         break;
  524.                                     case 7:
  525.                                         start_path(P_RIGHTDIAG, &aliens[i]);
  526.                                         break;
  527.                                     default:
  528.                                         aliens[i].steer = TURNSPEED;
  529.                                         aliens[i].path = -1;
  530.                                     }
  531.                                     if((aliens[i].path < 0) || (aliens[i].steer < 0)) {
  532.                                         goto newpath;
  533.                                     }
  534.                                 }
  535.                             } else {
  536.                                 if(random()%2) {
  537.                                     aliens[i].dir++;
  538.                                     if(aliens[i].dir > 15)
  539.                                         aliens[i].dir = 0;
  540.                                 } else {
  541.                                     aliens[i].dir--;
  542.                                     if(aliens[i].dir < 0)
  543.                                         aliens[i].dir = 15;
  544.                                 }
  545.                                 aliens[i].steer = TURNSPEED;
  546.                             }
  547.                         }
  548.                     }
  549.                     tc = TORPCHANCE - level/2 - weapon*5;
  550.                     if(tc < 35) tc = 35;
  551.  
  552.                     if(numetorps < maxetorps && (!(random()%tc))) {
  553.                         int xs, ys;
  554.             
  555.                         /* could aim better, not sure it should! */
  556.  
  557.                         if(aliens[i].x > plx + 200) {
  558.                             xs = -3;
  559.                         } else if(aliens[i].x > plx + 100) {
  560.                             xs = -2;
  561.                         } else if(aliens[i].x < plx - 200) {
  562.                             xs = 3;
  563.                         } else if(aliens[i].x < plx - 100) {
  564.                             xs = 2;
  565.                         } else {
  566.                             xs = 0;
  567.                         }
  568.                         ys = (ETORPSPEED+level/5) - ABS(xs);
  569.                         new_etorp(aliens[i].x, aliens[i].y, xs, ys);
  570.                     }
  571.                 }
  572.                 W_DrawImage(baseWin, 
  573.                             aliens[i].x-(aliens[i].shape->width/2), 
  574.                             aliens[i].y-(aliens[i].shape->height/2),
  575.                             aliens[i].dir < 0 ? 0 : aliens[i].dir, aliens[i].shape, W_Green);
  576.             } else {  /* paused */
  577.                 W_DrawImage(baseWin, 
  578.                             aliens[i].x-(aliens[i].shape->width/2), 
  579.                             aliens[i].y-(aliens[i].shape->height/2),
  580.                             aliens[i].dir < 0 ? 0 : aliens[i].dir, aliens[i].shape, W_Green);
  581.             }
  582.         }
  583.     }
  584.     if(livecount == 0) {
  585.         starspeed++;
  586. #ifdef SOUND
  587.         if(starspeed == 2)
  588.             play_sound(SND_WARP);
  589. #endif
  590.         if(starspeed >= 120) {
  591.             starspeed = -20;
  592.         } else if(starspeed == 1) {
  593.             init_aliens(++level);
  594.             gotlemon = 0;
  595.             starspeed = 1;
  596.             numtorps=0;
  597.         }
  598.     }
  599. }
  600.  
  601.  
  602. /*------------------player----------------*/
  603. static void init_player()
  604. {
  605.     int i;
  606.     for(i=0;i<MAXTORPS;i++)
  607.         torps[i].alive=0;
  608. }
  609.  
  610. static void new_torp(int x, int y, int xs, int ys)
  611. {
  612.     int i;
  613.  
  614.     for(i=0;i<maxtorps;i++) {
  615.         if(!torps[i].alive) {
  616.             torps[i].x = x;
  617.             torps[i].y = y;
  618.             torps[i].alive = 1;
  619.             torps[i].xspeed = xs;
  620.             torps[i].yspeed = ys;
  621.             numtorps++;
  622. #ifdef SOUND
  623.             play_sound(SND_FIRETORP);
  624. #endif
  625.             return;
  626.         }
  627.     }
  628. }
  629.  
  630. static void undo_torps()
  631. {
  632.     int i;
  633.  
  634.     for(i=0;i<MAXTORPS;i++) {
  635.         if(torps[i].alive) {
  636.             W_CacheClearArea(baseWin, 
  637.                              torps[i].x-(playerTorp->width/2), 
  638.                              torps[i].y-(playerTorp->height/2), 
  639.                              playerTorp->width, playerTorp->height+1);
  640.         }
  641.     }
  642. }
  643.  
  644. static void do_torps()
  645. {
  646.     int i,j,k, ne;
  647.  
  648.     for(i=0;i<MAXTORPS;i++) {
  649.         if(torps[i].alive) {
  650.             if(!paused) {
  651.                 torps[i].y += torps[i].yspeed;
  652.                 torps[i].x += torps[i].xspeed;
  653.                 torps[i].frame++;
  654.                 for(j=0;j<MAXALIENS;j++) {
  655.                     if(aliens[j].alive && !aliens[j].dying &&
  656.                        (ABS(torps[i].x - aliens[j].x) < 8) &&
  657.                        ((ABS(torps[i].y - aliens[j].y) < 8) ||
  658.                         (ABS((torps[i].y + torps[i].yspeed/2)-aliens[j].y) < 8))) {
  659.                         aliens[j].dying = 1;
  660.                         if(aliens[j].dir >= 0)
  661.                             attacking--;
  662.             
  663.                         torps[i].alive=0;
  664.                         numtorps--;
  665.                         if(j >= 10) {
  666.                             if(aliens[j].dir < 0)
  667.                                 score += 50;
  668.                             else {
  669.                                 score += (6-(j/10))*100;
  670.                                 if(!(random()%(gotlemon ? 3 : PRIZECHANCE)))
  671.                                     new_prize(aliens[j].x, aliens[j].y);
  672.                             }
  673.                             new_explosion(aliens[j].x, aliens[j].y, 0);
  674.                         } else {
  675.                             if(aliens[j].dir < 0)
  676.                                 score += 200;
  677.                             else {
  678.                                 ne=0; /* count how many escorts */
  679.                                 for(k = j+9;k < j+12; k++) {
  680.                                     if(aliens[k].escorting == j)
  681.                                         ne++;
  682.                                 }                   
  683.                                 score_flagship(aliens[j].x, aliens[j].y, ne);
  684.                             }
  685.                             new_explosion(aliens[j].x, aliens[j].y, 1);
  686.                         }
  687.                         goto skip;
  688.                     }
  689.                 }
  690.                 if(torps[i].y < -torps[i].yspeed || 
  691.                    torps[i].x < ABS(torps[i].xspeed) || 
  692.                    torps[i].x > WINWIDTH-ABS(torps[i].xspeed)) {
  693.                     torps[i].alive = 0;
  694.                     numtorps--;
  695.                 } else
  696.                     W_DrawImage(baseWin, 
  697.                                 torps[i].x-(playerTorp->width/2), 
  698.                                 torps[i].y-(playerTorp->height/2), 
  699.                                 torps[i].frame, playerTorp, W_Red);
  700.             skip: ;
  701.             } else {/* paused */
  702.                 W_DrawImage(baseWin, 
  703.                             torps[i].x-(playerTorp->width/2), 
  704.                             torps[i].y-(playerTorp->height/2), 
  705.                             torps[i].frame, playerTorp, W_Red);
  706.             }
  707.         }
  708.     }
  709. }
  710.  
  711. static void do_etorps()
  712. {
  713.     struct torp *t = first_etorp, *nextt;
  714.  
  715.     while(t) {
  716.         nextt=t->next;
  717.         if(t->alive) {
  718.             if(!paused) {
  719.                 t->y+=t->yspeed;
  720.                 t->x+=t->xspeed;
  721.                 t->frame++;
  722.                 if(t->y > WINHEIGHT || t->x < 0 || t->x > WINWIDTH) {
  723.                     if(t->next)
  724.                         t->next->prev = t->prev;
  725.                     if(t->prev)
  726.                         t->prev->next = t->next;
  727.                     if(t == first_etorp)
  728.                         first_etorp = t->next;
  729.                     free(t);
  730.                     numetorps--;
  731.                 } else if(!pldead && !plflash && !plshield &&
  732.                           (ABS(t->x - plx) < 8) &&
  733.                           (ABS(t->y - (WINHEIGHT - (int)playerShip->height / 2)) < 8)) { /* DEAD! */
  734.                     pldead = 1;
  735.                     new_explosion(plx, WINHEIGHT - playerShip->height/2, 2);
  736.                 } else {
  737.                     W_DrawImage(baseWin, 
  738.                                 t->x-(enemyTorp->width/2), 
  739.                                 t->y-(enemyTorp->height/2), 
  740.                                 t->frame, enemyTorp, W_Red);
  741.                 }
  742.             } else {
  743.                 W_DrawImage(baseWin, 
  744.                             t->x-(enemyTorp->width/2), 
  745.                             t->y-(enemyTorp->height/2), 
  746.                             t->frame, enemyTorp, W_Red);
  747.             }
  748.         }
  749.         t = nextt;
  750.     }
  751. }
  752.  
  753. static void undo_etorps()
  754. {
  755.     struct torp *t = first_etorp;
  756.  
  757.     while(t) {
  758.         W_CacheClearArea(baseWin, 
  759.                          t->x-(enemyTorp->width/2), 
  760.                          t->y-(enemyTorp->width/2), 
  761.                          enemyTorp->width, enemyTorp->height);
  762.         t=t->next;
  763.     }
  764. }
  765.  
  766. static void undo_player()
  767. {
  768.     int y = WINHEIGHT - playerShip->height, h = playerShip->height;
  769.     if(plshield) {
  770.         y -= 3;
  771.         h += 3;
  772.     }
  773.     W_CacheClearArea(baseWin, plx-(playerShip->width/2), y,
  774.                      playerShip->width, h);
  775. }
  776.  
  777. static void do_player()
  778. {
  779.     int mx, my, but;
  780.     static int torpok;
  781.     W_Event wev;
  782.     static int keys = 0;
  783.  
  784.     if(gameOver) {
  785.         while(W_EventsPending()) {
  786.             W_NextEvent(&wev);
  787.         
  788.             mouseControl = 1;
  789.             switch(wev.type) {
  790.             case W_EV_KEY:
  791.                 if(score_key(&wev))
  792.                     continue;
  793.                 switch(wev.key) {
  794.                 case 'q':
  795.                 case 'Q':
  796.                     xgal_exit(0);
  797.                     break;
  798.                 case 'm':
  799.                     mouseControl = 2;
  800.                     break;
  801.         default:
  802.             break;
  803.                 }
  804.                 if(mouseControl < 2)
  805.                     mouseControl = 0;        
  806.             case W_EV_BUTTON:
  807.                 if(!getting_name) {
  808.                     if(mouseControl)
  809.                         W_GrabPointer(baseWin);
  810.                     gameOver = 0;
  811.                     maxtorps = MINTORPS;
  812.                     weapon = 0;
  813.                     movespeed = MINSPEED;
  814.                     ships=2;
  815.                     level=1;
  816.                     init_aliens(level);
  817.                     gotlemon = 0;
  818.                     pldead = 0;
  819.                     score = 0;
  820.                     nextBonus = 20000;
  821.                     plx = WINWIDTH/2;
  822.                     W_ClearWindow(baseWin);
  823.                 }
  824.                 break;
  825.             }
  826.         }
  827.         return;
  828.     }
  829.  
  830.     while(W_EventsPending()) {
  831.         W_NextEvent(&wev);
  832.  
  833.         switch(wev.type) {
  834.         case W_EV_KEY_OFF:
  835.             switch(wev.key) {
  836.             case 'f'+128:
  837.                 keys &= ~(RIGHTKEY);
  838.                 break;
  839.             case 'b'+128:
  840.                 keys &= ~(LEFTKEY);
  841.                 break;
  842.             case ' ':
  843.                 keys &= ~(FIREKEY);
  844.                 break;
  845.             }
  846.             break;
  847.         case W_EV_KEY:
  848.             switch(wev.key) {
  849.             case 'f'+128:
  850.                 keys |= RIGHTKEY;
  851.                 break;
  852.             case 'b'+128:
  853.                 keys |= LEFTKEY;
  854.                 break;
  855.             case ' ':
  856.                 keys |= FIREKEY;
  857.                 break;
  858.             case 'k':
  859.                 mouseControl = 0;
  860.                 W_UngrabPointer();
  861.                 break;
  862.             case 'm':
  863.                 mouseControl = 1;
  864.                 W_GrabPointer(baseWin);
  865.                 break;
  866.             case 'q':
  867.                 if(!pldead) {
  868.                     new_explosion(plx, WINHEIGHT - ((playerShip->height)/2), 2);
  869.                     ships = 0;
  870.                     pldead = 1;
  871.                 }
  872.                 break;
  873.             case 'Q':
  874.                 xgal_exit(0);
  875.                 break;
  876.             case 'b':
  877.                 W_Buffer(baseWin, !W_IsBuffered(baseWin));
  878.                 W_ClearWindow(baseWin);
  879.                 break;
  880.             case 'p':
  881.                 paused=!paused;
  882.                 if(!paused) {
  883.                     undo_pause();
  884.                     if(mouseControl)
  885.                         W_GrabPointer(baseWin);
  886.                 } else
  887.                     W_UngrabPointer();
  888.                 break;
  889. #ifdef SOUND
  890.             case 's':
  891.                 playSounds = !playSounds;
  892.                 break;
  893. #endif
  894. #ifdef IM_A_BIG_FAT_CHEATER
  895.             case 'i':
  896.                 if(plflash >= 0)
  897.                     plflash = -2;
  898.                 else
  899.                     plflash = 0;
  900.                 break;
  901.             case 'l':
  902.                 {
  903.                     int i;
  904.                     for(i=0;i<MAXALIENS;i++)
  905.                         aliens[i].alive=0;
  906.                     if(starspeed != 1)
  907.                         level++;
  908.                 }
  909.                 break;
  910.             case 'c':
  911.                 score+= BONUSSHIPSCORE;
  912.                 break;
  913.             case 'h':
  914.                 plshield = SHIELDTIME;
  915. #ifdef SOUND
  916.                 play_sound(SND_SHIELD);
  917. #endif
  918.                 break;
  919.             case 'w':
  920.                 weapon++;
  921.                 if(weapon == 3)
  922.                     weapon=0;
  923.                 break;
  924.             case 't':
  925.                 maxtorps++;
  926.                 if(maxtorps > MAXTORPS)
  927.                     maxtorps = MINTORPS;
  928.                 break;
  929. #endif /* IM_A_BIG_FAT_CHEATER */
  930.             default:
  931.                 break;
  932.             }
  933.         }
  934.     }
  935.  
  936.     if(!paused) {
  937.         torpok--;
  938.  
  939.     W_GetMouse(baseWin, &mx, &my, &but);
  940.         if(!mouseControl) {
  941.         /*            W_GetMouse(baseWin, &mx, &my, &but);
  942.         } else {
  943.     */
  944.             if(keys & LEFTKEY)
  945.                 mx = 0;
  946.             else if(keys & RIGHTKEY)
  947.                 mx = WINWIDTH;
  948.             else
  949.                 mx = plx;
  950.         
  951.             if(keys & FIREKEY)
  952.                 but = W_LBUTTON;
  953.             else
  954.                 but = 0;
  955.         }
  956.         
  957.         if(pldead) {
  958.             pldead++;
  959.             if(pldead >= 100) {
  960.                 if(ships<=0) {
  961.                     gameOver = 1;
  962.                     W_UngrabPointer();
  963.                     if(check_score(score)) {
  964. #ifdef USE_REAL_NAMES
  965.                         add_score(getUsersFullName(), score);
  966.                         title_page = 1; pagetimer = 300;
  967. #else
  968.                         getting_name = 1;
  969. #endif
  970.                     }
  971.                 } else {
  972.                     ships--;
  973.                     maxtorps = MINTORPS;
  974.                     weapon = 0;
  975.                     movespeed = MINSPEED;
  976.                     pldead = 0;
  977.                     plflash = 50;
  978.                     plx = WINWIDTH/2;
  979.                 }
  980.             }
  981.             return;
  982.         }
  983.  
  984.         if(but && torpok <= 0 && (starspeed == 1)) {
  985.             switch(weapon) {
  986.             case SINGLESHOT:
  987.                 if(numtorps < maxtorps)
  988.                     new_torp(plx, WINHEIGHT - playerShip->height, 0, -TORPSPEED);
  989.                 break;
  990.             case DOUBLESHOT:
  991.                 if(numtorps < maxtorps-1) {
  992.                     new_torp(plx-5, WINHEIGHT - playerShip->height, 0, -TORPSPEED);
  993.                     new_torp(plx+5, WINHEIGHT - playerShip->height, 0, -TORPSPEED);
  994.                 }
  995.                 break;
  996.             case TRIPLESHOT:
  997.                 if(numtorps < maxtorps-2) {
  998.                     new_torp(plx-5, WINHEIGHT - playerShip->height, -2, 1-TORPSPEED);
  999.                     new_torp(plx,   WINHEIGHT - playerShip->height, 0,   -TORPSPEED);
  1000.                     new_torp(plx+5, WINHEIGHT - playerShip->height, 2, 1-TORPSPEED);
  1001.                 }
  1002.                 break;
  1003.             }
  1004.             torpok = TORPDELAY;
  1005.         }
  1006.  
  1007.         if(!but)
  1008.             torpok=0;
  1009.  
  1010.         if((mx/movespeed) > (plx/movespeed))
  1011.             plx+=movespeed;
  1012.         else if((mx/movespeed) < (plx/movespeed))
  1013.             plx-=movespeed;
  1014.     
  1015.         if(plx < playerShip->width/2)
  1016.             plx=playerShip->width/2;
  1017.         if(plx> WINWIDTH - playerShip->width/2)
  1018.             plx=WINWIDTH - playerShip->width/2;
  1019.     
  1020.         if(plflash > 0)
  1021.             plflash--;
  1022.         if(!(plflash % 2))
  1023.             W_DrawImage(baseWin, plx-(playerShip->width/2), WINHEIGHT - playerShip->height, counter, playerShip, W_Red);
  1024.         if(plshield > 0)
  1025.             plshield--;
  1026.         if(plshield && ((plshield > SHIELDTIME/4) || plshield % 2)) {
  1027.             W_DrawImage(baseWin, plx-(shieldImage->width/2), WINHEIGHT - shieldImage->height - 3, 0, shieldImage,
  1028.                         W_Cyan);
  1029.         }
  1030.     } else { /* paused */
  1031.         W_DrawImage(baseWin, plx-(playerShip->width/2), WINHEIGHT - playerShip->height, counter, playerShip, W_Red);
  1032.     }
  1033. }
  1034.  
  1035. int
  1036. main(argc, argv)
  1037. int     argc;
  1038. char  **argv;
  1039. {
  1040.     int ac;
  1041.     char *dpyname = 0;
  1042.     struct timeval tv, otv;
  1043.     long ut;
  1044.    
  1045.     gettimeofday(&otv, 0);
  1046.     for(ac = 1; ac < argc; ac++) {
  1047.         if(*argv[ac] == '-') {
  1048.             if(strcmp(argv[ac], "-scores") == 0) {
  1049.                 print_scores();
  1050.                 exit(0);
  1051.             }
  1052.             if(strcmp(argv[ac], "-display") == 0 && (ac+1 < argc)) {
  1053.                 dpyname = argv[ac+1];
  1054.                 ac++;
  1055. #if 0
  1056.             } else if (strcmp(argv[ac], "-b") == 0) {
  1057.                 useBuffered = !useBuffered;
  1058. #endif
  1059.             } else if (strcmp(argv[ac], "-keyboard") == 0) {
  1060.                 mouseControl = 0;
  1061.             } else if (strcmp(argv[ac], "-mouse") == 0) {
  1062.                 mouseControl = 1;
  1063. #ifdef SOUND
  1064.             } else if (strcmp(argv[ac], "-nosound") == 0) {
  1065.                 playSounds = 0;
  1066. #endif
  1067.             } else {
  1068.                 print_usage();
  1069.                 exit(0);
  1070.             }
  1071.         } else {
  1072.             print_usage();
  1073.             exit(0);
  1074.         }
  1075.     }
  1076.         
  1077.     W_Initialize(dpyname);
  1078.  
  1079.     backColor = W_Black;
  1080.     baseWin = W_MakeWindow("XGalaga", 0, 0, WINWIDTH, WINHEIGHT, 0, "tiny", 0, W_White);
  1081.     W_MapWindow(baseWin);
  1082.  
  1083.     /*    W_AutoRepeatOff();*/
  1084.  
  1085.     W_Flush();
  1086.  
  1087.     W_SetImageDir(IMAGEDIR);
  1088.  
  1089.     playerShip = getImage(I_PLAYER1);
  1090.     playerTorp = getImage(I_MTORP);
  1091.     enemyTorp = getImage(I_ETORP);
  1092.     shieldImage = getImage(I_SHIELD);
  1093.  
  1094.     level=1;
  1095.  
  1096.     load_scores();
  1097.     init_titles();
  1098.     init_player();
  1099.     init_stars();
  1100.     init_explosions();
  1101.     init_score();
  1102.     init_prizes();
  1103. #ifdef SOUND
  1104.     init_sound();
  1105. #endif
  1106.     init_aliens(level);
  1107.  
  1108.     ships = 2;
  1109.     nextBonus = 20000;
  1110.  
  1111.     while(1) {
  1112.         counter++;
  1113.         if(gameOver && getting_name)
  1114.             undo_name();
  1115.  
  1116.         undo_score();
  1117.         undo_explosions();
  1118.         undo_stars();
  1119.         undo_aliens();
  1120.         undo_prizes();
  1121.         undo_etorps();
  1122.         undo_torps();
  1123.         undo_player();
  1124.  
  1125.         if(paused)
  1126.             undo_pause();
  1127.  
  1128.         W_FlushClearAreaCache(baseWin);
  1129.  
  1130.         if(paused)
  1131.             do_pause();
  1132.  
  1133.         do_stars();
  1134.         do_player();
  1135.         do_torps();
  1136.         do_etorps();
  1137.         do_prizes();
  1138.         do_aliens();
  1139.         do_explosions();
  1140.         do_score();
  1141.         if(gameOver) {
  1142.             do_title();
  1143.             if(getting_name)
  1144.                 do_name();
  1145.         }
  1146.         W_DisplayBuffer(baseWin);
  1147.         W_Flush();
  1148.         gettimeofday(&tv, 0);
  1149.         if(tv.tv_sec > otv.tv_sec)
  1150.             tv.tv_usec += (tv.tv_sec - otv.tv_sec) * 1000000;
  1151.         ut = tv.tv_usec - otv.tv_usec;
  1152.         if(UTIMER - ut > 0) {
  1153.             struct timeval tv;
  1154.             unsigned long usecs = UTIMER - ut;
  1155.             tv.tv_sec  = usecs / 1000000L;
  1156.             tv.tv_usec = usecs % 1000000L;
  1157.             (void) select (0, 0, 0, 0, &tv);
  1158.     }
  1159.  
  1160.         gettimeofday(&otv, 0);
  1161.     }
  1162. }
  1163.