games-request@tekred.TEK.COM (05/06/87)
Submitted by: Bill Randle <games-request@tekred.TEK.COM> Mod.sources.games: Volume 1, Issue 8 Archive-name: rot22 [This is the latest and last version of the rot program. It should be pretty well bullet-proof and even includes a man page. This completely supersedes the previous version of rot (2.0, patchlevel 0) that was posted in v01i005. Many thanks to all the people that sent bug reports/fixes. -br] #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 1)." # Contents: README MANIFEST Makefile patchlvl.h rot.1 rot.c # Wrapped by billr@tekred on Tue May 5 16:41:11 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f README -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README\" else echo shar: Extracting \"README\" \(270 characters\) sed "s/^X//" >README <<'END_OF_README' XThis program cascades letters from the top of the terminal screen Xto the bottom in a waterfall effect. The original program has had Xseveral bugs fixed and added capability to properly handle padding. XAlso, this will be pretty slow at lower baudrates. X X 4/22/87 BR END_OF_README if test 270 -ne `wc -c <README`; then echo shar: \"README\" unpacked with wrong size! fi # end of overwriting check fi if test -f MANIFEST -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"MANIFEST\" else echo shar: Extracting \"MANIFEST\" \(294 characters\) sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST' X File Name Archive # Description X----------------------------------------------------------- X MANIFEST 1 This shipping list X Makefile 1 X README 1 X patchlvl.h 1 X rot.1 1 X rot.c 1 END_OF_MANIFEST if test 294 -ne `wc -c <MANIFEST`; then echo shar: \"MANIFEST\" unpacked with wrong size! fi # end of overwriting check fi if test -f Makefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"Makefile\" else echo shar: Extracting \"Makefile\" \(129 characters\) sed "s/^X//" >Makefile <<'END_OF_Makefile' X# Simple makefile for rot program X XCFLAGS = -O #-DSYSV X Xrot: rot.c X cc $(CFLAGS) -o rot rot.c -ltermlib X Xtest: rot X ./rot <rot.c END_OF_Makefile if test 129 -ne `wc -c <Makefile`; then echo shar: \"Makefile\" unpacked with wrong size! fi # end of overwriting check fi if test -f patchlvl.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"patchlvl.h\" else echo shar: Extracting \"patchlvl.h\" \(76 characters\) sed "s/^X//" >patchlvl.h <<'END_OF_patchlvl.h' X#define PATCHLEVEL 2 X X#define ROT_VERSION "2.0 patchlevel 2, 22 April 1987" END_OF_patchlvl.h if test 76 -ne `wc -c <patchlvl.h`; then echo shar: \"patchlvl.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f rot.1 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rot.1\" else echo shar: Extracting \"rot.1\" \(986 characters\) sed "s/^X//" >rot.1 <<'END_OF_rot.1' X.TH ROT 6 X.SH NAME Xrot \- a visual demonstration of X.I software X.I rot. X.SH SYNOPSIS X.B rot X<file> X.PP XThis program cascades letters from the top of the terminal screen Xto the bottom in a waterfall effect. X.PP XThis program reads from standard input and can be used as Xan output Xfilter. XAn amusing use is: X.sp X man rot | col -b | rot X.SH AUTHOR X.PP XOriginal source from Peter da Silva X.br X (ihnp4!shell!neuro1!hyd-ptd!peter) or X.br X (ihnp4!shell!neuro1!datafact!peter) or X.br X (ihnp4!shell!neuro1!baylor!peter). X.sp XMakefile and README from Bill Randle (billr@tekred.TEK.COM). X.sp XMan page from John G Dobnick X.br X (ihnp4!uwmcsd1!jgd) or X.br X (jgd@csd1.milw.wisc.edu). X.sp XBug fixes from: X.br X James Buster (bitbug@ucscb.ucsc.edu) X.br X Ed Falk (ed@sun -?) X.br X Andrew Klossner (andrew@lemming.gwd.tek.com) X.br X Andrew Scott Beals (bandy@amdcad.amd.com) X.br X Colin Plumb (ccplumb@watmath.uucp) X.br X Bill Randle (billr@tekred.tek.com) X.SH BUGS XThis is pretty slow at lower baudrates. END_OF_rot.1 if test 986 -ne `wc -c <rot.1`; then echo shar: \"rot.1\" unpacked with wrong size! fi # end of overwriting check fi if test -f rot.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rot.c\" else echo shar: Extracting \"rot.c\" \(10363 characters\) sed "s/^X//" >rot.c <<'END_OF_rot.c' X/* X * Revision History: X * X * Original source from: X * Peter da Silva (ihnp4!shell!neuro1!{hyd-ptd,datafact,baylor}!peter) X * X * Changes for padding added by: X * Andrew Scott Beals ({ucbvax,decwrl}!amdcad!bandy or bandy@amdcad.amd.com) X * 20 April 1987 X * X * Additional changes for padding, fix for computation of tglen, X * increase max lines, improve termlib handling, add System V #ifdefs. X * Bill Randle (billr@tekred.TEK.COM) X * 21 April 1987 X * X * Add padding for cl. X * Andrew Scott Beals ({ucbvax,decwrl}!amdcad!bandy or bandy@amdcad.amd.com) X * 22 April 1987 X * X * Add comments and scroll fixes from Colin Plumb (ccplumb@watmath.UUCP) X * More terminal handling cleanup and error checking. X * Bill Randle (billr@tekred.TEK.COM) X * 22 April 1987 X */ X X#include <stdio.h> X#include "patchlvl.h" X X#ifdef SYSV X# include <termio.h> X#else X# include <sgtty.h> X#endif X X/* -- Miscellaneous defines -- */ X#define FALSE 0 X#define TRUE 1 X#define MAXCOL 80 X#define MAXLI 36 X X#define min(a,b) ((a)<(b) ? a : b) X Xextern char *tgetstr(); X Xint lastx, lasty; Xstruct _c { X struct _c *c_next; X int c_line, c_column; X char c_mark; X} *clist; X X/* -- Global variables -- */ Xchar *tent; /* Pointer to tbuf */ Xextern char PC; /* Pad character */ Xextern char *UP, *BC; /* Upline, backsapce character */ Xextern short ospeed; /* Terminal output speed */ Xint tglen, bclen; X Xchar *cm, /* Cursor motion */ X *cl, /* Clear screen */ X *ti, /* Init terminal */ X *te; /* Reset terminal */ Xint li, /* lines on screen */ X co; /* columns ditto */ Xchar screen[MAXLI+1][MAXCOL]; Xchar newscreen[MAXLI+1][MAXCOL]; X Xmain(ac, av) Xint ac; Xchar **av; X{ X /* set ospeed so padding works correctly */ X#ifdef SYSV X struct termio p; X X if(ioctl(1, TCGETA, &p) != -1) X ospeed=p.c_cflag & CBAUD; X#else X struct sgttyb p; X X if(ioctl(1, TIOCGETP, &p) != -1) X ospeed=p.sg_ospeed; X#endif X X srand(getpid()); /* init random number generator */ X tinit(getenv("TERM")); /* init terminal */ X if(ac > 1) X /* do all files */ X while(--ac) X dropf(*++av); X else X /* or stdin */ X fdropf(stdin); X tend(); /* clean up terminal */ X} X X/* put character c at (x, y) */ Xat(x, y, c) Xint x, y; Xchar c; X{ X#ifdef DEBUG X _at(x, y); X#else X /* optimize cursor motion if goal is on *same* line */ X if(y==lasty) { X if(x!=lastx) { X if(x<lastx && (lastx-x)*bclen<tglen) X /* backspace into place if it takes */ X /* less characters than cursor motion */ X while(x<lastx) { X if (bclen > 1) X outs(BC); X else X putchar(*BC); X lastx--; X } X else if(x>lastx && x-lastx<tglen) X /* print intervening characters */ X while(x>lastx) { X putchar(newscreen[lasty][lastx]); X lastx++; X } X else X _at(x, y); X } X } else X _at(x, y); X#endif X c &= ~0200; X putchar(c); X if(c >= ' ' && c != '\177') X lastx++; X if(lastx>=co) { X lastx -= co; X lasty++; X } X} X X_at(x, y) Xint x, y; X{ X extern void outc(); X X tputs(tgoto(cm, x, y), 1, outc); /* handle padding */ X lastx = x; X lasty = y; X} X Xvoid Xoutc(c) Xregister c; X{ X putc(c, stdout); X} X X/* initialize terminal dependent variables */ Xtinit(name) Xchar *name; X{ X static char junkbuf[1024], *junkptr; X char tbuf[1024]; X int intr(); X X junkptr = junkbuf; X X tgetent(tbuf, name); X X if (!tgetflag("bs")) /* is backspace not used? */ X BC = tgetstr("bc",&junkptr); /* find out what is */ X else X BC = "\b"; /* make a backspace handy */ X bclen = strlen(BC); /* for optimization stuff */ X if (tgetstr("pc", &junkptr) != NULL) X PC = *junkptr; /* set pad character */ X else X PC = '\0'; X UP = tgetstr("up", &junkptr); X cm = tgetstr("cm", &junkptr); X if (cm == NULL) { X printf("Can't rot on dumb terminals.\n"); X exit(1); X } X cl = tgetstr("cl", &junkptr); X ti = tgetstr("ti", &junkptr); X te = tgetstr("te", &junkptr); X li = min(tgetnum("li"), MAXLI); X if (li == -1) X li = 24; X /* the original code had special case code for last line and */ X /* last column. Unfortunately, it didn't always work on all */ X /* terminals so we take the easy way out and don't use the */ X /* bottom line of the screen */ X li--; /* prevent bottom screen line from scrolling */ X co = min(tgetnum("co"), MAXCOL); X if (co == -1) X co = 80; X tglen = strlen(tgoto(cm, co-1, li-1)); /* for optimization stuff */ X if (ti != NULL) X outs(ti); X} X X/* cleanup terminal after use */ Xtend() X{ X if (te != NULL) X outs(te); X _at(0, li); X putchar('\n'); X fflush(stdout); X} X X/* read in a new screen */ Xreadscreen(fp) XFILE *fp; X{ X int line, column, p; X char tmp[256]; X X for(line=0; line<li; line++) X for(column=0; column<co; column++) X newscreen[line][column] = screen[line][column] = ' '; X for(column=0; column<co; column++) X newscreen[li][column] = screen[li][column] = '*'; X line=0; X while(line<li) { X if(!fgets(tmp, 256, fp)) X return; X X for(column=0, p=0; tmp[p]; p++) { X tmp[p] &= ~0200; X if(tmp[p] < ' ' || tmp[p] == 127) X switch(tmp[p]) { X case '\t': X while(++column % 8) X continue; X break; X case '\n': X column = 0; X line++; X break; X default: X newscreen[line][column] = '^'; X column++; X if(column>=co) { X column -= co; X line++; X } X newscreen[line][column] = X (tmp[p]+'@') & 127; X column++; X break; X } X else { X newscreen[line][column] = tmp[p]; X column++; X } X if(column >= co) { X column -= co; X line++; X } X if(line >= li) X break; X } X } X for(column=0; column<co; column++) X newscreen[line][column] = screen[li][column] = '*'; X} X Xdrawscreen() X{ X extern void outc(); X X lastx = lasty = 0; X if (cl != NULL) X tputs(cl, li, outc); /* for really slow terminals */ X update(); X} X X/* copy newscreen[][] to physical screen and screen[][] */ Xupdate() X{ X int l, c; X X for(l=0; l<li; l++) X for(c=0; c<co; c++) X /* copy any changes */ X if(screen[l][c] != newscreen[l][c]) { X /* are they *really* different? */ X if((screen[l][c] & ~0200) != X (newscreen[l][c] & ~0200)) X at(c, l, newscreen[l][c]); X screen[l][c] = newscreen[l][c]; X } X} X X/* add char at (column, line) to clist if feasable */ Xdrop(line, column) Xint line, column; X{ X struct _c *hold; X X if(line<0 || line>=li || column<0 || column>=co || /* off screen */ X screen[line][column]==' ' || /* empty */ X screen[line][column] & 0200) /* already in list */ X return; X if(screen[line+1][column]!=' ' && X (column==co-1 ||screen[line+1][column+1]!=' ') && X (column==0 ||screen[line+1][column-1]!=' ')) /* can't be dropped */ X return; X X hold = (struct _c *) malloc(sizeof(struct _c)); X hold -> c_next = clist; X hold -> c_column = column; X hold -> c_line = line; X hold -> c_mark = 0; X screen[line][column] |= 0200; X clist = hold; X} X X/* drop everything in the clist */ Xdrops() X{ X int line, column; X struct _c *hold; X X for(hold = clist; hold; hold=hold->c_next) { X line = hold->c_line; X column = hold->c_column; X /* add adjacent characters to clist */ X drop(line+1, column); X drop(line, column+1); X drop(line-1, column); X drop(line, column-1); X /* drop straight down if possible */ X if(newscreen[line+1][column]==' ') { X newscreen[line+1][column] = screen[line][column]; X newscreen[line][column] = ' '; X line++; X } X /* otherwise try and drop to the sides. Randomly pick X /* which side to try first. */ X else if(rand()&01000) { X if(column>0 && newscreen[line][column-1] == ' ' && X newscreen[line+1][column-1]==' ') { X newscreen[line][column-1] = X screen[line][column]; X newscreen[line][column] = ' '; X column--; X } X else if(column<co-1 && X newscreen[line][column+1] == ' ' && X newscreen[line+1][column+1]==' ') { X newscreen[line][column+1] = X screen[line][column]; X newscreen[line][column] = ' '; X column++; X } X else { X /* forget it */ X screen[line][column] &= ~0200; X newscreen[line][column] &= ~0200; X hold -> c_mark = 1; X } X } else { X if(column<co-1 && newscreen[line][column+1] == ' ' && X newscreen[line+1][column+1]==' ') { X newscreen[line][column+1] = X screen[line][column]; X newscreen[line][column] = ' '; X column++; X } X else if(column>0 && newscreen[line][column-1] == ' ' && X newscreen[line+1][column-1]==' ') { X newscreen[line][column-1] = X screen[line][column]; X newscreen[line][column] = ' '; X column--; X } X else { X /* forget it */ X newscreen[line][column] &= ~0200; X screen[line][column] &= ~0200; X hold -> c_mark = 1; X } X } X /* update list entry */ X hold -> c_column = column; X hold -> c_line = line; X } X X /* delete all list entries marked for deletion */ X /* do all at head of list */ X while(clist && clist->c_mark) { X struct _c *p = clist; X clist = clist -> c_next; X free(p); X } X /* ...and all in body */ X hold = clist; X while(hold && hold->c_next) X if(hold->c_next->c_mark) { X struct _c *p = hold->c_next; X hold->c_next = p->c_next; X free(p); X } else X hold=hold->c_next; X} X Xdroplet(line, column) Xint line, column; X{ X int ret; X while(column>=0 && screen[line][column]!=' ') X column--; X column++; X while(column<co && screen[line][column]!=' ') X drop(line, column++); X ret = clist != 0; X while(clist) { X drops(); X update(); X } X return ret; X} X Xdropscreen() X{ X int column, line; X int rubbish = 0, count = 0; X X do { X int start, limit, incr; X count++; X rubbish = 0; X if(count&1) { start=li-2; limit=0; incr = -1; } X else { start=0; limit=li-2; incr=1; } X for(line=start; line!=limit && !rubbish; line+=incr) { X if(line&1) X for(column=0; column<co && !rubbish; column++) X rubbish += droplet(line, column); X else X for(column=co-1; column>=0 && !rubbish; column--) X rubbish += droplet(line, column); X } X } while(rubbish); X} X Xdropf(file) Xchar *file; X{ X FILE *fp; X X if((fp = fopen(file, "r")) == NULL) { X perror(file); X return; X } X fdropf(fp); X} X Xfdropf(fp) XFILE *fp; X{ X int i; X X while(!feof(fp)) { X readscreen(fp); X drawscreen(); X for(i=0; i<20; i++) X droplet((rand()>>4) % li, (rand()>>4) % co); X dropscreen(); X } X} X Xouts(s) Xchar *s; X{ X fputs(s, stdout); X} END_OF_rot.c if test 10363 -ne `wc -c <rot.c`; then echo shar: \"rot.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 1 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive.mon@u23: