http://se.aminet.net/pub/X11/ftp.x.org/contrib/vms/xscreensaver-124.zip
[xscreensaver] / hacks / maze.c
1 /******************************************************************************
2  * [ maze ] ...
3  *
4  * modified:  [ 3-7-93 ]  Jamie Zawinski <jwz@mcom.com>
5  *              added the XRoger logo, cleaned up resources, made
6  *              grid size a parameter.
7  * modified:  [ 3-3-93 ]  Jim Randell <jmr@mddjmr.fc.hp.com>
8  *              Added the colour stuff and integrated it with jwz's
9  *              screenhack stuff.  There's still some work that could
10  *              be done on this, particularly allowing a resource to
11  *              specify how big the squares are.
12  * modified:  [ 10-4-88 ]  Richard Hess    ...!uunet!cimshop!rhess  
13  *              [ Revised primary execution loop within main()...
14  *              [ Extended X event handler, check_events()...
15  * modified:  [ 1-29-88 ]  Dave Lemke      lemke@sun.com  
16  *              [ Hacked for X11...
17  *              [  Note the word "hacked" -- this is extremely ugly, but at 
18  *              [   least it does the job.  NOT a good programming example 
19  *              [   for X.
20  * original:  [ 6/21/85 ]  Martin Weiss    Sun Microsystems  [ SunView ]
21  *
22  ******************************************************************************
23  Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
24   
25  All Rights Reserved
26   
27  Permission to use, copy, modify, and distribute this software and its
28  documentation for any purpose and without fee is hereby granted, 
29  provided that the above copyright notice appear in all copies and that
30  both that copyright notice and this permission notice appear in 
31  supporting documentation, and that the names of Sun or MIT not be
32  used in advertising or publicity pertaining to distribution of the
33  software without specific prior written permission. Sun and M.I.T. 
34  make no representations about the suitability of this software for 
35  any purpose. It is provided "as is" without any express or implied warranty.
36  
37  SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  PURPOSE. IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT
40  OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
41  OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
42  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
43  OR PERFORMANCE OF THIS SOFTWARE.
44  *****************************************************************************/
45
46 #include "screenhack.h"
47
48 #define XROGER
49
50 static int solve_delay, pre_solve_delay, post_solve_delay;
51
52 #include  <stdio.h>
53 #include  <X11/Xlib.h>
54 #include  <X11/Xutil.h>
55 #ifndef VMS
56 #include  <X11/bitmaps/gray1>
57 #else
58 #include "sys$common:[decw$include.bitmaps]gray1.xbm"
59 #endif
60
61 #define MAX_MAZE_SIZE_X 500
62 #define MAX_MAZE_SIZE_Y 500
63
64 #define MOVE_LIST_SIZE  (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
65
66 #define WALL_TOP        0x8000
67 #define WALL_RIGHT      0x4000
68 #define WALL_BOTTOM     0x2000
69 #define WALL_LEFT       0x1000
70
71 #define DOOR_IN_TOP     0x800
72 #define DOOR_IN_RIGHT   0x400
73 #define DOOR_IN_BOTTOM  0x200
74 #define DOOR_IN_LEFT    0x100
75 #define DOOR_IN_ANY     0xF00
76
77 #define DOOR_OUT_TOP    0x80
78 #define DOOR_OUT_RIGHT  0x40
79 #define DOOR_OUT_BOTTOM 0x20
80 #define DOOR_OUT_LEFT   0x10
81
82 #define START_SQUARE    0x2
83 #define END_SQUARE      0x1
84
85 #define border_x        (0)
86 #define border_y        (0)
87
88 #define get_random(x)   (random() % (x))
89   
90 static int logo_x, logo_y;
91
92 #ifdef XROGER
93 # define logo_width  128
94 # define logo_height 128
95 #else
96 #ifndef VMS
97 # include  <X11/bitmaps/xlogo64>
98 #else
99 # include "sys$common:[decw$include.bitmaps]xlogo64.xbm"
100 #endif
101 # define logo_width xlogo64_width
102 # define logo_height xlogo64_height
103 # define logo_bits xlogo64_bits
104 #endif
105
106 static unsigned short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
107
108 static struct {
109   unsigned char x;
110   unsigned char y;
111   unsigned char dir;
112 } move_list[MOVE_LIST_SIZE], save_path[MOVE_LIST_SIZE], path[MOVE_LIST_SIZE];
113
114 static int maze_size_x, maze_size_y;
115 static int sqnum, cur_sq_x, cur_sq_y, path_length;
116 static int start_x, start_y, start_dir, end_x, end_y, end_dir;
117 static int grid_width, grid_height;
118
119 static Display  *dpy;
120 static Window   win;
121 static GC       gc, cgc, tgc, logo_gc;
122 static Pixmap   logo_map;
123
124 static int      x = 0, y = 0, restart = 0, stop = 1, state = 1;
125
126 static int
127 check_events()                                  /* X event handler [ rhess ] */
128 {
129   XEvent        e;
130
131   if (XPending(dpy)) {
132     XNextEvent(dpy, &e);
133     switch (e.type) {
134
135     case ButtonPress:
136       switch (e.xbutton.button) {
137       case 3:
138         exit (0);
139         break;
140       case 2:
141         stop = !stop ;
142         if (state == 5) state = 4 ;
143         else {
144           restart = 1;
145           stop = 0;
146         }
147         break;
148       default:
149         restart = 1 ;
150         stop = 0 ;
151         break;
152       }
153       break;
154
155     case ConfigureNotify:
156       restart = 1;
157       break;
158     case UnmapNotify:
159       stop = 1;
160       XClearWindow (dpy, win);
161       XSync (dpy, False);
162       break;
163     case Expose:
164       restart = 1;
165       break;
166     }
167     return(1);
168   }
169   return(0);
170 }
171
172
173 static void
174 set_maze_sizes (width, height)
175      int width, height;
176 {
177   maze_size_x = width / grid_width;
178   maze_size_y = height / grid_height;
179 }
180
181
182 static void
183 initialize_maze()         /* draw the surrounding wall and start/end squares */
184 {
185   register int i, j, wall;
186   
187   /* initialize all squares */
188   for ( i=0; i<maze_size_x; i++) {
189     for ( j=0; j<maze_size_y; j++) {
190       maze[i][j] = 0;
191     }
192   }
193   
194   /* top wall */
195   for ( i=0; i<maze_size_x; i++ ) {
196     maze[i][0] |= WALL_TOP;
197   }
198   
199   /* right wall */
200   for ( j=0; j<maze_size_y; j++ ) {
201     maze[maze_size_x-1][j] |= WALL_RIGHT;
202   }
203   
204   /* bottom wall */
205   for ( i=0; i<maze_size_x; i++ ) {
206     maze[i][maze_size_y-1] |= WALL_BOTTOM;
207   }
208   
209   /* left wall */
210   for ( j=0; j<maze_size_y; j++ ) {
211     maze[0][j] |= WALL_LEFT;
212   }
213   
214   /* set start square */
215   wall = get_random(4);
216   switch (wall) {
217   case 0:       
218     i = get_random(maze_size_x);
219     j = 0;
220     break;
221   case 1:       
222     i = maze_size_x - 1;
223     j = get_random(maze_size_y);
224     break;
225   case 2:       
226     i = get_random(maze_size_x);
227     j = maze_size_y - 1;
228     break;
229   case 3:       
230     i = 0;
231     j = get_random(maze_size_y);
232     break;
233   }
234   maze[i][j] |= START_SQUARE;
235   maze[i][j] |= ( DOOR_IN_TOP >> wall );
236   maze[i][j] &= ~( WALL_TOP >> wall );
237   cur_sq_x = i;
238   cur_sq_y = j;
239   start_x = i;
240   start_y = j;
241   start_dir = wall;
242   sqnum = 0;
243   
244   /* set end square */
245   wall = (wall + 2)%4;
246   switch (wall) {
247   case 0:
248     i = get_random(maze_size_x);
249     j = 0;
250     break;
251   case 1:
252     i = maze_size_x - 1;
253     j = get_random(maze_size_y);
254     break;
255   case 2:
256     i = get_random(maze_size_x);
257     j = maze_size_y - 1;
258     break;
259   case 3:
260     i = 0;
261     j = get_random(maze_size_y);
262     break;
263   }
264   maze[i][j] |= END_SQUARE;
265   maze[i][j] |= ( DOOR_OUT_TOP >> wall );
266   maze[i][j] &= ~( WALL_TOP >> wall );
267   end_x = i;
268   end_y = j;
269   end_dir = wall;
270   
271   /* set logo */
272   if ((maze_size_x > 15) && (maze_size_y > 15))
273     {
274       int logow = 1 + logo_width / grid_width;
275       int logoh = 1 + logo_height / grid_height;
276       /* not closer than 3 grid units from a wall */
277       logo_x = get_random (maze_size_x - logow - 6) + 3;
278       logo_y = get_random (maze_size_y - logoh - 6) + 3;
279       for (i=0; i<logow; i++)
280         for (j=0; j<logoh; j++)
281           maze[logo_x + i][logo_y + j] |= DOOR_IN_TOP;
282     }
283   else
284     logo_y = logo_x = -1;
285 }
286
287 static int choose_door ();
288 static int backup ();
289 static void draw_wall ();
290 static void draw_solid_square ();
291 static void enter_square ();
292
293 static void
294 create_maze()             /* create a maze layout given the intiialized maze */
295 {
296   register int i, newdoor;
297   
298   do {
299     move_list[sqnum].x = cur_sq_x;
300     move_list[sqnum].y = cur_sq_y;
301     move_list[sqnum].dir = newdoor;
302     while ( ( newdoor = choose_door() ) == -1 ) { /* pick a door */
303       if ( backup() == -1 ) { /* no more doors ... backup */
304         return; /* done ... return */
305       }
306     }
307     
308     /* mark the out door */
309     maze[cur_sq_x][cur_sq_y] |= ( DOOR_OUT_TOP >> newdoor );
310     
311     switch (newdoor) {
312     case 0: cur_sq_y--;
313       break;
314     case 1: cur_sq_x++;
315       break;
316     case 2: cur_sq_y++;
317       break;
318     case 3: cur_sq_x--;
319       break;
320     }
321     sqnum++;
322     
323     /* mark the in door */
324     maze[cur_sq_x][cur_sq_y] |= ( DOOR_IN_TOP >> ((newdoor+2)%4) );
325     
326     /* if end square set path length and save path */
327     if ( maze[cur_sq_x][cur_sq_y] & END_SQUARE ) {
328       path_length = sqnum;
329       for ( i=0; i<path_length; i++) {
330         save_path[i].x = move_list[i].x;
331         save_path[i].y = move_list[i].y;
332         save_path[i].dir = move_list[i].dir;
333       }
334     }
335     
336   } while (1);
337   
338 }
339
340
341 static int
342 choose_door()                                            /* pick a new path */
343 {
344   int candidates[3];
345   register int num_candidates;
346   
347   num_candidates = 0;
348   
349   /* top wall */
350   if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_TOP )
351     goto rightwall;
352   if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_TOP )
353     goto rightwall;
354   if ( maze[cur_sq_x][cur_sq_y] & WALL_TOP )
355     goto rightwall;
356   if ( maze[cur_sq_x][cur_sq_y - 1] & DOOR_IN_ANY ) {
357     maze[cur_sq_x][cur_sq_y] |= WALL_TOP;
358     maze[cur_sq_x][cur_sq_y - 1] |= WALL_BOTTOM;
359     draw_wall(cur_sq_x, cur_sq_y, 0);
360     goto rightwall;
361   }
362   candidates[num_candidates++] = 0;
363   
364  rightwall:
365   /* right wall */
366   if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_RIGHT )
367     goto bottomwall;
368   if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_RIGHT )
369     goto bottomwall;
370   if ( maze[cur_sq_x][cur_sq_y] & WALL_RIGHT )
371     goto bottomwall;
372   if ( maze[cur_sq_x + 1][cur_sq_y] & DOOR_IN_ANY ) {
373     maze[cur_sq_x][cur_sq_y] |= WALL_RIGHT;
374     maze[cur_sq_x + 1][cur_sq_y] |= WALL_LEFT;
375     draw_wall(cur_sq_x, cur_sq_y, 1);
376     goto bottomwall;
377   }
378   candidates[num_candidates++] = 1;
379   
380  bottomwall:
381   /* bottom wall */
382   if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_BOTTOM )
383     goto leftwall;
384   if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_BOTTOM )
385     goto leftwall;
386   if ( maze[cur_sq_x][cur_sq_y] & WALL_BOTTOM )
387     goto leftwall;
388   if ( maze[cur_sq_x][cur_sq_y + 1] & DOOR_IN_ANY ) {
389     maze[cur_sq_x][cur_sq_y] |= WALL_BOTTOM;
390     maze[cur_sq_x][cur_sq_y + 1] |= WALL_TOP;
391     draw_wall(cur_sq_x, cur_sq_y, 2);
392     goto leftwall;
393   }
394   candidates[num_candidates++] = 2;
395   
396  leftwall:
397   /* left wall */
398   if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_LEFT )
399     goto donewall;
400   if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_LEFT )
401     goto donewall;
402   if ( maze[cur_sq_x][cur_sq_y] & WALL_LEFT )
403     goto donewall;
404   if ( maze[cur_sq_x - 1][cur_sq_y] & DOOR_IN_ANY ) {
405     maze[cur_sq_x][cur_sq_y] |= WALL_LEFT;
406     maze[cur_sq_x - 1][cur_sq_y] |= WALL_RIGHT;
407     draw_wall(cur_sq_x, cur_sq_y, 3);
408     goto donewall;
409   }
410   candidates[num_candidates++] = 3;
411   
412  donewall:
413   if (num_candidates == 0)
414     return ( -1 );
415   if (num_candidates == 1)
416     return ( candidates[0] );
417   return ( candidates[ get_random(num_candidates) ] );
418   
419 }
420
421
422 static int
423 backup()                                                  /* back up a move */
424 {
425   sqnum--;
426   cur_sq_x = move_list[sqnum].x;
427   cur_sq_y = move_list[sqnum].y;
428   return ( sqnum );
429 }
430
431
432 static void
433 draw_maze_border()                                  /* draw the maze outline */
434 {
435   register int i, j;
436   
437   
438   for ( i=0; i<maze_size_x; i++) {
439     if ( maze[i][0] & WALL_TOP ) {
440       XDrawLine(dpy, win, gc,
441                 border_x + grid_width * i,
442                 border_y,
443                 border_x + grid_width * (i+1) - 1,
444                 border_y);
445     }
446     if ((maze[i][maze_size_y - 1] & WALL_BOTTOM)) {
447       XDrawLine(dpy, win, gc,
448                 border_x + grid_width * i,
449                 border_y + grid_height * (maze_size_y) - 1,
450                 border_x + grid_width * (i+1) - 1,
451                 border_y + grid_height * (maze_size_y) - 1);
452     }
453   }
454   for ( j=0; j<maze_size_y; j++) {
455     if ( maze[maze_size_x - 1][j] & WALL_RIGHT ) {
456       XDrawLine(dpy, win, gc,
457                 border_x + grid_width * maze_size_x - 1,
458                 border_y + grid_height * j,
459                 border_x + grid_width * maze_size_x - 1,
460                 border_y + grid_height * (j+1) - 1);
461     }
462     if ( maze[0][j] & WALL_LEFT ) {
463       XDrawLine(dpy, win, gc,
464                 border_x,
465                 border_y + grid_height * j,
466                 border_x,
467                 border_y + grid_height * (j+1) - 1);
468     }
469   }
470   
471   if (logo_x != -1)
472     {
473       Window r;
474       int x, y;
475       unsigned int w, h, bw, d;
476       XGetGeometry (dpy, logo_map, &r, &x, &y, &w, &h, &bw, &d);
477       XCopyPlane (dpy, logo_map, win, logo_gc,
478                   0, 0, w, h,
479                   border_x + 3 + grid_width * logo_x,
480                   border_y + 3 + grid_height * logo_y, 1);
481     }
482   draw_solid_square (start_x, start_y, start_dir, tgc);
483   draw_solid_square (end_x, end_y, end_dir, tgc);
484 }
485
486
487 static void
488 draw_wall(i, j, dir)                                   /* draw a single wall */
489      int i, j, dir;
490 {
491   switch (dir) {
492   case 0:
493     XDrawLine(dpy, win, gc,
494               border_x + grid_width * i, 
495               border_y + grid_height * j,
496               border_x + grid_width * (i+1), 
497               border_y + grid_height * j);
498     break;
499   case 1:
500     XDrawLine(dpy, win, gc,
501               border_x + grid_width * (i+1), 
502               border_y + grid_height * j,
503               border_x + grid_width * (i+1), 
504               border_y + grid_height * (j+1));
505     break;
506   case 2:
507     XDrawLine(dpy, win, gc,
508               border_x + grid_width * i, 
509               border_y + grid_height * (j+1),
510               border_x + grid_width * (i+1), 
511               border_y + grid_height * (j+1));
512     break;
513   case 3:
514     XDrawLine(dpy, win, gc,
515               border_x + grid_width * i, 
516               border_y + grid_height * j,
517               border_x + grid_width * i, 
518               border_y + grid_height * (j+1));
519     break;
520   }
521 }
522
523 int bw;
524
525 static void
526 draw_solid_square(i, j, dir, gc)          /* draw a solid square in a square */
527      register int i, j, dir;
528      GC gc;
529 {
530   switch (dir) {
531   case 0: XFillRectangle(dpy, win, gc,
532                          border_x + bw + grid_width * i, 
533                          border_y - bw + grid_height * j, 
534                          grid_width - (bw+bw), grid_height);
535     break;
536   case 1: XFillRectangle(dpy, win, gc,
537                          border_x + bw + grid_width * i, 
538                          border_y + bw + grid_height * j, 
539                          grid_width, grid_height - (bw+bw));
540     break;
541   case 2: XFillRectangle(dpy, win, gc,
542                          border_x + bw + grid_width * i, 
543                          border_y + bw + grid_height * j, 
544                          grid_width - (bw+bw), grid_height);
545     break;
546   case 3: XFillRectangle(dpy, win, gc,
547                          border_x - bw + grid_width * i, 
548                          border_y + bw + grid_height * j, 
549                          grid_width, grid_height - (bw+bw));
550     break;
551   }
552   XSync (dpy, False);
553 }
554
555
556 static void
557 solve_maze()                             /* solve it with graphical feedback */
558 {
559   int i;
560   
561   
562   /* plug up the surrounding wall */
563   maze[start_x][start_y] |= (WALL_TOP >> start_dir);
564   maze[end_x][end_y] |= (WALL_TOP >> end_dir);
565   
566   /* initialize search path */
567   i = 0;
568   path[i].x = end_x;
569   path[i].y = end_y;
570   path[i].dir = -1;
571   
572   /* do it */
573   while (1) {
574     if ( ++path[i].dir >= 4 ) {
575       i--;
576       draw_solid_square( (int)(path[i].x), (int)(path[i].y), 
577                         (int)(path[i].dir), cgc);
578     }
579     else if ( ! (maze[path[i].x][path[i].y] & 
580                  (WALL_TOP >> path[i].dir))  && 
581              ( (i == 0) || ( (path[i].dir != 
582                               (int)(path[i-1].dir+2)%4) ) ) ) {
583       enter_square(i);
584       i++;
585       if ( maze[path[i].x][path[i].y] & START_SQUARE ) {
586         return;
587       }
588     } 
589     if (check_events()) return;
590     /* Abort solve on expose - cheapo repaint strategy */
591     if (solve_delay) usleep (solve_delay);
592   }
593
594
595
596 static void
597 enter_square(n)                            /* move into a neighboring square */
598      int n;
599 {
600   draw_solid_square( (int)path[n].x, (int)path[n].y, 
601                     (int)path[n].dir, tgc);
602   
603   path[n+1].dir = -1;
604   switch (path[n].dir) {
605   case 0: path[n+1].x = path[n].x;
606     path[n+1].y = path[n].y - 1;
607     break;
608   case 1: path[n+1].x = path[n].x + 1;
609     path[n+1].y = path[n].y;
610     break;
611   case 2: path[n+1].x = path[n].x;
612     path[n+1].y = path[n].y + 1;
613     break;
614   case 3: path[n+1].x = path[n].x - 1;
615     path[n+1].y = path[n].y;
616     break;
617   }
618 }
619
620 /* ----<eof> */
621
622
623 /*
624  *  jmr additions for Jamie Zawinski's <jwz@mcom.com> screensaver stuff,
625  *  note that the code above this has probably been hacked about in some
626  *  arbitrary way.
627  */
628
629 char *progclass = "Maze";
630
631 char *defaults[] = {
632   "Maze.background:     black",         /* to placate SGI */
633   "Maze.foreground:     white",         /* to placate SGI */
634   "*gridSize:   0",
635   "*solveDelay: 5000",
636   "*preDelay:   2000000",
637   "*postDelay:  4000000",
638   "*liveColor:  green",
639   "*deadColor:  red",
640 #ifdef XROGER
641   "*logoColor:  red3",
642 #endif
643   0
644 };
645
646 XrmOptionDescRec options[] = {
647   { "-grid-size",       ".gridSize",    XrmoptionSepArg, 0 },
648   { "-solve-delay",     ".solveDelay",  XrmoptionSepArg, 0 },
649   { "-pre-delay",       ".preDelay",    XrmoptionSepArg, 0 },
650   { "-post-delay",      ".postDelay",   XrmoptionSepArg, 0 },
651   { "-live-color",      ".liveColor",   XrmoptionSepArg, 0 },
652   { "-dead-color",      ".deadColor",   XrmoptionSepArg, 0 }
653 };
654
655 int options_size = (sizeof(options)/sizeof(options[0]));
656
657 void screenhack(display,window)
658      Display *display;
659      Window window;
660 {
661   Pixmap gray;
662   int size, root;
663   XWindowAttributes xgwa;
664   unsigned long bg, fg, pfg, pbg, lfg;
665
666   size = get_integer_resource ("gridSize", "Dimension");
667   root = get_boolean_resource("root", "Boolean");
668   solve_delay = get_integer_resource ("solveDelay", "Integer");
669   pre_solve_delay = get_integer_resource ("preDelay", "Integer");
670   post_solve_delay = get_integer_resource ("postDelay", "Integer");
671
672   if (size < 2) size = 7 + (random () % 30);
673   grid_width = grid_height = size;
674   bw = (size > 6 ? 3 : (size-1)/2);
675
676   dpy = display; win = window; /* the maze stuff uses global variables */
677
678   XGetWindowAttributes (dpy, win, &xgwa);
679
680   x = 0;
681   y = 0;
682
683   set_maze_sizes (xgwa.width, xgwa.height);
684
685   if (! root)
686     XSelectInput (dpy, win, ExposureMask|ButtonPressMask|StructureNotifyMask);
687   
688   gc = XCreateGC(dpy, win, 0, 0);
689   cgc = XCreateGC(dpy, win, 0, 0);
690   tgc = XCreateGC(dpy,win,0,0);
691   logo_gc = XCreateGC(dpy, win, 0, 0);
692   
693   gray = XCreateBitmapFromData (dpy,win,gray1_bits,gray1_width,gray1_height);
694
695   bg  = get_pixel_resource ("background","Background", dpy, xgwa.colormap);
696   fg  = get_pixel_resource ("foreground","Foreground", dpy, xgwa.colormap);
697   lfg = get_pixel_resource ("logoColor", "Foreground", dpy, xgwa.colormap);
698   pfg = get_pixel_resource ("liveColor", "Foreground", dpy, xgwa.colormap);
699   pbg = get_pixel_resource ("deadColor", "Foreground", dpy, xgwa.colormap);
700   if (mono_p) lfg = pfg = fg;
701
702   if (lfg == bg)
703     lfg = ((bg == WhitePixel (dpy, DefaultScreen (dpy)))
704            ? BlackPixel (dpy, DefaultScreen (dpy))
705            : WhitePixel (dpy, DefaultScreen (dpy)));
706
707   XSetForeground (dpy, gc, fg);
708   XSetBackground (dpy, gc, bg);
709   XSetForeground (dpy, cgc, pbg);
710   XSetBackground (dpy, cgc, bg);
711   XSetForeground (dpy, tgc, pfg);
712   XSetBackground (dpy, tgc, bg);
713   XSetForeground (dpy, logo_gc, lfg);
714   XSetBackground (dpy, logo_gc, bg);
715
716   XSetStipple (dpy, cgc, gray);
717   XSetFillStyle (dpy, cgc, FillOpaqueStippled);
718   
719 #ifdef XROGER
720   {
721     int w, h;
722     XGCValues gcv;
723     GC draw_gc, erase_gc;
724     extern void skull ();
725     /* round up to grid size */
726     w = ((logo_width  / grid_width) + 1)  * grid_width;
727     h = ((logo_height / grid_height) + 1) * grid_height;
728     logo_map = XCreatePixmap (dpy, win, w, h, 1);
729     gcv.foreground = 1L;
730     draw_gc = XCreateGC (dpy, logo_map, GCForeground, &gcv);
731     gcv.foreground = 0L;
732     erase_gc= XCreateGC (dpy, logo_map, GCForeground, &gcv);
733     XFillRectangle (dpy, logo_map, erase_gc, 0, 0, w, h);
734     skull (dpy, logo_map, draw_gc, erase_gc, 5, 0, w-10, h-10);
735     XFreeGC (dpy, draw_gc);
736     XFreeGC (dpy, erase_gc);
737   }
738 #else
739   if  (!(logo_map = XCreateBitmapFromData (dpy, win, logo_bits,
740                                            logo_width, logo_height)))
741     {
742       fprintf (stderr, "Can't create logo pixmap\n");
743       exit (1);
744     }
745 #endif
746   XMapRaised(dpy, win);
747   srandom(getpid());
748
749   restart = root;
750
751   while (1) {                            /* primary execution loop [ rhess ] */
752     if (check_events()) continue ;
753     if (restart || stop) goto pop;
754     switch (state) {
755     case 1:
756       initialize_maze();
757       break;
758     case 2:
759       XClearWindow(dpy, win);
760       draw_maze_border();
761       break;
762     case 3:
763       create_maze();
764       break;
765     case 4:
766       XSync (dpy, False);
767       usleep (pre_solve_delay);
768       break;
769     case 5:
770       solve_maze();
771       break;
772     case 6:
773       XSync (dpy, False);
774       usleep (post_solve_delay);
775       state = 0 ;
776       break;
777     default:
778       abort ();
779     }
780     ++state;
781   pop:
782     if (restart)
783       {
784         static XWindowAttributes wattr;
785         restart = 0;
786         stop = 0;
787         state = 1;
788         XGetWindowAttributes (dpy, win, &wattr);
789         set_maze_sizes (wattr.width, wattr.height);
790         XClearWindow (dpy, win);
791         XSync (dpy, False);
792       }
793   }
794 }