]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - test/worm.c
ncurses 5.7 - patch 20101113
[ncurses.git] / test / worm.c
index 61d97a9a404e866a774ee2671b23803d33de9b3a..98f099cb9cb6e94deb2af7b602705a4e9631dc69 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
 /****************************************************************************
- * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc.              *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -61,7 +61,7 @@ Options:
   traces will be dumped.  The program stops and waits for one character of
   input at the beginning and end of the interval.
 
   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.50 2007/12/22 23:55:13 tom Exp $
+  $Id: worm.c,v 1.60 2010/11/13 20:21:21 tom Exp $
 */
 
 #include <test.priv.h>
 */
 
 #include <test.priv.h>
@@ -70,11 +70,16 @@ Options:
 #include <pthread.h>
 #endif
 
 #include <pthread.h>
 #endif
 
+WANT_USE_WINDOW();
+
+#define MAX_WORMS      40
+#define MAX_LENGTH     1024
+
 static chtype flavor[] =
 {
     'O', '*', '#', '$', '%', '0', '@',
 };
 static chtype flavor[] =
 {
     'O', '*', '#', '$', '%', '0', '@',
 };
-static const short xinc[] =
+static const int xinc[] =
 {
     1, 1, 1, 0, -1, -1, -1, 0
 }, yinc[] =
 {
     1, 1, 1, 0, -1, -1, -1, 0
 }, yinc[] =
@@ -85,23 +90,26 @@ static const short xinc[] =
 typedef struct worm {
     int orientation;
     int head;
 typedef struct worm {
     int orientation;
     int head;
-    short *xpos;
-    short *ypos;
+    int *xpos;
+    int *ypos;
     chtype attrs;
 #ifdef USE_PTHREADS
     pthread_t thread;
 #endif
 } WORM;
 
     chtype attrs;
 #ifdef USE_PTHREADS
     pthread_t thread;
 #endif
 } WORM;
 
+static unsigned long sequence = 0;
 static bool quitting = FALSE;
 
 static bool quitting = FALSE;
 
-static WORM worm[40];
-static short **refs;
+static WORM worm[MAX_WORMS];
+static int **refs;
+static int last_x, last_y;
 
 static const char *field;
 static int length = 16, number = 3;
 static chtype trail = ' ';
 
 
 static const char *field;
 static int length = 16, number = 3;
 static chtype trail = ' ';
 
+static unsigned pending;
 #ifdef TRACE
 static int generation, trace_start, trace_end;
 #endif /* TRACE */
 #ifdef TRACE
 static int generation, trace_start, trace_end;
 #endif /* TRACE */
@@ -196,8 +204,7 @@ static const struct options {
 static void
 cleanup(void)
 {
 static void
 cleanup(void)
 {
-    standend();
-    refresh();
+    USING_WINDOW(stdscr, wrefresh);
     curs_set(1);
     endwin();
 }
     curs_set(1);
     endwin();
 }
@@ -209,11 +216,11 @@ onsig(int sig GCC_UNUSED)
     ExitProgram(EXIT_FAILURE);
 }
 
     ExitProgram(EXIT_FAILURE);
 }
 
-static float
+static double
 ranf(void)
 {
     long r = (rand() & 077777);
 ranf(void)
 {
     long r = (rand() & 077777);
-    return ((float) r / 32768.);
+    return ((double) r / 32768.);
 }
 
 static int
 }
 
 static int
