home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ncurses-1.9.9e-src.tgz / tar.out / fsf / ncurses / test / worm.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  8KB  |  360 lines

  1. /*
  2.  
  3.      @@@        @@@    @@@@@@@@@@     @@@@@@@@@@@    @@@@@@@@@@@@
  4.      @@@        @@@   @@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@@@@@
  5.      @@@        @@@  @@@@      @@@@   @@@@           @@@@ @@@  @@@@
  6.      @@@   @@   @@@  @@@        @@@   @@@            @@@  @@@   @@@
  7.      @@@  @@@@  @@@  @@@        @@@   @@@            @@@  @@@   @@@
  8.      @@@@ @@@@ @@@@  @@@        @@@   @@@            @@@  @@@   @@@
  9.       @@@@@@@@@@@@   @@@@      @@@@   @@@            @@@  @@@   @@@
  10.        @@@@  @@@@     @@@@@@@@@@@@    @@@            @@@  @@@   @@@
  11.         @@    @@       @@@@@@@@@@     @@@            @@@  @@@   @@@
  12.  
  13.                  Eric P. Scott
  14.               Caltech High Energy Physics
  15.                  October, 1980
  16.  
  17.         Hacks to turn this into a test frame for cursor movement:
  18.             Eric S. Raymond <esr@snark.thyrsus.com>
  19.                 January, 1995
  20.  
  21.         July 1995 (esr): worms is now in living color! :-)
  22.  
  23. Options:
  24.     -f            fill screen with copies of 'WORM' at start.
  25.     -l <n>            set worm length
  26.     -n <n>            set number of worms
  27.     -t            make worms leave droppings
  28.     -T <start> <end>    set trace interval
  29.     -S            set single-stepping during trace interval
  30.     -N            suppress cursor-movement optimization
  31.  
  32.   This program makes a good torture-test for the ncurses cursor-optimization
  33.   code.  You can use -T to set the worm move interval over which movement
  34.   traces will be dumped.  The program stops and waits for one character of
  35.   input at the beginning and end of the interval.
  36. */
  37.  
  38. #include <curses.h>
  39. #include <stdlib.h>
  40. #include <signal.h>
  41.  
  42. #define cursor(col,row) move(row,col)
  43.  
  44. short *ref[128];
  45. static chtype flavor[]={
  46.     'O' , '*', '#', '$', '%', '0', '@',
  47. };
  48. #define MAXWORMS    (sizeof(flavor)/sizeof(chtype))
  49. static short xinc[]={
  50.      1,  1,  1,  0, -1, -1, -1,  0
  51. }, yinc[]={
  52.     -1,  0,  1,  1,  1,  0, -1, -1
  53. };
  54. static struct worm {
  55.     int orientation, head;
  56.     short *xpos, *ypos;
  57. } worm[40];
  58.  
  59. static char *field;
  60. static int length=16, number=3;
  61. static chtype trail=' ';
  62.  
  63. #ifdef TRACE
  64. int generation, trace_start, trace_end, singlestep;
  65. #endif /* TRACE */
  66. static struct options {
  67.     int nopts;
  68.     int opts[3];
  69. } normal[8]={
  70.     { 3, { 7, 0, 1 } },
  71.     { 3, { 0, 1, 2 } },
  72.     { 3, { 1, 2, 3 } },
  73.     { 3, { 2, 3, 4 } },
  74.     { 3, { 3, 4, 5 } },
  75.     { 3, { 4, 5, 6 } },
  76.     { 3, { 5, 6, 7 } },
  77.     { 3, { 6, 7, 0 } }
  78. }, upper[8]={
  79.     { 1, { 1, 0, 0 } },
  80.     { 2, { 1, 2, 0 } },
  81.     { 0, { 0, 0, 0 } },
  82.     { 0, { 0, 0, 0 } },
  83.     { 0, { 0, 0, 0 } },
  84.     { 2, { 4, 5, 0 } },
  85.     { 1, { 5, 0, 0 } },
  86.     { 2, { 1, 5, 0 } }
  87. }, left[8]={
  88.     { 0, { 0, 0, 0 } },
  89.     { 0, { 0, 0, 0 } },
  90.     { 0, { 0, 0, 0 } },
  91.     { 2, { 2, 3, 0 } },
  92.     { 1, { 3, 0, 0 } },
  93.     { 2, { 3, 7, 0 } },
  94.     { 1, { 7, 0, 0 } },
  95.     { 2, { 7, 0, 0 } }
  96. }, right[8]={
  97.     { 1, { 7, 0, 0 } },
  98.     { 2, { 3, 7, 0 } },
  99.     { 1, { 3, 0, 0 } },
  100.     { 2, { 3, 4, 0 } },
  101.     { 0, { 0, 0, 0 } },
  102.     { 0, { 0, 0, 0 } },
  103.     { 0, { 0, 0, 0 } },
  104.     { 2, { 6, 7, 0 } }
  105. }, lower[8]={
  106.     { 0, { 0, 0, 0 } },
  107.     { 2, { 0, 1, 0 } },
  108.     { 1, { 1, 0, 0 } },
  109.     { 2, { 1, 5, 0 } },
  110.     { 1, { 5, 0, 0 } },
  111.     { 2, { 5, 6, 0 } },
  112.     { 0, { 0, 0, 0 } },
  113.     { 0, { 0, 0, 0 } }
  114. }, upleft[8]={
  115.     { 0, { 0, 0, 0 } },
  116.     { 0, { 0, 0, 0 } },
  117.     { 0, { 0, 0, 0 } },
  118.     { 0, { 0, 0, 0 } },
  119.     { 0, { 0, 0, 0 } },
  120.     { 1, { 3, 0, 0 } },
  121.     { 2, { 1, 3, 0 } },
  122.     { 1, { 1, 0, 0 } }
  123. }, upright[8]={
  124.     { 2, { 3, 5, 0 } },
  125.     { 1, { 3, 0, 0 } },
  126.     { 0, { 0, 0, 0 } },
  127.     { 0, { 0, 0, 0 } },
  128.     { 0, { 0, 0, 0 } },
  129.     { 0, { 0, 0, 0 } },
  130.     { 0, { 0, 0, 0 } },
  131.     { 1, { 5, 0, 0 } }
  132. }, lowleft[8]={
  133.     { 3, { 7, 0, 1 } },
  134.     { 0, { 0, 0, 0 } },
  135.     { 0, { 0, 0, 0 } },
  136.     { 1, { 1, 0, 0 } },
  137.     { 2, { 1, 7, 0 } },
  138.     { 1, { 7, 0, 0 } },
  139.     { 0, { 0, 0, 0 } },
  140.     { 0, { 0, 0, 0 } }
  141. }, lowright[8]={
  142.     { 0, { 0, 0, 0 } },
  143.     { 1, { 7, 0, 0 } },
  144.     { 2, { 5, 7, 0 } },
  145.     { 1, { 5, 0, 0 } },
  146.     { 0, { 0, 0, 0 } },
  147.     { 0, { 0, 0, 0 } },
  148.     { 0, { 0, 0, 0 } },
  149.     { 0, { 0, 0, 0 } }
  150. };
  151.  
  152. void onsig(int sig);
  153. float ranf(void);
  154.  
  155. int
  156. main(int argc, char *argv[])
  157. {
  158. int x, y;
  159. int n;
  160. struct worm *w;
  161. struct options *op;
  162. int h;
  163. short *ip;
  164. int last, bottom;
  165.  
  166.     for (x=1;x<argc;x++) {
  167.         register char *p;
  168.         p=argv[x];
  169.         if (*p=='-') p++;
  170.         switch (*p) {
  171.         case 'f':
  172.             field="WORM";
  173.             break;
  174.         case 'l':
  175.             if (++x==argc) goto usage;
  176.             if ((length=atoi(argv[x]))<2||length>1024) {
  177.                 fprintf(stderr,"%s: Invalid length\n",*argv);
  178.                 exit(1);
  179.             }
  180.             break;
  181.         case 'n':
  182.             if (++x==argc) goto usage;
  183.             if ((number=atoi(argv[x]))<1||number>40) {
  184.                 fprintf(stderr,"%s: Invalid number of worms\n",*argv);
  185.                 exit(1);
  186.             }
  187.             break;
  188.         case 't':
  189.             trail='.';
  190.             break;
  191. #ifdef TRACE
  192.         case 'S':
  193.             singlestep = TRUE;
  194.             break;
  195.         case 'T':
  196.             trace_start = atoi(argv[++x]);
  197.             trace_end   = atoi(argv[++x]);
  198.             break;
  199.         case 'N':
  200.             no_optimize = TRUE;        /* declared by ncurses */
  201.             break;
  202. #endif /* TRACE */
  203.         default:
  204.         usage:
  205.             fprintf(stderr, "usage: %s [-field] [-length #] [-number #] [-trail]\n",*argv);
  206.             exit(1);
  207.             break;
  208.         }
  209.     }
  210.  
  211.     signal(SIGINT, onsig);
  212.     initscr();
  213. #ifdef TRACE
  214.     noecho();
  215.     cbreak();
  216. #endif /* TRACE */
  217.     nonl();
  218.     bottom = LINES-1;
  219.     last = COLS-1;
  220.  
  221. #ifdef A_COLOR
  222.     if (has_colors())
  223.     {
  224.     start_color();
  225.  
  226.     init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
  227.     init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
  228.     init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
  229.     init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
  230.     init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
  231.     init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
  232.     init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
  233.  
  234.     flavor[0] |= COLOR_PAIR(COLOR_GREEN) | A_BOLD;
  235.     flavor[1] |= COLOR_PAIR(COLOR_RED) | A_BOLD;
  236.     flavor[2] |= COLOR_PAIR(COLOR_CYAN) | A_BOLD;
  237.     flavor[3] |= COLOR_PAIR(COLOR_WHITE) | A_BOLD;
  238.     flavor[4] |= COLOR_PAIR(COLOR_MAGENTA) | A_BOLD;
  239.     flavor[5] |= COLOR_PAIR(COLOR_BLUE) | A_BOLD;
  240.     flavor[6] |= COLOR_PAIR(COLOR_YELLOW) | A_BOLD;
  241.     }
  242. #endif /* A_COLOR */
  243.  
  244.     ip=(short *)malloc(LINES*COLS*sizeof (short));
  245.  
  246.     for (n=0;n<LINES;) {
  247.         ref[n++]=ip; ip+=COLS;
  248.     }
  249.     for (ip=ref[0],n=LINES*COLS;--n>=0;) *ip++=0;
  250.  
  251. #ifdef BADCORNER
  252.     /* if addressing the lower right corner doesn't work in your curses */
  253.     ref[bottom][last]=1;
  254. #endif /* BADCORNER */
  255.  
  256.     for (n=number, w= &worm[0];--n>=0;w++) {
  257.         w->orientation=w->head=0;
  258.         if (!(ip=(short *)malloc((length+1)*sizeof (short)))) {
  259.             fprintf(stderr,"%s: out of memory\n",*argv);
  260.             exit(1);
  261.         }
  262.         w->xpos=ip;
  263.         for (x=length;--x>=0;) *ip++ = -1;
  264.         if (!(ip=(short *)malloc((length+1)*sizeof (short)))) {
  265.             fprintf(stderr,"%s: out of memory\n",*argv);
  266.             exit(1);
  267.         }
  268.         w->ypos=ip;
  269.         for (y=length;--y>=0;) *ip++ = -1;
  270.     }
  271.     if (field) {
  272.         register char *p;
  273.         p=field;
  274.         for (y=bottom;--y>=0;) {
  275.             for (x=COLS;--x>=0;) {
  276.                 addch((chtype)(*p++));
  277.                 if (!*p) p=field;
  278.             }
  279.             addch('\n');
  280.         }
  281.     }
  282.     refresh();
  283.  
  284.     for (;;) {
  285. #ifdef TRACE
  286.         if (trace_start || trace_end) {
  287.             if (generation == trace_start) {
  288.             trace(TRACE_CALLS);
  289.             getch();
  290.             } else if (generation == trace_end) {
  291.             trace(0);
  292.             getch();
  293.             }
  294.  
  295.             if (singlestep && generation > trace_start && generation < trace_end)
  296.             getch();
  297.  
  298.             generation++;
  299.         }
  300. #endif /* TRACE */
  301.  
  302.         for (n=0,w= &worm[0];n<number;n++,w++) {
  303.             if ((x=w->xpos[h=w->head])<0) {
  304.                 cursor(x=w->xpos[h]=0,y=w->ypos[h]=bottom);
  305.                 addch(flavor[n % MAXWORMS]);
  306.                 ref[y][x]++;
  307.             }
  308.             else y=w->ypos[h];
  309.             if (++h==length) h=0;
  310.             if (w->xpos[w->head=h]>=0) {
  311.                 register int x1, y1;
  312.                 x1=w->xpos[h]; y1=w->ypos[h];
  313.                 if (--ref[y1][x1]==0) {
  314.                     cursor(x1,y1); addch(trail);
  315.                 }
  316.             }
  317.             op= &(x==0 ? (y==0 ? upleft : (y==bottom ? lowleft : left)) :
  318.                 (x==last ? (y==0 ? upright : (y==bottom ? lowright : right)) :
  319.             (y==0 ? upper : (y==bottom ? lower : normal))))[w->orientation];
  320.             switch (op->nopts) {
  321.             case 0:
  322.                 refresh();
  323.                 endwin();
  324.                 exit(0);
  325.             case 1:
  326.                 w->orientation=op->opts[0];
  327.                 break;
  328.             default:
  329.                 w->orientation=op->opts[(int)(ranf()*(float)op->nopts)];
  330.             }
  331.             cursor(x+=xinc[w->orientation], y+=yinc[w->orientation]);
  332.  
  333.             if (y < 0 ) y = 0;
  334.             addch(flavor[n % MAXWORMS]);
  335.             ref[w->ypos[h]=y][w->xpos[h]=x]++;
  336.         }
  337.         refresh();
  338.     }
  339. }
  340.  
  341. void
  342. onsig(int sig)
  343. {
  344.     standend();
  345.     refresh();
  346.     endwin();
  347.     exit(sig);
  348. }
  349.  
  350. float
  351. ranf(void)
  352. {
  353. float rv;
  354. long r = rand();
  355.  
  356.     r &= 077777;
  357.     rv =((float)r/32767.);
  358.     return rv;
  359. }
  360.