Home | History | Annotate | Line # | Download | only in worms
worms.c revision 1.21.2.1
      1  1.21.2.1      yamt /*	$NetBSD: worms.c,v 1.21.2.1 2012/10/30 18:58:27 yamt 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.21.2.1      yamt __RCSID("$NetBSD: worms.c,v 1.21.2.1 2012/10/30 18:58:27 yamt 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.11   hubertf #include <curses.h>
     66      1.11   hubertf #include <err.h>
     67       1.6       cgd #include <signal.h>
     68       1.1       cgd #include <stdio.h>
     69       1.2   mycroft #include <stdlib.h>
     70       1.6       cgd #include <unistd.h>
     71       1.1       cgd 
     72      1.11   hubertf static const struct options {
     73       1.1       cgd 	int nopts;
     74       1.1       cgd 	int opts[3];
     75       1.1       cgd }
     76       1.1       cgd 	normal[8] = {
     77       1.1       cgd 	{ 3, { 7, 0, 1 } },
     78       1.1       cgd 	{ 3, { 0, 1, 2 } },
     79       1.1       cgd 	{ 3, { 1, 2, 3 } },
     80       1.1       cgd 	{ 3, { 2, 3, 4 } },
     81       1.1       cgd 	{ 3, { 3, 4, 5 } },
     82       1.1       cgd 	{ 3, { 4, 5, 6 } },
     83       1.1       cgd 	{ 3, { 5, 6, 7 } },
     84       1.1       cgd 	{ 3, { 6, 7, 0 } }
     85       1.1       cgd },	upper[8] = {
     86       1.1       cgd 	{ 1, { 1, 0, 0 } },
     87       1.1       cgd 	{ 2, { 1, 2, 0 } },
     88       1.1       cgd 	{ 0, { 0, 0, 0 } },
     89       1.1       cgd 	{ 0, { 0, 0, 0 } },
     90       1.1       cgd 	{ 0, { 0, 0, 0 } },
     91       1.1       cgd 	{ 2, { 4, 5, 0 } },
     92       1.1       cgd 	{ 1, { 5, 0, 0 } },
     93       1.1       cgd 	{ 2, { 1, 5, 0 } }
     94       1.1       cgd },
     95       1.1       cgd 	left[8] = {
     96       1.1       cgd 	{ 0, { 0, 0, 0 } },
     97       1.1       cgd 	{ 0, { 0, 0, 0 } },
     98       1.1       cgd 	{ 0, { 0, 0, 0 } },
     99       1.1       cgd 	{ 2, { 2, 3, 0 } },
    100       1.1       cgd 	{ 1, { 3, 0, 0 } },
    101       1.1       cgd 	{ 2, { 3, 7, 0 } },
    102       1.1       cgd 	{ 1, { 7, 0, 0 } },
    103       1.1       cgd 	{ 2, { 7, 0, 0 } }
    104       1.1       cgd },
    105       1.1       cgd 	right[8] = {
    106       1.1       cgd 	{ 1, { 7, 0, 0 } },
    107       1.1       cgd 	{ 2, { 3, 7, 0 } },
    108       1.1       cgd 	{ 1, { 3, 0, 0 } },
    109       1.1       cgd 	{ 2, { 3, 4, 0 } },
    110       1.1       cgd 	{ 0, { 0, 0, 0 } },
    111       1.1       cgd 	{ 0, { 0, 0, 0 } },
    112       1.1       cgd 	{ 0, { 0, 0, 0 } },
    113       1.1       cgd 	{ 2, { 6, 7, 0 } }
    114       1.1       cgd },
    115       1.1       cgd 	lower[8] = {
    116       1.1       cgd 	{ 0, { 0, 0, 0 } },
    117       1.1       cgd 	{ 2, { 0, 1, 0 } },
    118       1.1       cgd 	{ 1, { 1, 0, 0 } },
    119       1.1       cgd 	{ 2, { 1, 5, 0 } },
    120       1.1       cgd 	{ 1, { 5, 0, 0 } },
    121       1.1       cgd 	{ 2, { 5, 6, 0 } },
    122       1.1       cgd 	{ 0, { 0, 0, 0 } },
    123       1.1       cgd 	{ 0, { 0, 0, 0 } }
    124       1.1       cgd },
    125       1.1       cgd 	upleft[8] = {
    126       1.1       cgd 	{ 0, { 0, 0, 0 } },
    127       1.1       cgd 	{ 0, { 0, 0, 0 } },
    128       1.1       cgd 	{ 0, { 0, 0, 0 } },
    129       1.1       cgd 	{ 0, { 0, 0, 0 } },
    130       1.1       cgd 	{ 0, { 0, 0, 0 } },
    131       1.1       cgd 	{ 1, { 3, 0, 0 } },
    132       1.1       cgd 	{ 2, { 1, 3, 0 } },
    133       1.1       cgd 	{ 1, { 1, 0, 0 } }
    134       1.1       cgd },
    135       1.1       cgd 	upright[8] = {
    136       1.1       cgd 	{ 2, { 3, 5, 0 } },
    137       1.1       cgd 	{ 1, { 3, 0, 0 } },
    138       1.1       cgd 	{ 0, { 0, 0, 0 } },
    139       1.1       cgd 	{ 0, { 0, 0, 0 } },
    140       1.1       cgd 	{ 0, { 0, 0, 0 } },
    141       1.1       cgd 	{ 0, { 0, 0, 0 } },
    142       1.1       cgd 	{ 0, { 0, 0, 0 } },
    143       1.1       cgd 	{ 1, { 5, 0, 0 } }
    144       1.1       cgd },
    145       1.1       cgd 	lowleft[8] = {
    146       1.1       cgd 	{ 3, { 7, 0, 1 } },
    147       1.1       cgd 	{ 0, { 0, 0, 0 } },
    148       1.1       cgd 	{ 0, { 0, 0, 0 } },
    149       1.1       cgd 	{ 1, { 1, 0, 0 } },
    150       1.1       cgd 	{ 2, { 1, 7, 0 } },
    151       1.1       cgd 	{ 1, { 7, 0, 0 } },
    152       1.1       cgd 	{ 0, { 0, 0, 0 } },
    153       1.1       cgd 	{ 0, { 0, 0, 0 } }
    154       1.1       cgd },
    155       1.1       cgd 	lowright[8] = {
    156       1.1       cgd 	{ 0, { 0, 0, 0 } },
    157       1.1       cgd 	{ 1, { 7, 0, 0 } },
    158       1.1       cgd 	{ 2, { 5, 7, 0 } },
    159       1.1       cgd 	{ 1, { 5, 0, 0 } },
    160       1.1       cgd 	{ 0, { 0, 0, 0 } },
    161       1.1       cgd 	{ 0, { 0, 0, 0 } },
    162       1.1       cgd 	{ 0, { 0, 0, 0 } },
    163       1.1       cgd 	{ 0, { 0, 0, 0 } }
    164       1.1       cgd };
    165       1.1       cgd 
    166       1.1       cgd 
    167      1.11   hubertf static const char	flavor[] = {
    168       1.1       cgd 	'O', '*', '#', '$', '%', '0', '@', '~'
    169       1.1       cgd };
    170      1.11   hubertf static const short	xinc[] = {
    171       1.1       cgd 	1,  1,  1,  0, -1, -1, -1,  0
    172       1.1       cgd }, yinc[] = {
    173       1.1       cgd 	-1,  0,  1,  1,  1,  0, -1, -1
    174       1.1       cgd };
    175       1.1       cgd static struct	worm {
    176       1.1       cgd 	int orientation, head;
    177       1.1       cgd 	short *xpos, *ypos;
    178       1.1       cgd } *worm;
    179       1.1       cgd 
    180      1.20  dholland static volatile sig_atomic_t sig_caught = 0;
    181      1.11   hubertf 
    182      1.13       jsm int	 main(int, char **);
    183      1.20  dholland static void nomem(void) __dead;
    184      1.20  dholland static void onsig(int);
    185       1.2   mycroft 
    186       1.6       cgd int
    187  1.21.2.1      yamt main(int argc, char *argv[])
    188       1.1       cgd {
    189       1.9     lukem 	int x, y, h, n;
    190       1.9     lukem 	struct worm *w;
    191      1.11   hubertf 	const struct options *op;
    192       1.9     lukem 	short *ip;
    193      1.11   hubertf 	int CO, LI, last, bottom, ch, length, number, trail;
    194       1.1       cgd 	short **ref;
    195      1.11   hubertf 	const char *field;
    196      1.11   hubertf 	char *mp;
    197      1.11   hubertf 	unsigned int delay = 0;
    198       1.1       cgd 
    199       1.9     lukem 	mp = NULL;
    200       1.1       cgd 	length = 16;
    201       1.1       cgd 	number = 3;
    202       1.1       cgd 	trail = ' ';
    203       1.1       cgd 	field = NULL;
    204      1.11   hubertf 	while ((ch = getopt(argc, argv, "d:fl:n:t")) != -1)
    205       1.1       cgd 		switch(ch) {
    206      1.11   hubertf 		case 'd':
    207      1.21    plunky 			if ((delay = (unsigned int)strtoul(optarg, NULL, 10)) < 1 || delay > 1000)
    208      1.11   hubertf 				errx(1, "invalid delay (1-1000)");
    209      1.11   hubertf 			delay *= 1000;  /* ms -> us */
    210      1.11   hubertf 			break;
    211       1.1       cgd 		case 'f':
    212       1.1       cgd 			field = "WORM";
    213       1.1       cgd 			break;
    214       1.1       cgd 		case 'l':
    215       1.1       cgd 			if ((length = atoi(optarg)) < 2 || length > 1024) {
    216      1.11   hubertf 				errx(1, "invalid length (%d - %d).",
    217       1.1       cgd 				     2, 1024);
    218       1.1       cgd 			}
    219       1.1       cgd 			break;
    220       1.1       cgd 		case 'n':
    221       1.1       cgd 			if ((number = atoi(optarg)) < 1) {
    222      1.11   hubertf 				errx(1, "invalid number of worms.");
    223       1.1       cgd 			}
    224       1.1       cgd 			break;
    225       1.1       cgd 		case 't':
    226       1.1       cgd 			trail = '.';
    227       1.1       cgd 			break;
    228       1.1       cgd 		case '?':
    229       1.1       cgd 		default:
    230       1.1       cgd 			(void)fprintf(stderr,
    231      1.11   hubertf 			    "usage: worms [-ft] [-d delay] [-l length] [-n number]\n");
    232       1.1       cgd 			exit(1);
    233       1.1       cgd 		}
    234       1.1       cgd 
    235       1.6       cgd 	if (!(worm = malloc((size_t)number *
    236       1.6       cgd 	    sizeof(struct worm))) || !(mp = malloc((size_t)1024)))
    237       1.1       cgd 		nomem();
    238      1.19  drochner 	if (!initscr())
    239      1.19  drochner 		errx(0, "couldn't initialize screen");
    240      1.14       jsm 	curs_set(0);
    241      1.11   hubertf 	CO = COLS;
    242      1.11   hubertf 	LI = LINES;
    243       1.4   mycroft 	last = CO - 1;
    244       1.4   mycroft 	bottom = LI - 1;
    245       1.6       cgd 	if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
    246       1.1       cgd 		nomem();
    247       1.6       cgd 	if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
    248       1.1       cgd 		nomem();
    249       1.1       cgd 	for (n = 0; n < LI; ++n) {
    250       1.1       cgd 		ref[n] = ip;
    251       1.1       cgd 		ip += CO;
    252       1.1       cgd 	}
    253       1.1       cgd 	for (ip = ref[0], n = LI * CO; --n >= 0;)
    254       1.1       cgd 		*ip++ = 0;
    255       1.1       cgd 	for (n = number, w = &worm[0]; --n >= 0; w++) {
    256       1.1       cgd 		w->orientation = w->head = 0;
    257       1.6       cgd 		if (!(ip = malloc((size_t)(length * sizeof(short)))))
    258       1.1       cgd 			nomem();
    259       1.1       cgd 		w->xpos = ip;
    260       1.1       cgd 		for (x = length; --x >= 0;)
    261       1.1       cgd 			*ip++ = -1;
    262       1.6       cgd 		if (!(ip = malloc((size_t)(length * sizeof(short)))))
    263       1.1       cgd 			nomem();
    264       1.1       cgd 		w->ypos = ip;
    265       1.1       cgd 		for (y = length; --y >= 0;)
    266       1.1       cgd 			*ip++ = -1;
    267       1.1       cgd 	}
    268       1.1       cgd 
    269       1.1       cgd 	(void)signal(SIGHUP, onsig);
    270       1.1       cgd 	(void)signal(SIGINT, onsig);
    271       1.1       cgd 	(void)signal(SIGQUIT, onsig);
    272       1.1       cgd 	(void)signal(SIGTSTP, onsig);
    273       1.1       cgd 	(void)signal(SIGTERM, onsig);
    274       1.1       cgd 
    275       1.1       cgd 	if (field) {
    276      1.11   hubertf 		const char *p = field;
    277       1.1       cgd 
    278      1.11   hubertf 		for (y = LI; --y >= 0;) {
    279       1.1       cgd 			for (x = CO; --x >= 0;) {
    280      1.11   hubertf 				addch(*p++);
    281       1.1       cgd 				if (!*p)
    282       1.1       cgd 					p = field;
    283       1.1       cgd 			}
    284      1.11   hubertf 			refresh();
    285       1.1       cgd 		}
    286       1.1       cgd 	}
    287       1.1       cgd 	for (;;) {
    288      1.11   hubertf 		refresh();
    289      1.11   hubertf 		if (sig_caught) {
    290      1.11   hubertf 			endwin();
    291      1.11   hubertf 			exit(0);
    292      1.11   hubertf 		}
    293      1.15   hubertf 		if (delay) {
    294      1.15   hubertf 			if (delay % 1000000 != 0)
    295      1.15   hubertf 				usleep(delay % 1000000);
    296      1.15   hubertf 			if (delay >= 1000000)
    297      1.15   hubertf 				sleep(delay / 1000000);
    298      1.15   hubertf 		}
    299       1.1       cgd 		for (n = 0, w = &worm[0]; n < number; n++, w++) {
    300       1.1       cgd 			if ((x = w->xpos[h = w->head]) < 0) {
    301      1.11   hubertf 				mvaddch(y = w->ypos[h] = bottom,
    302      1.11   hubertf 					x = w->xpos[h] = 0,
    303      1.11   hubertf 					flavor[n % sizeof(flavor)]);
    304       1.1       cgd 				ref[y][x]++;
    305       1.1       cgd 			}
    306       1.1       cgd 			else
    307       1.1       cgd 				y = w->ypos[h];
    308       1.1       cgd 			if (++h == length)
    309       1.1       cgd 				h = 0;
    310       1.1       cgd 			if (w->xpos[w->head = h] >= 0) {
    311       1.9     lukem 				int x1, y1;
    312       1.1       cgd 
    313       1.1       cgd 				x1 = w->xpos[h];
    314       1.1       cgd 				y1 = w->ypos[h];
    315       1.1       cgd 				if (--ref[y1][x1] == 0) {
    316      1.11   hubertf 					mvaddch(y1, x1, trail);
    317       1.1       cgd 				}
    318       1.1       cgd 			}
    319       1.1       cgd 			op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
    320       1.1       cgd 			switch (op->nopts) {
    321       1.1       cgd 			case 0:
    322      1.11   hubertf 				refresh();
    323       1.1       cgd 				abort();
    324       1.9     lukem 				return(1);
    325       1.1       cgd 			case 1:
    326       1.1       cgd 				w->orientation = op->opts[0];
    327       1.1       cgd 				break;
    328       1.1       cgd 			default:
    329       1.1       cgd 				w->orientation =
    330       1.1       cgd 				    op->opts[(int)random() % op->nopts];
    331       1.1       cgd 			}
    332      1.11   hubertf 			mvaddch(y += yinc[w->orientation],
    333      1.11   hubertf 				x += xinc[w->orientation],
    334      1.11   hubertf 				flavor[n % sizeof(flavor)]);
    335       1.1       cgd 			ref[w->ypos[h] = y][w->xpos[h] = x]++;
    336       1.1       cgd 		}
    337       1.1       cgd 	}
    338       1.1       cgd }
    339       1.1       cgd 
    340      1.20  dholland static void
    341  1.21.2.1      yamt onsig(int signo __unused)
    342       1.6       cgd {
    343      1.11   hubertf 	sig_caught = 1;
    344       1.1       cgd }
    345       1.1       cgd 
    346      1.20  dholland static void
    347  1.21.2.1      yamt nomem(void)
    348       1.1       cgd {
    349      1.11   hubertf 	errx(1, "not enough memory.");
    350       1.1       cgd }
    351