argv@island.UUCP (Dan Heller) (08/04/88)
Posting-number: Volume 4, Issue 12 Submitted-by: "Dan Heller" <argv@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@ucscb.ucsc.edu island!argv@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