home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume12 / rot / part01 / rot.c < prev   
C/C++ Source or Header  |  1990-05-05  |  10KB  |  478 lines

  1. /*
  2.  * Revision History:
  3.  *
  4.  * Original source from:
  5.  *  Peter da Silva (ihnp4!shell!neuro1!{hyd-ptd,datafact,baylor}!peter)
  6.  *
  7.  * Changes for padding added by:
  8.  *  Andrew Scott Beals ({ucbvax,decwrl}!amdcad!bandy or bandy@amdcad.amd.com)
  9.  *  20 April 1987
  10.  *
  11.  * Additional changes for padding, fix for computation of tglen,
  12.  * increase max lines, improve termlib handling, add System V #ifdefs.
  13.  *  Bill Randle (billr@tekred.TEK.COM)
  14.  *  21 April 1987
  15.  *
  16.  * Some long-standing 8-bit bugs fixed, and more randomness added.
  17.  *  Peter da Silva <peter@sugar.hackercorp.com> Dec 1 1989.
  18.  */
  19.  
  20. #include <stdio.h>
  21.  
  22. #ifdef SYSV
  23. # include <termio.h>
  24. #else
  25. # include <sgtty.h>
  26. #endif
  27.  
  28. /*        -- Miscellaneous defines --                     */
  29. #define FALSE 0
  30. #define TRUE 1
  31. #define MAXCOL 80
  32. #define MAXLI 34
  33.  
  34. extern char *tgetstr();
  35.  
  36. int lastx, lasty;
  37. struct _c {
  38.     struct _c *c_next;
  39.     int c_line, c_column;
  40.     char c_mark;
  41. } *clist;
  42.  
  43. /*        -- Global variables --                         */
  44. char *tent;                                               /* Pointer to tbuf */
  45. extern char PC;                                             /* Pad character */
  46. extern char *UP, *BC;                         /* Upline, backsapce character */
  47. extern short ospeed;                                /* Terminal output speed */
  48. int tglen;
  49.  
  50. char *cm,                                                   /* Cursor motion */
  51.      *cl,                                                    /* Clear screen */
  52.      *ti,                            /* Init terminal */
  53.      *te;                           /* Reset terminal */
  54. int  li,                                                  /* lines on screen */
  55.      co;                                                    /* columns ditto */
  56. char screen[MAXLI+1][MAXCOL];
  57. char newscreen[MAXLI+1][MAXCOL];
  58.  
  59. /* Options */
  60. int packflag = 0;
  61.  
  62. main(ac, av)
  63. int ac;
  64. char **av;
  65. {
  66.     /* set ospeed so padding works correctly */
  67. #ifdef SYSV
  68.     struct termio    p;
  69.  
  70.     if(ioctl(1, TCGETA, &p) != -1)
  71.         ospeed=p.c_cflag & CBAUD;
  72. #else
  73.     struct sgttyb    p;
  74.  
  75.     if(ioctl(1, TIOCGETP, &p) != -1)
  76.         ospeed=p.sg_ospeed;
  77. #endif
  78.  
  79.     srand(getpid());
  80.     tinit(getenv("TERM"));
  81.     while(av[1][0]=='-') {
  82.         while(av[1][1]) {
  83.             switch(av[1][1]) {
  84.                 case 'p': packflag=1; break;
  85.                 default: printf("rot [-p] [file]...\n");
  86.             }
  87.             av[1]++;
  88.         }
  89.         av++;
  90.     }
  91.     if(av[1])
  92.         while(*++av)
  93.             dropf(*av);
  94.     else
  95.         fdropf(stdin);
  96.     tend();
  97. }
  98.  
  99. at(x, y, c)
  100. int x, y;
  101. char c;
  102. {
  103. #ifdef DEBUG
  104.     _at(x, y);
  105. #else
  106.     if(y==lasty) {
  107.         if(x!=lastx) {
  108.             if(x<lastx && lastx-x<tglen)
  109.                 while(x<lastx) {
  110.                     putchar('\b');
  111.                     lastx--;
  112.                 }
  113.             else if(x>lastx && x-lastx<tglen)
  114.                 while(x>lastx) {
  115.                     putchar(0x7F&newscreen[lasty][lastx]);
  116.                     lastx++;
  117.                 }
  118.             else
  119.                 _at(x, y);
  120.         }
  121.     } else
  122.         _at(x, y);
  123. #endif
  124.     c &= 0x7F;
  125.     putchar(c);
  126.     if(c >= ' ' && c != '\177')
  127.         lastx++;
  128.     if(lastx>=co) {
  129.         lastx -= co;
  130.         lasty++;
  131.     }
  132. }
  133.  
  134. _at(x, y)
  135. int x, y;
  136. {
  137.     extern void    outc();
  138.  
  139.     tputs(tgoto(cm, x, y), 1, outc);     /* handle padding */
  140.     lastx = x;
  141.     lasty = y;
  142. }
  143.  
  144. void
  145. outc(c)
  146. register c;
  147. {
  148.     putc(c&0x7F, stdout);
  149. }
  150.  
  151. tinit(name)
  152. char *name;
  153. {
  154.     static char junkbuf[1024], *junkptr;
  155.     char tbuf[1024];
  156.     int  intr();
  157.  
  158.     junkptr = junkbuf;
  159.  
  160.     tgetent(tbuf, name);
  161.  
  162.     if (!tgetflag("bs"))        /* is backspace not used? */
  163.         BC = tgetstr("bc",&junkptr);    /* find out what is */
  164.     else
  165.         BC = "\b";        /* make a backspace handy */
  166.     if (tgetstr("pc", &junkptr) != NULL)
  167.         PC = *junkptr;  /* set pad character */
  168.     else
  169.         PC = '\0';
  170.     UP = tgetstr("up", &junkptr);
  171.     cm = tgetstr("cm", &junkptr);
  172.     if (cm == NULL) {
  173.         printf("Can't rot on dumb terminals.\n");
  174.         exit(1);
  175.     }
  176.     cl = tgetstr("cl", &junkptr);
  177.     ti = tgetstr("ti", &junkptr);
  178.     te = tgetstr("te", &junkptr);
  179.     li = min(tgetnum("li"), MAXLI);
  180.     if (li == -1)
  181.         li = 24;
  182.     co = min(tgetnum("co"), MAXCOL);
  183.     if (co == -1)
  184.         co = 80;
  185.     tglen = strlen(tgoto(cm, co-1, li-1));
  186. }
  187.  
  188. tend()
  189. {
  190.     outs(te);
  191.     _at(0, li-1);
  192.     putchar('\n');
  193.     fflush(stdout);
  194. }
  195.  
  196. readscreen(fp)
  197. FILE *fp;
  198. {
  199.     int line, column, p;
  200.     char tmp[256];
  201.  
  202.     for(line=0; line<li; line++)
  203.         for(column=0; column<co; column++)
  204.             newscreen[line][column] = screen[line][column] = ' ';
  205.     for(column=0; column<co; column++)
  206.         newscreen[li][column] = screen[li][column] = '*';
  207.     line=0;
  208.     while(line<li) {
  209.         if(!fgets(tmp, 256, fp))
  210.             return;
  211.  
  212.         for(column=0, p=0; tmp[p]; p++) {
  213.             tmp[p] &= ~0200;
  214.             if(tmp[p] < ' ' || tmp[p] == 127)
  215.                 switch(tmp[p]) {
  216.                     case '\t':
  217.                         while(++column % 8)
  218.                             continue;
  219.                         break;
  220.                     case '\n':
  221.                         column = 0;
  222.                         line++;
  223.                         break;
  224.                     default:
  225.                         newscreen[line][column] = '^';
  226.                         column++;
  227.                         if(column>=co) {
  228.                             column -= co;
  229.                             line++;
  230.                         }
  231.                         newscreen[line][column] =
  232.                             (tmp[p]+'@') & 127;
  233.                         column++;
  234.                         break;
  235.                 }
  236.             else {
  237.                 newscreen[line][column] = tmp[p];
  238.                 column++;
  239.             }
  240.             if(column >= co) {
  241.                 column -= co;
  242.                 line++;
  243.             }
  244.             if(line >= li)
  245.                 break;
  246.         }
  247.     }
  248.     for(column=0; column<co; column++)
  249.         newscreen[line][column] = screen[li][column] = '*';
  250. }
  251.  
  252. drawscreen()
  253. {
  254.     lastx = lasty = 0;
  255.     outs(cl);
  256.     update();
  257. }
  258.  
  259. update() /* copy new screen back to old screen */
  260. {
  261.     int l, c;
  262.  
  263.     for(l=0; l<li; l++)
  264.         for(c=0; c<co; c++)
  265.             if(screen[l][c] != newscreen[l][c]) {
  266.                 if((screen[l][c] & ~0200) !=
  267.                    (newscreen[l][c] & ~0200))
  268.                     at(c, l, newscreen[l][c]);
  269.                 screen[l][c] = newscreen[l][c];
  270.             }
  271. }
  272.  
  273. drop(line, column)
  274. int line, column;
  275. {
  276.     struct _c *hold, *temp;
  277.  
  278.     if(line<0 || line>=li || column<0 || column>=co ||
  279.        (line>=li-2 && column >= co-1) || /* scroll potential */
  280.        screen[line][column]==' ' || /* empty */
  281.        screen[line][column] & 0200) /* already in list */
  282.         return;
  283.     if(screen[line+1][column]!=' ' &&
  284.        (column==co-1 ||screen[line+1][column+1]!=' ') &&
  285.        (column==0 ||screen[line+1][column-1]!=' '))
  286.         return;
  287.  
  288.     hold = (struct _c *) malloc(sizeof(struct _c));
  289.     hold -> c_next;
  290.     hold -> c_column = column;
  291.     hold -> c_line = line;
  292.     hold -> c_mark = 0;
  293.     screen[line][column] |= 0200;
  294.  
  295.     for(temp = clist; temp && temp->c_next; temp=temp->c_next)
  296.         if(!(rand()&1111))
  297.             break;
  298.     if(temp) {
  299.         hold->c_next = temp->c_next;
  300.         temp->c_next = hold;
  301.     } else {
  302.         hold->c_next = clist;
  303.         clist = hold;
  304.     }
  305. }
  306.  
  307. drops()
  308. {
  309.     int l, c;
  310.     struct _c *hold;
  311.     for(hold = clist; hold; hold=hold->c_next) {
  312.         int line = hold->c_line, column=hold->c_column;
  313.         if(line>= li-2 && column>=co-1) {
  314.             newscreen[line][column] &= ~0200;
  315.             screen[line][column] &= ~0200;
  316.             hold->c_mark = 1;
  317.             continue;
  318.         }
  319.         if(newscreen[line+1][column+1] == ' ' &&
  320.            newscreen[line+1][column-1] == ' ')
  321.             drop(line+1, column);
  322.         drop(line, column+1);
  323.         drop(line-1, column);
  324.         drop(line, column-1);
  325.         if(newscreen[line+1][column]==' ' ||
  326.            (packflag &&
  327.             newscreen[line+1][column]==(screen[line][column]&~0200)
  328.            )
  329.           ) {
  330.             newscreen[line+1][column] = screen[line][column];
  331.             newscreen[line][column] = ' ';
  332.             line++;
  333.         } else if(rand()&01000) {
  334.             if(column>0 && newscreen[line][column-1] == ' ' &&
  335.                 newscreen[line+1][column-1]==' ') {
  336.                 newscreen[line][column-1] =
  337.                     screen[line][column];
  338.                 newscreen[line][column] = ' ';
  339.                 column--;
  340.             }
  341.             else if(column<co-1 &&
  342.                 newscreen[line][column+1] == ' ' &&
  343.                 newscreen[line+1][column+1]==' ') {
  344.                     newscreen[line][column+1] =
  345.                         screen[line][column];
  346.                     newscreen[line][column] = ' ';
  347.                     column++;
  348.             }
  349.             else {
  350.                 screen[line][column] &= ~0200;
  351.                 newscreen[line][column] &= ~0200;
  352.                 hold -> c_mark = 1;
  353.             }
  354.         } else {
  355.             if(column<co-1 && newscreen[line][column+1] == ' ' &&
  356.                 newscreen[line+1][column+1]==' ') {
  357.                 newscreen[line][column+1] =
  358.                     screen[line][column];
  359.                 newscreen[line][column] = ' ';
  360.                 column++;
  361.             }
  362.             else if(column>0 && newscreen[line][column-1] == ' ' &&
  363.                 newscreen[line+1][column-1]==' ') {
  364.                 newscreen[line][column-1] =
  365.                     screen[line][column];
  366.                 newscreen[line][column] = ' ';
  367.                 column--;
  368.             }
  369.             else {
  370.                 newscreen[line][column] &= ~0200;
  371.                 screen[line][column] &= ~0200;
  372.                 hold -> c_mark = 1;
  373.             }
  374.         }
  375.         hold -> c_column = column;
  376.         hold -> c_line = line;
  377.         fflush(stdout);
  378.     }
  379.  
  380.     while(clist && clist->c_mark) {
  381.         struct _c *p = clist;
  382.         clist = clist -> c_next;
  383.         free(p);
  384.     }
  385.     hold = clist;
  386.     while(hold && hold->c_next)
  387.         if(hold->c_next->c_mark) {
  388.             struct _c *p = hold->c_next;
  389.             hold->c_next = p->c_next;
  390.             free(p);
  391.         } else
  392.             hold=hold->c_next;
  393. }
  394.  
  395. droplet(line, column)
  396. int line, column;
  397. {
  398.     int ret;
  399.     if(line==li-1)
  400.         return 0;
  401.     while(column>=0 &&
  402.           screen[line][column]!=' ' &&
  403.           screen[line+1][column]==' ')
  404.         column--;
  405.     column++;
  406.     while(column<co &&
  407.           screen[line][column]!=' ' &&
  408.           screen[line+1][column]==' ')
  409.         drop(line, column++);
  410.     ret = clist != 0;
  411.     while(clist) {
  412.         drops();
  413.         update();
  414.     }
  415.     return ret;
  416. }
  417.  
  418. dropscreen()
  419. {
  420.     int column, line;
  421.     int rubbish = 0, count = 0;
  422.  
  423.     do {
  424.         int start, limit, incr;
  425.         count++;
  426.         rubbish = 0;
  427.         if(count&1) { start=li-2; limit=0; incr = -1; }
  428.         else { start=0; limit=li-2; incr=1; }
  429.         for(line=start; line!=limit && !rubbish; line+=incr) {
  430.             if(line&1)
  431.                 for(column=0; column<co && !rubbish; column++)
  432.                     rubbish += droplet(line, column);
  433.             else
  434.                 for(column=co-1; column>=0 && !rubbish; column--)
  435.                     rubbish += droplet(line, column);
  436.         }
  437.     } while(rubbish);
  438. }
  439.  
  440. dropf(file)
  441. char *file;
  442. {
  443.     FILE *fp;
  444.  
  445.     if(!(fp = fopen(file, "r"))) {
  446.         perror(file);
  447.         return -1;
  448.     }
  449.     fdropf(fp);
  450. }
  451.  
  452. fdropf(fp)
  453. FILE *fp;
  454. {
  455.     int i;
  456.  
  457.     while(!feof(fp)) {
  458.         readscreen(fp);
  459.         drawscreen();
  460.         for(i=0; i<20; i++)
  461.             droplet((rand()>>4) % (li-1), (rand()>>4) % co);
  462.         dropscreen();
  463.     }
  464. }
  465.  
  466. outs(s)
  467. char *s;
  468. {
  469.     fputs(s, stdout);
  470. }
  471.  
  472. min(a, b)
  473. int a, b;
  474. {
  475.     if(a<b) return a;
  476.     return b;
  477. }
  478.