home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / demos / maze / maze.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-23  |  18.2 KB  |  759 lines

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