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