summaryrefslogtreecommitdiffstats
path: root/worms
diff options
context:
space:
mode:
authorhubertf <hubertf@NetBSD.org>1999-07-30 02:23:27 +0000
committerhubertf <hubertf@NetBSD.org>1999-07-30 02:23:27 +0000
commit15f2f45599ebe7e34a9d0f3f08fdacf2328a39f6 (patch)
tree9338141a103a36eb0dd78c2e504c1ca53c220165 /worms
parentad5cd40187b784a973ea41e3d848a7cb9258f229 (diff)
downloadbsdgames-darwin-15f2f45599ebe7e34a9d0f3f08fdacf2328a39f6.tar.gz
bsdgames-darwin-15f2f45599ebe7e34a9d0f3f08fdacf2328a39f6.tar.zst
bsdgames-darwin-15f2f45599ebe7e34a9d0f3f08fdacf2328a39f6.zip
This patch converts worms(6) to use curses, thereby
simplifying the code and improving its portability. It also adds a delay option from OpenBSD, to allow reasonable speed display on fast terminals, adds use of const, and fixes signal handling and use of errx() where appropriate. Patch supplied in PR 6661 by Joseph Myers <jsm28@cam.ac.uk>.
Diffstat (limited to 'worms')
-rw-r--r--worms/worms.617
-rw-r--r--worms/worms.c207
2 files changed, 59 insertions, 165 deletions
diff --git a/worms/worms.6 b/worms/worms.6
index d161b26f..4e660b48 100644
--- a/worms/worms.6
+++ b/worms/worms.6
@@ -1,4 +1,4 @@
-.\" $NetBSD: worms.6,v 1.9 1999/03/10 09:29:08 erh Exp $
+.\" $NetBSD: worms.6,v 1.10 1999/07/30 02:23:27 hubertf Exp $
.\"
.\" Copyright (c) 1989, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -41,24 +41,29 @@
.Sh SYNOPSIS
.Nm
.Op Fl ft
+.Op Fl d Ar delay
.Op Fl l Ar length
.Op Fl n Ar number
.Sh DESCRIPTION
A
.Ux
-version of the DEC-2136 program ``worms''.
+version of the DEC-2136 program
+.Dq worms .
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl f
-Makes a ``field'' for the worm(s) to eat.
+Makes a
+.Dq field
+for the worm(s) to eat.
.It Fl t
Makes each worm leave a trail behind it.
+.It Fl d
+Specifies 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 l
Specifies a length for each worm; the default is 16.
.It Fl n
Specifies the number of worms; the default is 3.
.El
-.Sh BUGS
-The lower-right-hand character position will not be updated properly
-on a terminal that wraps at the right margin.
diff --git a/worms/worms.c b/worms/worms.c
index 9452986f..f56aaaf8 100644
--- a/worms/worms.c
+++ b/worms/worms.c
@@ -1,4 +1,4 @@
-/* $NetBSD: worms.c,v 1.10 1998/09/13 15:27:31 hubertf Exp $ */
+/* $NetBSD: worms.c,v 1.11 1999/07/30 02:23:27 hubertf Exp $ */
/*
* Copyright (c) 1980, 1993
@@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
#if 0
static char sccsid[] = "@(#)worms.c 8.1 (Berkeley) 5/31/93";
#else
-__RCSID("$NetBSD: worms.c,v 1.10 1998/09/13 15:27:31 hubertf Exp $");
+__RCSID("$NetBSD: worms.c,v 1.11 1999/07/30 02:23:27 hubertf Exp $");
#endif
#endif /* not lint */
@@ -65,15 +65,15 @@ __RCSID("$NetBSD: worms.c,v 1.10 1998/09/13 15:27:31 hubertf Exp $");
*
*/
#include <sys/types.h>
-#include <sys/ioctl.h>
+#include <curses.h>
+#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <termios.h>
#include <unistd.h>
-static struct options {
+static const struct options {
int nopts;
int opts[3];
}
@@ -167,13 +167,11 @@ static struct options {
{ 0, { 0, 0, 0 } }
};
-#define cursor(c, r) tputs(tgoto(CM, c, r), 1, fputchar)
-char *tcp;
-static char flavor[] = {
+static const char flavor[] = {
'O', '*', '#', '$', '%', '0', '@', '~'
};
-static short xinc[] = {
+static const short xinc[] = {
1, 1, 1, 0, -1, -1, -1, 0
}, yinc[] = {
-1, 0, 1, 1, 1, 0, -1, -1
@@ -183,60 +181,51 @@ static struct worm {
short *xpos, *ypos;
} *worm;
-void fputchar __P((int));
+volatile sig_atomic_t sig_caught = 0;
+
int main __P((int, char **));
void nomem __P((void)) __attribute__((__noreturn__));
-void onsig __P((int)) __attribute__((__noreturn__));
-int tgetent __P((char *, char *));
-int tgetflag __P((char *));
-int tgetnum __P((char *));
-char *tgetstr __P((char *, char **));
-char *tgoto __P((char *, int, int));
-int tputs __P((char *, int, void (*)(int)));
+void onsig __P((int));
int
main(argc, argv)
int argc;
char *argv[];
{
- extern char *UP;
int x, y, h, n;
struct worm *w;
- struct options *op;
+ const struct options *op;
short *ip;
- char *term;
- int CO, IN, LI, last, bottom, ch, length, number, trail, Wrap;
+ int CO, LI, last, bottom, ch, length, number, trail;
short **ref;
- char *AL, *BC, *CM, *EI, *HO, *IC, *IM, *IP, *SR;
- char *field, tcb[100], *mp;
- struct termios ti;
-#ifdef TIOCGWINSZ
- struct winsize ws;
-#endif
+ const char *field;
+ char *mp;
+ unsigned int delay = 0;
mp = NULL;
length = 16;
number = 3;
trail = ' ';
field = NULL;
- while ((ch = getopt(argc, argv, "fl:n:t")) != -1)
+ while ((ch = getopt(argc, argv, "d:fl:n:t")) != -1)
switch(ch) {
+ case 'd':
+ if ((delay = (unsigned int)strtoul(optarg, (char **)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) {
- (void)fprintf(stderr,
- "worms: invalid length (%d - %d).\n",
+ errx(1, "invalid length (%d - %d).",
2, 1024);
- exit(1);
}
break;
case 'n':
if ((number = atoi(optarg)) < 1) {
- (void)fprintf(stderr,
- "worms: invalid number of worms.\n");
- exit(1);
+ errx(1, "invalid number of worms.");
}
break;
case 't':
@@ -245,55 +234,18 @@ main(argc, argv)
case '?':
default:
(void)fprintf(stderr,
- "usage: worms [-ft] [-l length] [-n number]\n");
+ "usage: worms [-ft] [-d delay] [-l length] [-n number]\n");
exit(1);
}
- if (!(term = getenv("TERM"))) {
- (void)fprintf(stderr, "worms: no TERM environment variable.\n");
- exit(1);
- }
if (!(worm = malloc((size_t)number *
sizeof(struct worm))) || !(mp = malloc((size_t)1024)))
nomem();
- if (tgetent(mp, term) <= 0) {
- (void)fprintf(stderr, "worms: %s: unknown terminal type.\n",
- term);
- exit(1);
- }
- tcp = tcb;
- if (!(CM = tgetstr("cm", &tcp))) {
- (void)fprintf(stderr,
- "worms: terminal incapable of cursor motion.\n");
- exit(1);
- }
- AL = tgetstr("al", &tcp);
- BC = tgetflag("bs") ? "\b" : tgetstr("bc", &tcp);
- EI = tgetstr("ei", &tcp);
- HO = tgetstr("ho", &tcp);
- IC = tgetstr("ic", &tcp);
- IM = tgetstr("im", &tcp);
- IN = tgetflag("in");
- IP = tgetstr("ip", &tcp);
- SR = tgetstr("sr", &tcp);
- UP = tgetstr("up", &tcp);
-#ifdef TIOCGWINSZ
- if (ioctl(fileno(stdout), TIOCGWINSZ, &ws) != -1 &&
- ws.ws_col && ws.ws_row) {
- CO = ws.ws_col;
- LI = ws.ws_row;
- } else
-#endif
- {
- if ((CO = tgetnum("co")) <= 0)
- CO = 80;
- if ((LI = tgetnum("li")) <= 0)
- LI = 24;
- }
+ initscr();
+ CO = COLS;
+ LI = LINES;
last = CO - 1;
bottom = LI - 1;
- tcgetattr(fileno(stdout), &ti);
- Wrap = tgetflag("am");
if (!(ip = malloc((size_t)(LI * CO * sizeof(short)))))
nomem();
if (!(ref = malloc((size_t)(LI * sizeof(short *)))))
@@ -304,8 +256,6 @@ main(argc, argv)
}
for (ip = ref[0], n = LI * CO; --n >= 0;)
*ip++ = 0;
- if (Wrap)
- ref[bottom][last] = 1;
for (n = number, w = &worm[0]; --n >= 0; w++) {
w->orientation = w->head = 0;
if (!(ip = malloc((size_t)(length * sizeof(short)))))
@@ -327,78 +277,30 @@ main(argc, argv)
(void)signal(SIGTSTP, onsig);
(void)signal(SIGTERM, onsig);
- tputs(tgetstr("ti", &tcp), 1, fputchar);
- tputs(tgetstr("cl", &tcp), 1, fputchar);
if (field) {
- char *p = field;
+ const char *p = field;
- for (y = bottom; --y >= 0;) {
+ for (y = LI; --y >= 0;) {
for (x = CO; --x >= 0;) {
- fputchar(*p++);
- if (!*p)
- p = field;
- }
- if (!Wrap)
- fputchar('\n');
- (void)fflush(stdout);
- }
- if (Wrap) {
- if (IM && !IN) {
- for (x = last; --x > 0;) {
- fputchar(*p++);
- if (!*p)
- p = field;
- }
- y = *p++;
- if (!*p)
- p = field;
- fputchar(*p);
- if (BC)
- tputs(BC, 1, fputchar);
- else
- cursor(last - 1, bottom);
- tputs(IM, 1, fputchar);
- if (IC)
- tputs(IC, 1, fputchar);
- fputchar(y);
- if (IP)
- tputs(IP, 1, fputchar);
- tputs(EI, 1, fputchar);
- }
- else if (SR || AL) {
- if (HO)
- tputs(HO, 1, fputchar);
- else
- cursor(0, 0);
- if (SR)
- tputs(SR, 1, fputchar);
- else
- tputs(AL, LI, fputchar);
- for (x = CO; --x >= 0;) {
- fputchar(*p++);
- if (!*p)
- p = field;
- }
- }
- else for (x = last; --x >= 0;) {
- fputchar(*p++);
+ addch(*p++);
if (!*p)
p = field;
}
- }
- else for (x = CO; --x >= 0;) {
- fputchar(*p++);
- if (!*p)
- p = field;
+ refresh();
}
}
for (;;) {
- (void)fflush(stdout);
+ refresh();
+ if (sig_caught) {
+ endwin();
+ exit(0);
+ }
+ if (delay) usleep(delay);
for (n = 0, w = &worm[0]; n < number; n++, w++) {
if ((x = w->xpos[h = w->head]) < 0) {
- cursor(x = w->xpos[h] = 0,
- y = w->ypos[h] = bottom);
- fputchar(flavor[n % sizeof(flavor)]);
+ mvaddch(y = w->ypos[h] = bottom,
+ x = w->xpos[h] = 0,
+ flavor[n % sizeof(flavor)]);
ref[y][x]++;
}
else
@@ -411,15 +313,13 @@ main(argc, argv)
x1 = w->xpos[h];
y1 = w->ypos[h];
if (--ref[y1][x1] == 0) {
- cursor(x1, y1);
- if (trail)
- fputchar(trail);
+ 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:
- (void)fflush(stdout);
+ refresh();
abort();
return(1);
case 1:
@@ -429,10 +329,9 @@ main(argc, argv)
w->orientation =
op->opts[(int)random() % op->nopts];
}
- cursor(x += xinc[w->orientation],
- y += yinc[w->orientation]);
- if (!Wrap || x != last || y != bottom)
- fputchar(flavor[n % sizeof(flavor)]);
+ mvaddch(y += yinc[w->orientation],
+ x += xinc[w->orientation],
+ flavor[n % sizeof(flavor)]);
ref[w->ypos[h] = y][w->xpos[h] = x]++;
}
}
@@ -440,23 +339,13 @@ main(argc, argv)
void
onsig(signo)
- int signo;
-{
- tputs(tgetstr("cl", &tcp), 1, fputchar);
- tputs(tgetstr("te", &tcp), 1, fputchar);
- exit(0);
-}
-
-void
-fputchar(c)
- int c;
+ int signo __attribute__((__unused__));
{
- (void)putchar(c);
+ sig_caught = 1;
}
void
nomem()
{
- (void)fprintf(stderr, "worms: not enough memory.\n");
- exit(1);
+ errx(1, "not enough memory.");
}