(linenum→info "unix/slp.c:2238")

bsd-games/2.17/worms/worms.c

    1: /*      $NetBSD: worms.c,v 1.16 2004/09/12 04:51:32 christos Exp $   */
    2: 
    3: /*
    4:  * Copyright (c) 1980, 1993
    5:  *      The Regents of the University of California.  All rights reserved.
    6:  *
    7:  * Redistribution and use in source and binary forms, with or without
    8:  * modification, are permitted provided that the following conditions
    9:  * are met:
   10:  * 1. Redistributions of source code must retain the above copyright
   11:  *    notice, this list of conditions and the following disclaimer.
   12:  * 2. Redistributions in binary form must reproduce the above copyright
   13:  *    notice, this list of conditions and the following disclaimer in the
   14:  *    documentation and/or other materials provided with the distribution.
   15:  * 3. Neither the name of the University nor the names of its contributors
   16:  *    may be used to endorse or promote products derived from this software
   17:  *    without specific prior written permission.
   18:  *
   19:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29:  * SUCH DAMAGE.
   30:  */
   31: 
   32: #include <sys/cdefs.h>
   33: #ifndef lint
   34: __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
   35:         The Regents of the University of California.  All rights reserved.\n");
   36: #endif /* not lint */
   37: 
   38: #ifndef lint
   39: #if 0
   40: static char sccsid[] = "@(#)worms.c     8.1 (Berkeley) 5/31/93";
   41: #else
   42: __RCSID("$NetBSD: worms.c,v 1.16 2004/09/12 04:51:32 christos Exp $");
   43: #endif
   44: #endif /* not lint */
   45: 
   46: /*
   47:  *
   48:  *       @@@        @@@    @@@@@@@@@@     @@@@@@@@@@@    @@@@@@@@@@@@
   49:  *       @@@        @@@   @@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@@@@@
   50:  *       @@@        @@@  @@@@      @@@@   @@@@           @@@@ @@@  @@@@
   51:  *       @@@   @@   @@@  @@@        @@@   @@@            @@@  @@@   @@@
   52:  *       @@@  @@@@  @@@  @@@        @@@   @@@            @@@  @@@   @@@
   53:  *       @@@@ @@@@ @@@@  @@@        @@@   @@@            @@@  @@@   @@@
   54:  *        @@@@@@@@@@@@   @@@@      @@@@   @@@            @@@  @@@   @@@
   55:  *         @@@@  @@@@     @@@@@@@@@@@@    @@@            @@@  @@@   @@@
   56:  *          @@    @@       @@@@@@@@@@     @@@            @@@  @@@   @@@
   57:  *
   58:  *                               Eric P. Scott
   59:  *                        Caltech High Energy Physics
   60:  *                               October, 1980
   61:  *
   62:  */
   63: #include <sys/types.h>
   64: 
   65: #include <curses.h>
   66: #include <err.h>
   67: #include <signal.h>
   68: #include <stdio.h>
   69: #include <stdlib.h>
   70: #include <unistd.h>
   71: 
   72: static const struct options {
   73:         int nopts;
   74:         int opts[3];
   75: }
   76:         normal[8] = {
   77:         { 3, { 7, 0, 1 } },
   78:         { 3, { 0, 1, 2 } },
   79:         { 3, { 1, 2, 3 } },
   80:         { 3, { 2, 3, 4 } },
   81:         { 3, { 3, 4, 5 } },
   82:         { 3, { 4, 5, 6 } },
   83:         { 3, { 5, 6, 7 } },
   84:         { 3, { 6, 7, 0 } }
   85: },      upper[8] = {
   86:         { 1, { 1, 0, 0 } },
   87:         { 2, { 1, 2, 0 } },
   88:         { 0, { 0, 0, 0 } },
   89:         { 0, { 0, 0, 0 } },
   90:         { 0, { 0, 0, 0 } },
   91:         { 2, { 4, 5, 0 } },
   92:         { 1, { 5, 0, 0 } },
   93:         { 2, { 1, 5, 0 } }
   94: },
   95:         left[8] = {
   96:         { 0, { 0, 0, 0 } },
   97:         { 0, { 0, 0, 0 } },
   98:         { 0, { 0, 0, 0 } },
   99:         { 2, { 2, 3, 0 } },
  100:         { 1, { 3, 0, 0 } },
  101:         { 2, { 3, 7, 0 } },
  102:         { 1, { 7, 0, 0 } },
  103:         { 2, { 7, 0, 0 } }
  104: },
  105:         right[8] = {
  106:         { 1, { 7, 0, 0 } },
  107:         { 2, { 3, 7, 0 } },
  108:         { 1, { 3, 0, 0 } },
  109:         { 2, { 3, 4, 0 } },
  110:         { 0, { 0, 0, 0 } },
  111:         { 0, { 0, 0, 0 } },
  112:         { 0, { 0, 0, 0 } },
  113:         { 2, { 6, 7, 0 } }
  114: },
  115:         lower[8] = {
  116:         { 0, { 0, 0, 0 } },
  117:         { 2, { 0, 1, 0 } },
  118:         { 1, { 1, 0, 0 } },
  119:         { 2, { 1, 5, 0 } },
  120:         { 1, { 5, 0, 0 } },
  121:         { 2, { 5, 6, 0 } },
  122:         { 0, { 0, 0, 0 } },
  123:         { 0, { 0, 0, 0 } }
  124: },
  125:         upleft[8] = {
  126:         { 0, { 0, 0, 0 } },
  127:         { 0, { 0, 0, 0 } },
  128:         { 0, { 0, 0, 0 } },
  129:         { 0, { 0, 0, 0 } },
  130:         { 0, { 0, 0, 0 } },
  131:         { 1, { 3, 0, 0 } },
  132:         { 2, { 1, 3, 0 } },
  133:         { 1, { 1, 0, 0 } }
  134: },
  135:         upright[8] = {
  136:         { 2, { 3, 5, 0 } },
  137:         { 1, { 3, 0, 0 } },
  138:         { 0, { 0, 0, 0 } },
  139:         { 0, { 0, 0, 0 } },
  140:         { 0, { 0, 0, 0 } },
  141:         { 0, { 0, 0, 0 } },
  142:         { 0, { 0, 0, 0 } },
  143:         { 1, { 5, 0, 0 } }
  144: },
  145:         lowleft[8] = {
  146:         { 3, { 7, 0, 1 } },
  147:         { 0, { 0, 0, 0 } },
  148:         { 0, { 0, 0, 0 } },
  149:         { 1, { 1, 0, 0 } },
  150:         { 2, { 1, 7, 0 } },
  151:         { 1, { 7, 0, 0 } },
  152:         { 0, { 0, 0, 0 } },
  153:         { 0, { 0, 0, 0 } }
  154: },
  155:         lowright[8] = {
  156:         { 0, { 0, 0, 0 } },
  157:         { 1, { 7, 0, 0 } },
  158:         { 2, { 5, 7, 0 } },
  159:         { 1, { 5, 0, 0 } },
  160:         { 0, { 0, 0, 0 } },
  161:         { 0, { 0, 0, 0 } },
  162:         { 0, { 0, 0, 0 } },
  163:         { 0, { 0, 0, 0 } }
  164: };
  165: 
  166: 
  167: static const char       flavor[] = {
  168:         'O', '*', '#', '$', '%', '0', '@', '~'
  169: };
  170: static const short      xinc[] = {
  171:         1,  1,  1,  0, -1, -1, -1,  0
  172: }, yinc[] = {
  173:         -1,  0,  1,  1,  1,  0, -1, -1
  174: };
  175: static struct   worm {
  176:         int orientation, head;
  177:         short *xpos, *ypos;
  178: } *worm;
  179: 
  180: volatile sig_atomic_t sig_caught = 0;
  181: 
  182: int      main(int, char **);
  183: void     nomem(void) __attribute__((__noreturn__));
  184: void     onsig(int);
  185: 
  186: int
  187: main(argc, argv)
  188:         int argc;
  189:         char *argv[];
  190: {
  191:         int x, y, h, n;
  192:         struct worm *w;
  193:         const struct options *op;
  194:         short *ip;
  195:         int CO, LI, last, bottom, ch, length, number, trail;
  196:         short **ref;
  197:         const char *field;
  198:         char *mp;
  199:         unsigned int delay = 0;
  200: 
  201:         /* Revoke setgid privileges */
  202:         setregid(getgid(), getgid());
  203: 
  204:         mp = NULL;
  205:         length = 16;
  206:         number = 3;
  207:         trail = ' ';
  208:         field = NULL;
  209:         while ((ch = getopt(argc, argv, "d:fl:n:t")) != -1)
  210:                 switch(ch) {
  211:                 case 'd':
  212:                         if ((delay = (unsigned int)strtoul(optarg, (char **)NULL, 10)) < 1 || delay > 1000)
  213:                                 errx(1, "invalid delay (1-1000)");
  214:                         delay *= 1000;  /* ms -> us */
  215:                         break;
  216:                 case 'f':
  217:                         field = "WORM";
  218:                         break;
  219:                 case 'l':
  220:                         if ((length = atoi(optarg)) < 2 || length > 1024) {
  221:                                 errx(1, "invalid length (%d - %d).",
  222:                                      2, 1024);
  223:                         }
  224:                         break;
  225:                 case 'n':
  226:                         if ((number = atoi(optarg)) < 1) {
  227:                                 errx(1, "invalid number of worms.");
  228:                         }
  229:                         break;
  230:                 case 't':
  231:                         trail = '.';
  232:                         break;
  233:                 case '?':
  234:                 default:
  235:                         (void)fprintf(stderr,
  236:                             "usage: worms [-ft] [-d delay] [-l length] [-n number]\n");
  237:                         exit(1);
  238:                 }
  239: 
  240:         if (!(worm = malloc((size_t)number *
  241:             sizeof(struct worm))) || !(mp = malloc((size_t)1024)))
  242:                 nomem();
  243:         initscr();
  244:         curs_set(0);
  245:         CO = COLS;
  246:         LI = LINES;
  247:         last = CO - 1;
  248:         bottom = LI - 1;
  249:         if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
  250:                 nomem();
  251:         if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
  252:                 nomem();
  253:         for (n = 0; n < LI; ++n) {
  254:                 ref[n] = ip;
  255:                 ip += CO;
  256:         }
  257:         for (ip = ref[0], n = LI * CO; --n >= 0;)
  258:                 *ip++ = 0;
  259:         for (n = number, w = &worm[0]; --n >= 0; w++) {
  260:                 w->orientation = w->head = 0;
  261:                 if (!(ip = malloc((size_t)(length * sizeof(short)))))
  262:                         nomem();
  263:                 w->xpos = ip;
  264:                 for (x = length; --x >= 0;)
  265:                         *ip++ = -1;
  266:                 if (!(ip = malloc((size_t)(length * sizeof(short)))))
  267:                         nomem();
  268:                 w->ypos = ip;
  269:                 for (y = length; --y >= 0;)
  270:                         *ip++ = -1;
  271:         }
  272: 
  273:         (void)signal(SIGHUP, onsig);
  274:         (void)signal(SIGINT, onsig);
  275:         (void)signal(SIGQUIT, onsig);
  276:         (void)signal(SIGTSTP, onsig);
  277:         (void)signal(SIGTERM, onsig);
  278: 
  279:         if (field) {
  280:                 const char *p = field;
  281: 
  282:                 for (y = LI; --y >= 0;) {
  283:                         for (x = CO; --x >= 0;) {
  284:                                 addch(*p++);
  285:                                 if (!*p)
  286:                                         p = field;
  287:                         }
  288:                         refresh();
  289:                 }
  290:         }
  291:         for (;;) {
  292:                 refresh();
  293:                 if (sig_caught) {
  294:                         endwin();
  295:                         exit(0);
  296:                 }
  297:                 if (delay) {
  298:                         if (delay % 1000000 != 0)
  299:                                 usleep(delay % 1000000);
  300:                         if (delay >= 1000000)
  301:                                 sleep(delay / 1000000);
  302:                 }
  303:                 for (n = 0, w = &worm[0]; n < number; n++, w++) {
  304:                         if ((x = w->xpos[h = w->head]) < 0) {
  305:                                 mvaddch(y = w->ypos[h] = bottom,
  306:                                         x = w->xpos[h] = 0,
  307:                                         flavor[n % sizeof(flavor)]);
  308:                                 ref[y][x]++;
  309:                         }
  310:                         else
  311:                                 y = w->ypos[h];
  312:                         if (++h == length)
  313:                                 h = 0;
  314:                         if (w->xpos[w->head = h] >= 0) {
  315:                                 int x1, y1;
  316: 
  317:                                 x1 = w->xpos[h];
  318:                                 y1 = w->ypos[h];
  319:                                 if (--ref[y1][x1] == 0) {
  320:                                         mvaddch(y1, x1, trail);
  321:                                 }
  322:                         }
  323:                         op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
  324:                         switch (op->nopts) {
  325:                         case 0:
  326:                                 refresh();
  327:                                 abort();
  328:                                 return(1);
  329:                         case 1:
  330:                                 w->orientation = op->opts[0];
  331:                                 break;
  332:                         default:
  333:                                 w->orientation =
  334:                                     op->opts[(int)random() % op->nopts];
  335:                         }
  336:                         mvaddch(y += yinc[w->orientation],
  337:                                 x += xinc[w->orientation],
  338:                                 flavor[n % sizeof(flavor)]);
  339:                         ref[w->ypos[h] = y][w->xpos[h] = x]++;
  340:                 }
  341:         }
  342: }
  343: 
  344: void
  345: onsig(signo)
  346:         int signo __attribute__((__unused__));
  347: {
  348:         sig_caught = 1;
  349: }
  350: 
  351: void
  352: nomem()
  353: {
  354:         errx(1, "not enough memory.");
  355: }
Syntax (Markdown)