@@ -221,28 +228,27 @@ draw_worm(WINDOW *win, void *data)
 {
     WORM *w = (WORM *) data;
     const struct options *op;
 {
     WORM *w = (WORM *) data;
     const struct options *op;
+    unsigned mask = (unsigned) (~(1 << (w - worm)));
+    chtype attrs = w->attrs | ((mask & pending) ? A_REVERSE : 0);
 
     int x;
     int y;
     int h;
 
 
     int x;
     int y;
     int h;
 
-    int bottom = LINES - 1;
-    int last = COLS - 1;
-
     bool done = FALSE;
 
     if ((x = w->xpos[h = w->head]) < 0) {
     bool done = FALSE;
 
     if ((x = w->xpos[h = w->head]) < 0) {
-       wmove(win, y = w->ypos[h] = bottom, x = w->xpos[h] = 0);
-       waddch(win, w->attrs);
+       wmove(win, y = w->ypos[h] = last_y, x = w->xpos[h] = 0);
+       waddch(win, attrs);
        refs[y][x]++;
     } else {
        y = w->ypos[h];
     }
 
        refs[y][x]++;
     } else {
        y = w->ypos[h];
     }
 
-    if (x > last)
-       x = last;
-    if (y > bottom)
-       y = bottom;
+    if (x > last_x)
+       x = last_x;
+    if (y > last_y)
+       y = last_y;
 
     if (++h == length)
        h = 0;
 
     if (++h == length)
        h = 0;
@@ -262,18 +268,18 @@ draw_worm(WINDOW *win, void *data)
     op = &(x == 0
           ? (y == 0
              ? upleft
     op = &(x == 0
           ? (y == 0
              ? upleft
-             : (y == bottom
+             : (y == last_y
                 ? lowleft
                 : left))
                 ? lowleft
                 : left))
-          : (x == last
+          : (x == last_x
              ? (y == 0
                 ? upright
              ? (y == 0
                 ? upright
-                : (y == bottom
+                : (y == last_y
                    ? lowright
                    : right))
              : (y == 0
                 ? upper
                    ? lowright
                    : right))
              : (y == 0
                 ? upper
-                : (y == bottom
+                : (y == last_y
                    ? lower
                    : normal))))[w->orientation];
 
                    ? lower
                    : normal))))[w->orientation];
 
@@ -285,7 +291,7 @@ draw_worm(WINDOW *win, void *data)
        w->orientation = op->opts[0];
        break;
     default:
        w->orientation = op->opts[0];
        break;
     default:
-       w->orientation = op->opts[(int) (ranf() * (float) op->nopts)];
+       w->orientation = op->opts[(int) (ranf() * (double) op->nopts)];
        break;
     }
 
        break;
     }
 
@@ -296,7 +302,7 @@ draw_worm(WINDOW *win, void *data)
 
        if (y < 0)
            y = 0;
 
        if (y < 0)
            y = 0;
-       waddch(win, w->attrs);
+       waddch(win, attrs);
 
        w->ypos[h] = y;
        w->xpos[h] = x;
 
        w->ypos[h] = y;
        w->xpos[h] = x;
@@ -306,28 +312,32 @@ draw_worm(WINDOW *win, void *data)
     return done;
 }
 
     return done;
 }
 
-#if !defined(NCURSES_VERSION_PATCH) || (NCURSES_VERSION_PATCH < 20070915)
-static int
-use_window(WINDOW *win, int (*func) (WINDOW *, void *), void *data)
-{
-    return func(win, data);
-}
-#endif
-
 #ifdef USE_PTHREADS
 static bool
 #ifdef USE_PTHREADS
 static bool
-quit_worm(void)
+quit_worm(int bitnum)
 {
 {
-    napms(20);                 /* let the other thread(s) have a chance */
+    pending |= (1 << bitnum);
+    napms(10);                 /* let the other thread(s) have a chance */
+    pending &= ~(1 << bitnum);
     return quitting;
 }
 
 static void *
 start_worm(void *arg)
 {
     return quitting;
 }
 
 static void *
 start_worm(void *arg)
 {
-    while (!quit_worm()) {
-       use_window(stdscr, draw_worm, arg);
+    unsigned long compare = 0;
+    Trace(("start_worm"));
+    while (!quit_worm(((struct worm *) arg) - worm)) {
+       while (compare < sequence) {
+           ++compare;
+#if HAVE_USE_WINDOW
+           use_window(stdscr, draw_worm, arg);
+#else
+           draw_worm(stdscr, arg);
+#endif
+       }
     }
     }
+    Trace(("...start_worm (done)"));
     return NULL;
 }
 #endif
     return NULL;
 }
 #endif
@@ -350,21 +360,64 @@ draw_all_worms(void)
     }
 #else
     for (n = 0, w = &worm[0]; n < number; n++, w++) {
     }
 #else
     for (n = 0, w = &worm[0]; n < number; n++, w++) {
-       if (use_window(stdscr, draw_worm, w))
+       if (
+#if HAVE_USE_WINDOW
+              USING_WINDOW2(stdscr, draw_worm, w)
+#else
+              draw_worm(stdscr, w)
+#endif
+           )
            done = TRUE;
     }
 #endif
     return done;
 }
 
            done = TRUE;
     }
 #endif
     return done;
 }
 
