Home | History | Annotate | Line # | Download | only in worms
worms.c revision 1.23.6.1
      1  1.23.6.1    martin /*	$NetBSD: worms.c,v 1.23.6.1 2023/04/25 16:12:05 martin Exp $	*/
      2       1.6       cgd 
      3       1.1       cgd /*
      4       1.6       cgd  * Copyright (c) 1980, 1993
      5       1.6       cgd  *	The Regents of the University of California.  All rights reserved.
      6       1.1       cgd  *
      7       1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8       1.1       cgd  * modification, are permitted provided that the following conditions
      9       1.1       cgd  * are met:
     10       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15      1.12       agc  * 3. Neither the name of the University nor the names of its contributors
     16       1.1       cgd  *    may be used to endorse or promote products derived from this software
     17       1.1       cgd  *    without specific prior written permission.
     18       1.1       cgd  *
     19       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29       1.1       cgd  * SUCH DAMAGE.
     30       1.1       cgd  */
     31       1.1       cgd 
     32       1.9     lukem #include <sys/cdefs.h>
     33       1.1       cgd #ifndef lint
     34      1.18     lukem __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
     35      1.18     lukem  The Regents of the University of California.  All rights reserved.");
     36       1.1       cgd #endif /* not lint */
     37       1.1       cgd 
     38       1.1       cgd #ifndef lint
     39       1.6       cgd #if 0
     40       1.6       cgd static char sccsid[] = "@(#)worms.c	8.1 (Berkeley) 5/31/93";
     41       1.6       cgd #else
     42  1.23.6.1    martin __RCSID("$NetBSD: worms.c,v 1.23.6.1 2023/04/25 16:12:05 martin Exp $");
     43       1.6       cgd #endif
     44       1.1       cgd #endif /* not lint */
     45       1.1       cgd 
     46       1.1       cgd /*
     47       1.1       cgd  *
     48       1.1       cgd  *	 @@@        @@@    @@@@@@@@@@     @@@@@@@@@@@    @@@@@@@@@@@@
     49       1.1       cgd  *	 @@@        @@@   @@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@@@@@
     50       1.1       cgd  *	 @@@        @@@  @@@@      @@@@   @@@@           @@@@ @@@  @@@@
     51       1.1       cgd  *	 @@@   @@   @@@  @@@        @@@   @@@            @@@  @@@   @@@
     52       1.1       cgd  *	 @@@  @@@@  @@@  @@@        @@@   @@@            @@@  @@@   @@@
     53       1.1       cgd  *	 @@@@ @@@@ @@@@  @@@        @@@   @@@            @@@  @@@   @@@
     54       1.1       cgd  *	  @@@@@@@@@@@@   @@@@      @@@@   @@@            @@@  @@@   @@@
     55       1.1       cgd  *	   @@@@  @@@@     @@@@@@@@@@@@    @@@            @@@  @@@   @@@
     56       1.1       cgd  *	    @@    @@       @@@@@@@@@@     @@@            @@@  @@@   @@@
     57       1.1       cgd  *
     58       1.1       cgd  *				 Eric P. Scott
     59       1.1       cgd  *			  Caltech High Energy Physics
     60       1.1       cgd  *				 October, 1980
     61       1.1       cgd  *
     62       1.1       cgd  */
     63       1.1       cgd #include <sys/types.h>
     64       1.6       cgd 
     65  1.23.6.1    martin #include <ctype.h>
     66      1.11   hubertf #include <curses.h>
     67      1.11   hubertf #include <err.h>
     68  1.23.6.1    martin #include <limits.h>
     69       1.6       cgd #include <signal.h>
     70  1.23.6.1    martin #include <stdbool.h>
     71       1.1       cgd #include <stdio.h>
     72       1.2   mycroft #include <stdlib.h>
     73  1.23.6.1    martin #include <strings.h>
     74       1.6       cgd #include <unistd.h>
     75       1.1       cgd 
     76      1.11   hubertf static const struct options {
     77       1.1       cgd 	int nopts;
     78       1.1       cgd 	int opts[3];
     79       1.1       cgd }
     80       1.1       cgd 	normal[8] = {
     81       1.1       cgd 	{ 3, { 7, 0, 1 } },
     82       1.1       cgd 	{ 3, { 0, 1, 2 } },
     83       1.1       cgd 	{ 3, { 1, 2, 3 } },
     84       1.1       cgd 	{ 3, { 2, 3, 4 } },
     85       1.1       cgd 	{ 3, { 3, 4, 5 } },
     86       1.1       cgd 	{ 3, { 4, 5, 6 } },
     87       1.1       cgd 	{ 3, { 5, 6, 7 } },
     88       1.1       cgd 	{ 3, { 6, 7, 0 } }
     89       1.1       cgd },	upper[8] = {
     90       1.1       cgd 	{ 1, { 1, 0, 0 } },
     91       1.1       cgd 	{ 2, { 1, 2, 0 } },
     92       1.1       cgd 	{ 0, { 0, 0, 0 } },
     93       1.1       cgd 	{ 0, { 0, 0, 0 } },
     94       1.1       cgd 	{ 0, { 0, 0, 0 } },
     95       1.1       cgd 	{ 2, { 4, 5, 0 } },
     96       1.1       cgd 	{ 1, { 5, 0, 0 } },
     97       1.1       cgd 	{ 2, { 1, 5, 0 } }
     98       1.1       cgd },
     99       1.1       cgd 	left[8] = {
    100       1.1       cgd 	{ 0, { 0, 0, 0 } },
    101       1.1       cgd 	{ 0, { 0, 0, 0 } },
    102       1.1       cgd 	{ 0, { 0, 0, 0 } },
    103       1.1       cgd 	{ 2, { 2, 3, 0 } },
    104       1.1       cgd 	{ 1, { 3, 0, 0 } },
    105       1.1       cgd 	{ 2, { 3, 7, 0 } },
    106       1.1       cgd 	{ 1, { 7, 0, 0 } },
    107       1.1       cgd 	{ 2, { 7, 0, 0 } }
    108       1.1       cgd },
    109       1.1       cgd 	right[8] = {
    110       1.1       cgd 	{ 1, { 7, 0, 0 } },
    111       1.1       cgd 	{ 2, { 3, 7, 0 } },
    112       1.1       cgd 	{ 1, { 3, 0, 0 } },
    113       1.1       cgd 	{ 2, { 3, 4, 0 } },
    114       1.1       cgd 	{ 0, { 0, 0, 0 } },
    115       1.1       cgd 	{ 0, { 0, 0, 0 } },
    116       1.1       cgd 	{ 0, { 0, 0, 0 } },
    117       1.1       cgd 	{ 2, { 6, 7, 0 } }
    118       1.1       cgd },
    119       1.1       cgd 	lower[8] = {
    120       1.1       cgd 	{ 0, { 0, 0, 0 } },
    121       1.1       cgd 	{ 2, { 0, 1, 0 } },
    122       1.1       cgd 	{ 1, { 1, 0, 0 } },
    123       1.1       cgd 	{ 2, { 1, 5, 0 } },
    124       1.1       cgd 	{ 1, { 5, 0, 0 } },
    125       1.1       cgd 	{ 2, { 5, 6, 0 } },
    126       1.1       cgd 	{ 0, { 0, 0, 0 } },
    127       1.1       cgd 	{ 0, { 0, 0, 0 } }
    128       1.1       cgd },
    129       1.1       cgd 	upleft[8] = {
    130       1.1       cgd 	{ 0, { 0, 0, 0 } },
    131       1.1       cgd 	{ 0, { 0, 0, 0 } },
    132       1.1       cgd 	{ 0, { 0, 0, 0 } },
    133       1.1       cgd 	{ 0, { 0, 0, 0 } },
    134       1.1       cgd 	{ 0, { 0, 0, 0 } },
    135       1.1       cgd 	{ 1, { 3, 0, 0 } },
    136       1.1       cgd 	{ 2, { 1, 3, 0 } },
    137       1.1       cgd 	{ 1, { 1, 0, 0 } }
    138       1.1       cgd },
    139       1.1       cgd 	upright[8] = {
    140       1.1       cgd 	{ 2, { 3, 5, 0 } },
    141       1.1       cgd 	{ 1, { 3, 0, 0 } },
    142       1.1       cgd 	{ 0, { 0, 0, 0 } },
    143       1.1       cgd 	{ 0, { 0, 0, 0 } },
    144       1.1       cgd 	{ 0, { 0, 0, 0 } },
    145       1.1       cgd 	{ 0, { 0, 0, 0 } },
    146       1.1       cgd 	{ 0, { 0, 0, 0 } },
    147       1.1       cgd 	{ 1, { 5, 0, 0 } }
    148       1.1       cgd },
    149       1.1       cgd 	lowleft[8] = {
    150       1.1       cgd 	{ 3, { 7, 0, 1 } },
    151       1.1       cgd 	{ 0, { 0, 0, 0 } },
    152       1.1       cgd 	{ 0, { 0, 0, 0 } },
    153       1.1       cgd 	{ 1, { 1, 0, 0 } },
    154       1.1       cgd 	{ 2, { 1, 7, 0 } },
    155       1.1       cgd 	{ 1, { 7, 0, 0 } },
    156       1.1       cgd 	{ 0, { 0, 0, 0 } },
    157       1.1       cgd 	{ 0, { 0, 0, 0 } }
    158       1.1       cgd },
    159       1.1       cgd 	lowright[8] = {
    160       1.1       cgd 	{ 0, { 0, 0, 0 } },
    161       1.1       cgd 	{ 1, { 7, 0, 0 } },
    162       1.1       cgd 	{ 2, { 5, 7, 0 } },
    163       1.1       cgd 	{ 1, { 5, 0, 0 } },
    164       1.1       cgd 	{ 0, { 0, 0, 0 } },
    165       1.1       cgd 	{ 0, { 0, 0, 0 } },
    166       1.1       cgd 	{ 0, { 0, 0, 0 } },
    167       1.1       cgd 	{ 0, { 0, 0, 0 } }
    168       1.1       cgd };
    169       1.1       cgd 
    170       1.1       cgd 
    171      1.11   hubertf static const char	flavor[] = {
    172  1.23.6.1    martin 	'O', '*', '#', '$', '%', '0', '@', '~',
    173  1.23.6.1    martin 	'+', 'w', ':', '^', '_', '&', 'x', 'o'
    174       1.1       cgd };
    175      1.11   hubertf static const short	xinc[] = {
    176       1.1       cgd 	1,  1,  1,  0, -1, -1, -1,  0
    177       1.1       cgd }, yinc[] = {
    178       1.1       cgd 	-1,  0,  1,  1,  1,  0, -1, -1
    179       1.1       cgd };
    180       1.1       cgd static struct	worm {
    181       1.1       cgd 	int orientation, head;
    182       1.1       cgd 	short *xpos, *ypos;
    183       1.1       cgd } *worm;
    184       1.1       cgd 
    185      1.20  dholland static volatile sig_atomic_t sig_caught = 0;
    186      1.11   hubertf 
    187      1.20  dholland static void nomem(void) __dead;
    188      1.20  dholland static void onsig(int);
    189       1.2   mycroft 
    190       1.6       cgd int
    191      1.22  dholland main(int argc, char *argv[])
    192       1.1       cgd {
    193       1.9     lukem 	int x, y, h, n;
    194       1.9     lukem 	struct worm *w;
    195      1.11   hubertf 	const struct options *op;
    196       1.9     lukem 	short *ip;
    197      1.11   hubertf 	int CO, LI, last, bottom, ch, length, number, trail;
    198  1.23.6.1    martin 	unsigned int seed;
    199       1.1       cgd 	short **ref;
    200      1.11   hubertf 	const char *field;
    201  1.23.6.1    martin 	char *ep;
    202      1.23       nia 	unsigned int delay = 20000;
    203  1.23.6.1    martin 	unsigned long ul;
    204  1.23.6.1    martin 	bool argerror = false;
    205       1.1       cgd 
    206       1.1       cgd 	length = 16;
    207       1.1       cgd 	number = 3;
    208       1.1       cgd 	trail = ' ';
    209       1.1       cgd 	field = NULL;
    210  1.23.6.1    martin 	seed = 0;
    211  1.23.6.1    martin 	while ((ch = getopt(argc, argv, "d:fl:n:S:t")) != -1) {
    212       1.1       cgd 		switch(ch) {
    213      1.11   hubertf 		case 'd':
    214  1.23.6.1    martin 			ul = strtoul(optarg, &ep, 10);
    215  1.23.6.1    martin 			if (ep != optarg) {
    216  1.23.6.1    martin 				while (isspace(*(unsigned char *)ep))
    217  1.23.6.1    martin 					ep++;
    218  1.23.6.1    martin 			}
    219  1.23.6.1    martin 			if (ep == optarg ||
    220  1.23.6.1    martin 			    (*ep != '\0' &&
    221  1.23.6.1    martin 				( ep[1] == '\0' ? (*ep != 'm' && *ep != 'u') :
    222  1.23.6.1    martin 				( strcasecmp(ep, "ms") != 0 &&
    223  1.23.6.1    martin 				  strcasecmp(ep, "us") != 0 )) )) {
    224  1.23.6.1    martin 				    errx(1, "-d: invalid delay (%s)", optarg);
    225  1.23.6.1    martin 			}
    226  1.23.6.1    martin 			/*
    227  1.23.6.1    martin 			 * if ul >= INT_MAX/1000 we don't need the *1000,
    228  1.23.6.1    martin 			 * as even without that it will exceed the limit
    229  1.23.6.1    martin 			 * just below and be treated as an error.
    230  1.23.6.1    martin 			 * (This does assume >=32 bit int, but so does POSIX)
    231  1.23.6.1    martin 			 */
    232  1.23.6.1    martin 			if (*ep != 'u' && ul < INT_MAX / 1000)
    233  1.23.6.1    martin 				ul *= 1000;  /* ms -> us */
    234  1.23.6.1    martin 			if (ul > 1000*1000) {
    235  1.23.6.1    martin 				errx(1,
    236  1.23.6.1    martin 				   "-d: delay (%s) out of range [0 - 1000]",
    237  1.23.6.1    martin 				   optarg);
    238  1.23.6.1    martin 			}
    239  1.23.6.1    martin 			delay = (unsigned int)ul;
    240  1.23.6.1    martin 			continue;
    241       1.1       cgd 		case 'f':
    242       1.1       cgd 			field = "WORM";
    243  1.23.6.1    martin 			continue;
    244       1.1       cgd 		case 'l':
    245  1.23.6.1    martin 			ul = strtoul(optarg, &ep, 10);
    246  1.23.6.1    martin 			if (ep == optarg || *ep != '\0' ||
    247  1.23.6.1    martin 			    ul < 2 || ul > 1024) {
    248  1.23.6.1    martin 				errx(1, "-l: invalid length (%s) [%d - %d].",
    249  1.23.6.1    martin 				     optarg, 2, 1024);
    250       1.1       cgd 			}
    251  1.23.6.1    martin 			length = (int)ul;
    252  1.23.6.1    martin 			continue;
    253       1.1       cgd 		case 'n':
    254  1.23.6.1    martin 			ul = strtoul(optarg, &ep, 10);
    255  1.23.6.1    martin 			if (ep == optarg || *ep != '\0' ||
    256  1.23.6.1    martin 			    ul < 1 || ul > INT_MAX / 10 ) {
    257  1.23.6.1    martin 				errx(1, "-n: invalid number of worms (%s).",
    258  1.23.6.1    martin 				    optarg);
    259       1.1       cgd 			}
    260  1.23.6.1    martin 			/* upper bound is further limited later */
    261  1.23.6.1    martin 			number = (int)ul;
    262  1.23.6.1    martin 			continue;
    263  1.23.6.1    martin 		case 'S':
    264  1.23.6.1    martin 			ul = strtoul(optarg, &ep, 0);
    265  1.23.6.1    martin 			if (ep == optarg || *ep != '\0' ||
    266  1.23.6.1    martin 			    ul > UINT_MAX ) {
    267  1.23.6.1    martin 				errx(1, "-S: invalid seed (%s).", optarg);
    268  1.23.6.1    martin 			}
    269  1.23.6.1    martin 			seed = (unsigned int)ul;
    270  1.23.6.1    martin 			continue;
    271       1.1       cgd 		case 't':
    272       1.1       cgd 			trail = '.';
    273  1.23.6.1    martin 			continue;
    274       1.1       cgd 		case '?':
    275       1.1       cgd 		default:
    276  1.23.6.1    martin 			argerror = true;
    277  1.23.6.1    martin 			break;
    278       1.1       cgd 		}
    279  1.23.6.1    martin 		break;
    280  1.23.6.1    martin 	}
    281  1.23.6.1    martin 
    282  1.23.6.1    martin 	if (argerror || argc > optind)
    283  1.23.6.1    martin 		errx(1,
    284  1.23.6.1    martin 		    "Usage: worms [-ft] [-d delay] [-l length] [-n number]");
    285  1.23.6.1    martin 		/* -S omitted deliberately, not useful often enough */
    286       1.1       cgd 
    287      1.19  drochner 	if (!initscr())
    288  1.23.6.1    martin 		errx(1, "couldn't initialize screen");
    289      1.14       jsm 	curs_set(0);
    290      1.11   hubertf 	CO = COLS;
    291      1.11   hubertf 	LI = LINES;
    292  1.23.6.1    martin 
    293  1.23.6.1    martin 	if (CO == 0 || LI == 0) {
    294  1.23.6.1    martin 		endwin();
    295  1.23.6.1    martin 		errx(1, "screen must be a rectangle, not (%dx%d)", CO, LI);
    296  1.23.6.1    martin 	}
    297  1.23.6.1    martin 	if (CO >= INT_MAX / LI) {
    298  1.23.6.1    martin 		endwin();
    299  1.23.6.1    martin 		errx(1, "screen (%dx%d) too large for worms", CO, LI);
    300  1.23.6.1    martin 	}
    301  1.23.6.1    martin 
    302  1.23.6.1    martin 	/* now known that LI*CO cannot overflow an int => also not a long */
    303  1.23.6.1    martin 
    304  1.23.6.1    martin 	if (LI < 3 || CO < 3 || LI * CO < 40) {
    305  1.23.6.1    martin 		/*
    306  1.23.6.1    martin 		 * The placement algorithm is too weak for dimensions < 3.
    307  1.23.6.1    martin 		 * Need at least 40 spaces so we can have (n > 1) worms
    308  1.23.6.1    martin 		 * of a reasonable length, and still leave empty space.
    309  1.23.6.1    martin 		 */
    310  1.23.6.1    martin 		endwin();
    311  1.23.6.1    martin 		errx(1, "screen (%dx%d) too small for worms", CO, LI);
    312  1.23.6.1    martin 	}
    313  1.23.6.1    martin 
    314  1.23.6.1    martin 	ul = (unsigned long)CO * LI;
    315  1.23.6.1    martin 	if ((unsigned long)length > ul / 20) {
    316  1.23.6.1    martin 		endwin();
    317  1.23.6.1    martin 		errx(1, "-l: worms too long (%d) for screen; max: %lu",
    318  1.23.6.1    martin 		    length, ul / 20);
    319  1.23.6.1    martin 	}
    320  1.23.6.1    martin 
    321  1.23.6.1    martin 	ul /= (length * 3);	/* no more than 33% arena occupancy */
    322  1.23.6.1    martin 	if ((unsigned long)(unsigned)number > ul) {
    323  1.23.6.1    martin 		endwin();
    324  1.23.6.1    martin 		errx(1, "-n: too many worms (%d) max: %lu", number, ul);
    325  1.23.6.1    martin 	}
    326  1.23.6.1    martin 	if (!(worm = calloc((size_t)number, sizeof(struct worm))))
    327  1.23.6.1    martin 		nomem();
    328  1.23.6.1    martin 
    329       1.4   mycroft 	last = CO - 1;
    330       1.4   mycroft 	bottom = LI - 1;
    331       1.6       cgd 	if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
    332       1.1       cgd 		nomem();
    333       1.6       cgd 	if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
    334       1.1       cgd 		nomem();
    335       1.1       cgd 	for (n = 0; n < LI; ++n) {
    336       1.1       cgd 		ref[n] = ip;
    337       1.1       cgd 		ip += CO;
    338       1.1       cgd 	}
    339       1.1       cgd 	for (ip = ref[0], n = LI * CO; --n >= 0;)
    340       1.1       cgd 		*ip++ = 0;
    341       1.1       cgd 	for (n = number, w = &worm[0]; --n >= 0; w++) {
    342       1.1       cgd 		w->orientation = w->head = 0;
    343       1.6       cgd 		if (!(ip = malloc((size_t)(length * sizeof(short)))))
    344       1.1       cgd 			nomem();
    345       1.1       cgd 		w->xpos = ip;
    346       1.1       cgd 		for (x = length; --x >= 0;)
    347       1.1       cgd 			*ip++ = -1;
    348       1.6       cgd 		if (!(ip = malloc((size_t)(length * sizeof(short)))))
    349       1.1       cgd 			nomem();
    350       1.1       cgd 		w->ypos = ip;
    351       1.1       cgd 		for (y = length; --y >= 0;)
    352       1.1       cgd 			*ip++ = -1;
    353       1.1       cgd 	}
    354       1.1       cgd 
    355       1.1       cgd 	(void)signal(SIGHUP, onsig);
    356       1.1       cgd 	(void)signal(SIGINT, onsig);
    357       1.1       cgd 	(void)signal(SIGQUIT, onsig);
    358       1.1       cgd 	(void)signal(SIGTSTP, onsig);
    359       1.1       cgd 	(void)signal(SIGTERM, onsig);
    360       1.1       cgd 
    361       1.1       cgd 	if (field) {
    362      1.11   hubertf 		const char *p = field;
    363       1.1       cgd 
    364      1.11   hubertf 		for (y = LI; --y >= 0;) {
    365       1.1       cgd 			for (x = CO; --x >= 0;) {
    366      1.11   hubertf 				addch(*p++);
    367       1.1       cgd 				if (!*p)
    368       1.1       cgd 					p = field;
    369       1.1       cgd 			}
    370      1.11   hubertf 			refresh();
    371       1.1       cgd 		}
    372       1.1       cgd 	}
    373  1.23.6.1    martin 	srandom(seed ? seed : arc4random());
    374       1.1       cgd 	for (;;) {
    375      1.11   hubertf 		refresh();
    376      1.11   hubertf 		if (sig_caught) {
    377      1.11   hubertf 			endwin();
    378      1.11   hubertf 			exit(0);
    379      1.11   hubertf 		}
    380      1.15   hubertf 		if (delay) {
    381      1.15   hubertf 			if (delay % 1000000 != 0)
    382      1.15   hubertf 				usleep(delay % 1000000);
    383      1.15   hubertf 			if (delay >= 1000000)
    384      1.15   hubertf 				sleep(delay / 1000000);
    385      1.15   hubertf 		}
    386       1.1       cgd 		for (n = 0, w = &worm[0]; n < number; n++, w++) {
    387       1.1       cgd 			if ((x = w->xpos[h = w->head]) < 0) {
    388      1.11   hubertf 				mvaddch(y = w->ypos[h] = bottom,
    389      1.11   hubertf 					x = w->xpos[h] = 0,
    390      1.11   hubertf 					flavor[n % sizeof(flavor)]);
    391       1.1       cgd 				ref[y][x]++;
    392       1.1       cgd 			}
    393       1.1       cgd 			else
    394       1.1       cgd 				y = w->ypos[h];
    395       1.1       cgd 			if (++h == length)
    396       1.1       cgd 				h = 0;
    397       1.1       cgd 			if (w->xpos[w->head = h] >= 0) {
    398       1.9     lukem 				int x1, y1;
    399       1.1       cgd 
    400       1.1       cgd 				x1 = w->xpos[h];
    401       1.1       cgd 				y1 = w->ypos[h];
    402       1.1       cgd 				if (--ref[y1][x1] == 0) {
    403      1.11   hubertf 					mvaddch(y1, x1, trail);
    404       1.1       cgd 				}
    405       1.1       cgd 			}
    406  1.23.6.1    martin 
    407  1.23.6.1    martin 			op = &(!x
    408  1.23.6.1    martin 				? (!y
    409  1.23.6.1    martin 				    ? upleft
    410  1.23.6.1    martin 				    : (y == bottom ? lowleft : left))
    411  1.23.6.1    martin 				: (x == last
    412  1.23.6.1    martin 				    ? (!y ? upright
    413  1.23.6.1    martin 					  : (y == bottom ? lowright : right))
    414  1.23.6.1    martin 				    : (!y ? upper
    415  1.23.6.1    martin 					  : (y == bottom ? lower : normal)))
    416  1.23.6.1    martin 			      )[w->orientation];
    417  1.23.6.1    martin 
    418       1.1       cgd 			switch (op->nopts) {
    419       1.1       cgd 			case 0:
    420      1.11   hubertf 				refresh();
    421  1.23.6.1    martin 				endwin();
    422       1.1       cgd 				abort();
    423  1.23.6.1    martin 				/* NOTREACHED */
    424       1.1       cgd 			case 1:
    425       1.1       cgd 				w->orientation = op->opts[0];
    426       1.1       cgd 				break;
    427       1.1       cgd 			default:
    428       1.1       cgd 				w->orientation =
    429       1.1       cgd 				    op->opts[(int)random() % op->nopts];
    430       1.1       cgd 			}
    431      1.11   hubertf 			mvaddch(y += yinc[w->orientation],
    432      1.11   hubertf 				x += xinc[w->orientation],
    433      1.11   hubertf 				flavor[n % sizeof(flavor)]);
    434       1.1       cgd 			ref[w->ypos[h] = y][w->xpos[h] = x]++;
    435       1.1       cgd 		}
    436       1.1       cgd 	}
    437       1.1       cgd }
    438       1.1       cgd 
    439      1.20  dholland static void
    440      1.22  dholland onsig(int signo __unused)
    441       1.6       cgd {
    442      1.11   hubertf 	sig_caught = 1;
    443       1.1       cgd }
    444       1.1       cgd 
    445  1.23.6.1    martin /* This is never called before curses is initialised */
    446      1.20  dholland static void
    447      1.22  dholland nomem(void)
    448       1.1       cgd {
    449  1.23.6.1    martin 	endwin();
    450      1.11   hubertf 	errx(1, "not enough memory.");
    451       1.1       cgd }
    452