Home | History | Annotate | Line # | Download | only in worms
worms.c revision 1.21
      1  1.21    plunky /*	$NetBSD: worms.c,v 1.21 2011/08/31 16:24:56 plunky 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    plunky __RCSID("$NetBSD: worms.c,v 1.21 2011/08/31 16:24:56 plunky 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.1       cgd main(argc, argv)
    188   1.1       cgd 	int argc;
    189   1.6       cgd 	char *argv[];
    190   1.1       cgd {
    191   1.9     lukem 	int x, y, h, n;
    192   1.9     lukem 	struct worm *w;
    193  1.11   hubertf 	const struct options *op;
    194   1.9     lukem 	short *ip;
    195  1.11   hubertf 	int CO, LI, last, bottom, ch, length, number, trail;
    196   1.1       cgd 	short **ref;
    197  1.11   hubertf 	const char *field;
    198  1.11   hubertf 	char *mp;
    199  1.11   hubertf 	unsigned int delay = 0;
    200   1.1       cgd 
    201   1.9     lukem 	mp = NULL;
    202   1.1       cgd 	length = 16;
    203   1.1       cgd 	number = 3;
    204   1.1       cgd 	trail = ' ';
    205   1.1       cgd 	field = NULL;
    206  1.11   hubertf 	while ((ch = getopt(argc, argv, "d:fl:n:t")) != -1)
    207   1.1       cgd 		switch(ch) {
    208  1.11   hubertf 		case 'd':
    209  1.21    plunky 			if ((delay = (unsigned int)strtoul(optarg, NULL, 10)) < 1 || delay > 1000)
    210  1.11   hubertf 				errx(1, "invalid delay (1-1000)");
    211  1.11   hubertf 			delay *= 1000;  /* ms -> us */
    212  1.11   hubertf 			break;
    213   1.1       cgd 		case 'f':
    214   1.1       cgd 			field = "WORM";
    215   1.1       cgd 			break;
    216   1.1       cgd 		case 'l':
    217   1.1       cgd 			if ((length = atoi(optarg)) < 2 || length > 1024) {
    218  1.11   hubertf 				errx(1, "invalid length (%d - %d).",
    219   1.1       cgd 				     2, 1024);
    220   1.1       cgd 			}
    221   1.1       cgd 			break;
    222   1.1       cgd 		case 'n':
    223   1.1       cgd 			if ((number = atoi(optarg)) < 1) {
    224  1.11   hubertf 				errx(1, "invalid number of worms.");
    225   1.1       cgd 			}
    226   1.1       cgd 			break;
    227   1.1       cgd 		case 't':
    228   1.1       cgd 			trail = '.';
    229   1.1       cgd 			break;
    230   1.1       cgd 		case '?':
    231   1.1       cgd 		default:
    232   1.1       cgd 			(void)fprintf(stderr,
    233  1.11   hubertf 			    "usage: worms [-ft] [-d delay] [-l length] [-n number]\n");
    234   1.1       cgd 			exit(1);
    235   1.1       cgd 		}
    236   1.1       cgd 
    237   1.6       cgd 	if (!(worm = malloc((size_t)number *
    238   1.6       cgd 	    sizeof(struct worm))) || !(mp = malloc((size_t)1024)))
    239   1.1       cgd 		nomem();
    240  1.19  drochner 	if (!initscr())
    241  1.19  drochner 		errx(0, "couldn't initialize screen");
    242  1.14       jsm 	curs_set(0);
    243  1.11   hubertf 	CO = COLS;
    244  1.11   hubertf 	LI = LINES;
    245   1.4   mycroft 	last = CO - 1;
    246   1.4   mycroft 	bottom = LI - 1;
    247   1.6       cgd 	if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
    248   1.1       cgd 		nomem();
    249   1.6       cgd 	if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
    250   1.1       cgd 		nomem();
    251   1.1       cgd 	for (n = 0; n < LI; ++n) {
    252   1.1       cgd 		ref[n] = ip;
    253   1.1       cgd 		ip += CO;
    254   1.1       cgd 	}
    255   1.1       cgd 	for (ip = ref[0], n = LI * CO; --n >= 0;)
    256   1.1       cgd 		*ip++ = 0;
    257   1.1       cgd 	for (n = number, w = &worm[0]; --n >= 0; w++) {
    258   1.1       cgd 		w->orientation = w->head = 0;
    259   1.6       cgd 		if (!(ip = malloc((size_t)(length * sizeof(short)))))
    260   1.1       cgd 			nomem();
    261   1.1       cgd 		w->xpos = ip;
    262   1.1       cgd 		for (x = length; --x >= 0;)
    263   1.1       cgd 			*ip++ = -1;
    264   1.6       cgd 		if (!(ip = malloc((size_t)(length * sizeof(short)))))
    265   1.1       cgd 			nomem();
    266   1.1       cgd 		w->ypos = ip;
    267   1.1       cgd 		for (y = length; --y >= 0;)
    268   1.1       cgd 			*ip++ = -1;
    269   1.1       cgd 	}
    270   1.1       cgd 
    271   1.1       cgd 	(void)signal(SIGHUP, onsig);
    272   1.1       cgd 	(void)signal(SIGINT, onsig);
    273   1.1       cgd 	(void)signal(SIGQUIT, onsig);
    274   1.1       cgd 	(void)signal(SIGTSTP, onsig);
    275   1.1       cgd 	(void)signal(SIGTERM, onsig);
    276   1.1       cgd 
    277   1.1       cgd 	if (field) {
    278  1.11   hubertf 		const char *p = field;
    279   1.1       cgd 
    280  1.11   hubertf 		for (y = LI; --y >= 0;) {
    281   1.1       cgd 			for (x = CO; --x >= 0;) {
    282  1.11   hubertf 				addch(*p++);
    283   1.1       cgd 				if (!*p)
    284   1.1       cgd 					p = field;
    285   1.1       cgd 			}
    286  1.11   hubertf 			refresh();
    287   1.1       cgd 		}
    288   1.1       cgd 	}
    289   1.1       cgd 	for (;;) {
    290  1.11   hubertf 		refresh();
    291  1.11   hubertf 		if (sig_caught) {
    292  1.11   hubertf 			endwin();
    293  1.11   hubertf 			exit(0);
    294  1.11   hubertf 		}
    295  1.15   hubertf 		if (delay) {
    296  1.15   hubertf 			if (delay % 1000000 != 0)
    297  1.15   hubertf 				usleep(delay % 1000000);
    298  1.15   hubertf 			if (delay >= 1000000)
    299  1.15   hubertf 				sleep(delay / 1000000);
    300  1.15   hubertf 		}
    301   1.1       cgd 		for (n = 0, w = &worm[0]; n < number; n++, w++) {
    302   1.1       cgd 			if ((x = w->xpos[h = w->head]) < 0) {
    303  1.11   hubertf 				mvaddch(y = w->ypos[h] = bottom,
    304  1.11   hubertf 					x = w->xpos[h] = 0,
    305  1.11   hubertf 					flavor[n % sizeof(flavor)]);
    306   1.1       cgd 				ref[y][x]++;
    307   1.1       cgd 			}
    308   1.1       cgd 			else
    309   1.1       cgd 				y = w->ypos[h];
    310   1.1       cgd 			if (++h == length)
    311   1.1       cgd 				h = 0;
    312   1.1       cgd 			if (w->xpos[w->head = h] >= 0) {
    313   1.9     lukem 				int x1, y1;
    314   1.1       cgd 
    315   1.1       cgd 				x1 = w->xpos[h];
    316   1.1       cgd 				y1 = w->ypos[h];
    317   1.1       cgd 				if (--ref[y1][x1] == 0) {
    318  1.11   hubertf 					mvaddch(y1, x1, trail);
    319   1.1       cgd 				}
    320   1.1       cgd 			}
    321   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];
    322   1.1       cgd 			switch (op->nopts) {
    323   1.1       cgd 			case 0:
    324  1.11   hubertf 				refresh();
    325   1.1       cgd 				abort();
    326   1.9     lukem 				return(1);
    327   1.1       cgd 			case 1:
    328   1.1       cgd 				w->orientation = op->opts[0];
    329   1.1       cgd 				break;
    330   1.1       cgd 			default:
    331   1.1       cgd 				w->orientation =
    332   1.1       cgd 				    op->opts[(int)random() % op->nopts];
    333   1.1       cgd 			}
    334  1.11   hubertf 			mvaddch(y += yinc[w->orientation],
    335  1.11   hubertf 				x += xinc[w->orientation],
    336  1.11   hubertf 				flavor[n % sizeof(flavor)]);
    337   1.1       cgd 			ref[w->ypos[h] = y][w->xpos[h] = x]++;
    338   1.1       cgd 		}
    339   1.1       cgd 	}
    340   1.1       cgd }
    341   1.1       cgd 
    342  1.20  dholland static void
    343   1.6       cgd onsig(signo)
    344  1.17     perry 	int signo __unused;
    345   1.6       cgd {
    346  1.11   hubertf 	sig_caught = 1;
    347   1.1       cgd }
    348   1.1       cgd 
    349  1.20  dholland static void
    350   1.1       cgd nomem()
    351   1.1       cgd {
    352  1.11   hubertf 	errx(1, "not enough memory.");
    353   1.1       cgd }
    354