diff options
author | hubertf <hubertf@NetBSD.org> | 1999-07-30 02:23:27 +0000 |
---|---|---|
committer | hubertf <hubertf@NetBSD.org> | 1999-07-30 02:23:27 +0000 |
commit | 15f2f45599ebe7e34a9d0f3f08fdacf2328a39f6 (patch) | |
tree | 9338141a103a36eb0dd78c2e504c1ca53c220165 /worms/worms.c | |
parent | ad5cd40187b784a973ea41e3d848a7cb9258f229 (diff) | |
download | bsdgames-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/worms.c')
-rw-r--r-- | worms/worms.c | 207 |
1 files changed, 48 insertions, 159 deletions
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."); } |