--- /dev/null
+.\" $NetBSD: worms.6,v 1.15 2012/08/12 17:30:03 wiz Exp $
+.\"
+.\" Copyright (c) 1989, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)worms.6 8.1 (Berkeley) 5/31/93
+.\"
+.Dd July 31, 2012
+.Dt WORMS 6
+.Os
+.Sh NAME
+.Nm worms
+.Nd animate worms on a display terminal
+.Sh SYNOPSIS
+.Nm
+.Op Fl ft
+.Op Fl d Ar delay
+.Op Fl l Ar length
+.Op Fl n Ar number
+.Sh DESCRIPTION
+.Nm
+is a
+.Ux
+version of the DEC-2136 program
+.Dq worms .
+.Pp
+The options are as follows:
+.Bl -tag -width XlXlengthXX
+.It Fl d Ar delay
+Specifies
+.Ar delay
+as a delay, in milliseconds, between each update.
+This is useful for fast terminals.
+Reasonable values are around 20-200;
+the default is 0.
+.It Fl f
+Makes a
+.Dq field
+for the worm(s) to eat.
+.It Fl l Ar length
+Specifies
+.Ar length
+as a length for each worm; the default is 16.
+.It Fl n Ar number
+Specifies
+.Ar number
+as the number of worms; the default is 3.
+.It Fl t
+Makes each worm leave a trail behind it.
+.El
--- /dev/null
+/* $NetBSD: worms.c,v 1.22 2012/06/19 05:46:09 dholland Exp $ */
+
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)worms.c 8.1 (Berkeley) 5/31/93";
+#else
+__RCSID("$NetBSD: worms.c,v 1.22 2012/06/19 05:46:09 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ *
+ * @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
+ * @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
+ * @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
+ * @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
+ * @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
+ * @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
+ * @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
+ * @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
+ * @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
+ *
+ * Eric P. Scott
+ * Caltech High Energy Physics
+ * October, 1980
+ *
+ */
+#include <sys/types.h>
+
+#include <curses.h>
+#include <err.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static const struct options {
+ int nopts;
+ int opts[3];
+}
+ normal[8] = {
+ { 3, { 7, 0, 1 } },
+ { 3, { 0, 1, 2 } },
+ { 3, { 1, 2, 3 } },
+ { 3, { 2, 3, 4 } },
+ { 3, { 3, 4, 5 } },
+ { 3, { 4, 5, 6 } },
+ { 3, { 5, 6, 7 } },
+ { 3, { 6, 7, 0 } }
+}, upper[8] = {
+ { 1, { 1, 0, 0 } },
+ { 2, { 1, 2, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 2, { 4, 5, 0 } },
+ { 1, { 5, 0, 0 } },
+ { 2, { 1, 5, 0 } }
+},
+ left[8] = {
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 2, { 2, 3, 0 } },
+ { 1, { 3, 0, 0 } },
+ { 2, { 3, 7, 0 } },
+ { 1, { 7, 0, 0 } },
+ { 2, { 7, 0, 0 } }
+},
+ right[8] = {
+ { 1, { 7, 0, 0 } },
+ { 2, { 3, 7, 0 } },
+ { 1, { 3, 0, 0 } },
+ { 2, { 3, 4, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 2, { 6, 7, 0 } }
+},
+ lower[8] = {
+ { 0, { 0, 0, 0 } },
+ { 2, { 0, 1, 0 } },
+ { 1, { 1, 0, 0 } },
+ { 2, { 1, 5, 0 } },
+ { 1, { 5, 0, 0 } },
+ { 2, { 5, 6, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } }
+},
+ upleft[8] = {
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 1, { 3, 0, 0 } },
+ { 2, { 1, 3, 0 } },
+ { 1, { 1, 0, 0 } }
+},
+ upright[8] = {
+ { 2, { 3, 5, 0 } },
+ { 1, { 3, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 1, { 5, 0, 0 } }
+},
+ lowleft[8] = {
+ { 3, { 7, 0, 1 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 1, { 1, 0, 0 } },
+ { 2, { 1, 7, 0 } },
+ { 1, { 7, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } }
+},
+ lowright[8] = {
+ { 0, { 0, 0, 0 } },
+ { 1, { 7, 0, 0 } },
+ { 2, { 5, 7, 0 } },
+ { 1, { 5, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } },
+ { 0, { 0, 0, 0 } }
+};
+
+
+static const char flavor[] = {
+ 'O', '*', '#', '$', '%', '0', '@', '~'
+};
+static const short xinc[] = {
+ 1, 1, 1, 0, -1, -1, -1, 0
+}, yinc[] = {
+ -1, 0, 1, 1, 1, 0, -1, -1
+};
+static struct worm {
+ int orientation, head;
+ short *xpos, *ypos;
+} *worm;
+
+static volatile sig_atomic_t sig_caught = 0;
+
+int main(int, char **);
+static void nomem(void) __dead;
+static void onsig(int);
+
+int
+main(int argc, char *argv[])
+{
+ int x, y, h, n;
+ struct worm *w;
+ const struct options *op;
+ short *ip;
+ int CO, LI, last, bottom, ch, length, number, trail;
+ short **ref;
+ const char *field;
+ char *mp;
+ unsigned int delay = 0;
+
+ mp = NULL;
+ length = 16;
+ number = 3;
+ trail = ' ';
+ field = NULL;
+ while ((ch = getopt(argc, argv, "d:fl:n:t")) != -1)
+ switch(ch) {
+ case 'd':
+ if ((delay = (unsigned int)strtoul(optarg, NULL, 10)) < 1 || delay > 1000)
+ errx(1, "invalid delay (1-1000)");
+ delay *= 1000; /* ms -> us */
+ break;
+ case 'f':
+ field = "WORM";
+ break;
+ case 'l':
+ if ((length = atoi(optarg)) < 2 || length > 1024) {
+ errx(1, "invalid length (%d - %d).",
+ 2, 1024);
+ }
+ break;
+ case 'n':
+ if ((number = atoi(optarg)) < 1) {
+ errx(1, "invalid number of worms.");
+ }
+ break;
+ case 't':
+ trail = '.';
+ break;
+ case '?':
+ default:
+ (void)fprintf(stderr,
+ "usage: worms [-ft] [-d delay] [-l length] [-n number]\n");
+ exit(1);
+ }
+
+ if (!(worm = malloc((size_t)number *
+ sizeof(struct worm))) || !(mp = malloc((size_t)1024)))
+ nomem();
+ if (!initscr())
+ errx(0, "couldn't initialize screen");
+ curs_set(0);
+ CO = COLS;
+ LI = LINES;
+ last = CO - 1;
+ bottom = LI - 1;
+ if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
+ nomem();
+ if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
+ nomem();
+ for (n = 0; n < LI; ++n) {
+ ref[n] = ip;
+ ip += CO;
+ }
+ for (ip = ref[0], n = LI * CO; --n >= 0;)
+ *ip++ = 0;
+ for (n = number, w = &worm[0]; --n >= 0; w++) {
+ w->orientation = w->head = 0;
+ if (!(ip = malloc((size_t)(length * sizeof(short)))))
+ nomem();
+ w->xpos = ip;
+ for (x = length; --x >= 0;)
+ *ip++ = -1;
+ if (!(ip = malloc((size_t)(length * sizeof(short)))))
+ nomem();
+ w->ypos = ip;
+ for (y = length; --y >= 0;)
+ *ip++ = -1;
+ }
+
+ (void)signal(SIGHUP, onsig);
+ (void)signal(SIGINT, onsig);
+ (void)signal(SIGQUIT, onsig);
+ (void)signal(SIGTSTP, onsig);
+ (void)signal(SIGTERM, onsig);
+
+ if (field) {
+ const char *p = field;
+
+ for (y = LI; --y >= 0;) {
+ for (x = CO; --x >= 0;) {
+ addch(*p++);
+ if (!*p)
+ p = field;
+ }
+ refresh();
+ }
+ }
+ for (;;) {
+ refresh();
+ if (sig_caught) {
+ endwin();
+ exit(0);
+ }
+ if (delay) {
+ if (delay % 1000000 != 0)
+ usleep(delay % 1000000);
+ if (delay >= 1000000)
+ sleep(delay / 1000000);
+ }
+ for (n = 0, w = &worm[0]; n < number; n++, w++) {
+ if ((x = w->xpos[h = w->head]) < 0) {
+ mvaddch(y = w->ypos[h] = bottom,
+ x = w->xpos[h] = 0,
+ flavor[n % sizeof(flavor)]);
+ ref[y][x]++;
+ }
+ else
+ y = w->ypos[h];
+ if (++h == length)
+ h = 0;
+ if (w->xpos[w->head = h] >= 0) {
+ int x1, y1;
+
+ x1 = w->xpos[h];
+ y1 = w->ypos[h];
+ if (--ref[y1][x1] == 0) {
+ mvaddch(y1, x1, trail);
+ }
+ }
+ op = &(!x ? (!y ? upleft : (y == bottom ? lowleft : left)) : (x == last ? (!y ? upright : (y == bottom ? lowright : right)) : (!y ? upper : (y == bottom ? lower : normal))))[w->orientation];
+ switch (op->nopts) {
+ case 0:
+ refresh();
+ abort();
+ return(1);
+ case 1:
+ w->orientation = op->opts[0];
+ break;
+ default:
+ w->orientation =
+ op->opts[(int)random() % op->nopts];
+ }
+ mvaddch(y += yinc[w->orientation],
+ x += xinc[w->orientation],
+ flavor[n % sizeof(flavor)]);
+ ref[w->ypos[h] = y][w->xpos[h] = x]++;
+ }
+ }
+}
+
+static void
+onsig(int signo __unused)
+{
+ sig_caught = 1;
+}
+
+static void
+nomem(void)
+{
+ errx(1, "not enough memory.");
+}