aboutsummaryrefslogtreecommitdiff
path: root/contrib/ncurses/test/worm.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ncurses/test/worm.c')
-rw-r--r--contrib/ncurses/test/worm.c372
1 files changed, 372 insertions, 0 deletions
diff --git a/contrib/ncurses/test/worm.c b/contrib/ncurses/test/worm.c
new file mode 100644
index 000000000000..a02113b370f0
--- /dev/null
+++ b/contrib/ncurses/test/worm.c
@@ -0,0 +1,372 @@
+/*
+
+ @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
+ @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
+ @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
+ @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
+ @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
+ @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
+ @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
+ @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
+ @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
+
+ Eric P. Scott
+ Caltech High Energy Physics
+ October, 1980
+
+ Hacks to turn this into a test frame for cursor movement:
+ Eric S. Raymond <esr@snark.thyrsus.com>
+ January, 1995
+
+ July 1995 (esr): worms is now in living color! :-)
+
+Options:
+ -f fill screen with copies of 'WORM' at start.
+ -l <n> set worm length
+ -n <n> set number of worms
+ -t make worms leave droppings
+ -T <start> <end> set trace interval
+ -S set single-stepping during trace interval
+ -N suppress cursor-movement optimization
+
+ This program makes a good torture-test for the ncurses cursor-optimization
+ code. You can use -T to set the worm move interval over which movement
+ traces will be dumped. The program stops and waits for one character of
+ input at the beginning and end of the interval.
+
+ $Id: worm.c,v 1.23 1999/03/06 22:52:04 tom Exp $
+*/
+
+#include <test.priv.h>
+
+#include <term.h> /* for tparm() */
+
+#include <signal.h>
+
+#define cursor(col,row) move(row,col)
+
+short *ref[128];
+static chtype flavor[]={
+ 'O' , '*', '#', '$', '%', '0', '@',
+};
+#define MAXWORMS (sizeof(flavor)/sizeof(chtype))
+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[40];
+
+static const char *field;
+static int length=16, number=3;
+static chtype trail=' ';
+
+#ifdef TRACE
+int generation, trace_start, trace_end, singlestep;
+#endif /* TRACE */
+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 RETSIGTYPE onsig(int sig);
+static float ranf(void);
+
+int
+main(int argc, char *argv[])
+{
+int x, y;
+int n;
+struct worm *w;
+const struct options *op;
+int h;
+short *ip;
+int last, bottom;
+
+ for (x=1;x<argc;x++) {
+ register char *p;
+ p=argv[x];
+ if (*p=='-') p++;
+ switch (*p) {
+ case 'f':
+ field="WORM";
+ break;
+ case 'l':
+ if (++x==argc) goto usage;
+ if ((length=atoi(argv[x]))<2||length>1024) {
+ fprintf(stderr,"%s: Invalid length\n",*argv);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 'n':
+ if (++x==argc) goto usage;
+ if ((number=atoi(argv[x]))<1||number>40) {
+ fprintf(stderr,"%s: Invalid number of worms\n",*argv);
+ return EXIT_FAILURE;
+ }
+ break;
+ case 't':
+ trail='.';
+ break;
+#ifdef TRACE
+ case 'S':
+ singlestep = TRUE;
+ break;
+ case 'T':
+ trace_start = atoi(argv[++x]);
+ trace_end = atoi(argv[++x]);
+ break;
+ case 'N':
+ _nc_optimize_enable ^= OPTIMIZE_ALL; /* declared by ncurses */
+ break;
+#endif /* TRACE */
+ default:
+ usage:
+ fprintf(stderr, "usage: %s [-field] [-length #] [-number #] [-trail]\n",*argv);
+ return EXIT_FAILURE;
+ }
+ }
+
+ signal(SIGINT, onsig);
+ initscr();
+ noecho();
+ cbreak();
+ nonl();
+
+ curs_set(0);
+
+ bottom = LINES-1;
+ last = COLS-1;
+
+#ifdef A_COLOR
+ if (has_colors())
+ {
+ int bg = COLOR_BLACK;
+ start_color();
+#ifdef NCURSES_VERSION
+ if (use_default_colors() == OK)
+ bg = -1;
+#endif
+
+ init_pair(COLOR_GREEN, COLOR_GREEN, bg);
+ init_pair(COLOR_RED, COLOR_RED, bg);
+ init_pair(COLOR_CYAN, COLOR_CYAN, bg);
+ init_pair(COLOR_WHITE, COLOR_WHITE, bg);
+ init_pair(COLOR_MAGENTA, COLOR_MAGENTA, bg);
+ init_pair(COLOR_BLUE, COLOR_BLUE, bg);
+ init_pair(COLOR_YELLOW, COLOR_YELLOW, bg);
+
+ flavor[0] |= COLOR_PAIR(COLOR_GREEN) | A_BOLD;
+ flavor[1] |= COLOR_PAIR(COLOR_RED) | A_BOLD;
+ flavor[2] |= COLOR_PAIR(COLOR_CYAN) | A_BOLD;
+ flavor[3] |= COLOR_PAIR(COLOR_WHITE) | A_BOLD;
+ flavor[4] |= COLOR_PAIR(COLOR_MAGENTA) | A_BOLD;
+ flavor[5] |= COLOR_PAIR(COLOR_BLUE) | A_BOLD;
+ flavor[6] |= COLOR_PAIR(COLOR_YELLOW) | A_BOLD;
+ }
+#endif /* A_COLOR */
+
+ ip=(short *)malloc(LINES*COLS*sizeof (short));
+
+ for (n=0;n<LINES;) {
+ ref[n++]=ip; ip+=COLS;
+ }
+ for (ip=ref[0],n=LINES*COLS;--n>=0;) *ip++=0;
+
+#ifdef BADCORNER
+ /* if addressing the lower right corner doesn't work in your curses */
+ ref[bottom][last]=1;
+#endif /* BADCORNER */
+
+ for (n=number, w= &worm[0];--n>=0;w++) {
+ w->orientation=w->head=0;
+ if (!(ip=(short *)malloc((length+1)*sizeof (short)))) {
+ fprintf(stderr,"%s: out of memory\n",*argv);
+ return EXIT_FAILURE;
+ }
+ w->xpos=ip;
+ for (x=length;--x>=0;) *ip++ = -1;
+ if (!(ip=(short *)malloc((length+1)*sizeof (short)))) {
+ fprintf(stderr,"%s: out of memory\n",*argv);
+ return EXIT_FAILURE;
+ }
+ w->ypos=ip;
+ for (y=length;--y>=0;) *ip++ = -1;
+ }
+ if (field) {
+ register const char *p;
+ p=field;
+ for (y=bottom;--y>=0;) {
+ for (x=COLS;--x>=0;) {
+ addch((chtype)(*p++));
+ if (!*p) p=field;
+ }
+ addch('\n');
+ }
+ }
+ napms(10);
+ refresh();
+
+ for (;;) {
+#ifdef TRACE
+ if (trace_start || trace_end) {
+ if (generation == trace_start) {
+ trace(TRACE_CALLS);
+ getch();
+ } else if (generation == trace_end) {
+ trace(0);
+ getch();
+ }
+
+ if (singlestep && generation > trace_start && generation < trace_end)
+ getch();
+
+ generation++;
+ }
+#endif /* TRACE */
+
+ 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);
+ addch(flavor[n % MAXWORMS]);
+ ref[y][x]++;
+ }
+ else y=w->ypos[h];
+ if (++h==length) h=0;
+ if (w->xpos[w->head=h]>=0) {
+ register int x1, y1;
+ x1=w->xpos[h]; y1=w->ypos[h];
+ if (--ref[y1][x1]==0) {
+ cursor(x1,y1); addch(trail);
+ }
+ }
+ op= &(x==0 ? (y==0 ? upleft : (y==bottom ? lowleft : left)) :
+ (x==last ? (y==0 ? upright : (y==bottom ? lowright : right)) :
+ (y==0 ? upper : (y==bottom ? lower : normal))))[w->orientation];
+ switch (op->nopts) {
+ case 0:
+ refresh();
+ curs_set(1);
+ endwin();
+ return EXIT_SUCCESS;
+ case 1:
+ w->orientation=op->opts[0];
+ break;
+ default:
+ w->orientation=op->opts[(int)(ranf()*(float)op->nopts)];
+ }
+ cursor(x+=xinc[w->orientation], y+=yinc[w->orientation]);
+
+ if (y < 0 ) y = 0;
+ addch(flavor[n % MAXWORMS]);
+ ref[w->ypos[h]=y][w->xpos[h]=x]++;
+ }
+ napms(10);
+ refresh();
+ }
+}
+
+static RETSIGTYPE
+onsig(int sig GCC_UNUSED)
+{
+ standend();
+ refresh();
+ curs_set(1);
+ endwin();
+ exit(EXIT_FAILURE);
+}
+
+static float
+ranf(void)
+{
+float rv;
+long r = rand();
+
+ r &= 077777;
+ rv =((float)r/32767.);
+ return rv;
+}