+
+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->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.width - 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)