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

bsd-games/2.17/worm/worm.c

    1: /*      $NetBSD: worm.c,v 1.25 2004/01/27 20:30:31 jsm 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[] = "@(#)worm.c      8.1 (Berkeley) 5/31/93";
   41: #else
   42: __RCSID("$NetBSD: worm.c,v 1.25 2004/01/27 20:30:31 jsm Exp $");
   43: #endif
   44: #endif /* not lint */
   45: 
   46: /*
   47:  * Worm.  Written by Michael Toy
   48:  * UCSC
   49:  */
   50: 
   51: #include <ctype.h>
   52: #include <curses.h>
   53: #include <err.h>
   54: #include <signal.h>
   55: #include <stdlib.h>
   56: #include <termios.h>
   57: #include <unistd.h>
   58: 
   59: #define newlink() (struct body *) malloc(sizeof (struct body));
   60: #define HEAD '@'
   61: #define BODY 'o'
   62: #define LENGTH 7
   63: #define RUNLEN 8
   64: #define CNTRL(p) (p-'A'+1)
   65: 
   66: WINDOW *tv;
   67: WINDOW *stw;
   68: struct body {
   69:         int x;
   70:         int y;
   71:         struct body *prev;
   72:         struct body *next;
   73: } *head, *tail, goody;
   74: int growing = 0;
   75: int running = 0;
   76: int slow = 0;
   77: int score = 0;
   78: int start_len = LENGTH;
   79: int visible_len;
   80: int lastch;
   81: char outbuf[BUFSIZ];
   82: 
   83: void    crash(void) __attribute__((__noreturn__));
   84: void    display(const struct body *, char);
   85: int     main(int, char **);
   86: void    leave(int) __attribute__((__noreturn__));
   87: void    life(void);
   88: void    newpos(struct body *);
   89: void    process(int);
   90: void    prize(void);
   91: int     rnd(int);
   92: void    setup(void);
   93: void    wake(int);
   94: 
   95: int
   96: main(argc, argv)
   97:         int argc;
   98:         char **argv;
   99: {
  100: 
  101:         /* Revoke setgid privileges */
  102:         setregid(getgid(), getgid());
  103: 
  104:         setbuf(stdout, outbuf);
  105:         srand(getpid());
  106:         signal(SIGALRM, wake);
  107:         signal(SIGINT, leave);
  108:         signal(SIGQUIT, leave);
  109:         initscr();
  110:         cbreak();
  111:         noecho();
  112: #ifdef KEY_LEFT
  113:         keypad(stdscr, TRUE);
  114: #endif
  115:         slow = (baudrate() <= 1200);
  116:         clear();
  117:         if (COLS < 18 || LINES < 5) {
  118:                 /*
  119:                  * Insufficient room for the line with " Worm" and the
  120:                  * score if fewer than 18 columns; insufficient room for
  121:                  * anything much if fewer than 5 lines.
  122:                  */
  123:                 endwin();
  124:                 errx(1, "screen too small");
  125:         }
  126:         if (argc == 2)
  127:                 start_len = atoi(argv[1]);
  128:         if ((start_len <= 0) || (start_len > ((LINES-3) * (COLS-2)) / 3))
  129:                 start_len = LENGTH;
  130:         stw = newwin(1, COLS-1, 0, 0);
  131:         tv = newwin(LINES-1, COLS-1, 1, 0);
  132:         box(tv, '*', '*');
  133:         scrollok(tv, FALSE);
  134:         scrollok(stw, FALSE);
  135:         wmove(stw, 0, 0);
  136:         wprintw(stw, " Worm");
  137:         refresh();
  138:         wrefresh(stw);
  139:         wrefresh(tv);
  140:         life();                        /* Create the worm */
  141:         prize();               /* Put up a goal */
  142:         while(1)
  143:         {
  144:                 if (running)
  145:                 {
  146:                         running--;
  147:                         process(lastch);
  148:                 }
  149:                 else
  150:                 {
  151:                     fflush(stdout);
  152:                     process(getch());
  153:                 }
  154:         }
  155: }
  156: 
  157: void
  158: life()
  159: {
  160:         struct body *bp, *np;
  161:         int i, j = 1;
  162: 
  163:         np = NULL;
  164:         head = newlink();
  165:         if (head == NULL)
  166:                 err(1, NULL);
  167:         head->x = start_len % (COLS-5) + 2;
  168:         head->y = LINES / 2;
  169:         head->next = NULL;
  170:         display(head, HEAD);
  171:         for (i = 0, bp = head; i < start_len; i++, bp = np) {
  172:                 np = newlink();
  173:                 if (np == NULL)
  174:                         err(1, NULL);
  175:                 np->next = bp;
  176:                 bp->prev = np;
  177:                 if (((bp->x <= 2) && (j == 1)) || ((bp->x >= COLS-4) && (j == -1))) {
  178:                         j *= -1;
  179:                         np->x = bp->x;
  180:                         np->y = bp->y + 1;
  181:                 } else {
  182:                         np->x = bp->x - j;
  183:                         np->y = bp->y;
  184:                 }
  185:                 display(np, BODY);
  186:         }
  187:         tail = np;
  188:         tail->prev = NULL;
  189:         visible_len = start_len + 1;
  190: }
  191: 
  192: void
  193: display(pos, chr)
  194:         const struct body *pos;
  195:         char chr;
  196: {
  197:         wmove(tv, pos->y, pos->x);
  198:         waddch(tv, chr);
  199: }
  200: 
  201: void
  202: leave(dummy)
  203:         int dummy;
  204: {
  205:         endwin();
  206: 
  207:         if (dummy == 0){       /* called via crash() */
  208:                 printf("\nWell, you ran into something and the game is over.\n");
  209:                 printf("Your final score was %d\n\n", score);
  210:         }
  211:         exit(0);
  212: }
  213: 
  214: void
  215: wake(dummy)
  216:         int dummy __attribute__((__unused__));
  217: {
  218:         signal(SIGALRM, wake);
  219:         fflush(stdout);
  220:         process(lastch);
  221: }
  222: 
  223: int
  224: rnd(range)
  225:         int range;
  226: {
  227:         return abs((rand()>>5)+(rand()>>5)) % range;
  228: }
  229: 
  230: void
  231: newpos(bp)
  232:         struct body * bp;
  233: {
  234:         if (visible_len == (LINES-3) * (COLS-3) - 1) {
  235:                 endwin();
  236: 
  237:                 printf("\nYou won!\n");
  238:                 printf("Your final score was %d\n\n", score);
  239:                 exit(0);
  240:         }
  241:         do {
  242:                 bp->y = rnd(LINES-3)+ 1;
  243:                 bp->x = rnd(COLS-3) + 1;
  244:                 wmove(tv, bp->y, bp->x);
  245:         } while(winch(tv) != ' ');
  246: }
  247: 
  248: void
  249: prize()
  250: {
  251:         int value;
  252: 
  253:         value = rnd(9) + 1;
  254:         newpos(&goody);
  255:         waddch(tv, value+'0');
  256:         wrefresh(tv);
  257: }
  258: 
  259: void
  260: process(ch)
  261:         int ch;
  262: {
  263:         int x,y;
  264:         struct body *nh;
  265: 
  266:         alarm(0);
  267:         x = head->x;
  268:         y = head->y;
  269:         switch(ch)
  270:         {
  271: #ifdef KEY_LEFT
  272:                 case KEY_LEFT:
  273: #endif
  274:                 case 'h':
  275:                         x--; break;
  276: 
  277: #ifdef KEY_DOWN
  278:                 case KEY_DOWN:
  279: #endif
  280:                 case 'j':
  281:                         y++; break;
  282: 
  283: #ifdef KEY_UP
  284:                 case KEY_UP:
  285: #endif
  286:                 case 'k':
  287:                         y--; break;
  288: 
  289: #ifdef KEY_RIGHT
  290:                 case KEY_RIGHT:
  291: #endif
  292:                 case 'l':
  293:                         x++; break;
  294: 
  295:                 case 'H': x--; running = RUNLEN; ch = tolower(ch); break;
  296:                 case 'J': y++; running = RUNLEN/2; ch = tolower(ch); break;
  297:                 case 'K': y--; running = RUNLEN/2; ch = tolower(ch); break;
  298:                 case 'L': x++; running = RUNLEN; ch = tolower(ch); break;
  299:                 case '\f': setup(); return;
  300: 
  301:                 case ERR:
  302:                 case CNTRL('C'):
  303:                 case CNTRL('D'):
  304:                         crash();
  305:                         return;
  306: 
  307:                 default: if (! running) alarm(1);
  308:                            return;
  309:         }
  310:         lastch = ch;
  311:         if (growing == 0)
  312:         {
  313:                 display(tail, ' ');
  314:                 tail->next->prev = NULL;
  315:                 nh = tail->next;
  316:                 free(tail);
  317:                 tail = nh;
  318:                 visible_len--;
  319:         }
  320:         else growing--;
  321:         display(head, BODY);
  322:         wmove(tv, y, x);
  323:         if (isdigit(ch = winch(tv)))
  324:         {
  325:                 growing += ch-'0';
  326:                 prize();
  327:                 score += growing;
  328:                 running = 0;
  329:                 wmove(stw, 0, COLS - 12);
  330:                 wprintw(stw, "Score: %3d", score);
  331:                 wrefresh(stw);
  332:         }
  333:         else if(ch != ' ') crash();
  334:         nh = newlink();
  335:         if (nh == NULL)
  336:                 err(1, NULL);
  337:         nh->next = NULL;
  338:         nh->prev = head;
  339:         head->next = nh;
  340:         nh->y = y;
  341:         nh->x = x;
  342:         display(nh, HEAD);
  343:         head = nh;
  344:         visible_len++;
  345:         if (!(slow && running))
  346:         {
  347:                 wmove(tv, head->y, head->x);
  348:                 wrefresh(tv);
  349:         }
  350:         if (!running)
  351:                 alarm(1);
  352: }
  353: 
  354: void
  355: crash()
  356: {
  357:         leave(0);
  358: }
  359: 
  360: void
  361: setup()
  362: {
  363:         clear();
  364:         refresh();
  365:         touchwin(stw);
  366:         wrefresh(stw);
  367:         touchwin(tv);
  368:         wrefresh(tv);
  369:         alarm(1);
  370: }
Syntax (Markdown)