+static int
+get_input(void)
+{
+    int ch;
+    ch = USING_WINDOW(stdscr, wgetch);
+    return ch;
+}
+
+#ifdef KEY_RESIZE
+static int
+update_refs(WINDOW *win)
+{
+    int x, y;
+
+    (void) win;
+    if (last_x != COLS - 1) {
+       for (y = 0; y <= last_y; y++) {
+           refs[y] = typeRealloc(int, (size_t) COLS, refs[y]);
+           for (x = last_x + 1; x < COLS; x++)
+               refs[y][x] = 0;
+       }
+       last_x = COLS - 1;
+    }
+    if (last_y != LINES - 1) {
+       for (y = LINES; y <= last_y; y++)
+           free(refs[y]);
+       refs = typeRealloc(int *, (size_t) LINES, refs);
+       for (y = last_y + 1; y < LINES; y++) {
+           refs[y] = typeMalloc(int, (size_t) COLS);
+           for (x = 0; x < COLS; x++)
+               refs[y][x] = 0;
+       }
+       last_y = LINES - 1;
+    }
+    return OK;
+}
+#endif
+
 int
 main(int argc, char *argv[])
 {
     int x, y;
     int n;
     struct worm *w;
 int
 main(int argc, char *argv[])
 {
     int x, y;
     int n;
     struct worm *w;
-    short *ip;
-    int last, bottom;
+    int *ip;
     bool done = FALSE;
 
     setlocale(LC_ALL, "");
     bool done = FALSE;
 
     setlocale(LC_ALL, "");
@@ -381,7 +434,7 @@ main(int argc, char *argv[])
        case 'l':
            if (++x == argc)
                goto usage;
        case 'l':
            if (++x == argc)
                goto usage;
-           if ((length = atoi(argv[x])) < 2 || length > 1024) {
+           if ((length = atoi(argv[x])) < 2 || length > MAX_LENGTH) {
                fprintf(stderr, "%s: Invalid length\n", *argv);
                ExitProgram(EXIT_FAILURE);
            }
                fprintf(stderr, "%s: Invalid length\n", *argv);
                ExitProgram(EXIT_FAILURE);
            }
@@ -389,7 +442,7 @@ main(int argc, char *argv[])
        case 'n':
            if (++x == argc)
                goto usage;
        case 'n':
            if (++x == argc)
                goto usage;
-           if ((number = atoi(argv[x])) < 1 || number > 40) {
+           if ((number = atoi(argv[x])) < 1 || number > MAX_WORMS) {
                fprintf(stderr, "%s: Invalid number of worms\n", *argv);
                ExitProgram(EXIT_FAILURE);
            }
                fprintf(stderr, "%s: Invalid number of worms\n", *argv);
                ExitProgram(EXIT_FAILURE);
            }
@@ -422,8 +475,8 @@ main(int argc, char *argv[])
 
     curs_set(0);
 
 
     curs_set(0);
 
-    bottom = LINES - 1;
-    last = COLS - 1;
+    last_y = LINES - 1;
+    last_x = COLS - 1;
 
 #ifdef A_COLOR
     if (has_colors()) {
 
 #ifdef A_COLOR
     if (has_colors()) {
@@ -435,7 +488,7 @@ main(int argc, char *argv[])
 #endif
 
 #define SET_COLOR(num, fg) \
 #endif
 
 #define SET_COLOR(num, fg) \
-           init_pair(num+1, fg, bg); \
+           init_pair(num+1, (short) fg, (short) bg); \
            flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
 
        SET_COLOR(0, COLOR_GREEN);
            flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
 
        SET_COLOR(0, COLOR_GREEN);
@@ -448,9 +501,9 @@ main(int argc, char *argv[])
     }
 #endif /* A_COLOR */
 
     }
 #endif /* A_COLOR */
 
-    refs = typeMalloc(short *, LINES);
+    refs = typeMalloc(int *, (size_t) LINES);
     for (y = 0; y < LINES; y++) {
     for (y = 0; y < LINES; y++) {
-       refs[y] = typeMalloc(short, COLS);
+       refs[y] = typeMalloc(int, (size_t) COLS);
        for (x = 0; x < COLS; x++) {
            refs[y][x] = 0;
        }
        for (x = 0; x < COLS; x++) {
            refs[y][x] = 0;
        }
@@ -458,22 +511,22 @@ main(int argc, char *argv[])
 
 #ifdef BADCORNER
     /* if addressing the lower right corner doesn't work in your curses */
 
 #ifdef BADCORNER
     /* if addressing the lower right corner doesn't work in your curses */
-    refs[bottom][last] = 1;
+    refs[last_y][last_x] = 1;
 #endif /* BADCORNER */
 
     for (n = number, w = &worm[0]; --n >= 0; w++) {
 #endif /* BADCORNER */
 
     for (n = number, w = &worm[0]; --n >= 0; w++) {
-       w->attrs = flavor[n % SIZEOF(flavor)];
+       w->attrs = flavor[(unsigned) n % SIZEOF(flavor)];
        w->orientation = 0;
        w->head = 0;
 
        w->orientation = 0;
        w->head = 0;
 
-       if (!(ip = typeMalloc(short, (length + 1)))) {
+       if (!(ip = typeMalloc(int, (size_t) (length + 1)))) {
            fprintf(stderr, "%s: out of memory\n", *argv);
            ExitProgram(EXIT_FAILURE);
        }
        w->xpos = ip;
        for (x = length; --x >= 0;)
            *ip++ = -1;
            fprintf(stderr, "%s: out of memory\n", *argv);
            ExitProgram(EXIT_FAILURE);
        }
        w->xpos = ip;
        for (x = length; --x >= 0;)
            *ip++ = -1;
-       if (!(ip = typeMalloc(short, (length + 1)))) {
+       if (!(ip = typeMalloc(int, (size_t) (length + 1)))) {
            fprintf(stderr, "%s: out of memory\n", *argv);
            ExitProgram(EXIT_FAILURE);
        }
            fprintf(stderr, "%s: out of memory\n", *argv);
            ExitProgram(EXIT_FAILURE);
        }
@@ -484,7 +537,7 @@ main(int argc, char *argv[])
     if (field) {
        const char *p;
        p = field;
     if (field) {
        const char *p;
        p = field;
-       for (y = bottom; --y >= 0;) {
+       for (y = last_y; --y >= 0;) {
            for (x = COLS; --x >= 0;) {
                addch((chtype) (*p++));
                if (!*p)
            for (x = COLS; --x >= 0;) {
                addch((chtype) (*p++));
                if (!*p)
@@ -492,50 +545,34 @@ main(int argc, char *argv[])
            }
        }
     }
            }
        }
     }
-    napms(10);
-    refresh();
+    USING_WINDOW(stdscr, wrefresh);
     nodelay(stdscr, TRUE);
 
     while (!done) {
        int ch;
 
     nodelay(stdscr, TRUE);
 
     while (!done) {
        int ch;
 
-       if ((ch = getch()) > 0) {
+       ++sequence;
+       if ((ch = get_input()) > 0) {
 #ifdef TRACE
            if (trace_start || trace_end) {
                if (generation == trace_start) {
                    trace(TRACE_CALLS);
 #ifdef TRACE
            if (trace_start || trace_end) {
                if (generation == trace_start) {
                    trace(TRACE_CALLS);
-                   getch();
+                   get_input();
                } else if (generation == trace_end) {
                    trace(0);
                } else if (generation == trace_end) {
                    trace(0);
-                   getch();
+                   get_input();
                }
 
                generation++;
            }
 #endif
                }
 
                generation++;
            }
 #endif
+
 #ifdef KEY_RESIZE
            if (ch == KEY_RESIZE) {
 #ifdef KEY_RESIZE
            if (ch == KEY_RESIZE) {
-               if (last != COLS - 1) {
-                   for (y = 0; y <= bottom; y++) {
-                       refs[y] = typeRealloc(short, COLS, refs[y]);
-                       for (x = last + 1; x < COLS; x++)
-                           refs[y][x] = 0;
-                   }
-                   last = COLS - 1;
-               }
-               if (bottom != LINES - 1) {
-                   for (y = LINES; y <= bottom; y++)
-                       free(refs[y]);
-                   refs = typeRealloc(short *, LINES, refs);
-                   for (y = bottom + 1; y < LINES; y++) {
-                       refs[y] = typeMalloc(short, COLS);
-                       for (x = 0; x < COLS; x++)
-                           refs[y][x] = 0;
-                   }
-                   bottom = LINES - 1;
-               }
+               USING_WINDOW(stdscr, update_refs);
            }
 #endif
            }
 #endif
+
            /*
             * Make it simple to put this into single-step mode, or resume
             * normal operation -T.Dickey
            /*
             * Make it simple to put this into single-step mode, or resume
             * normal operation -T.Dickey
@@ -553,9 +590,10 @@ main(int argc, char *argv[])
 
        done = draw_all_worms();
        napms(10);
 
        done = draw_all_worms();
        napms(10);
-       refresh();
+       USING_WINDOW(stdscr, wrefresh);
     }
 
     }
 
+    Trace(("Cleanup"));
     cleanup();
 #ifdef NO_LEAKS
     for (y = 0; y < LINES; y++) {
     cleanup();
 #ifdef NO_LEAKS
     for (y = 0; y < LINES; y++) {
@@ -571,6 +609,7 @@ main(int argc, char *argv[])
     /*
      * Do this just in case one of the threads did not really exit.
      */
     /*
      * Do this just in case one of the threads did not really exit.
      */
+    Trace(("join all threads"));
     for (n = 0; n < number; n++) {
        pthread_join(worm[n].thread, NULL);
     }
     for (n = 0; n < number; n++) {
        pthread_join(worm[n].thread, NULL);
     }