diff options
author | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
---|---|---|
committer | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
commit | d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch) | |
tree | cbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /hacks/munch.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'hacks/munch.c')
-rw-r--r-- | hacks/munch.c | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/hacks/munch.c b/hacks/munch.c new file mode 100644 index 0000000..836731a --- /dev/null +++ b/hacks/munch.c @@ -0,0 +1,476 @@ +/* Munching Squares and Mismunch + * + * Portions copyright 1992-2014 Jamie Zawinski <jwz@jwz.org> + * + * Permission to use, copy, modify, distribute, and sell this + * software and its documentation for any purpose is hereby + * granted without fee, provided that the above copyright notice + * appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation. No + * representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or + * implied warranty. + * + * Portions Copyright 1997, Tim Showalter + * + * Permission is granted to copy, modify, and use this as long + * as this notice remains intact. No warranties are expressed or + * implied. CMU Sucks. + * + * Portions Copyright 2004 Steven Hazel <sah@thalassocracy.org> + * + * (The "mismunch" part). + * + * "munch.c" and "mismunch.c" merged by jwz, 29-Aug-2008. + * + * + * + *********************************************************************** + * + * HAKMEM + * + * MIT AI Memo 239, Feb. 29, 1972. + * Beeler, M., Gosper, R.W., and Schroeppel, R. + * + * http://www.inwap.com/pdp10/hbaker/hakmem/hacks.html#item146 + * + *********************************************************************** + * + * ITEM 146: MUNCHING SQUARES + * + * Another simple display program. It is thought that this was + * discovered by Jackson Wright on the RLE PDP-1 circa 1962. + * + * DATAI 2 + * ADDB 1,2 + * ROTC 2,-22 + * XOR 1,2 + * JRST .-4 + * + * 2=X, 3=Y. Try things like 1001002 in data switches. This also + * does * interesting things with operations other than XOR, and + * rotations * other than -22. (Try IOR; AND; TSC; FADR; FDV(!); + * ROT * -14, -9, -20, * ...) + * + * ITEM 147 (Schroeppel): + * + * Munching squares is just views of the graph Y = X XOR T for + * consecutive values of T = time. + * + * ITEM 147 (Cohen, Beeler): + * + * A modification to munching squares which reveals them in frozen + * states through opening and closing curtains: insert FADR 2,1 + * before the XOR. Try data switches = + * + * 4000,,4 1000,,2002 2000,,4 0,,1002 + * + * (Notation: <left half>,,<right half>) + * Also try the FADR after the XOR, switches = 1001,,1. + * + *********************************************************************** + */ + +#include <math.h> +#include "screenhack.h" + +typedef struct _muncher { + int mismunch; + int width; + int atX, atY; + int kX, kT, kY; + int grav; + XColor fgc; + int yshadow, xshadow; + int x, y, t; + int doom; + int done; +} muncher; + + +struct state { + Display *dpy; + Window window; + + GC gc; + int delay, simul, clear, xor; + int logminwidth, logmaxwidth; + int restart, window_width, window_height; + + int draw_n; /* number of squares before we have to clear */ + int draw_i; + int mismunch; + + muncher **munchers; +}; + + +/* + * dumb way to get # of digits in number. Probably faster than actually + * doing a log and a division, maybe. + */ +static int dumb_log_2(int k) +{ + int r = -1; + while (k > 0) { + k >>= 1; r++; + } + return r; +} + + +static void calc_logwidths (struct state *st) +{ + /* Choose a range of square sizes based on the window size. We want + a power of 2 for the square width or the munch doesn't fill up. + Also, if a square doesn't fit inside an area 20% smaller than the + window, it's too big. Mismunched squares that big make things + look too noisy. */ + + if (st->window_height < st->window_width && + st->window_width < st->window_height * 5) { + st->logmaxwidth = (int)dumb_log_2(st->window_height * 0.8); + } else { + st->logmaxwidth = (int)dumb_log_2(st->window_width * 0.8); + } + + if (st->logmaxwidth < 2) { + st->logmaxwidth = 2; + } + + /* we always want three sizes of squares */ + st->logminwidth = st->logmaxwidth - 2; + + if (st->logminwidth < 2) { + st->logminwidth = 2; + } +} + + + +static muncher *make_muncher (struct state *st) +{ + int logwidth; + XWindowAttributes xgwa; + muncher *m = (muncher *) malloc(sizeof(muncher)); + + XGetWindowAttributes(st->dpy, st->window, &xgwa); + + m->mismunch = st->mismunch; + + /* choose size -- power of two */ + logwidth = (st->logminwidth + + (random() % (1 + st->logmaxwidth - st->logminwidth))); + + m->width = 1 << logwidth; + + /* draw at this location */ + m->atX = (random() % (xgwa.width <= m->width ? 1 + : xgwa.width - m->width)); + m->atY = (random() % (xgwa.height <= m->width ? 1 + : xgwa.height - m->width)); + + /* wrap-around by these values; no need to % as we end up doing that + later anyway */ + m->kX = ((random() % 2) + ? (random() % m->width) : 0); + m->kT = ((random() % 2) + ? (random() % m->width) : 0); + m->kY = ((random() % 2) + ? (random() % m->width) : 0); + + /* set the gravity of the munch, or rather, which direction we draw + stuff in. */ + m->grav = random() % 2; + + /* I like this color scheme better than random colors. */ + switch (random() % 4) { + case 0: + m->fgc.red = random() % 65536; + m->fgc.blue = random() % 32768; + m->fgc.green = random() % 16384; + break; + + case 1: + m->fgc.red = 0; + m->fgc.blue = random() % 65536; + m->fgc.green = random() % 16384; + break; + + case 2: + m->fgc.red = random() % 8192; + m->fgc.blue = random() % 8192; + m->fgc.green = random() % 49152; + break; + + case 3: + m->fgc.red = random() % 65536; + m->fgc.green = m->fgc.red; + m->fgc.blue = m->fgc.red; + break; + } + + /* Sometimes draw a mostly-overlapping copy of the square. This + generates all kinds of neat blocky graphics when drawing in xor + mode. */ + if (!m->mismunch || (random() % 4)) { + m->xshadow = 0; + m->yshadow = 0; + } else { + m->xshadow = (random() % (m->width/3)) - (m->width/6); + m->yshadow = (random() % (m->width/3)) - (m->width/6); + } + + /* Start with a random y value -- this sort of controls the type of + deformities seen in the squares. */ + m->y = random() % 256; + + m->t = 0; + + /* + Doom each square to be aborted at some random point. + (When doom == (width - 1), the entire square will be drawn.) + */ + m->doom = (m->mismunch ? (random() % m->width) : (m->width - 1)); + m->done = 0; + + return m; +} + + +static void munch (struct state *st, muncher *m) +{ + int drawX, drawY; + XWindowAttributes xgwa; + + if (m->done) { + return; + } + + XGetWindowAttributes(st->dpy, st->window, &xgwa); + + if (!mono_p) { + /* XXX there are probably bugs with this. */ + if (XAllocColor(st->dpy, xgwa.colormap, &m->fgc)) { + XSetForeground(st->dpy, st->gc, m->fgc.pixel); + } + } + + /* Finally draw this pass of the munching error. */ + + for(m->x = 0; m->x < m->width; m->x++) { + /* figure out the next point */ + + /* + The ordinary Munching Squares calculation is: + m->y = ((m->x ^ ((m->t + m->kT) % m->width)) + m->kY) % m->width; + + We create some feedback by plugging in y in place of x, and + make a couple of values negative so that some parts of some + squares get drawn in the wrong place. + */ + if (m->mismunch) + m->y = ((-m->y ^ ((-m->t + m->kT) % m->width)) + m->kY) % m->width; + else + m->y = ((m->x ^ ((m->t + m->kT) % m->width)) + m->kY) % m->width; + + drawX = ((m->x + m->kX) % m->width) + m->atX; + drawY = (m->grav ? m->y + m->atY : m->atY + m->width - 1 - m->y); + + XDrawPoint(st->dpy, st->window, st->gc, drawX, drawY); + if ((m->xshadow != 0) || (m->yshadow != 0)) { + /* draw the corresponding shadow point */ + XDrawPoint(st->dpy, st->window, st->gc, drawX + m->xshadow, drawY + m->yshadow); + } + /* XXX may want to change this to XDrawPoints, + but it's fast enough without it for the moment. */ + + } + + m->t++; + if (m->t > m->doom) { + m->done = 1; + } +} + + +static void * +munch_init (Display *dpy, Window w) +{ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + XWindowAttributes xgwa; + XGCValues gcv; + int i; + char *mm; + + st->dpy = dpy; + st->window = w; + st->restart = 0; + + /* get the dimensions of the window */ + XGetWindowAttributes(st->dpy, w, &xgwa); + + /* create the gc */ + gcv.foreground= get_pixel_resource(st->dpy, xgwa.colormap, + "foreground","Foreground"); + gcv.background= get_pixel_resource(st->dpy, xgwa.colormap, + "background","Background"); + + st->gc = XCreateGC(st->dpy, w, GCForeground|GCBackground, &gcv); + + st->delay = get_integer_resource(st->dpy, "delay", "Integer"); + if (st->delay < 0) st->delay = 0; + + st->simul = get_integer_resource(st->dpy, "simul", "Integer"); + if (st->simul < 1) st->simul = 1; + + st->clear = get_integer_resource(st->dpy, "clear", "Integer"); + if (st->clear < 0) st->clear = 0; + + st->xor = get_boolean_resource(st->dpy, "xor", "Boolean"); + + mm = get_string_resource (st->dpy, "mismunch", "Mismunch"); + if (!mm || !*mm || !strcmp(mm, "random")) + st->mismunch = random() & 1; + else + st->mismunch = get_boolean_resource (st->dpy, "mismunch", "Mismunch"); + + st->window_width = xgwa.width; + st->window_height = xgwa.height; + + calc_logwidths(st); + + /* always draw xor on mono. */ + if (mono_p || st->xor) { + XSetFunction(st->dpy, st->gc, GXxor); + } + + st->munchers = (muncher **) calloc(st->simul, sizeof(muncher *)); + for (i = 0; i < st->simul; i++) { + st->munchers[i] = make_muncher(st); + } + + return st; +} + +static unsigned long +munch_draw (Display *dpy, Window w, void *closure) +{ + struct state *st = (struct state *) closure; + int i; + + for (i = 0; i < 5; i++) { + + /* for (draw_i = 0; draw_i < simul; draw_i++) */ + { + munch(st, st->munchers[st->draw_i]); + + if (st->munchers[st->draw_i]->done) { + st->draw_n++; + + free(st->munchers[st->draw_i]); + st->munchers[st->draw_i] = make_muncher(st); + } + } + + st->draw_i++; + if (st->draw_i >= st->simul) { + int i = 0; + st->draw_i = 0; + if (st->restart || (st->clear && st->draw_n >= st->clear)) { + + char *mm = get_string_resource (st->dpy, "mismunch", "Mismunch"); + if (!mm || !*mm || !strcmp(mm, "random")) + st->mismunch = random() & 1; + + for (i = 0; i < st->simul; i++) { + free(st->munchers[i]); + st->munchers[i] = make_muncher(st); + } + + XClearWindow(st->dpy, w); + st->draw_n = 0; + st->restart = 0; + } + } + + } + + return st->delay; +} + + +static void +munch_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ + struct state *st = (struct state *) closure; + if (w != st->window_width || + h != st->window_height) { + st->window_width = w; + st->window_height = h; + calc_logwidths(st); + st->restart = 1; + st->draw_i = 0; + } +} + +static Bool +munch_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + struct state *st = (struct state *) closure; + if (screenhack_event_helper (dpy, window, event)) + { + int i; + st->window_height--; + munch_reshape(dpy, window, closure, st->window_width, st->window_height); + st->mismunch = random() & 1; + for (i = 0; i < st->simul; i++) { + free (st->munchers[i]); + st->munchers[i] = make_muncher(st); + } + XClearWindow(dpy, window); + return True; + } + return False; +} + +static void +munch_free (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + free (st); +} + + +static const char *munch_defaults [] = { + ".lowrez: true", + ".background: black", + ".foreground: white", + "*fpsSolid: true", + "*delay: 10000", + "*mismunch: random", + "*simul: 5", + "*clear: 65", + "*xor: True", +#ifdef HAVE_MOBILE + "*ignoreRotation: True", +#endif + + 0 +}; + +static XrmOptionDescRec munch_options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-simul", ".simul", XrmoptionSepArg, 0 }, + { "-clear", ".clear", XrmoptionSepArg, "true" }, + { "-xor", ".xor", XrmoptionNoArg, "true" }, + { "-no-xor", ".xor", XrmoptionNoArg, "false" }, + { "-classic", ".mismunch", XrmoptionNoArg, "false" }, + { "-mismunch", ".mismunch", XrmoptionNoArg, "true" }, + { "-random", ".mismunch", XrmoptionNoArg, "random" }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Munch", munch) |