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