home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / worms / worms.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  10.3 KB  |  445 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1980 Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)worms.c    5.9 (Berkeley) 2/28/91";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  *
  46.  *     @@@        @@@    @@@@@@@@@@     @@@@@@@@@@@    @@@@@@@@@@@@
  47.  *     @@@        @@@   @@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@@@@@
  48.  *     @@@        @@@  @@@@      @@@@   @@@@           @@@@ @@@  @@@@
  49.  *     @@@   @@   @@@  @@@        @@@   @@@            @@@  @@@   @@@
  50.  *     @@@  @@@@  @@@  @@@        @@@   @@@            @@@  @@@   @@@
  51.  *     @@@@ @@@@ @@@@  @@@        @@@   @@@            @@@  @@@   @@@
  52.  *      @@@@@@@@@@@@   @@@@      @@@@   @@@            @@@  @@@   @@@
  53.  *       @@@@  @@@@     @@@@@@@@@@@@    @@@            @@@  @@@   @@@
  54.  *        @@    @@       @@@@@@@@@@     @@@            @@@  @@@   @@@
  55.  *
  56.  *                 Eric P. Scott
  57.  *              Caltech High Energy Physics
  58.  *                 October, 1980
  59.  *
  60.  */
  61. #include <sys/types.h>
  62. #include <stdio.h>
  63. #ifdef USG
  64. #include <termio.h>
  65. #else
  66. #include <sgtty.h>
  67. #endif
  68. #include <signal.h>
  69.  
  70. static struct options {
  71.     int nopts;
  72.     int opts[3];
  73. }
  74.     normal[8] = {
  75.     { 3, { 7, 0, 1 } },
  76.     { 3, { 0, 1, 2 } },
  77.     { 3, { 1, 2, 3 } },
  78.     { 3, { 2, 3, 4 } },
  79.     { 3, { 3, 4, 5 } },
  80.     { 3, { 4, 5, 6 } },
  81.     { 3, { 5, 6, 7 } },
  82.     { 3, { 6, 7, 0 } }
  83. },    upper[8] = {
  84.     { 1, { 1, 0, 0 } },
  85.     { 2, { 1, 2, 0 } },
  86.     { 0, { 0, 0, 0 } },
  87.     { 0, { 0, 0, 0 } },
  88.     { 0, { 0, 0, 0 } },
  89.     { 2, { 4, 5, 0 } },
  90.     { 1, { 5, 0, 0 } },
  91.     { 2, { 1, 5, 0 } }
  92. },
  93.     left[8] = {
  94.     { 0, { 0, 0, 0 } },
  95.     { 0, { 0, 0, 0 } },
  96.     { 0, { 0, 0, 0 } },
  97.     { 2, { 2, 3, 0 } },
  98.     { 1, { 3, 0, 0 } },
  99.     { 2, { 3, 7, 0 } },
  100.     { 1, { 7, 0, 0 } },
  101.     { 2, { 7, 0, 0 } }
  102. },
  103.     right[8] = {
  104.     { 1, { 7, 0, 0 } },
  105.     { 2, { 3, 7, 0 } },
  106.     { 1, { 3, 0, 0 } },
  107.     { 2, { 3, 4, 0 } },
  108.     { 0, { 0, 0, 0 } },
  109.     { 0, { 0, 0, 0 } },
  110.     { 0, { 0, 0, 0 } },
  111.     { 2, { 6, 7, 0 } }
  112. },
  113.     lower[8] = {
  114.     { 0, { 0, 0, 0 } },
  115.     { 2, { 0, 1, 0 } },
  116.     { 1, { 1, 0, 0 } },
  117.     { 2, { 1, 5, 0 } },
  118.     { 1, { 5, 0, 0 } },
  119.     { 2, { 5, 6, 0 } },
  120.     { 0, { 0, 0, 0 } },
  121.     { 0, { 0, 0, 0 } }
  122. },
  123.     upleft[8] = {
  124.     { 0, { 0, 0, 0 } },
  125.     { 0, { 0, 0, 0 } },
  126.     { 0, { 0, 0, 0 } },
  127.     { 0, { 0, 0, 0 } },
  128.     { 0, { 0, 0, 0 } },
  129.     { 1, { 3, 0, 0 } },
  130.     { 2, { 1, 3, 0 } },
  131.     { 1, { 1, 0, 0 } }
  132. },
  133.     upright[8] = {
  134.     { 2, { 3, 5, 0 } },
  135.     { 1, { 3, 0, 0 } },
  136.     { 0, { 0, 0, 0 } },
  137.     { 0, { 0, 0, 0 } },
  138.     { 0, { 0, 0, 0 } },
  139.     { 0, { 0, 0, 0 } },
  140.     { 0, { 0, 0, 0 } },
  141.     { 1, { 5, 0, 0 } }
  142. },
  143.     lowleft[8] = {
  144.     { 3, { 7, 0, 1 } },
  145.     { 0, { 0, 0, 0 } },
  146.     { 0, { 0, 0, 0 } },
  147.     { 1, { 1, 0, 0 } },
  148.     { 2, { 1, 7, 0 } },
  149.     { 1, { 7, 0, 0 } },
  150.     { 0, { 0, 0, 0 } },
  151.     { 0, { 0, 0, 0 } }
  152. },
  153.     lowright[8] = {
  154.     { 0, { 0, 0, 0 } },
  155.     { 1, { 7, 0, 0 } },
  156.     { 2, { 5, 7, 0 } },
  157.     { 1, { 5, 0, 0 } },
  158.     { 0, { 0, 0, 0 } },
  159.     { 0, { 0, 0, 0 } },
  160.     { 0, { 0, 0, 0 } },
  161.     { 0, { 0, 0, 0 } }
  162. };
  163.  
  164. #define    cursor(c, r)    tputs(tgoto(CM, c, r), 1, fputchar)
  165.  
  166. char *tcp;
  167. int fputchar();
  168.  
  169. static char    flavor[] = {
  170.     'O', '*', '#', '$', '%', '0', '@', '~'
  171. };
  172. static short    xinc[] = {
  173.     1,  1,  1,  0, -1, -1, -1,  0
  174. }, yinc[] = {
  175.     -1,  0,  1,  1,  1,  0, -1, -1
  176. };
  177. static struct    worm {
  178.     int orientation, head;
  179.     short *xpos, *ypos;
  180. } *worm;
  181.  
  182. main(argc, argv)
  183.     int argc;
  184.     char **argv;
  185. {
  186.     extern int optind;
  187.     extern short ospeed;
  188.     extern char *optarg, *UP;
  189.     register int x, y, h, n;
  190.     register struct worm *w;
  191.     register struct options *op;
  192.     register short *ip;
  193.     register char *term;
  194.     int CO, IN, LI, last, bottom, ch, length, number, trail, Wrap;
  195.     void onsig();
  196.     short **ref;
  197.     char *AL, *BC, *CM, *EI, *HO, *IC, *IM, *IP, *SR;
  198.     char *field, tcb[100], *mp, *malloc(), *getenv(), *tgetstr(), *tgoto();
  199.     long random();
  200. #ifdef USG
  201.     struct termio sg;
  202. #else
  203.     struct sgttyb sg;
  204. #endif
  205.  
  206.     length = 16;
  207.     number = 3;
  208.     trail = ' ';
  209.     field = NULL;
  210.     while ((ch = getopt(argc, argv, "fl:n:t")) != EOF)
  211.         switch(ch) {
  212.         case 'f':
  213.             field = "WORM";
  214.             break;
  215.         case 'l':
  216.             if ((length = atoi(optarg)) < 2 || length > 1024) {
  217.                 (void)fprintf(stderr,
  218.                     "worms: invalid length (%d - %d).\n",
  219.                      2, 1024);
  220.                 exit(1);
  221.             }
  222.             break;
  223.         case 'n':
  224.             if ((number = atoi(optarg)) < 1) {
  225.                 (void)fprintf(stderr,
  226.                     "worms: invalid number of worms.\n");
  227.                 exit(1);
  228.             }
  229.             break;
  230.         case 't':
  231.             trail = '.';
  232.             break;
  233.         case '?':
  234.         default:
  235.             (void)fprintf(stderr,
  236.                 "usage: worms [-ft] [-length #] [-number #]\n");
  237.             exit(1);
  238.         }
  239.  
  240.     if (!(term = getenv("TERM"))) {
  241.         (void)fprintf(stderr, "worms: no TERM environment variable.\n");
  242.         exit(1);
  243.     }
  244.     if (!(worm = (struct worm *)malloc((u_int)number *
  245.         sizeof(struct worm))) || !(mp = malloc((u_int)1024)))
  246.         nomem();
  247.     if (tgetent(mp, term) <= 0) {
  248.         (void)fprintf(stderr, "worms: %s: unknown terminal type.\n",
  249.             term);
  250.         exit(1);
  251.     }
  252.     tcp = tcb;
  253.     if (!(CM = tgetstr("cm", &tcp))) {
  254.         (void)fprintf(stderr,
  255.             "worms: terminal incapable of cursor motion.\n");
  256.         exit(1);
  257.     }
  258.     AL = tgetstr("al", &tcp);
  259.     BC = tgetflag("bs") ? "\b" : tgetstr("bc", &tcp);
  260.     if ((CO = tgetnum("co")) <= 0)
  261.         CO = 80;
  262.     last = CO - 1;
  263.     EI = tgetstr("ei", &tcp);
  264.     HO = tgetstr("ho", &tcp);
  265.     IC = tgetstr("ic", &tcp);
  266.     IM = tgetstr("im", &tcp);
  267.     IN = tgetflag("in");
  268.     IP = tgetstr("ip", &tcp);
  269.     if ((LI = tgetnum("li")) <= 0)
  270.         LI = 24;
  271.     bottom = LI - 1;
  272.     SR = tgetstr("sr", &tcp);
  273.     UP = tgetstr("up", &tcp);
  274. #ifdef USG
  275.     ioctl(1, TCGETA, &sg);
  276.     ospeed = sg.c_cflag&CBAUD;
  277. #else
  278.     gtty(1, &sg);
  279.     ospeed = sg.sg_ospeed;
  280. #endif
  281.     Wrap = tgetflag("am");
  282.     if (!(ip = (short *)malloc((u_int)(LI * CO * sizeof(short)))))
  283.         nomem();
  284.     if (!(ref = (short **)malloc((u_int)(LI * sizeof(short *)))))
  285.         nomem();
  286.     for (n = 0; n < LI; ++n) {
  287.         ref[n] = ip;
  288.         ip += CO;
  289.     }
  290.     for (ip = ref[0], n = LI * CO; --n >= 0;)
  291.         *ip++ = 0;
  292.     if (Wrap)
  293.         ref[bottom][last] = 1;
  294.     for (n = number, w = &worm[0]; --n >= 0; w++) {
  295.         w->orientation = w->head = 0;
  296.         if (!(ip = (short *)malloc((u_int)(length * sizeof(short)))))
  297.             nomem();
  298.         w->xpos = ip;
  299.         for (x = length; --x >= 0;)
  300.             *ip++ = -1;
  301.         if (!(ip = (short *)malloc((u_int)(length * sizeof(short)))))
  302.             nomem();
  303.         w->ypos = ip;
  304.         for (y = length; --y >= 0;)
  305.             *ip++ = -1;
  306.     }
  307.  
  308.     (void)signal(SIGHUP, onsig);
  309.     (void)signal(SIGINT, onsig);
  310.     (void)signal(SIGQUIT, onsig);
  311.     (void)signal(SIGSTOP, onsig);
  312.     (void)signal(SIGTSTP, onsig);
  313.     (void)signal(SIGTERM, onsig);
  314.  
  315.     tputs(tgetstr("ti", &tcp), 1, fputchar);
  316.     tputs(tgetstr("cl", &tcp), 1, fputchar);
  317.     if (field) {
  318.         register char *p = field;
  319.  
  320.         for (y = bottom; --y >= 0;) {
  321.             for (x = CO; --x >= 0;) {
  322.                 fputchar(*p++);
  323.                 if (!*p)
  324.                     p = field;
  325.             }
  326.             if (!Wrap)
  327.                 fputchar('\n');
  328.             (void)fflush(stdout);
  329.         }
  330.         if (Wrap) {
  331.             if (IM && !IN) {
  332.                 for (x = last; --x > 0;) {
  333.                     fputchar(*p++);
  334.                     if (!*p)
  335.                         p = field;
  336.                 }
  337.                 y = *p++;
  338.                 if (!*p)
  339.                     p = field;
  340.                 fputchar(*p);
  341.                 if (BC)
  342.                     tputs(BC, 1, fputchar);
  343.                 else
  344.                     cursor(last - 1, bottom);
  345.                 tputs(IM, 1, fputchar);
  346.                 if (IC)
  347.                     tputs(IC, 1, fputchar);
  348.                 fputchar(y);
  349.                 if (IP)
  350.                     tputs(IP, 1, fputchar);
  351.                 tputs(EI, 1, fputchar);
  352.             }
  353.             else if (SR || AL) {
  354.                 if (HO)
  355.                     tputs(HO, 1, fputchar);
  356.                 else
  357.                     cursor(0, 0);
  358.                 if (SR)
  359.                     tputs(SR, 1, fputchar);
  360.                 else
  361.                     tputs(AL, LI, fputchar);
  362.                 for (x = CO; --x >= 0;) {
  363.                     fputchar(*p++);
  364.                     if (!*p)
  365.                         p = field;
  366.                 }
  367.             }
  368.             else for (x = last; --x >= 0;) {
  369.                 fputchar(*p++);
  370.                 if (!*p)
  371.                     p = field;
  372.             }
  373.         }
  374.         else for (x = CO; --x >= 0;) {
  375.             fputchar(*p++);
  376.             if (!*p)
  377.                 p = field;
  378.         }
  379.     }
  380.     for (;;) {
  381.         (void)fflush(stdout);
  382.         for (n = 0, w = &worm[0]; n < number; n++, w++) {
  383.             if ((x = w->xpos[h = w->head]) < 0) {
  384.                 cursor(x = w->xpos[h] = 0,
  385.                      y = w->ypos[h] = bottom);
  386.                 fputchar(flavor[n % sizeof(flavor)]);
  387.                 ref[y][x]++;
  388.             }
  389.             else
  390.                 y = w->ypos[h];
  391.             if (++h == length)
  392.                 h = 0;
  393.             if (w->xpos[w->head = h] >= 0) {
  394.                 register int x1, y1;
  395.  
  396.                 x1 = w->xpos[h];
  397.                 y1 = w->ypos[h];
  398.                 if (--ref[y1][x1] == 0) {
  399.                     cursor(x1, y1);
  400.                     if (trail)
  401.                         fputchar(trail);
  402.                 }
  403.             }
  404.             op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
  405.             switch (op->nopts) {
  406.             case 0:
  407.                 (void)fflush(stdout);
  408.                 abort();
  409.                 return;
  410.             case 1:
  411.                 w->orientation = op->opts[0];
  412.                 break;
  413.             default:
  414.                 w->orientation =
  415.                     op->opts[(int)random() % op->nopts];
  416.             }
  417.             cursor(x += xinc[w->orientation],
  418.                 y += yinc[w->orientation]);
  419.             if (!Wrap || x != last || y != bottom)
  420.                 fputchar(flavor[n % sizeof(flavor)]);
  421.             ref[w->ypos[h] = y][w->xpos[h] = x]++;
  422.         }
  423.     }
  424. }
  425.  
  426. void
  427. onsig()
  428. {
  429.     tputs(tgetstr("cl", &tcp), 1, fputchar);
  430.     tputs(tgetstr("te", &tcp), 1, fputchar);
  431.     exit(0);
  432. }
  433.  
  434. fputchar(c)
  435.     char c;
  436. {
  437.     putchar(c);
  438. }
  439.  
  440. nomem()
  441. {
  442.     (void)fprintf(stderr, "worms: not enough memory.\n");
  443.     exit(1);
  444. }
  445.