[net.bizarre] Another bizarre program

chris@umcp-cs.UUCP (Chris Torek) (07/31/85)

For those who liked floop, Peter da Silva has written something somewhat
similar.  He asked that I post it, as some site upstream of him seems to
like bizarre things so much that it won't let go of them.

[I take no responsibility for the bugs in the program.  In particular,
don't try it on a terminal that has padding in its termcap....]
-----
From: seismo!ut-sally!shell!neuro1!hyd-ptd!peter (Peter da Silva @ Hydril PTD, Houston, TX)
Subject:         Amusing little program.
Word-Of-The-Day: ass

The following code should be fairly amusing...
--
Peter da Silva (ihnp4!shell!neuro1!{hyd-ptd,datafact,baylor}!peter)

	Those who can, do; those who can't, write.
	Those who can't write work for Tekweek.

----------------
cat > rot.c << '+++'
#include <stdio.h>

/*		-- Miscellaneous defines --				     */
#define FALSE 0
#define TRUE 1
#define MAXCOL 80
#define MAXLI 24

int lastx, lasty;
struct _c {
	struct _c *c_next;
	int c_line, c_column;
	char c_mark;
} *clist;

/*		-- Global variables --					     */
char *tent;                                               /* Pointer to tbuf */
char PC;                                                    /* Pad character */
char *UP, *BC;                                /* Upline, backsapce character */
short ospeed;                                       /* Terminal output speed */
int tglen;

char *cm,                                                   /* Cursor motion */
     *cl,                                                    /* Clear screen */
     *ti,						    /* Init terminal */
     *te;						   /* Reset terminal */
int  li,                                                  /* lines on screen */
     co;                                                    /* columns ditto */
char screen[MAXLI+1][MAXCOL];
char newscreen[MAXLI+1][MAXCOL];

main(ac, av)
int ac;
char **av;
{
	srand(getpid());
	tinit(getenv("TERM"));
	if(av[1])
		while(*++av)
			dropf(*av);
	else
		fdropf(stdin);
	tend();
}

at(x, y, c)
int x, y;
char c;
{
#ifdef DEBUG
	_at(x, y);
#else
	if(y==lasty) {
		if(x!=lastx) {
			if(x<lastx && lastx-x<tglen)
				while(x<lastx) {
					putchar('\b');
					lastx--;
				}
			else if(x>lastx && x-lastx<tglen)
				while(x>lastx) {
					putchar(newscreen[lasty][lastx]);
					lastx++;
				}
			else
				_at(x, y);
		}
	} else
		_at(x, y);
#endif
	c &= ~0200;
	putchar(c);
	if(c >= ' ' && c != '\177')
		lastx++;
	if(lastx>=co) {
		lastx -= co;
		lasty++;
	}
}

_at(x, y)
int x, y;
{
	outs(tgoto(cm, x, y));
	lastx = x;
	lasty = y;
}

tinit(name)
char *name;
{
	static char junkbuf[1024], *junkptr;
	char tbuf[1024];
	int  intr();

	junkptr = junkbuf;

	tgetent(tbuf, name);

	PC = tgetstr("pc", &junkptr);
	UP = tgetstr("up", &junkptr);
	BC = tgetstr("bc", &junkptr);
	cm = tgetstr("cm", &junkptr);
	cl = tgetstr("cl", &junkptr);
	ti = tgetstr("ti", &junkptr);
	te = tgetstr("te", &junkptr);
	li = min(tgetnum("li"), MAXLI);
	co = min(tgetnum("co"), MAXCOL);
	tglen = strlen(tgoto(co-1, li-1));
}

tend()
{
	outs(te);
	_at(0, li-1);
	putchar('\n');
	fflush(stdout);
}

readscreen(fp)
FILE *fp;
{
	int line, column, p;
	char tmp[256];

	for(line=0; line<li; line++)
		for(column=0; column<co; column++)
			newscreen[line][column] = screen[line][column] = ' ';
	for(column=0; column<co; column++)
		newscreen[li][column] = screen[li][column] = '*';
	line=0;
	while(line<li) {
		if(!fgets(tmp, 256, fp))
			return;

		for(column=0, p=0; tmp[p]; p++) {
			tmp[p] &= ~0200;
			if(tmp[p] < ' ' || tmp[p] == 127)
				switch(tmp[p]) {
					case '\t':
						while(++column % 8)
							continue;
						break;
					case '\n':
						column = 0;
						line++;
						break;
					default:
						newscreen[line][column] = '^';
						column++;
						if(column>=co) {
							column -= co;
							line++;
						}
						newscreen[line][column] =
							(tmp[p]+'@') & 127;
						column++;
						break;
				}
			else {
				newscreen[line][column] = tmp[p];
				column++;
			}
			if(column >= co) {
				column -= co;
				line++;
			}
			if(line >= li)
				break;
		}
	}
	for(column=0; column<co; column++)
		newscreen[line][column] = screen[li][column] = '*';
}

drawscreen()
{
	lastx = lasty = 0;
	outs(cl);
	update();
}

update() /* copy new screen back to old screen */
{
	int l, c;

	for(l=0; l<li; l++)
		for(c=0; c<co; c++)
			if(screen[l][c] != newscreen[l][c]) {
				if((screen[l][c] & ~0200) !=
				   (newscreen[l][c] & ~0200))
					at(c, l, newscreen[l][c]);
				screen[l][c] = newscreen[l][c];
			}
}

drop(line, column)
int line, column;
{
	struct _c *hold;

	if(line<0 || line>=li || column<0 || column>=co ||
	   (line>=li-2 && column >= co-1) || /* scroll potential */
	   screen[line][column]==' ' || /* empty */
	   screen[line][column] & 0200) /* already in list */
		return;
	if(screen[line+1][column]!=' ' &&
	   (column==co-1 ||screen[line+1][column+1]!=' ') &&
	   (column==0 ||screen[line+1][column-1]!=' '))
		return;

	hold = (struct _c *) malloc(sizeof(struct _c));
	hold -> c_next = clist;
	hold -> c_column = column;
	hold -> c_line = line;
	hold -> c_mark = 0;
	screen[line][column] |= 0200;
	clist = hold;
}

drops()
{
	int l, c;
	struct _c *hold;
	for(hold = clist; hold; hold=hold->c_next) {
		int line = hold->c_line, column=hold->c_column;
		if(line>= li-2 && column>=co-1) {
			newscreen[line][column] &= ~0200;
			screen[line][column] &= ~0200;
			hold->c_mark = 1;
			continue;
		}
		drop(line+1, column);
		drop(line, column+1);
		drop(line-1, column);
		drop(line, column-1);
		if(newscreen[line+1][column]==' ') {
			newscreen[line+1][column] = screen[line][column];
			newscreen[line][column] = ' ';
			line++;
		} else if(rand()&01000) {
			if(column>0 && newscreen[line][column-1] == ' ' &&
			    newscreen[line+1][column-1]==' ') {
				newscreen[line][column-1] =
					screen[line][column];
				newscreen[line][column] = ' ';
				column--;
			}
			else if(column<co-1 &&
				newscreen[line][column+1] == ' ' &&
				newscreen[line+1][column+1]==' ') {
					newscreen[line][column+1] =
						screen[line][column];
					newscreen[line][column] = ' ';
					column++;
			}
			else {
				screen[line][column] &= ~0200;
				newscreen[line][column] &= ~0200;
				hold -> c_mark = 1;
			}
		} else {
			if(column<co-1 && newscreen[line][column+1] == ' ' &&
			    newscreen[line+1][column+1]==' ') {
				newscreen[line][column+1] =
					screen[line][column];
				newscreen[line][column] = ' ';
				column++;
			}
			else if(column>0 && newscreen[line][column-1] == ' ' &&
			    newscreen[line+1][column-1]==' ') {
				newscreen[line][column-1] =
					screen[line][column];
				newscreen[line][column] = ' ';
				column--;
			}
			else {
				newscreen[line][column] &= ~0200;
				screen[line][column] &= ~0200;
				hold -> c_mark = 1;
			}
		}
		hold -> c_column = column;
		hold -> c_line = line;
		fflush(stdout);
	}

	while(clist && clist->c_mark) {
		struct _c *p = clist;
		clist = clist -> c_next;
		free(p);
	}
	hold = clist;
	while(hold && hold->c_next)
		if(hold->c_next->c_mark) {
			struct _c *p = hold->c_next;
			hold->c_next = p->c_next;
			free(p);
		} else
			hold=hold->c_next;
}

droplet(line, column)
int line, column;
{
	int ret;
	while(column>=0 && screen[line][column]!=' ')
		column--;
	column++;
	while(column<co && screen[line][column]!=' ')
		drop(line, column++);
	ret = clist != 0;
	while(clist) {
		drops();
		update();
	}
	return ret;
}

dropscreen()
{
	int column, line;
	int rubbish = 0, count = 0;

	do {
		int start, limit, incr;
		count++;
		rubbish = 0;
		if(count&1) { start=li-2; limit=0; incr = -1; }
		else { start=0; limit=li-2; incr=1; }
		for(line=start; line!=limit && !rubbish; line+=incr) {
			if(line&1)
				for(column=0; column<co && !rubbish; column++)
					rubbish += droplet(line, column);
			else
				for(column=co-1; column>=0 && !rubbish; column--)
					rubbish += droplet(line, column);
		}
	} while(rubbish);
}

dropf(file)
char *file;
{
	FILE *fp;

	if(!(fp = fopen(file, "r"))) {
		perror(file);
		return -1;
	}
	fdropf(fp);
}

fdropf(fp)
FILE *fp;
{
	int i;

	while(!feof(fp)) {
		readscreen(fp);
		drawscreen();
		for(i=0; i<20; i++)
			droplet((rand()>>4) % li, (rand()>>4) % co);
		dropscreen();
	}
}

outs(s)
char *s;
{
	fputs(s, stdout);
}

min(a, b)
int a, b;
{
	if(a<b) return a;
	return b;
}
+++
cc rot.c -O -o rot -ltermlib
rot <rot.c
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland