v04i012: *crumble* do interesting things to a Sun console

Dan Heller argv at island.UUCP
Thu Aug 4 09:01:32 AEST 1988


Posting-number: Volume 4, Issue 12
Submitted-by: "Dan Heller" <argv at island.UUCP>
Archive-name: crumble

#! /bin/sh
echo extracting crumble.c via dumbshar
sed 's/^X//' << \EOF > crumble.c
X/*
X * Crumble your screen.
X *
X * This program must be run on a SUN workstation only.  However, you can
X * run it under either X or Suntools or on a bare sun monitor.  If you want
X * to do all out war (see below) or use the -w option, you must use suntools.
X *
X * Written by:
X *
X *	Don Hatch		Dan Heller
X *  splat at ucscb.ucsc.edu   island!argv at sun.com
X *
X * common usage:
X *   subtle (rlogin somewhere else and run this)
X *     crumble -hf
X *     crumble -hf
X *   fun and cute (let these run all night)
X *     crumble -d
X *     crumble -d -c
X *   destructive (but fun)
X *     crumble -C -c
X *     crumble -f -d -c
X *   all out WAR (and *LOTS* of fun! mwahahahaha!!)
X *     crumble -C -f -m 200 | rsh other_sun crumble -C -f (suntools required)
X *   (note: you should be able to _see_ the victim's console for best effect)
X *
X * \fBPlease send creative ideas for more usage to the authors!\fR
X *
X * compile: (triple click the next line and stuff it)
X	cc -O -s crumble.c -lsuntool -lsunwindow -lpixrect -o crumble
X *
X * Command line options:
X *
X * -v		verbose
X * -vf		flip chars vertically
X * -hf		swap chars horizontally
X * -s timeout	sleep between each char
X * -a timeout   I forget what this is for
X * -m number	max pixels to try to blow up
X * -u useconds  before explosion, flash this fast
X * -t		testing
X * -b		start at bottom of screen and eat up
X * -B		same, but grab the whole character
X * -c		blow up letters on contact
X * -f [N]	show target on fire button (default 1000)
X * -d		drop characters without crumbling
X *		note, if -c specified, chars drop until contact with something
X * -w		just do stuff in a window
X * -C		grab chunks of screen and obliterate them
X * -r		reverse video for monochrome monitors
X * -value	value is a color value for "off" pixels (color displays only)
X * +value	value is a color value for "on" pixels (color displays only)
X *
X * If there are remaining args (one is checked), it is the display device name.
X * For example, on a Sun3-110, you might want to use your greyscale screen,
X * not your monochrome screen.  So, you could specify:
X * crumble -255 +254 /dev/fb
X * for color, or:
X * crumble /dev/bwtwo0
X * for monochrome.
X *
X * Obviously, you can't mix some of these arguments.  Trail and error
X * is the best way to figure out which don't work.
X *
X * Environment variable: DEV_FB to default to a frame buffer.
X */
X#include <stdio.h>
X#include <sys/file.h>
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X#include <math.h>
X#include <signal.h>
X#include <ctype.h>
X#include <suntool/fullscreen.h>
X
X#define round(x) floor((x)+.5)
X#define ison(x,y) (pr_get(pr,x,y) == ON)
X#define isoff(x,y) (pr_get(pr,x,y) == OFF)
X#define put(x,y,z) pr_put(pr,x,y,z)
X#define swap(a,b) (a ^= b ^= a ^= b)
X
Xint ON = 1, OFF = 0;
Xstruct pixrect *pr, *pr2;
Xint MAX = 300;
Xint n;
Xstruct pr_pos A[10000];
Xint verbose, sleepytime, usleepytime, alarmtime, testing, hflip, vflip,
X	do_crumble, bottom_up, bottom_up_2, do_drop, do_chunks, do_window,
X	do_focus, getting, putting;
Xchar *device = NULL;
X#define DEFAULT_DEVICE "/dev/fb"
X
X#define append(x,y) (n>=MAX ? 0 : (A[n].x=x,A[n].y=y,n++,1))
X#define when break; case
X#define otherwise break; default
Xchar *getenv();
X
X#define XOR (PIX_SRC ^ PIX_DST)
X
Xmain(argc, argv)
Xchar **argv;
X{
X    Canvas canvas;
X    int catch();
X    register int x,y,y2,y3;
X    register int this, this3;
X    int val, sum;
X    register int a,b;
X
X    putting = !isatty(1);
X    getting = !isatty(0);
X
X    while (*++argv) {
X	if (!strcmp(*argv, "-v"))
X	    verbose = 1;
X	else if (!strcmp(*argv, "-vf")) /* flip chars vertically */
X	    vflip = 1;
X	else if (!strcmp(*argv, "-hf")) /* swap chars horizontally */
X	    hflip = 1;
X	else if (!strcmp(*argv, "-s"))  /* be subtle, sleep between chars */
X	    sleepytime = atoi(*++argv);
X	else if (!strcmp(*argv, "-a"))  /* i forget what this is for */
X	    alarmtime = atoi(*++argv);
X	else if (!strcmp(*argv, "-m"))  /* max pixels to try to blow up */
X	    MAX = atoi(*++argv);
X	else if (!strcmp(*argv, "-u"))  /* before explosion, flash this fast */
X	    usleepytime = atoi(*++argv);
X	else if (!strcmp(*argv, "-t"))
X	    testing = 1;
X	else if (!strcmp(*argv, "-b"))  /* start at the bottom and eat up */
X	    bottom_up = 1;
X	else if (!strcmp(*argv, "-B"))  /* same, but grab the whole character */
X	    bottom_up_2 = 1;
X	else if (!strcmp(*argv, "-c"))  /* blow up (crumble) on contact */
X	    do_crumble = 1;
X	else if (!strcmp(*argv, "-f")) { /* show target on fire button */
X	    if (argv[1] && isdigit(argv[1][0]))
X		do_focus = atoi(*++argv);
X	    else
X	        do_focus = 1000;
X	}
X	else if (!strcmp(*argv, "-d"))  /* drop characters without crumbling */
X	    do_drop = 1;  /* note, if -c specified, chars drop until contact */
X	else if (!strcmp(*argv, "-w"))  /* just do stuff in a window */
X	    do_window = 1;
X	else if (!strcmp(*argv, "-C"))  /* grab chunks of screen */
X	    do_chunks = 1;
X	else if (!strcmp(*argv, "-r"))  /* reverse video for monochrome */
X	    OFF = !(ON = !ON);
X	else if (**argv == '-' && isdigit(argv[0][1]))
X	    OFF = atoi(*argv + 1); /* set off pixels explicitly */
X	else if (**argv == '+' && isdigit(argv[0][1]))
X	    ON = atoi(*argv + 1); /* set on pixels explicitly */
X	else
X	    device = *argv; /* if other than /dev/fb */
X    }
X    if (!device && !(device = getenv("DEV_FB")))
X	device = DEFAULT_DEVICE;
X
X    if (!(pr = pr_open(device)))
X	exit(1); /* pr_open does a perror anyway! how stupid */
X
X    if (!(pr2 = mem_create(pr->pr_width, pr->pr_height, 1)))
X	perror("mem_create"), exit(1);
X
X    pr_rop(pr2,0,0,pr2->pr_width, pr2->pr_height,PIX_NOT(PIX_DST),NULL,0,0);
X
X    if (do_window || putting) {
X	int catch_events();
X	Frame frame;
X	Canvas canvas;
X	Pixwin *pw;
X	struct fullscreen *fs;
X	int fd;
X	setbuf(stdout, 0);
X	frame = window_create(0, FRAME,
X	    WIN_X, 0, WIN_Y, 0,
X	    WIN_WIDTH, 30, WIN_HEIGHT, 30,
X	    0);
X	canvas = window_create(frame, CANVAS,
X	    WIN_CONSUME_PICK_EVENTS,
X		WIN_NO_EVENTS,
X		WIN_MOUSE_BUTTONS,
X		LOC_MOVE,
X		0,
X	    WIN_EVENT_PROC, catch_events,
X	    0);
X	pw = canvas_pixwin(canvas);
X	fd = (int) window_get(canvas, WIN_FD);
X	if (alarmtime)
X	    alarm(alarmtime);
X	win_grabio(fd);
X	if (getenv("OFF")) {
X	    Cursor cursor = window_get(canvas, WIN_CURSOR);
X	    cursor_set(cursor, CURSOR_SHOW_CURSOR, 0, 0);
X	    window_set(canvas, WIN_CURSOR, cursor, 0);
X	}
X	window_main_loop(frame);
X	win_releaseio(fd);
X	exit(0);
X    }
X    srandom(getpid());
X    if (getting) {
X	int ID, x, y;
X	while (scanf("%d %d %d", &ID, &x, &y) == 3)
X	    do_event(ID,x,y);
X    } else if (bottom_up) {
X	for (y = pr->pr_height-1; y >= 0; --y) {
X	    n = 0;
X	    for (x = 0; x < pr->pr_width; ++x)
X		if (ison(x,y)) {
X		    A[n].x = x;
X		    A[n].y = y;
X		    n++;
X		}
X	    crumble(pr);
X	}
X    } else if (bottom_up_2)
X	while (1)
X	for (y = pr->pr_height-1; y >= 0; y -= 2)
X	    for (x = 0; x < pr->pr_width; ++x)
X		do_letter(x,y);
X    else
X	while (1) {
X	    y = random()% (pr->pr_height-1);
X	    x = random()% (pr->pr_width-1);
X	    do_letter(x,y);
X	}
X}
X
Xdo_letter(x,y)
Xregister int x,y;
X{
X    if (testing) {
X	printf("%d ", pr_get(pr,x,y));
X	return;
X    }
X    n = 0;
X    if (ison(x,y) && fetch(pr,x,y) == 1) {
X	unfetch();
X	if (verbose)
X	    printf("%d ", n);
X	putlist();
X	if (sleepytime)
X	    sleep(sleepytime);
X    } else
X        unfetch();
X}
X
Xint edge_ok = 1;
X/*
X * return 1 on success (got something)
X * 0 if got nothing,
X * -1 if went off edge
X */
Xfetch(pr,x,y)
Xstruct pixrect *pr;
X{
X    if (!ison(x,y))
X	return 0;
X    if (do_chunks && ison(x,y))
X	while (ison(x,y+1))
X	    y++;
X    return _fetch(x,y);
X}
X/*
X * return 1 if stayed on screen, -1 if went off screen or got too big.
X */
X_fetch(x,y)
Xregister int x,y;
X{
X    int i;
X    char ind[8];
X    static struct pr_pos dirs[8] = {
X    {-1,0}, {1,0}, {0,-1}, {0,1}, {-1,-1}, {-1,1}, {1,-1}, {1,1}
X    };
X    if (pr_get(pr,x,y) == PIX_ERR)
X	return edge_ok ? 0 : -1;
X    if (isoff(x,y) || !pr_get(pr2, x,y))
X	return 0;
X    for (i = 1; i < 8; ++i)
X	ind[i] = i;
X    if (append(x,y)) {
X	pr_put(pr2,x,y,0);
X	if (do_chunks) {
X	    register int i1, i2;
X	    for (i = 1; i <= 5; ++i) {
X	        i1 = random() % 4;
X	        i2 = random() % 4;	/* scramble first four directions */
X		if (i1 != i2)
X		    swap(ind[i1], ind[i2]);
X	    }
X	}
X	for (i = 0; i < 8; ++i)
X	    if (_fetch(x+dirs[ind[i]].x, y+dirs[ind[i]].y) == -1)
X		return -1;
X	return 1;
X    } else
X	return do_chunks ? 1 : -1; /* if do_chunks, then return the chunk */
X}
Xunfetch()
X{
X    int i;
X    for (i=0; i < n; ++i) {
X	pr_put(pr2, A[i].x,A[i].y,1);
X    }
X}
Xputlist()
X{
X    int i;
X    int x,y;
X    struct pr_pos dest, drop();
X    struct pixrect *make_letter_pr();
X    struct pixrect *p = make_letter_pr(&x, &y);
X    if (verbose)
X	dump(p);
X    if (do_focus) {
X	focus(pr, A[0].x, A[0].y);
X	buzz(pr, p, x, y);
X    }
X    if (hflip || vflip)
X	reverse(pr, p, x, y, p->pr_width, p->pr_height);
X    if (do_drop) {
X        dest = drop(pr, p, x, y, p->pr_width, p->pr_height);
X	for (i = 0; i < n; ++i)
X	    A[i].y += dest.y - y;
X    }
X    if (do_crumble)
X	crumble(pr);
X    pr_destroy(p);
X}
X#define max4(a,b,c,d) max(max(max(a,b),c),d)
X#define min4(a,b,c,d) min(min(min(a,b),c),d)
X
Xbuzz(pr, p, off_x, off_y)
Xstruct pixrect *pr, *p;
Xregister int off_x,off_y;
X{
X    int size = max4(off_x, pr->pr_width-off_x, off_y, pr->pr_height-off_x);
X    size = min(size, do_focus);
X    if (p)
X    for (; size >= 0; --size) {
X	pr_rop(pr, off_x, off_y, p->pr_width, p->pr_height, PIX_NOT(PIX_DST),
X							NULL, 0,0);
X	if (usleepytime)
X	    usleep(usleepytime);
X	pr_rop(pr, off_x, off_y, p->pr_width, p->pr_height, PIX_NOT(PIX_DST),
X							NULL, 0,0);
X	if (usleepytime)
X	    usleep(usleepytime);
X    }
X}
Xfocus(pr, x,y)
Xstruct pixrect *pr;
Xregister int x,y;
X{
X    int size = max4(x, pr->pr_width-x, y, pr->pr_height-y);
X    size = min(size, do_focus);
X    for (; size >= 0; --size) {
X	frame(pr, x-size, y-size, x+size, y+size, PIX_NOT(PIX_DST));
X	frame(pr, x-size, y-size, x+size, y+size, PIX_NOT(PIX_DST));
X    }
X}
Xframe(pr, xmin, ymin, xmax, ymax, op, value)
Xstruct pixrect *pr;
Xregister int xmin, xmax, ymin, ymax, op, value;
X{
X    pr_vector(pr, xmin, ymin, xmax, ymin, op, 1);
X    pr_vector(pr, xmax, ymin, xmax, ymax, op, 1);
X    pr_vector(pr, xmax, ymax, xmin, ymax, op, 1);
X    pr_vector(pr, xmin, ymax, xmin, ymin, op, 1);
X}
X/*
X * Make a small pixrect containing the points currently stored in the A array.
X * Coordinates of the new pixrect with respect to the global pr are returned
X * in *x, *y.
X */
Xstruct pixrect *
Xmake_letter_pr(x, y)
Xint *x, *y;
X{
X    int i;
X    struct pr_pos dest, drop();
X    register int minx,maxx,miny,maxy;
X    struct pixrect *p;
X    minx=maxx=A[0].x;
X    miny=maxy=A[0].y;
X    for (i=1; i < n; ++i) {
X	minx = min(minx, A[i].x);
X	miny = min(miny, A[i].y);
X	maxx = max(maxx, A[i].x);
X	maxy = max(maxy, A[i].y);
X    }
X    *x = minx-1;
X    *y = miny-1;
X    p = mem_create(maxx-minx+3, maxy-miny+3, pr->pr_depth);
X    for (i=0; i < n; ++i) {
X	pr_put(p, A[i].x - *x, A[i].y - *y, ON);
X    }
X    return p;
X}
Xcrumble(pr)
Xstruct pixrect *pr;
X{
X    int moved, i;
X    do {
X	moved = 0;
X	for (i = 0; i < n; ++i) {
X	    struct pr_pos pos, newpos;
X	    pos = newpos = A[i];
X	    if (random() % 30 && isoff(pos.x, pos.y+1))
X		newpos.y = pos.y+1;
X	    else
X		switch(random() % 2) {
X		    when 0:
X			if (isoff(pos.x+1, pos.y+1)) {
X			    newpos.x = pos.x+1;
X			    newpos.y = pos.y+1;
X			} else goto defaul;
X		    when 1:
X			if (isoff(pos.x-1, pos.y+1)) {
X			    newpos.x = pos.x-1;
X			    newpos.y = pos.y+1;
X			} else goto defaul;
X		    otherwise:
X		    defaul:
X			if (isoff(pos.x, pos.y+1))
X			    newpos.y = pos.y+1;
X		}
X	    if (newpos.x != pos.x || newpos.y != pos.y) {
X		moved = 1;
X		if (random() % 30) {
X		    pr_put(pr, pos.x, pos.y, OFF);
X		    pr_put(pr, newpos.x, newpos.y, ON);
X		    A[i] = newpos;
X		}
X	    }
X	}
X    } while (moved);
X}
Xreverse(pr,p,x,y,w,h)
Xstruct pixrect *pr, *p;
X{
X    pr_rop(pr,x,y,w,h,XOR,p,0,0);
X    pr_reverse_rop(pr,x,y,w,h,XOR,p,0,0);
X}
Xpr_reverse_rop(dpr,dx,dy,w,h,op,spr,sx,sy)
Xstruct pixrect *spr, *dpr;
X{
X    int x,y;
X    for (y=0;y<h;++y)
X	for (x=0;x<w;++x)
X	    pr_rop(dpr, dx+x, dy+y, 1, 1, op, spr, sx + (vflip? w-1-x : x),
X						   sy + (hflip? h-1-y : y));
X}
Xstruct pr_pos
Xdrop(pr,p,x,y,w,h)
Xstruct pixrect *pr, *p;
X{
X    register int X,Y;
X    struct pr_pos dest;
X    while (canfall(pr,p,x,y+1,w,h)) {
X	for (Y=h-1; Y >= 0; Y--)
X	    for (X=0; X < w; X++)
X	    if (pr_get(p, X, Y) == ON) {
X	        pr_put(pr, X+x, Y+y, OFF);
X	        pr_put(pr, X+x, Y+y+1, ON);
X	    }
X	y++;
X    }
X    dest.x = x;
X    dest.y = y;
X    return dest;
X}
Xcanfall(pr,p,x,y,w,h)
Xstruct pixrect *pr, *p;
X{
X    int i,j;
X    for (j=0;j<h;++j)
X    for (i=0;i<w;++i)
X	if (pr_get(p,i,j) == ON && pr_get(p,i,j+1) != ON)
X	    if (pr_get(pr,x+i,y+j) != OFF)
X		return 0;
X    return 1;
X}
Xdump(p)
Xstruct pixrect *p;
X{
X    int x,y;
X    printf("size=%d,%d\n",p->pr_width, p->pr_height);
X    puts("=================================");
X    for (y=0; y < p->pr_height; ++y) {
X        for (x=0; x < p->pr_width; ++x)
X	    printf("%c ", (pr_get(p,x,y) == ON) ? '*' : ' ');
X	puts("");
X    }
X    puts("=================================");
X}
Xshoot(x,y)
Xint *x, *y;
X{
X    while (1) {
X	if (!isoff(*x,*y))
X	    break;
X	if (verbose)
X	    pr_put(pr,*x,*y,ON);
X	--*x;
X	if (!isoff(*x,*y))
X	    break;
X	if (verbose)
X	    pr_put(pr,*x,*y,ON);
X	--*y;
X    }
X}
Xcatch_events(canvas, event, data)
Xregister Canvas canvas;
Xregister Event *event;
X{
X    register int ID = event->ie_code;
X    register Pixrect *newicon = NULL;
X    int fd = (int) window_get(canvas, WIN_FD);
X    int x,y;
X    static start_fast;
X
X    if (!event_is_down(event) && ID != LOC_MOVE)
X	return;
X    x = event_x(event);
X    y = event_y(event);
X    if (getenv("Y"))
X	y += atoi(getenv("Y"));
X    else
X        y += 18;
X    if (getenv("X"))
X	x += atoi(getenv("X"));
X    else
X        x += 5;
X
X    if (ID != MS_RIGHT && putting) {
X	send(ID,x,y);
X	return;
X    }
X    if (verbose)
X        printf("Got %d (%d,%d)\n", ID,x,y);
X    win_releaseio(fd);
X    do_event(ID,x,y);
X    if (ID != MS_RIGHT)
X        win_grabio(fd);
X}
Xsend(ID, x,y)
X{
X    printf("%d %d %d\n", ID, x,y);
X}
Xdo_event(ID,x,y)
X{
X    if (verbose)
X        printf("Got %d (%d,%d)\n", ID,x,y);
X    switch(ID) {
X	when LOC_MOVE:  unshow_target();
X			show_target(x,y);
X			shoot(&x, &y);
X	when MS_LEFT:
X			unshow_target();
X			if (putting)
X			    send(x,y);
X			else {
X			    shoot(&x,&y);
X			    do_letter(x,y);
X			}
X    }
X}
Xshort bullseye_image[] = {
X/* Format_version=1, Width=16, Height=16, Depth=1, Valid_bits_per_item=16
X */
X	0x07C0,0x1830,0x2008,0x4384,0x4C64,0x8822,0x9012,0x9112,
X	0x9012,0x8822,0x4C64,0x4384,0x2008,0x1830,0x07C0,0x0000
X};
Xmpr_static(bullseye, 16, 16, 1, bullseye_image);
Xint prevx = -1, prevy = -1;
Xint target_on = 0;
Xshow_target(x,y)
X{
X    if (target_on)
X	unshow_target();
X    pr_rop(pr, x-7,y-7,bullseye.pr_width,bullseye.pr_height,XOR,&bullseye,0,0);
X    prevx = x;
X    prevy = y;
X    target_on = 1;
X}
Xunshow_target()
X{
X    if (target_on)
X	pr_rop(pr, prevx-7,prevy-7,bullseye.pr_width,bullseye.pr_height,XOR,&bullseye,0,0);
X    target_on = 0;
X}
EOF
exit 0



More information about the Comp.sources.misc mailing list