visible_len++;
struct body 	*newlink __P((void));void	process __P((int));void	prize __P((void));int	rnd __P((int));void	setup __P((void));void	suspend __P((int));intmain(argc, argv)	int argc;	char **argv;{	int retval;	struct timeval t, tod;	struct timezone tz;	fd_set rset;	/* revoke */	setegid(getgid());	setgid(getgid());	FD_ZERO(&rset);	setbuf(stdout, outbuf);	srandom(getpid());	signal(SIGINT, leave);	signal(SIGQUIT, leave);	signal(SIGTSTP, suspend);	/* process control signal */	initscr();	cbreak();	noecho();	keypad(stdscr, TRUE);	slow = (baudrate() <= 1200);	clear();	if (argc == 2)		start_len = atoi(argv[1]);	if ((start_len <= 0) || (start_len > ((LINES-3) * (COLS-2)) / 3))		start_len = LENGTH;	stw = newwin(1, COLS-1, 0, 0);	tv = newwin(LINES-1, COLS-1, 1, 0);	box(tv, '*', '*');	scrollok(tv, FALSE);	scrollok(stw, FALSE);	wmove(stw, 0, 0);	wprintw(stw, " Worm");	refresh();	wrefresh(stw);	wrefresh(tv);	life();			/* Create the worm */	prize();		/* Put up a goal */	while(1)	{		if (running)		{			running--;			process(lastch);		}		else		{			/* fflush(stdout); */			/* Delay could be a command line option */			t.tv_sec = 1;			t.tv_usec = 0;			(void)gettimeofday(&tod, &tz);			FD_SET(STDIN_FILENO, &rset);			retval = select(STDIN_FILENO + 1, &rset, NULL, NULL, &t);			if (retval > 0)				process(getch());			else				process(lastch);		}	}}voidlife(){	register struct body *bp, *np;	register int i,j = 1;	head = newlink();	head->x = start_len % (COLS-5) + 2;	head->y = LINES / 2;	head->next = NULL;	display(head, HEAD);	for (i = 0, bp = head; i < start_len; i++, bp = np) {		np = newlink();		np->next = bp;		bp->prev = np;		if (((bp->x <= 2) && (j == 1)) || ((bp->x >= COLS-4) && (j == -1))) {			j *= -1;			np->x = bp->x;			np->y = bp->y + 1;		} else {			np->x = bp->x - j;			np->y = bp->y;		}		display(np, BODY);	}	tail = np;	tail->prev = NULL;}voiddisplay(pos, chr)	struct body *pos;	char chr;{	wmove(tv, pos->y, pos->x);	waddch(tv, chr);}voidleave(dummy)	int dummy;{	endwin();	exit(0);}intrnd(range)	int range;{	return random() % range;}voidnewpos(bp)	struct body * bp;{	do {		bp->y = rnd(LINES-3)+ 2;		bp->x = rnd(COLS-3) + 1;		wmove(tv, bp->y, bp->x);	} while(winch(tv) != ' ');}voidprize(){	int value;	value = rnd(9) + 1;	newpos(&goody);	waddch(tv, value+'0');	wrefresh(tv);}voidprocess(ch)	int ch;{	register int x,y;	struct body *nh;	x = head->x;	y = head->y;	switch(ch)	{#ifdef KEY_LEFT		case KEY_LEFT:#endif		case 'h':			x--; break;#ifdef KEY_DOWN		case KEY_DOWN:#endif		case 'j':			y++; break;#ifdef KEY_UP		case KEY_UP:#endif		case 'k':			y--; break;#ifdef KEY_RIGHT		case KEY_RIGHT:#endif		case 'l':			x++; break;		case 'H': x--; running = RUNLEN; ch = tolower(ch); break;		case 'J': y++; running = RUNLEN/2; ch = tolower(ch); break;		case 'K': y--; running = RUNLEN/2; ch = tolower(ch); break;		case 'L': x++; running = RUNLEN; ch = tolower(ch); break;		case '\f': setup(); return;		case CNTRL('Z'): suspend(0); return;		case CNTRL('C'): crash(); return;		case CNTRL('D'): crash(); return;		default: return;	}	lastch = ch;	if (growing == 0)	{		display(tail, ' ');		tail->next->prev = NULL;		nh = tail->next;		free(tail);		tail = nh;	}	else growing--;	display(head, BODY);	wmove(tv, y, x);	if (isdigit(ch = winch(tv)))	{		growing += ch-'0';		prize();		score += growing;		running = 0;		wmove(stw, 0, COLS - 12);		wprintw(stw, "Score: %3d", score);		wrefresh(stw);	}	else if(ch != ' ') crash();	nh = newlink();	nh->next = NULL;	nh->prev = head;	head->next = nh;	nh->y = y;	nh->x = x;	display(nh, HEAD);	head = nh;	if (!(slow && running)) {		wmove(tv, head->y, head->x);		wrefresh(tv);	}}struct body *newlink(){	struct body *tmp;	if ((tmp = (struct body *) malloc(sizeof (struct body))) == NULL) {		endwin();		errx(1, "out of memory");	}	return (tmp);}