Home | History | Annotate | Line # | Download | only in worm
worm.c revision 1.20
      1 /*	$NetBSD: worm.c,v 1.20 2001/08/29 23:25:58 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. 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.20 2001/08/29 23:25:58 jsm 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 	setgid(getgid());
    106 
    107 	setbuf(stdout, outbuf);
    108 	srand(getpid());
    109 	signal(SIGALRM, wake);
    110 	signal(SIGINT, leave);
    111 	signal(SIGQUIT, leave);
    112 	initscr();
    113 	crmode();
    114 	noecho();
    115 #ifdef KEY_LEFT
    116 	keypad(stdscr, TRUE);
    117 #endif
    118 	slow = (baudrate() <= 1200);
    119 	clear();
    120 	if (argc == 2)
    121 		start_len = atoi(argv[1]);
    122 	if ((start_len <= 0) || (start_len > ((LINES-3) * (COLS-2)) / 3))
    123 		start_len = LENGTH;
    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, j = 1;
    156 
    157 	np = NULL;
    158 	head = newlink();
    159 	if (head == NULL)
    160 		err(1, NULL);
    161 	head->x = start_len % (COLS-5) + 2;
    162 	head->y = LINES / 2;
    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 			err(1, NULL);
    169 		np->next = bp;
    170 		bp->prev = np;
    171 		if (((bp->x <= 2) && (j == 1)) || ((bp->x >= COLS-4) && (j == -1))) {
    172 			j *= -1;
    173 			np->x = bp->x;
    174 			np->y = bp->y + 1;
    175 		} else {
    176 			np->x = bp->x - j;
    177 			np->y = bp->y;
    178 		}
    179 		display(np, BODY);
    180 	}
    181 	tail = np;
    182 	tail->prev = NULL;
    183 }
    184 
    185 void
    186 display(pos, chr)
    187 	const struct body *pos;
    188 	char chr;
    189 {
    190 	wmove(tv, pos->y, pos->x);
    191 	waddch(tv, chr);
    192 }
    193 
    194 void
    195 leave(dummy)
    196 	int dummy;
    197 {
    198 	endwin();
    199 
    200 	if (dummy == 0){	/* called via crash() */
    201 		printf("\nWell, you ran into something and the game is over.\n");
    202 		printf("Your final score was %d\n\n", score);
    203 	}
    204 	exit(0);
    205 }
    206 
    207 void
    208 wake(dummy)
    209 	int dummy __attribute__((__unused__));
    210 {
    211 	signal(SIGALRM, wake);
    212 	fflush(stdout);
    213 	process(lastch);
    214 }
    215 
    216 int
    217 rnd(range)
    218 	int range;
    219 {
    220 	return abs((rand()>>5)+(rand()>>5)) % range;
    221 }
    222 
    223 void
    224 newpos(bp)
    225 	struct body * bp;
    226 {
    227 	do {
    228 		bp->y = rnd(LINES-3)+ 2;
    229 		bp->x = rnd(COLS-3) + 1;
    230 		wmove(tv, bp->y, bp->x);
    231 	} while(winch(tv) != ' ');
    232 }
    233 
    234 void
    235 prize()
    236 {
    237 	int value;
    238 
    239 	value = rnd(9) + 1;
    240 	newpos(&goody);
    241 	waddch(tv, value+'0');
    242 	wrefresh(tv);
    243 }
    244 
    245 void
    246 process(ch)
    247 	int ch;
    248 {
    249 	int x,y;
    250 	struct body *nh;
    251 
    252 	alarm(0);
    253 	x = head->x;
    254 	y = head->y;
    255 	switch(ch)
    256 	{
    257 #ifdef KEY_LEFT
    258 		case KEY_LEFT:
    259 #endif
    260 		case 'h':
    261 			x--; break;
    262 
    263 #ifdef KEY_DOWN
    264 		case KEY_DOWN:
    265 #endif
    266 		case 'j':
    267 			y++; break;
    268 
    269 #ifdef KEY_UP
    270 		case KEY_UP:
    271 #endif
    272 		case 'k':
    273 			y--; break;
    274 
    275 #ifdef KEY_RIGHT
    276 		case KEY_RIGHT:
    277 #endif
    278 		case 'l':
    279 			x++; break;
    280 
    281 		case 'H': x--; running = RUNLEN; ch = tolower(ch); break;
    282 		case 'J': y++; running = RUNLEN/2; ch = tolower(ch); break;
    283 		case 'K': y--; running = RUNLEN/2; ch = tolower(ch); break;
    284 		case 'L': x++; running = RUNLEN; ch = tolower(ch); break;
    285 		case '\f': setup(); return;
    286 
    287 		case ERR:
    288 		case CNTRL('C'):
    289 		case CNTRL('D'):
    290 			crash();
    291 			return;
    292 
    293 		default: if (! running) alarm(1);
    294 			   return;
    295 	}
    296 	lastch = ch;
    297 	if (growing == 0)
    298 	{
    299 		display(tail, ' ');
    300 		tail->next->prev = NULL;
    301 		nh = tail->next;
    302 		free(tail);
    303 		tail = nh;
    304 	}
    305 	else growing--;
    306 	display(head, BODY);
    307 	wmove(tv, y, x);
    308 	if (isdigit(ch = winch(tv)))
    309 	{
    310 		growing += ch-'0';
    311 		prize();
    312 		score += growing;
    313 		running = 0;
    314 		wmove(stw, 0, 68);
    315 		wprintw(stw, "Score: %3d", score);
    316 		wrefresh(stw);
    317 	}
    318 	else if(ch != ' ') crash();
    319 	nh = newlink();
    320 	if (nh == NULL)
    321 		err(1, NULL);
    322 	nh->next = NULL;
    323 	nh->prev = head;
    324 	head->next = nh;
    325 	nh->y = y;
    326 	nh->x = x;
    327 	display(nh, HEAD);
    328 	head = nh;
    329 	if (!(slow && running))
    330 	{
    331 		wmove(tv, head->y, head->x);
    332 		wrefresh(tv);
    333 	}
    334 	if (!running)
    335 		alarm(1);
    336 }
    337 
    338 void
    339 crash()
    340 {
    341 	leave(0);
    342 }
    343 
    344 void
    345 setup()
    346 {
    347 	clear();
    348 	refresh();
    349 	touchwin(stw);
    350 	wrefresh(stw);
    351 	touchwin(tv);
    352 	wrefresh(tv);
    353 	alarm(1);
    354 }
    355