Home | History | Annotate | Line # | Download | only in worm
worm.c revision 1.16.2.1
      1 /*	$NetBSD: worm.c,v 1.16.2.1 1999/12/27 18:29:06 wrstuden 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. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 #ifndef lint
     38 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
     39 	The Regents of the University of California.  All rights reserved.\n");
     40 #endif /* not lint */
     41 
     42 #ifndef lint
     43 #if 0
     44 static char sccsid[] = "@(#)worm.c	8.1 (Berkeley) 5/31/93";
     45 #else
     46 __RCSID("$NetBSD: worm.c,v 1.16.2.1 1999/12/27 18:29:06 wrstuden Exp $");
     47 #endif
     48 #endif /* not lint */
     49 
     50 /*
     51  * Worm.  Written by Michael Toy
     52  * UCSC
     53  */
     54 
     55 #include <ctype.h>
     56 #include <curses.h>
     57 #include <err.h>
     58 #include <signal.h>
     59 #include <stdlib.h>
     60 #include <termios.h>
     61 #include <unistd.h>
     62 
     63 #define newlink() (struct body *) malloc(sizeof (struct body));
     64 #define HEAD '@'
     65 #define BODY 'o'
     66 #define LENGTH 7
     67 #define RUNLEN 8
     68 #define CNTRL(p) (p-'A'+1)
     69 
     70 WINDOW *tv;
     71 WINDOW *stw;
     72 struct body {
     73 	int x;
     74 	int y;
     75 	struct body *prev;
     76 	struct body *next;
     77 } *head, *tail, goody;
     78 int growing = 0;
     79 int running = 0;
     80 int slow = 0;
     81 int score = 0;
     82 int start_len = LENGTH;
     83 int lastch;
     84 char outbuf[BUFSIZ];
     85 
     86 void	crash __P((void)) __attribute__((__noreturn__));
     87 void	display __P((const struct body *, char));
     88 int	main __P((int, char **));
     89 void	leave __P((int)) __attribute__((__noreturn__));
     90 void	life __P((void));
     91 void	newpos __P((struct body *));
     92 void	process __P((int));
     93 void	prize __P((void));
     94 int	rnd __P((int));
     95 void	setup __P((void));
     96 void	wake __P((int));
     97 
     98 int
     99 main(argc, argv)
    100 	int argc;
    101 	char **argv;
    102 {
    103 
    104 	/* Revoke setgid privileges */
    105 	setregid(getgid(), getgid());
    106 
    107 	if (argc == 2)
    108 		start_len = atoi(argv[1]);
    109 	if ((start_len <= 0) || (start_len > 500))
    110 		start_len = LENGTH;
    111 	setbuf(stdout, outbuf);
    112 	srand(getpid());
    113 	signal(SIGALRM, wake);
    114 	signal(SIGINT, leave);
    115 	signal(SIGQUIT, leave);
    116 	initscr();
    117 	crmode();
    118 	noecho();
    119 #ifdef KEY_LEFT
    120 	keypad(stdscr, TRUE);
    121 #endif
    122 	slow = (baudrate() <= 1200);
    123 	clear();
    124 	stw = newwin(1, COLS-1, 0, 0);
    125 	tv = newwin(LINES-1, COLS-1, 1, 0);
    126 	box(tv, '*', '*');
    127 	scrollok(tv, FALSE);
    128 	scrollok(stw, FALSE);
    129 	wmove(stw, 0, 0);
    130 	wprintw(stw, " Worm");
    131 	refresh();
    132 	wrefresh(stw);
    133 	wrefresh(tv);
    134 	life();			/* Create the worm */
    135 	prize();		/* Put up a goal */
    136 	while(1)
    137 	{
    138 		if (running)
    139 		{
    140 			running--;
    141 			process(lastch);
    142 		}
    143 		else
    144 		{
    145 		    fflush(stdout);
    146 		    process(getch());
    147 		}
    148 	}
    149 }
    150 
    151 void
    152 life()
    153 {
    154 	struct body *bp, *np;
    155 	int i;
    156 
    157 	np = NULL;
    158 	head = newlink();
    159 	if (head == NULL)
    160 		errx(1, "out of memory");
    161 	head->x = start_len+2;
    162 	head->y = 12;
    163 	head->next = NULL;
    164 	display(head, HEAD);
    165 	for (i = 0, bp = head; i < start_len; i++, bp = np) {
    166 		np = newlink();
    167 		if (np == NULL)
    168 			errx(1, "out of memory");
    169 		np->next = bp;
    170 		bp->prev = np;
    171 		np->x = bp->x - 1;
    172 		np->y = bp->y;
    173 		display(np, BODY);
    174 	}
    175 	tail = np;
    176 	tail->prev = NULL;
    177 }
    178 
    179 void
    180 display(pos, chr)
    181 	const struct body *pos;
    182 	char chr;
    183 {
    184 	wmove(tv, pos->y, pos->x);
    185 	waddch(tv, chr);
    186 }
    187 
    188 void
    189 leave(dummy)
    190 	int dummy;
    191 {
    192 	endwin();
    193 
    194 	if (dummy == 0){	/* called via crash() */
    195 		printf("\nWell, you ran into something and the game is over.\n");
    196 		printf("Your final score was %d\n\n", score);
    197 	}
    198 	exit(0);
    199 }
    200 
    201 void
    202 wake(dummy)
    203 	int dummy __attribute__((__unused__));
    204 {
    205 	signal(SIGALRM, wake);
    206 	fflush(stdout);
    207 	process(lastch);
    208 }
    209 
    210 int
    211 rnd(range)
    212 	int range;
    213 {
    214 	return abs((rand()>>5)+(rand()>>5)) % range;
    215 }
    216 
    217 void
    218 newpos(bp)
    219 	struct body * bp;
    220 {
    221 	do {
    222 		bp->y = rnd(LINES-3)+ 2;
    223 		bp->x = rnd(COLS-3) + 1;
    224 		wmove(tv, bp->y, bp->x);
    225 	} while(winch(tv) != ' ');
    226 }
    227 
    228 void
    229 prize()
    230 {
    231 	int value;
    232 
    233 	value = rnd(9) + 1;
    234 	newpos(&goody);
    235 	waddch(tv, value+'0');
    236 	wrefresh(tv);
    237 }
    238 
    239 void
    240 process(ch)
    241 	int ch;
    242 {
    243 	int x,y;
    244 	struct body *nh;
    245 
    246 	alarm(0);
    247 	x = head->x;
    248 	y = head->y;
    249 	switch(ch)
    250 	{
    251 #ifdef KEY_LEFT
    252 		case KEY_LEFT:
    253 #endif
    254 		case 'h':
    255 			x--; break;
    256 
    257 #ifdef KEY_DOWN
    258 		case KEY_DOWN:
    259 #endif
    260 		case 'j':
    261 			y++; break;
    262 
    263 #ifdef KEY_UP
    264 		case KEY_UP:
    265 #endif
    266 		case 'k':
    267 			y--; break;
    268 
    269 #ifdef KEY_RIGHT
    270 		case KEY_RIGHT:
    271 #endif
    272 		case 'l':
    273 			x++; break;
    274 
    275 		case 'H': x--; running = RUNLEN; ch = tolower(ch); break;
    276 		case 'J': y++; running = RUNLEN/2; ch = tolower(ch); break;
    277 		case 'K': y--; running = RUNLEN/2; ch = tolower(ch); break;
    278 		case 'L': x++; running = RUNLEN; ch = tolower(ch); break;
    279 		case '\f': setup(); return;
    280 
    281 		case ERR:
    282 		case CNTRL('C'):
    283 		case CNTRL('D'):
    284 			crash();
    285 			return;
    286 
    287 		default: if (! running) alarm(1);
    288 			   return;
    289 	}
    290 	lastch = ch;
    291 	if (growing == 0)
    292 	{
    293 		display(tail, ' ');
    294 		tail->next->prev = NULL;
    295 		nh = tail->next;
    296 		free(tail);
    297 		tail = nh;
    298 	}
    299 	else growing--;
    300 	display(head, BODY);
    301 	wmove(tv, y, x);
    302 	if (isdigit(ch = winch(tv)))
    303 	{
    304 		growing += ch-'0';
    305 		prize();
    306 		score += growing;
    307 		running = 0;
    308 		wmove(stw, 0, 68);
    309 		wprintw(stw, "Score: %3d", score);
    310 		wrefresh(stw);
    311 	}
    312 	else if(ch != ' ') crash();
    313 	nh = newlink();
    314 	if (nh == NULL)
    315 		errx(1, "out of memory");
    316 	nh->next = NULL;
    317 	nh->prev = head;
    318 	head->next = nh;
    319 	nh->y = y;
    320 	nh->x = x;
    321 	display(nh, HEAD);
    322 	head = nh;
    323 	if (!(slow && running))
    324 	{
    325 		wmove(tv, head->y, head->x);
    326 		wrefresh(tv);
    327 	}
    328 	if (!running)
    329 		alarm(1);
    330 }
    331 
    332 void
    333 crash()
    334 {
    335 	leave(0);
    336 }
    337 
    338 void
    339 setup()
    340 {
    341 	clear();
    342 	refresh();
    343 	touchwin(stw);
    344 	wrefresh(stw);
    345 	touchwin(tv);
    346 	wrefresh(tv);
    347 	alarm(1);
    348 }
    349