home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 332_01 / bugs.c < prev    next >
C/C++ Source or Header  |  1990-03-30  |  11KB  |  517 lines

  1. /*----------------------------------------------------*- Fundamental -*-
  2.  
  3. Facility:        bugs(6)
  4.  
  5. File:            bugs.c
  6.  
  7. Associated files:    - (none)
  8.  
  9. Description:        Bugs me. Bugs anyone.
  10.  
  11. Notes:            Needs curses.
  12.  
  13. Author:            Steve Ward
  14.  
  15. Editor:            Anders Thulin
  16.             Rydsvagen 288
  17.             S-582 50 Linkoping
  18.             SWEDEN
  19.  
  20. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
  21.  
  22. Edit history :
  23.  
  24. Vers  Ed   Date           By                Comments
  25. ----  ---  ----------  ----------------  -------------------------------
  26.  1.0    0  19xx-xx-xx  Steve Ward
  27.  1.1    1  1990-03-16  Anders Thulin     Changed H19/H89 screen handling to
  28.                          curses. Still buggy, though :-)
  29.  
  30. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
  31.  
  32. /*---  Configuration:  --------------------------------------------------
  33.  
  34. System configuration options:
  35. =============================
  36.  
  37.   ANSI        ANSI C conformant compiler
  38.   BSD        BSD Unix
  39.   SYSV        AT&T System V.x Unix
  40.  
  41. If you have an ANSI compiler, defined ANSI only.  Otherwise, define
  42. the alternative that most closely matches your environment.
  43.  
  44.  
  45. Program configuration:
  46. ======================
  47.  
  48.   NBUGS        Max. number of bugs permitted
  49.  
  50.  
  51. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  52.  
  53. #define    ANSI     1
  54. #define    BSD     0
  55. #define    SYSV     0
  56.  
  57. #define    NBUGS    25
  58.  
  59. /* - - End of configurations - - - - - - - - - - - - - - - - - - - - - - - - */
  60.  
  61. #include <curses.h>
  62. #include <stdio.h>
  63.  
  64. #if ANSI
  65. # include <stdlib.h>
  66.  extern int getopt(int argc, char **argv, char *optstring);
  67.  extern int optind;
  68. #endif
  69.  
  70. #if BSD
  71.  extern int getopt();
  72.  extern void exit();
  73.  extern int optind;
  74. # define EXIT_FAILURE   1
  75. # define EXIT_SUCCESS    0
  76. #endif
  77.  
  78. #if SYSV
  79.  extern int getopt();
  80.  extern void exit();
  81.  extern int optind;
  82. # define EXIT_FAILURE   1
  83. # define EXIT_SUCCESS    0
  84. #endif
  85.  
  86. #ifndef TRUE
  87. #define TRUE 1
  88. #define FALSE 0
  89. #endif
  90.  
  91. /*----------------------------------------------------------------------
  92.  
  93. Known problems:
  94.  
  95. curses
  96.  
  97.   The program relies on non-blocking calls to getch() so that it can
  98.   quit as soon as the `user' presses a key.  Older implementations of
  99.   curses don't have the function nodelay() which sets up for nonblocking
  100.   calls to getch().
  101.  
  102.   It may be possible to remove the calls to getch() altogether.
  103.   Instead, catch SIGINT (or whatever is used to indicate that user
  104.   wants to quit) to make an orderly exit from curses.
  105.  
  106. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  107.  
  108.  
  109. /*
  110.     "Bugs"
  111.     written by Steve Ward for the H19/H89 display terminal
  112.     BD says..."This one is WIERD!!!"
  113. */
  114.  
  115. #define BOT    0
  116. #define LEFT    0
  117. #define RADIUS2    21
  118.  
  119. int    Top,        /* Pagesize-1                */
  120.     Right;        /* Linelength-2                */
  121.  
  122. struct bug {
  123.   int X,Y;
  124.   int Dir;    /* 0-down, 1-left, 2-up, 3-right.    */
  125.   int State;
  126. } bugs[NBUGS];
  127.  
  128. char    Wflg, Cflg;
  129. int    CurX, CurY;
  130. int    CBugs;
  131.  
  132. int XMotion[20] = { 0, 1, 0, -1,  1, 1, -1, -1};
  133. int YMotion[20] = {-1, 0, 1,  0, -1, 1,  1, -1};
  134.  
  135. /* Q & D fix for placech():  */
  136.  
  137. #define placech(ch, tx, ty)         \
  138.     do {                \
  139.       mvaddch((ty), (tx), (ch));    \
  140.       refresh();            \
  141.     } while (0)
  142.  
  143. /*----------------------------------------------------------------------
  144.   Local functions:
  145. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  146.  
  147. #if __STDC__ != 0
  148.  static int  alive(struct bug *bb);
  149.  static void mkbug(struct *bb, int xp, int yp, int direc);
  150.  static void r(struct bug *bb, int dx, int dy, int ch);
  151.  static void randbug(struct bug *bb);
  152.  static void step(struct bug *bb);
  153.  static void turn(struct bug *bb);
  154. #else
  155.  static int  alive();
  156.  static void mkbug();
  157.  static void r();
  158.  static void randbug();
  159.  static void step();
  160.  static void turn();
  161. #endif
  162.  
  163. static int alive(bb)
  164. struct bug *bb;
  165. {
  166.   int px,py;
  167.   px = bb->X; py = bb->Y;
  168.   switch((bb->Dir) & 03) {
  169.     case 0: return(py>=BOT-4);
  170.     case 1: return(px<=Right+6);
  171.     case 2: return(py<=Top+4);
  172.     case 3: return(px>=LEFT-4); 
  173.   }
  174.   /*NOTREACHED*/
  175. }
  176.  
  177. static void step(bb)
  178. struct bug *bb;
  179. {
  180.   switch ((*bb).State) {
  181.     case 0: r(bb,1,0,' '); r(bb,1,-1,'\\'); (*bb).State++; break;
  182.     case 1:    r(bb,-1,0,' ');
  183.             r(bb,-1,-1,'/');
  184.             (*bb).State++;    break;
  185.     case 2:    r(bb,1,1,' ');
  186.             r(bb,1,0,'\\');
  187.             (*bb).State++;    break;
  188.     case 3:    r(bb,-1,1,' ');
  189.             r(bb,-1,0,'/');
  190.             (*bb).State++;    break;
  191.     case 4:    r(bb,0,-1,'0');
  192.             r(bb,0,0,'O');
  193.             r(bb,1,-1,'/');
  194.             r(bb,-1,-1,'\\');
  195.             r(bb,1,0,'/');
  196.             r(bb,-1,0,'\\');
  197.             (*bb).State++;    break;
  198.     case 5:    r(bb,1,2,' ');
  199.             r(bb,1,1,'\\');
  200.             (*bb).State++;    break;
  201.     case 6:    r(bb,-1,2,' ');
  202.             r(bb,-1,1,'/');
  203.             (*bb).State++;    break;
  204.     case 7:    r(bb,1,1,'/');
  205.             r(bb,0,1,' ');
  206.             r(bb,-1,1,'\\');
  207.             switch (((*bb).Dir) & 03) {
  208.              case 0: (*bb).Y--; break;
  209.              case 2: (*bb).Y++; break;
  210.              case 1: (*bb).X++; break;
  211.              case 3: (*bb).X--; break; }
  212.             (*bb).State = 0;    break;
  213. /* Diagonal movement:                        */
  214.  
  215.     case 20:    r(bb,1,1,' ');
  216.             r(bb,1,0,'-');
  217.             (*bb).State++;    break;
  218.     case 21:    r(bb,-1,-1,' ');
  219.             r(bb,0,-1,'|');
  220.             (*bb).State++;    break;
  221.     case 22:    r(bb,0,1,' ');
  222.             r(bb,1,1,'/');
  223.             (*bb).State++;    break;
  224.     case 23:    r(bb,-1,0,' ');
  225.             r(bb,-1,-1,'/');
  226.             (*bb).State++;    break;
  227.     case 24:    r(bb,1,-1,'0');
  228.             r(bb,0,0,'O');
  229.             r(bb,1,1,' ');
  230.             r(bb,0,1,'|');
  231.             r(bb,-1,-1,' ');
  232.             r(bb,-1,0,'-');
  233.             r(bb,1,0,'|');
  234.             r(bb,0,-1,'-');
  235.             (*bb).State++;    break;
  236.     case 25:    r(bb,-1,2,' ');
  237.             r(bb,0,2,'/');
  238.             (*bb).State++;    break;
  239.     case 26:    r(bb,-2,1,' ');
  240.             r(bb,-2,0,'/');
  241.             (*bb).State++;    break;
  242.     case 27:    r(bb,-1,1,' ');
  243.             r(bb,0,2,' ');
  244.             r(bb,-2,0,' ');
  245.             r(bb,1,0,'|');
  246.             r(bb,0,-1,'-');
  247.             switch (((*bb).Dir)& 03) {
  248.              case 0: (*bb).X++; (*bb).Y--; break;
  249.              case 1: (*bb).X++; (*bb).Y++; break;
  250.              case 2: (*bb).X--; (*bb).Y++; break;
  251.              case 3: (*bb).X--; (*bb).Y--; break; }
  252.             (*bb).State = 20;    break;
  253.  
  254. /* turn from diag to orthogonal (45 deg CCW)                */
  255.  
  256.     case 40:    r(bb,-1,0,' ');
  257.             r(bb,-2,0,'/');
  258.             (*bb).State++; break;
  259.     case 41:    r(bb,-1,0,'O');
  260.             r(bb,-1,2,' ');
  261.             r(bb,-1,1,'|');
  262.             r(bb,-2,0,'\\');
  263.             r(bb,-2,1,'\\');
  264.             (*bb).State++; break;
  265.     case 42:    r(bb,1,1,' ');
  266.             r(bb,0,1,'\\');
  267.             r(bb,-1,1,'\\');
  268.             r(bb,-2,0,' ');
  269.             r(bb,-2,-1,'/');
  270.             r(bb,0,-1,'/');
  271.             (*bb).Dir = (((*bb).Dir)+1) & 03;
  272.             (*bb).State = 0; break;
  273.  
  274. /* Turn from ortho to diagonal:                    */
  275.  
  276.     case 50:    r(bb,-1,0,' ');
  277.             r(bb,-1,-1,'/');
  278.             (*bb).State++; break;
  279.     case 51:    r(bb,-1,1,' ');
  280.             r(bb,-1,0,'/');
  281.             (*bb).State++; break;
  282.     case 52:    r(bb,1,2,' ');
  283.             r(bb,0,1,'|');
  284.             r(bb,-1,1,'O');
  285.             r(bb,1,0,' ');
  286.             r(bb,-1,2,' ');
  287.             r(bb,0,2,'/');
  288.             r(bb,-1,0,' ');
  289.             r(bb,-2,0,'/');
  290.             r(bb,-2,1,'-');
  291.             (*bb).State++; break;
  292.     case 53:    r(bb,0,2,' ');
  293.             r(bb,-1,2,'|');
  294.             r(bb,-2,0,' ');
  295.             r(bb,-1,0,'-');
  296.             (*bb).Dir = (((*bb).Dir) | 04);
  297.             (*bb).State = 20; break;
  298.   }
  299. }
  300.  
  301. static void mkbug(bb, xp, yp, direc)
  302. struct bug *bb;
  303. int xp, yp, direc;
  304. {
  305.   bb->X = xp;
  306.   bb->Y = yp;
  307.   bb->State = 0;
  308.   bb->Dir = direc;
  309.  
  310.   if (direc < 4) {
  311.     r(bb,0,0,'0');
  312.     r(bb,0,1,'O');
  313.     r(bb,1,0,'/');
  314.     r(bb,1,1,'/');
  315.     r(bb,1,2,'/');
  316.     r(bb,-1,2,'\\');
  317.     r(bb,-1,1,'\\');
  318.     r(bb,-1,0,'\\');
  319.   } else {
  320.     bb->State = 20;
  321.     r(bb,0,0,'0');
  322.     r(bb,1,1,'/');
  323.     r(bb,-1,-1,'/');
  324.     r(bb,0,1,'|');
  325.     r(bb,-1,0,'-');
  326.     r(bb,-1,1,'O');
  327.     r(bb,-1,2,'|');
  328.     r(bb,-2,1,'-');
  329.   }
  330. }
  331.  
  332.  
  333. static void r(bb, dx, dy, ch)
  334. struct bug *bb;
  335. int         dx, dy;
  336. char        ch;
  337. {
  338.   int tx, ty, direc;
  339.  
  340.   direc = (bb->Dir) & 03;
  341.   if ((direc == 1) || (direc == 3)) {
  342.     switch (ch) {
  343.       case '/':     ch = '\\'; break;
  344.       case '\\': ch = '/'; break;
  345.       case '|':     ch = '-'; break;
  346.       case '-':     ch = '|'; break;
  347.       default:     break;
  348.     }
  349.   }
  350.  
  351.   switch (direc) {
  352.     case 0: tx = dx+bb->X; ty = dy+bb->Y; break;
  353.     case 2: tx = bb->X-dx; ty = bb->Y-dy; break;
  354.     case 1: tx = bb->X-dy; ty = bb->Y+dx; break;
  355.     case 3: tx = bb->X+dy; ty = bb->Y-dx; break;
  356.   }
  357.   placech(ch,tx,ty); 
  358. }
  359.  
  360.  
  361. static void randbug(bb)
  362. struct bug *bb;
  363. {
  364.   int x,y,dir;
  365.   dir = rand()%8;
  366.   x = rand()%80;
  367.   y = rand()%24;
  368.   if (Cflg) {
  369.     x = (Right-LEFT)/2;
  370.     y = (Top-BOT)/2;
  371.   } else switch(dir & 03) {
  372.     case 0: y=24+4; break;
  373.     case 2: y = -4; break;
  374.     case 1: x = -4; break;
  375.     case 3: x=80+4; break;
  376.   }
  377.   mkbug(bb,x,y,dir);
  378. }
  379.  
  380. static void turn(bb)
  381. struct bug *bb;
  382. {
  383.   if (bb->State == 0) {
  384.     bb->State = 50;
  385.   } else if (bb->State == 20) {
  386.     bb->State = 40;
  387.   }
  388.   return;
  389. }
  390.  
  391. int main(argc,argv)
  392. int   argc;
  393. char *argv[];
  394. {
  395.   int c;
  396.   int errflg;
  397.   int i,j,xdist,ydist,xmot,ymot;
  398.   char *arg;
  399.  
  400.   CurX = 1000; CurY = 1000;
  401.   Wflg = 0; Cflg = 0;
  402.   CBugs = 5;
  403.  
  404.   errflg = 0;
  405.   while ((c = getopt(argc, argv, "cCwW")) != EOF) {
  406.     switch(c) {
  407.       case '?':
  408.         errflg = 1;
  409.         break;
  410.  
  411.       case 'c':
  412.       case 'C':
  413.         Cflg++;
  414.         break;
  415.  
  416.       case 'w':
  417.       case 'W' :
  418.         Wflg++;
  419.         break;
  420.     }
  421.   }
  422.  
  423.   if (optind < argc) {
  424.     CBugs = atoi(argv[optind++]);
  425.   }
  426.   if (optind < argc) {
  427.     fprintf(stderr, "error: unexpected argument '%s'\n", argv[optind]);
  428.     errflg = 1;
  429.   }
  430.   if (errflg != 0) {
  431.     fprintf(stderr, "usage: [-c] [-w] [nr_of_bugs]\n");
  432.     exit(EXIT_FAILURE);
  433.   }
  434.  
  435.   if (CBugs>NBUGS) CBugs=NBUGS;
  436.  
  437.   initscr();
  438.   noecho();
  439.   nodelay(stdscr, TRUE);
  440.   cbreak();
  441.   clear();
  442.   Top = LINES-1; Right = COLS-2;  
  443.  
  444.   if (Wflg) {
  445.     for (i=LEFT; i<Right; i++) placech('-',i,Top);
  446.     for (i=Top; i>BOT; i--) placech('|',Right,i);
  447.     for (i=LEFT; i<Right; i++) placech('-',i,BOT);
  448.     for (i=Top; i>BOT; i--) placech('|',LEFT,i);
  449.   }
  450.  
  451.   for (i=0; i<CBugs; i++) {
  452.     randbug(&bugs[i]);
  453.   }
  454.  
  455.   /*  3.  Bug!  */
  456.  
  457.   for (;;) {
  458.  
  459.     /*  Had enough?  */
  460.  
  461.     if (getch() != ERR) {    /* Key hit - quit */
  462.       break;
  463.     }
  464.  
  465.     i = rand() % CBugs;
  466.     if (!alive(&bugs[i])) {
  467.       randbug(&bugs[i]);
  468.     } else {
  469.       step(&bugs[i]);
  470.       j = (bugs[i]).State;
  471.       xmot = XMotion[(bugs[i]).Dir];
  472.       ymot = YMotion[(bugs[i]).Dir];
  473.       if ((j == 0) || (j == 20)) {
  474.         if (Wflg) {
  475.       xdist = (bugs[i]).X;
  476.       ydist = xdist-Right;
  477.       if ((xmot>0) && (ydist<0) && (ydist*ydist < RADIUS2))
  478.         turn(&bugs[i]);
  479.       ydist = xdist-LEFT;
  480.       if ((xmot<0)&&(ydist>0) && (ydist*ydist < RADIUS2))
  481.         turn(&bugs[i]);
  482.       xdist = (bugs[i]).Y;
  483.       ydist = xdist-Top;
  484.       if ((ymot>0)&&(ydist<0) && (ydist*ydist < RADIUS2))
  485.         turn(&bugs[i]);
  486.       ydist = xdist-BOT;
  487.       if ((ymot<0)&&(ydist>0) && (ydist*ydist < RADIUS2))
  488.         turn(&bugs[i]);
  489.         }
  490.       }
  491.  
  492.       if ((j == 0) || (j == 20)) {
  493.         for (j=0;j<CBugs;j++) {
  494.           if (j==i)
  495.             continue;
  496.       xdist = (bugs[j]).X - (bugs[i]).X;
  497.       ydist = (bugs[j]).Y - (bugs[i]).Y;
  498.       if ((xdist*xdist+ydist*ydist) < 21) {
  499.             if (((xdist*xmot)<=0) && ((ydist*ymot)<=0))
  500.           continue;
  501.         turn(&bugs[i]);
  502.         break;
  503.           }
  504.         }
  505.         if (!(rand()%15))
  506.           turn(&bugs[i]);
  507.       }
  508.     }
  509.   }
  510.  
  511.   /*  4.  Clean up and exit:  */
  512.  
  513.   endwin();
  514.  
  515.   return EXIT_SUCCESS;
  516. }
  517.