home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / OS2MAZ.ZIP / OS2MAZE.C < prev    next >
C/C++ Source or Header  |  1992-09-11  |  87KB  |  2,258 lines

  1. /*
  2.          This OS/2 1.3 program will generate a three dimensional maze on a VGA
  3.     display.  A different random number seed will produce a different maze.
  4.  
  5.          Written on September 1, 1992 by James L. Dean
  6.                                          406 40th Street
  7.                                          New Orleans, LA 70124
  8. */
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <math.h>
  12. #include <malloc.h>
  13. #include <memory.h>
  14. #include <stdlib.h>
  15. #include <conio.h>
  16. #include <dos.h>
  17. #define INCL_BASE
  18. #include <os2.h>
  19.  
  20. #define TRUE 1
  21. #define FALSE 0
  22.  
  23. /* screen constants */
  24. #define WIDTH_OF_SCREEN           8.0
  25. #define HEIGHT_OF_SCREEN          6.0 /* same units as WIDTH_OF_SCREEN */
  26.  
  27. /* graphics constants */
  28. #define NUM_X_PIXELS            640
  29. #define NUM_Y_PIXELS            480
  30. #define NUM_COLORS               16
  31. #define RGB_INCREMENT             4     /* 64/NUM_COLORS */
  32. #define stack_size            32767
  33. #define NUM_CELLS             38400     /* NUM_X_PIXELS*NUM_Y_PIXELS/8 */
  34. #define VGA_control           0x3ce     /* graphics controller control port */
  35. #define VGA_control_data      0x3cf     /* graphics controller data port */
  36. #define VGA_read_map           0x04     /* read map register in graphics port */
  37. #define VGA_mode               0x05     /* mode register in graphics port */
  38. #define VGA_bit_mask           0x08     /* bitmask register in graphics port */     
  39. #define VGA_sequence          0x3c4     /* sequencer control port */
  40. #define VGA_sequence_data     0x3c5     /* sequencer data port   */
  41. #define VGA_map_mask           0x02     /* map mask register in sequencer */
  42.  
  43. /* maze constants */
  44. #define PIXELS_PER_ROOM          40
  45. #define RESOLUTION                6     /* larger numbers give more detail
  46.                                            but take more time and memory */
  47.  
  48. typedef struct
  49.           {
  50.             int   x;
  51.             int   y;
  52.           } box_rec;
  53.  
  54. typedef struct
  55.           {
  56.             unsigned char red;
  57.             unsigned char green;
  58.             unsigned char blue;
  59.           } rgb_rec;
  60.  
  61. typedef struct stack_rec_record
  62.           {
  63.             char index_1;
  64.             int  index_2;
  65.           } stack_rec;
  66.  
  67. typedef struct
  68.           {
  69.             double x;
  70.             double y;
  71.             double z;
  72.           } vertex_rec;
  73.  
  74. static void   adjust_perspective(int,int,float huge *,float huge *,float huge *,
  75.                double,double,double,double,double);
  76. static void   clear_screen(void);
  77. static void   draw_line_on_page(char **,int,int,int,int);
  78. static void   evaluate_and_transform(double,double,double,double,int,int,
  79.                double,double,float huge *,float huge *,float huge *,double *,
  80.                double *,double *,double *,double *,vertex_rec *,int huge *,
  81.                int huge *,unsigned char huge *);
  82. static double f(double,double);
  83. static void   free_memory(float huge **,float huge **,
  84.                float huge **,int huge **,int huge **,
  85.                unsigned char huge **,unsigned char huge **,int,char ***,int,
  86.                char ***,int,stack_rec **);
  87. static void   generate_maze(int *,char **,char **,int,int,stack_rec *,int,
  88.                int,int,int,int);
  89. static void   get_cursor(USHORT *,USHORT *,VIOCURSORINFO *);
  90. static void   hash(int *,int *,int *,int *,int *,int *,int *,int *);
  91. static void   increment(int *,int *,int *,int *,int *,int *,int *,int *);
  92.        void   main(void);
  93. static int    memory_allocated(long,float huge **,float huge **,
  94.                float huge **,int huge **,int huge **,
  95.                unsigned char huge **,unsigned char huge **,int,int,char ***,int,
  96.                int,char ***,int,stack_rec **);
  97. static void   mode_thread(void);
  98. static void   plot(int,int huge *,int,int huge *,long,float huge *,float huge *,
  99.                double,double,double,double,unsigned char huge *,
  100.                unsigned char huge *,int,double);
  101. static void   save_redraw_thread(void);
  102. static void   set_cursor_position(USHORT,USHORT);
  103. static void   set_cursor_type(VIOCURSORINFO *);
  104. static void   set_initial_video_mode(void);
  105. static void   set_pixel(int,int,short);
  106. static void   set_point_on_page(char **,int,int);
  107. static void   shade(int,int,float huge *,float huge *,float huge *,
  108.                unsigned char huge *,vertex_rec *);
  109. static void   solve_maze(stack_rec *,char **,int *,int *,int,int);
  110. static void   sort_back_to_front(long,float huge *,int huge *,int huge *);
  111. static void   titillate(void);
  112. static int    VGA_640_480_16(void);
  113.  
  114. static char          **base_page;
  115. static USHORT        cursor_column;
  116. static USHORT        cursor_row;
  117. static int           delta_x [6] [720];
  118. static int           delta_y [6] [720];
  119.        VIOCURSORINFO initial_cursor_type;
  120. static int           max_x;
  121. static int           max_y;
  122. static char          **page;
  123. static int           tem_int;
  124. static char          titillator [4] = { '|', '/', '-', '\\' };
  125.        VIOCURSORINFO titillator_cursor_type;
  126. static int           titillator_index;
  127. static int           x_dot_max;
  128. static int           y_dot_max;
  129.  
  130. /* video globals */
  131.  
  132.        VIOMODEINFO   default_video_mode;
  133.        PVIOPALSTATE  invisible_palette;
  134.        BYTE          invisible_palette_byte [38];
  135.        VIOCOLORREG   maze_color;
  136.        PVIOPALSTATE  maze_palette;
  137.        BYTE          maze_palette_byte [38];
  138. static rgb_rec       maze_rgb [16];
  139.        VIOMODEINFO   maze_video_mode;
  140. static int           mode_id;
  141. static char          mode_thread_stack [stack_size];
  142.        VIOPHYSBUF    phys_buf;
  143. static char          save_redraw_thread_stack [stack_size];
  144. static int           save_redraw_id;
  145. static unsigned char scr_lock;    
  146. static int           VGA_base_adr;
  147. static long huge     *video_plane [4];  /* save area for video planes */
  148.  
  149. void main()
  150.   {
  151.     static double             aspect_ratio;
  152.     static unsigned char huge *base_z;
  153.     static unsigned char huge *color;
  154.     static vertex_rec         light;
  155.     static int                max_x_plus_1;
  156.     static int                max_y_plus_1;
  157.     static int                num_columns;
  158.     static long               num_primes;
  159.     static int                num_rooms_in_maze;
  160.     static int                num_rows;
  161.     static int                num_x_divisions;
  162.     static int                num_x_dots;
  163.     static int                num_y_divisions;
  164.     static int                num_y_dots;
  165.     static int                r_n [8];
  166.     static int                response;
  167.     static double             rotation;
  168.     static stack_rec          *stack;
  169.     static double             tilt;
  170.     static int huge           *x_division_index;
  171.     static double             x_max;
  172.     static double             x_min;
  173.     static float huge         *x_prime;
  174.     static double             x_prime_max;
  175.     static int huge           *y_division_index;
  176.     static double             y_max;
  177.     static double             y_min;
  178.     static float huge         *y_prime;
  179.     static double             y_prime_max;
  180.     static double             y_prime_min;
  181.     static float huge         *z_prime;
  182.     static double             z_prime_max;
  183.     static double             z_prime_min;
  184.  
  185.     aspect_ratio=(HEIGHT_OF_SCREEN/WIDTH_OF_SCREEN)
  186.      /(((double) NUM_Y_PIXELS)/((double) NUM_X_PIXELS));
  187.     num_columns=2*NUM_X_PIXELS/(3*PIXELS_PER_ROOM)-1;
  188.     num_columns=2*num_columns+1;
  189.     max_x=8*(num_columns/2)+6;
  190.     max_x_plus_1=max_x+1;
  191.     num_x_dots=RESOLUTION*max_x_plus_1;
  192.     x_dot_max=num_x_dots-1;
  193.     num_rows=(int) ((2.0/sqrt(3.0))*aspect_ratio*((double) NUM_Y_PIXELS)
  194.      /((double) PIXELS_PER_ROOM));
  195.     max_y=4*num_rows;
  196.     max_y_plus_1=max_y+1;
  197.     num_y_dots=RESOLUTION*max_y_plus_1;
  198.     y_dot_max=num_y_dots-1;
  199.     num_rooms_in_maze=num_rows*num_columns-(num_columns/2);
  200.     num_x_divisions=num_y_dots+2;
  201.     num_y_divisions=num_x_dots+2;
  202.     num_primes=(long) num_x_divisions;
  203.     num_primes*=((long) num_y_divisions);
  204.     if (memory_allocated(num_primes,&x_prime,&y_prime,
  205.      &z_prime,&x_division_index,&y_division_index,&color,&base_z,max_x_plus_1,
  206.      max_y_plus_1,&base_page,num_x_dots,num_y_dots,&page,num_rooms_in_maze,
  207.      &stack))
  208.       {
  209.         clear_screen();
  210.         printf("                                 Maze Generator\n\n\n\n");
  211.         printf(
  212.         "     After the maze is displayed, press \"S\" to see the solution.\n");
  213.         generate_maze(&r_n[0],base_page,page,max_x,max_y,
  214.          stack,x_dot_max,y_dot_max,num_rooms_in_maze,num_columns,num_rows);
  215.         x_min=-1.0;
  216.         x_max=(double) num_y_dots;
  217.         y_min=-1.0;
  218.         y_max=(double) num_x_dots;
  219.         rotation=0.0;
  220.         tilt=30.0; 
  221.         light.x=1.5;
  222.         light.y=-1.0;
  223.         light.z=2.6;
  224.         evaluate_and_transform(x_min,x_max,y_min,y_max,num_x_divisions,
  225.          num_y_divisions,rotation,tilt,x_prime,y_prime,z_prime,&x_prime_max,
  226.          &y_prime_min,&y_prime_max,&z_prime_min,&z_prime_max,&light,
  227.          x_division_index,y_division_index,base_z);
  228.         shade(num_x_divisions,num_y_divisions,x_prime,y_prime,z_prime,color,
  229.          &light);
  230.         adjust_perspective(num_x_divisions,num_y_divisions,x_prime,y_prime,
  231.          z_prime,x_prime_max,y_prime_min,y_prime_max,z_prime_min,z_prime_max);
  232.         sort_back_to_front(num_primes,x_prime,x_division_index,
  233.          y_division_index);
  234.         if (VGA_640_480_16())
  235.           {
  236.             plot(num_x_divisions,x_division_index,num_y_divisions,
  237.              y_division_index,num_primes,y_prime,z_prime,y_prime_min,
  238.              y_prime_max,z_prime_min,z_prime_max,color,base_z,FALSE,
  239.              aspect_ratio);
  240.             fflush(stdin);
  241.             response=getch();
  242.             fflush(stdin);
  243.             if ((response == (int) 's') || (response == (int) 'S'))
  244.               {
  245.                 plot(num_x_divisions,x_division_index,num_y_divisions,
  246.                  y_division_index,num_primes,y_prime,z_prime,y_prime_min,
  247.                  y_prime_max,z_prime_min,z_prime_max,color,base_z,TRUE,
  248.                  aspect_ratio);
  249.                 fflush(stdin);
  250.                 response=getch();
  251.                 fflush(stdin);
  252.               }
  253.             set_initial_video_mode();
  254.           }
  255.         else
  256.           printf("? 640 x 480 x 16 VGA mode is not available\n");
  257.         set_cursor_type(&initial_cursor_type);
  258.         free_memory(&x_prime,&y_prime,&z_prime,&x_division_index,
  259.          &y_division_index,&color,&base_z,max_y_plus_1,&base_page,num_y_dots,
  260.          &page,num_rooms_in_maze,&stack);
  261.       }
  262.     else
  263.       printf("? not enough memory\n");
  264.     return;
  265.   }
  266.  
  267. static void clear_screen()
  268.   {
  269.     unsigned char fill [2];
  270.     VIOMODEINFO   video_mode_info;
  271.  
  272.     video_mode_info.cb=(unsigned int) 12;
  273.     VioGetMode(&video_mode_info,(HVIO) 0);
  274.     fill[0]=(unsigned char) ' ';
  275.     fill[1]=(unsigned char) 7;
  276.     VioScrollUp((USHORT) 0,(USHORT) 0,
  277.      (USHORT) (video_mode_info.row-1),
  278.      (USHORT) (video_mode_info.col-1),
  279.      (USHORT) 0xffff,(PBYTE) &fill[0],(HVIO) 0);
  280.     VioSetCurPos((USHORT) 0,(USHORT) 0,(HVIO) 0);
  281.     return;
  282.   }
  283.  
  284. static void get_cursor(cursor_row,cursor_column,cursor_type)
  285.   USHORT        *cursor_row;
  286.   USHORT        *cursor_column;
  287.   VIOCURSORINFO *cursor_type;
  288.     {
  289.       VioGetCurPos((PUSHORT) cursor_row,(PUSHORT) cursor_column,(HVIO) 0);
  290.       VioGetCurType((PVIOCURSORINFO) cursor_type,(HVIO) 0);
  291.       return;
  292.     }
  293.  
  294. static void set_cursor_position(cursor_row,cursor_column)
  295.   USHORT cursor_row;
  296.   USHORT cursor_column;
  297.     {
  298.       VioSetCurPos(cursor_row,cursor_column,(HVIO) 0);
  299.       return;
  300.     }
  301.  
  302. static void set_cursor_type(cursor_type)
  303.   VIOCURSORINFO *cursor_type;
  304.     {
  305.       VioSetCurType((PVIOCURSORINFO) cursor_type,(HVIO) 0);
  306.       return;
  307.     }
  308.  
  309. static void titillate()
  310.     {
  311.       set_cursor_position(cursor_row,cursor_column);
  312.       titillator_index++;
  313.       if (titillator_index > 3)
  314.         titillator_index=0;
  315.       putchar((int) titillator[titillator_index]);
  316.       return;
  317.     }
  318.  
  319. static int memory_allocated(num_primes,x_prime,y_prime,
  320.  z_prime,x_division_index,y_division_index,color,base_z,max_x_plus_1,
  321.  max_y_plus_1,base_page,num_x_dots,num_y_dots,page,num_rooms_in_maze,stack)
  322.   long               num_primes;
  323.   float huge         **x_prime;
  324.   float huge         **y_prime;
  325.   float huge         **z_prime;
  326.   int   huge         **x_division_index;
  327.   int   huge         **y_division_index;
  328.   unsigned char huge **color;
  329.   unsigned char huge **base_z;
  330.   int                max_x_plus_1;
  331.   int                max_y_plus_1;
  332.   char               ***base_page;
  333.   int                num_x_dots;
  334.   int                num_y_dots;
  335.   char               ***page;
  336.   int                num_rooms_in_maze;
  337.   stack_rec          **stack;
  338.     {
  339.       static   int result;
  340.       register int y;
  341.  
  342.       result=(((*base_page)=(char **)
  343.        malloc(((unsigned int) max_y_plus_1)*sizeof(char *)))
  344.        != NULL);
  345.       if (result)
  346.         {
  347.           for (y=0; ((result) && (y < max_y_plus_1)); y++)
  348.             result=(((*base_page)[y]=(char *)
  349.              malloc(((unsigned int) max_x_plus_1)*sizeof(char)))
  350.              != NULL);
  351.           if (! result)
  352.             {
  353.               --y;
  354.               while (y > 0)
  355.                 free((void *) (*base_page)[--y]);
  356.               free((void *) (*base_page));
  357.             }
  358.         }
  359.       if (result)
  360.         {
  361.           result=(((*page)=(char **)
  362.            malloc(((unsigned int) num_y_dots)*sizeof(char *)))
  363.            != NULL);
  364.           if (result)
  365.             {
  366.               for (y=0; ((result) && (y < num_y_dots)); y++)
  367.                 result=(((*page)[y]=(char *)
  368.                  malloc(((unsigned int) num_x_dots)*sizeof(char)))
  369.                  != NULL);
  370.               if (! result)
  371.                 {
  372.                   --y;
  373.                   while (y > 0)
  374.                     free((void *) (*page)[--y]);
  375.                   free((void *) (*page));
  376.                   for (y=0; y < max_y_plus_1; y++)
  377.                     free((void *) (*base_page)[y]);
  378.                   free((void *) (*base_page));
  379.                 }
  380.             }
  381.           else
  382.             {
  383.               for (y=0; y < max_y_plus_1; y++)
  384.                 free((void *) (*base_page)[y]);
  385.               free((void *) (*base_page));
  386.             }
  387.         }
  388.       if (result)
  389.         {
  390.           if (! (result
  391.            =((*x_prime=(float huge *)
  392.            halloc(num_primes,sizeof(float))) != NULL)))
  393.             {
  394.               for (y=0; y < num_y_dots; y++)
  395.                 free((void *) (*page)[y]);
  396.               free((void *) (*page));
  397.               for (y=0; y < max_y_plus_1; y++)
  398.                 free((void *) (*base_page)[y]);
  399.               free((void *) (*base_page));
  400.             }
  401.         }
  402.       if (result)
  403.         {
  404.           if (! (result=((*y_prime
  405.            =(float huge *) halloc(num_primes,sizeof(float)))
  406.            != NULL)))
  407.             {
  408.               hfree((void huge *) *x_prime);
  409.               for (y=0; y < num_y_dots; y++)
  410.                 free((void *) (*page)[y]);
  411.               free((void *) (*page));
  412.               for (y=0; y < max_y_plus_1; y++)
  413.                 free((void *) (*base_page)[y]);
  414.               free((void *) (*base_page));
  415.             }
  416.         }
  417.       if (result)
  418.         {
  419.           if (! (result=((*z_prime
  420.            =(float huge *) halloc(num_primes,sizeof(float))) 
  421.            != NULL)))
  422.             {
  423.               hfree((void huge *) *y_prime);
  424.               hfree((void huge *) *x_prime);
  425.               for (y=0; y < num_y_dots; y++)
  426.                 free((void *) (*page)[y]);
  427.               free((void *) (*page));
  428.               for (y=0; y < max_y_plus_1; y++)
  429.                 free((void *) (*base_page)[y]);
  430.               free((void *) (*base_page));
  431.             }
  432.         }
  433.       if (result)
  434.         {
  435.           if (! (result=((*x_division_index
  436.            =(int huge *) halloc(num_primes,sizeof(int))) != NULL)))
  437.             {
  438.               hfree((void huge *) *z_prime);
  439.               hfree((void huge *) *y_prime);
  440.               hfree((void huge *) *x_prime);
  441.               for (y=0; y < num_y_dots; y++)
  442.                 free((void *) (*page)[y]);
  443.               free((void *) (*page));
  444.               for (y=0; y < max_y_plus_1; y++)
  445.                 free((void *) (*base_page)[y]);
  446.               free((void *) (*base_page));
  447.             }
  448.         }
  449.       if (result)
  450.         {
  451.           if (! (result=((*y_division_index
  452.            =(int huge *) halloc(num_primes,sizeof(int))) != NULL)))
  453.             {
  454.               hfree((void huge *) *x_division_index);
  455.               hfree((void huge *) *z_prime);
  456.               hfree((void huge *) *y_prime);
  457.               hfree((void huge *) *x_prime);
  458.             }
  459.         }
  460.       if (result)
  461.         {
  462.           if (! (result=((*color=(unsigned char huge *) 
  463.            halloc(num_primes,sizeof(unsigned char))) != NULL)))
  464.             {
  465.               hfree((void huge *) *y_division_index);
  466.               hfree((void huge *) *x_division_index);
  467.               hfree((void huge *) *z_prime);
  468.               hfree((void huge *) *y_prime);
  469.               hfree((void huge *) *x_prime);
  470.               for (y=0; y < num_y_dots; y++)
  471.                 free((void *) (*page)[y]);
  472.               free((void *) (*page));
  473.               for (y=0; y < max_y_plus_1; y++)
  474.                 free((void *) (*base_page)[y]);
  475.               free((void *) (*base_page));
  476.             }
  477.         }
  478.       if (result)
  479.         {
  480.           if (! (result=((*base_z=(unsigned char huge *) 
  481.            halloc(num_primes,sizeof(unsigned char))) != NULL)))
  482.             {
  483.               hfree((void huge *) *color);
  484.               hfree((void huge *) *y_division_index);
  485.               hfree((void huge *) *x_division_index);
  486.               hfree((void huge *) *z_prime);
  487.               hfree((void huge *) *y_prime);
  488.               hfree((void huge *) *x_prime);
  489.               for (y=0; y < num_y_dots; y++)
  490.                 free((void *) (*page)[y]);
  491.               free((void *) (*page));
  492.               for (y=0; y < max_y_plus_1; y++)
  493.                 free((void *) (*base_page)[y]);
  494.               free((void *) (*base_page));
  495.             }
  496.         }
  497.       if (result)
  498.         {
  499.           if (! (result=((*stack=(stack_rec *) malloc(
  500.            ((unsigned int) num_rooms_in_maze)*sizeof(stack_rec)))
  501.            != NULL)))
  502.             {
  503.               hfree((void *) *base_z);
  504.               hfree((void *) *color);
  505.               hfree((void *) *y_division_index);
  506.               hfree((void *) *x_division_index);
  507.               hfree((void *) *z_prime);
  508.               hfree((void *) *y_prime);
  509.               hfree((void *) *x_prime);
  510.               for (y=0; y < num_y_dots; y++)
  511.                 free((void *) (*page)[y]);
  512.               free((void *) (*page));
  513.               for (y=0; y < max_y_plus_1; y++)
  514.                 free((void *) (*base_page)[y]);
  515.               free((void *) (*base_page));
  516.             }
  517.         }
  518.       return(result);
  519.     }
  520.  
  521. static void set_point_on_page(
  522.   char **page,
  523.   int  x,
  524.   int  y)
  525.     {
  526.       static int x_offset = 0;
  527.       static int x_out = 0;
  528.       static int y_offset = 0;
  529.       static int y_out = 0;
  530.  
  531.       for (x_offset = 0; x_offset < RESOLUTION; x_offset++)
  532.         {
  533.           x_out=x+x_offset;
  534.           for (y_offset=0; y_offset < RESOLUTION; y_offset++)
  535.             {
  536.               y_out=y+y_offset;
  537.               page[y_out][x_out]='W';
  538.             }
  539.         }
  540.       return;
  541.     }
  542.  
  543. static void draw_line_on_page(
  544.   char **page,
  545.   int  x1,
  546.   int  y1,
  547.   int  x2,
  548.   int  y2)
  549.     {
  550.       static int error = 0;
  551.       static int error_prime_x = 0;
  552.       static int error_prime_y = 0;
  553.       static int permissible_delta_x = 0;
  554.       static int permissible_delta_y = 0;
  555.       static int x = 0;
  556.       static int x_diff = 0;
  557.       static int y = 0;
  558.       static int y_diff = 0;
  559.  
  560.       if (x2 >= x1)
  561.         permissible_delta_x=1;
  562.       else
  563.         permissible_delta_x=-1;
  564.       if (y2 >= y1)
  565.         permissible_delta_y=1;
  566.       else
  567.         permissible_delta_y=-1;
  568.       x=x1;
  569.       y=y1;
  570.       x_diff=x2-x1;
  571.       y_diff=y2-y1;
  572.       set_point_on_page(page,x,y);
  573.       while ((x != x2) || (y != y2))
  574.         {
  575.           error_prime_x=error+permissible_delta_x*y_diff;
  576.           error_prime_y=error-permissible_delta_y*x_diff;
  577.           if (abs(error_prime_x) <= abs(error_prime_y)) 
  578.             {
  579.               x+=permissible_delta_x;
  580.               error=error_prime_x;
  581.             } 
  582.           else
  583.             {
  584.               y+=permissible_delta_y;
  585.               error=error_prime_y;
  586.             }
  587.           set_point_on_page(page,x,y);
  588.         }
  589.       return;
  590.     } 
  591.  
  592. static void solve_maze(
  593.   stack_rec *stack,
  594.   char      **base_page,
  595.   int       *num_rooms_in_solution,
  596.   int       *adjacency,
  597.   int       max_x,
  598.   int       max_y)
  599.     {
  600.       int delta_index;
  601.       int passage_found;
  602.       int stack_head;
  603.       int x;
  604.       int x_next;
  605.       int y;
  606.       int y_next;
  607.  
  608.       *num_rooms_in_solution=1;
  609.       *adjacency=0;
  610.       x=3;
  611.       y=2;
  612.       stack_head=-1;
  613.       base_page[y][x]='S';
  614.       do
  615.         {
  616.           delta_index=0;
  617.           passage_found=FALSE;
  618.           do
  619.             {
  620.               while ((delta_index < 6) && (! passage_found))
  621.                 {
  622.                   x_next=x+delta_x[delta_index][0];
  623.                   y_next=y+delta_y[delta_index][0];
  624.                   if (base_page[y_next][x_next] == ' ')
  625.                     passage_found=TRUE;
  626.                   else
  627.                     delta_index++;
  628.                 }
  629.               if (! passage_found) 
  630.                 {
  631.                   delta_index=(int) (stack[stack_head].index_1);
  632.                   base_page[y][x]=' ';
  633.                   x-=delta_x[delta_index][0];
  634.                   y-=delta_y[delta_index][0];
  635.                   base_page[y][x]=' ';
  636.                   x-=delta_x[delta_index][0];
  637.                   y-=delta_y[delta_index][0];
  638.                   stack_head--;
  639.                   delta_index++;
  640.                 }
  641.             }
  642.           while (! passage_found);
  643.           base_page[y_next][x_next]='S';
  644.           x_next+=delta_x[delta_index][0];
  645.           y_next+=delta_y[delta_index][0];
  646.           if (y_next <= max_y) 
  647.             {
  648.               stack_head++;
  649.               stack[stack_head].index_1=(char) delta_index;
  650.               base_page[y_next][x_next]='S';
  651.               x=x_next;
  652.               y=y_next;
  653.             }
  654.         }
  655.       while (y_next < max_y);
  656.       x=max_x-3;
  657.       y=max_y-2;
  658.       *adjacency=0;
  659.       while (stack_head >= 0)
  660.         {
  661.           for (delta_index=0; delta_index < 6; delta_index++)
  662.             {
  663.               x_next=x+delta_x[delta_index][0];
  664.               y_next=y+delta_y[delta_index][0];
  665.               if (base_page[y_next][x_next] != 'S')
  666.                 {
  667.                   if (base_page[y_next][x_next] == 'W')
  668.                     {
  669.                       x_next+=delta_x[delta_index][0];
  670.                       y_next+=delta_y[delta_index][0];
  671.                       if (x_next < 0)
  672.                         (*adjacency)++;
  673.                       else
  674.                         if (x_next > max_x)
  675.                           (*adjacency)++;
  676.                         else
  677.                           if (y_next < 0)
  678.                             (*adjacency)++;
  679.                           else
  680.                             if (y_next > max_y)
  681.                               (*adjacency)++;
  682.                             else
  683.                               {
  684.                                 if (base_page[y_next][x_next] == 'S')
  685.                                   (*adjacency)++;
  686.                               }
  687.                     }
  688.                 }
  689.             }
  690.           x-=(2*delta_x[stack[stack_head].index_1][0]);
  691.           y-=(2*delta_y[stack[stack_head].index_1][0]);
  692.           stack_head--;
  693.           (*num_rooms_in_solution)++;
  694.         }
  695.       for (delta_index=0; delta_index < 6; delta_index++)
  696.         {
  697.           x_next=x+delta_x[delta_index][0];
  698.           y_next=y+delta_y[delta_index][0];
  699.           if (base_page[y_next][x_next] != ' ')
  700.             {
  701.               if (base_page[y_next][x_next] == 'W')
  702.                 {
  703.                   x_next+=delta_x[delta_index][0];
  704.                   y_next+=delta_y[delta_index][0];
  705.                   if (x_next < 0)
  706.                     (*adjacency)++;
  707.                   else
  708.                     if (x_next > max_x)
  709.                       (*adjacency)++;
  710.                     else
  711.                       if (y_next < 0)
  712.                         (*adjacency)++;
  713.                       else
  714.                         if (y_next > max_y)
  715.                           (*adjacency)++;
  716.                         else
  717.                           {
  718.                             if (base_page[y_next][x_next] == 'S')
  719.                               (*adjacency)++;
  720.                           }
  721.                 }
  722.             }
  723.         }
  724.       return;
  725.     }
  726.  
  727. static void generate_maze(
  728.   int       *r_n,
  729.   char      **base_page,
  730.   char      **page,
  731.   int       max_x,
  732.   int       max_y,
  733.   stack_rec *stack,
  734.   int       x_dot_max,
  735.   int       y_dot_max,
  736.   int       num_rooms_in_maze,
  737.   int       num_columns,
  738.   int       num_rows)
  739.     {
  740.       static   int  adjacency;
  741.       static   int  column_num;
  742.       static   int  counter_0;
  743.       static   int  counter_1;
  744.       static   int  counter_2;
  745.       static   int  counter_3;
  746.       static   int  counter_4;
  747.       static   int  counter_5;
  748.       static   int  counter_6;
  749.       static   int  counter_7;
  750.       static   int  delta_index_1a;
  751.       static   int  delta_index_1b;
  752.       static   int  delta_index_1c;
  753.       static   int  delta_index_1d;
  754.       static   int  delta_index_1e;
  755.       static   int  delta_index_1f;
  756.       static   int  delta_index_2;
  757.       static   int  num_rooms_in_solution;
  758.       static   int  passage_found;
  759.       register int  r_n_index_1;
  760.       register int  r_n_index_2;
  761.       static   int  row_num;
  762.       static   int  search_complete;
  763.       static   char seed [256];
  764.       static   int  seed_length;
  765.       static   int  stack_head;
  766.       static   int  tem_int;
  767.       static   int  x;
  768.       static   int  x_mod_8;
  769.       static   int  x_next;
  770.       static   int  y;
  771.       static   int  y_mod_4;
  772.       static   int  y_next;
  773.       static   int  y_previous;
  774.  
  775.       printf("\n     Random number seed?  ");
  776.       gets(&seed[0]);
  777.       get_cursor(&cursor_row,&cursor_column,&initial_cursor_type);
  778.       memcpy((void *) &titillator_cursor_type,
  779.        (const void *) &initial_cursor_type,sizeof(VIOCURSORINFO));
  780.       titillator_cursor_type.attr=0xffff;
  781.       set_cursor_type(&titillator_cursor_type);
  782.       titillator_index=0;
  783.       seed_length=strlen(&seed[0]);
  784.       for (r_n_index_1=0; ((r_n_index_1 < seed_length) && (r_n_index_1 < 8));
  785.        ++r_n_index_1)
  786.         r_n[r_n_index_1]=(int) (seed[r_n_index_1] % 10);
  787.       r_n_index_2=7;
  788.       while (r_n_index_1 > 0)
  789.         {
  790.            r_n_index_1--;
  791.            r_n[r_n_index_2]=r_n[r_n_index_1];
  792.            r_n_index_2--;
  793.         }
  794.       while (r_n_index_2 >= 0)
  795.         {
  796.           r_n[r_n_index_2]=0;
  797.           r_n_index_2--;
  798.         }
  799.       counter_0=r_n[0];
  800.       counter_1=r_n[1];
  801.       counter_2=r_n[2];
  802.       counter_3=r_n[3];
  803.       counter_4=r_n[4];
  804.       counter_5=r_n[5];
  805.       counter_6=r_n[6];
  806.       counter_7=r_n[7];
  807.       hash(&counter_0,&counter_1,&counter_2,&counter_3,&counter_4,&counter_5,
  808.        &counter_6,&counter_7);
  809.       delta_y[0][0]=-1;
  810.       delta_x[0][0]=-2;
  811.       delta_y[1][0]=1;
  812.       delta_x[1][0]=-2;
  813.       delta_y[2][0]=-2;
  814.       delta_x[2][0]=0;
  815.       delta_y[3][0]=2;
  816.       delta_x[3][0]=0;
  817.       delta_y[4][0]=-1;
  818.       delta_x[4][0]=2;
  819.       delta_y[5][0]=1;
  820.       delta_x[5][0]=2;
  821.       delta_index_2=0;
  822.       for (delta_index_1a=0; delta_index_1a < 6; delta_index_1a++)
  823.         for (delta_index_1b=0; delta_index_1b < 6; delta_index_1b++)
  824.           if (delta_index_1a != delta_index_1b)
  825.            for (delta_index_1c=0; delta_index_1c < 6; delta_index_1c++)
  826.              if ((delta_index_1a != delta_index_1c)
  827.              &&  (delta_index_1b != delta_index_1c))
  828.                for (delta_index_1d=0; delta_index_1d < 6; delta_index_1d++)
  829.                   if ((delta_index_1a != delta_index_1d)
  830.                   &&  (delta_index_1b != delta_index_1d)
  831.                   &&  (delta_index_1c != delta_index_1d))
  832.                     for (delta_index_1e=0; delta_index_1e < 6; 
  833.                      delta_index_1e++)
  834.                       if ((delta_index_1a != delta_index_1e)
  835.                       &&  (delta_index_1b != delta_index_1e)
  836.                       &&  (delta_index_1c != delta_index_1e)
  837.                       &&  (delta_index_1d != delta_index_1e))
  838.                         for (delta_index_1f=0; delta_index_1f < 6; 
  839.                          delta_index_1f++) 
  840.                           if ((delta_index_1a != delta_index_1f)
  841.                           &&  (delta_index_1b != delta_index_1f)
  842.                           &&  (delta_index_1c != delta_index_1f)
  843.                           &&  (delta_index_1d != delta_index_1f)
  844.                           &&  (delta_index_1e != delta_index_1f))
  845.                             {
  846.                               delta_x[delta_index_1a][delta_index_2]
  847.                                =delta_x[0][0];
  848.                               delta_y[delta_index_1a][delta_index_2]
  849.                                =delta_y[0][0];
  850.                               delta_x[delta_index_1b][delta_index_2]
  851.                                =delta_x[1][0];
  852.                               delta_y[delta_index_1b][delta_index_2]
  853.                                =delta_y[1][0];
  854.                               delta_x[delta_index_1c][delta_index_2]
  855.                                =delta_x[2][0];
  856.                               delta_y[delta_index_1c][delta_index_2]
  857.                                =delta_y[2][0];
  858.                               delta_x[delta_index_1d][delta_index_2]
  859.                                =delta_x[3][0];
  860.                               delta_y[delta_index_1d][delta_index_2]
  861.                                =delta_y[3][0];
  862.                               delta_x[delta_index_1e][delta_index_2]
  863.                                =delta_x[4][0];
  864.                               delta_y[delta_index_1e][delta_index_2]
  865.                                =delta_y[4][0];
  866.                               delta_x[delta_index_1f][delta_index_2]
  867.                                =delta_x[5][0];
  868.                               delta_y[delta_index_1f][delta_index_2]
  869.                                =delta_y[5][0];
  870.                               delta_index_2++;
  871.                             };
  872.       do
  873.         {
  874.           titillate();
  875.           r_n[0]=counter_0+1;
  876.           r_n[1]=counter_1+1;
  877.           r_n[2]=counter_2+1;
  878.           r_n[3]=counter_3+1;
  879.           r_n[4]=counter_4+1;
  880.           r_n[5]=counter_5+1;
  881.           r_n[6]=counter_6+1;
  882.           r_n[7]=counter_7+1;
  883.           y_mod_4=1;
  884.           for (y=0; y <= max_y; y++) 
  885.             {
  886.               if (y_mod_4 == 1)
  887.                 {
  888.                   x_mod_8=1;
  889.                   for (x=0; x <= max_x; x++)
  890.                     {
  891.                       if (((x_mod_8 == 0)
  892.                         && (y != 0)
  893.                         && (y != max_y))
  894.                       ||  (x_mod_8 == 3)
  895.                       ||  (x_mod_8 == 4)
  896.                       ||  (x_mod_8 == 5))
  897.                         base_page[y][x]='W';
  898.                       else
  899.                         base_page[y][x]=' ';
  900.                       x_mod_8++;
  901.                       if (x_mod_8 >= 8)
  902.                         x_mod_8=0;
  903.                     }
  904.                 } 
  905.               else
  906.                 {
  907.                   if (y_mod_4 == 0 || y_mod_4 == 2)
  908.                     {
  909.                       x_mod_8=1;
  910.                       for (x=0; x <= max_x; x++)
  911.                         {
  912.                           if ((x_mod_8 == 2) || (x_mod_8 == 6))
  913.                             base_page[y][x]='W';
  914.                           else
  915.                             base_page[y][x]=' ';
  916.                           x_mod_8++;
  917.                           if (x_mod_8 >= 8)
  918.                             x_mod_8 = 0;
  919.                         }
  920.                     }
  921.                   else
  922.                     {
  923.                       x_mod_8=1;
  924.                       for (x=0; x <= max_x; x++)
  925.                         {
  926.                           if ((x_mod_8 == 0)
  927.                           ||  (x_mod_8 == 1)
  928.                           ||  (x_mod_8 == 4)
  929.                           ||  (x_mod_8 == 7))
  930.                             base_page[y][x]='W';
  931.                           else
  932.                             base_page[y][x]=' ';
  933.                           x_mod_8++;
  934.                           if (x_mod_8 >= 8)
  935.                             x_mod_8=0;
  936.                       }
  937.                     }
  938.                 }
  939.               y_mod_4++;
  940.               if (y_mod_4 >= 4)
  941.                 y_mod_4=0;
  942.             }
  943.           column_num=r_n[0];
  944.           r_n_index_1=0;
  945.           r_n_index_2=1;
  946.           while (r_n_index_2 < 8)
  947.             {
  948.               tem_int=r_n[r_n_index_2];
  949.               r_n[r_n_index_1]=tem_int;
  950.               column_num+=tem_int;
  951.               if (column_num >= 727)
  952.                 column_num-=727;
  953.               r_n_index_1=r_n_index_2;
  954.               r_n_index_2++;
  955.             }
  956.           r_n[7]=column_num;
  957.           column_num%=num_columns;
  958.           x=4*column_num+3;
  959.           row_num=r_n[0];
  960.           r_n_index_1=0;
  961.           r_n_index_2=1;
  962.           while (r_n_index_2 < 8)
  963.             {
  964.               tem_int=r_n[r_n_index_2];
  965.               r_n[r_n_index_1]=tem_int;
  966.               row_num+=tem_int;
  967.               if (row_num >= 727)
  968.                 row_num-=727;
  969.               r_n_index_1=r_n_index_2;
  970.               r_n_index_2++;
  971.             }
  972.           r_n[7]=row_num;
  973.           if (column_num%2)
  974.             {
  975.               row_num%=(num_rows-1);
  976.               y=4*row_num+4;
  977.             }
  978.           else
  979.             {
  980.               row_num%=num_rows;
  981.               y=4*row_num+2;
  982.             }
  983.           base_page[y][x]=' ';
  984.           stack_head=-1;
  985.           do
  986.             {
  987.               delta_index_1a=0;
  988.               do
  989.                 {
  990.                   delta_index_2=r_n[0];
  991.                   r_n_index_1=0;
  992.                   r_n_index_2=1;
  993.                   while (r_n_index_2 < 8)
  994.                     {
  995.                       tem_int=r_n[r_n_index_2];
  996.                       r_n[r_n_index_1]=tem_int;
  997.                       delta_index_2+=tem_int;
  998.                       if (delta_index_2 >= 727)
  999.                         delta_index_2-=727;
  1000.                       r_n_index_1=r_n_index_2;
  1001.                       r_n_index_2++;
  1002.                     }
  1003.                   r_n[7]=delta_index_2;
  1004.                 }
  1005.               while (delta_index_2 >= 720);
  1006.               passage_found=FALSE;
  1007.               search_complete=FALSE;
  1008.               while (! search_complete)
  1009.                 {
  1010.                   while ((delta_index_1a < 6) && (! passage_found))
  1011.                     {
  1012.                       x_next=x+2*delta_x[delta_index_1a][delta_index_2];
  1013.                       if (x_next <= 0)
  1014.                         delta_index_1a++;
  1015.                       else
  1016.                         if (x_next > max_x)
  1017.                           delta_index_1a++;
  1018.                         else
  1019.                           {
  1020.                             y_next=y+2*delta_y[delta_index_1a][delta_index_2];
  1021.                             if (y_next <= 0)
  1022.                               delta_index_1a++;
  1023.                             else
  1024.                               if (y_next > max_y)
  1025.                                 delta_index_1a++;
  1026.                               else
  1027.                                 if (base_page[y_next][x_next] == 'W')
  1028.                                   passage_found=TRUE;
  1029.                                 else
  1030.                                   delta_index_1a++;
  1031.                           }
  1032.                     }
  1033.                   if (! passage_found)
  1034.                     {
  1035.                       if (stack_head >= 0)
  1036.                         {
  1037.                           delta_index_1a=(int) (stack[stack_head].index_1);
  1038.                           delta_index_2=stack[stack_head].index_2;
  1039.                           x-=2*delta_x[delta_index_1a][delta_index_2];
  1040.                           y-=2*delta_y[delta_index_1a][delta_index_2];
  1041.                           stack_head--;
  1042.                           delta_index_1a++;
  1043.                         }
  1044.                     }
  1045.                   search_complete=((passage_found)
  1046.                    || ((stack_head == -1) && (delta_index_1a >= 6)));
  1047.                 }
  1048.               if (passage_found)
  1049.                 {
  1050.                   stack_head++;
  1051.                   stack[stack_head].index_1=(char) delta_index_1a;
  1052.                   stack[stack_head].index_2=delta_index_2;
  1053.                   base_page[y_next][x_next]=' ';
  1054.                   base_page[(y+y_next)/2][(x+x_next)/2]=' ';
  1055.                   x=x_next;
  1056.                   y=y_next;
  1057.                 }
  1058.             }
  1059.           while (stack_head != -1);
  1060.           base_page[0][3]='S';
  1061.           base_page[max_y][max_x-3]=' ';
  1062.           solve_maze(stack,base_page,&num_rooms_in_solution,&adjacency,max_x,
  1063.            max_y);
  1064.           increment(&counter_0,&counter_1,&counter_2,&counter_3,&counter_4,
  1065.            &counter_5,&counter_6,&counter_7);
  1066.         }
  1067.       while ((3*num_rooms_in_solution < num_rooms_in_maze)
  1068.       ||     (2*adjacency > 3*num_rooms_in_solution));
  1069.       for (x = 0; x <= x_dot_max; x++) 
  1070.         for (y = 0; y <= y_dot_max; y++)
  1071.           page[y][x]=' ';
  1072.       y_previous=-1;
  1073.       y_next=1;
  1074.       for (y = 0; y <= max_y; y++)
  1075.         {
  1076.           x=0;
  1077.           for (x_next = 1; x_next <= max_x; x_next++)
  1078.             {
  1079.               if (base_page[y][x] == 'W')
  1080.                 {
  1081.                   if (base_page[y][x_next] == 'W')
  1082.                     draw_line_on_page(page,RESOLUTION*x,RESOLUTION*y,
  1083.                      RESOLUTION*x_next,RESOLUTION*y);
  1084.                   if (y_previous >= 0)
  1085.                     {
  1086.                       if (base_page[y_previous][x_next] == 'W')
  1087.                         draw_line_on_page(page,RESOLUTION*x,RESOLUTION*y,
  1088.                          RESOLUTION*x_next,RESOLUTION*y_previous);
  1089.                     }
  1090.                   if (y_next <= max_y) 
  1091.                     {
  1092.                       if (base_page[y_next][x_next] == 'W')
  1093.                         draw_line_on_page(page,RESOLUTION*x,RESOLUTION*y,
  1094.                          RESOLUTION*x_next,RESOLUTION*y_next);
  1095.                     }
  1096.                 }
  1097.               x=x_next;
  1098.             }
  1099.           y_previous=y;
  1100.           y_next++;
  1101.         }
  1102.       return;
  1103.     }
  1104.  
  1105. static int substitution_high [100] =
  1106.              { 4,1,2,8,8,9,9,6,5,7,2,1,2,9,8,8,6,3,5,1,9,5,4,4,9,8,6,0,8,0,
  1107.                6,0,2,4,1,9,2,0,7,4,7,3,0,0,2,6,8,9,4,0,8,3,2,3,2,5,2,4,6,9,
  1108.                7,9,1,3,5,7,1,1,4,5,8,1,6,0,5,7,8,2,3,3,7,3,5,1,7,5,4,0,3,6,
  1109.                3,7,7,1,9,4,0,5,6,6 
  1110.              };
  1111. static int substitution_low [100] =
  1112.              { 1,2,2,1,5,5,4,6,4,6,4,4,5,6,6,3,0,9,6,5,7,2,0,9,3,4,2,3,9,1,
  1113.                9,9,9,3,8,9,3,4,1,5,0,5,2,7,0,8,8,0,4,5,0,3,6,8,1,7,8,8,7,1,
  1114.                3,2,7,7,1,8,0,3,7,5,2,6,4,0,9,9,7,7,4,6,2,0,0,1,7,3,6,6,1,1,
  1115.                2,4,5,9,8,2,8,8,3,5 
  1116.              };
  1117. static void hash(counter_0,counter_1,counter_2,counter_3,counter_4,counter_5,
  1118.  counter_6,counter_7)
  1119.   int *counter_0;
  1120.   int *counter_1;
  1121.   int *counter_2;
  1122.   int *counter_3;
  1123.   int *counter_4;
  1124.   int *counter_5;
  1125.   int *counter_6;
  1126.   int *counter_7;
  1127.     {
  1128.       register int iteration;
  1129.       static   int seed_0;
  1130.       static   int seed_1;
  1131.       static   int seed_2;
  1132.       static   int seed_3;
  1133.       static   int seed_4;
  1134.       static   int seed_5;
  1135.       static   int seed_6;
  1136.       static   int seed_7;
  1137.       register int substitution_index;
  1138.       static   int tem_0;
  1139.       static   int tem_1;
  1140.       static   int tem_2;
  1141.  
  1142.       seed_0=(*counter_0);
  1143.       seed_1=(*counter_1);
  1144.       seed_2=(*counter_2);
  1145.       seed_3=(*counter_3);
  1146.       seed_4=(*counter_4);
  1147.       seed_5=(*counter_5);
  1148.       seed_6=(*counter_6);
  1149.       seed_7=(*counter_7);
  1150.       for (iteration=1; iteration <= 8; iteration++)
  1151.         {
  1152.           substitution_index=10*seed_1+seed_0;
  1153.           tem_0=substitution_low[substitution_index];
  1154.           tem_1=substitution_high[substitution_index];
  1155.           substitution_index=10*seed_3+seed_2;
  1156.           seed_0=substitution_low[substitution_index];
  1157.           tem_2=substitution_high[substitution_index];
  1158.           substitution_index=10*seed_5+seed_4;
  1159.           seed_2=substitution_low[substitution_index];
  1160.           seed_1=substitution_high[substitution_index];
  1161.           substitution_index=10*seed_7+seed_6;
  1162.           seed_5=substitution_low[substitution_index];
  1163.           seed_7=substitution_high[substitution_index];
  1164.           seed_3=tem_0;
  1165.           seed_6=tem_1;
  1166.           seed_4=tem_2;
  1167.         }
  1168.       (*counter_0)=seed_0;
  1169.       (*counter_1)=seed_1;
  1170.       (*counter_2)=seed_2;
  1171.       (*counter_3)=seed_3;
  1172.       (*counter_4)=seed_4;
  1173.       (*counter_5)=seed_5;
  1174.       (*counter_6)=seed_6;
  1175.       (*counter_7)=seed_7;
  1176.       return;
  1177.     }
  1178.  
  1179. static void increment(counter_0,counter_1,counter_2,counter_3,counter_4,
  1180.  counter_5,counter_6,counter_7)
  1181.   int *counter_0;
  1182.   int *counter_1;
  1183.   int *counter_2;
  1184.   int *counter_3;
  1185.   int *counter_4;
  1186.   int *counter_5;
  1187.   int *counter_6;
  1188.   int *counter_7;
  1189.     {
  1190.       register tem;
  1191.  
  1192.       tem=(*counter_0)+1;
  1193.       if (tem <= 9)
  1194.         (*counter_0)=tem;
  1195.       else
  1196.         {
  1197.           (*counter_0)=0;
  1198.           tem=(*counter_1)+1;
  1199.           if (tem <= 9)
  1200.             (*counter_1)=tem;
  1201.           else
  1202.             {
  1203.               (*counter_1)=0;
  1204.               tem=(*counter_2)+1;
  1205.               if (tem <= 9)
  1206.                 (*counter_2)=tem;
  1207.               else
  1208.                 {
  1209.                   (*counter_2)=0;
  1210.                   tem=(*counter_3)+1;
  1211.                   if (tem <= 9)
  1212.                     (*counter_3)=tem;
  1213.                   else
  1214.                     {
  1215.                       (*counter_3)=0;
  1216.                       tem=(*counter_4)+1;
  1217.                       if (tem <= 9)
  1218.                         (*counter_4)=tem;
  1219.                       else
  1220.                         {
  1221.                           (*counter_4)=0;
  1222.                           tem=(*counter_5)+1;
  1223.                           if (tem <= 9)
  1224.                             (*counter_5)=tem;
  1225.                           else
  1226.                             {
  1227.                               (*counter_5)=0;
  1228.                               tem=(*counter_6)+1;
  1229.                               if (tem <= 9)
  1230.                                 (*counter_6)=tem;
  1231.                               else
  1232.                                 {
  1233.                                   (*counter_6)=0;
  1234.                                   tem=(*counter_7)+1;
  1235.                                   if (tem <= 9)
  1236.                                     (*counter_7)=tem;
  1237.                                   else
  1238.                                     (*counter_7)=0;
  1239.                                 }
  1240.                             }
  1241.                         }
  1242.                     }
  1243.                 }
  1244.             }
  1245.         }
  1246.       return;
  1247.     }
  1248.  
  1249. static void evaluate_and_transform(x_min,x_max,y_min,y_max,num_x_divisions,
  1250.  num_y_divisions,rotation,tilt,x_prime,y_prime,z_prime,x_prime_max,y_prime_min,
  1251.  y_prime_max,z_prime_min,z_prime_max,light,x_division_index,y_division_index,
  1252.  base_z)
  1253.   double             x_min;
  1254.   double             x_max;
  1255.   double             y_min;
  1256.   double             y_max;
  1257.   int                num_x_divisions;
  1258.   int                num_y_divisions;
  1259.   double             rotation;
  1260.   double             tilt;
  1261.   float huge         *x_prime;
  1262.   float huge         *y_prime;
  1263.   float huge         *z_prime;
  1264.   double             *x_prime_max;
  1265.   double             *y_prime_min;
  1266.   double             *y_prime_max;
  1267.   double             *z_prime_min;
  1268.   double             *z_prime_max;
  1269.   vertex_rec         *light;
  1270.   int huge           *x_division_index;
  1271.   int huge           *y_division_index;
  1272.   unsigned char huge *base_z;
  1273.     {
  1274.       static   double cos_rotation;
  1275.       static   double cos_tilt;
  1276.       static   double magnitude;
  1277.       static   long   prime_num;
  1278.       static   double radians;
  1279.       static   double radians_per_degree;
  1280.       static   double sin_rotation;
  1281.       static   double sin_tilt;
  1282.       static   double x;
  1283.       static   double x_delta;
  1284.       register int    x_division_num;
  1285.       static   double x_rotated;
  1286.       static   double y;
  1287.       static   double y_delta;
  1288.       register int    y_division_num;
  1289.       static   double z;
  1290.  
  1291.       radians_per_degree=atan(1.0)/45.0;
  1292.       radians=tilt*radians_per_degree;
  1293.       cos_tilt=cos(radians);
  1294.       sin_tilt=sin(radians);
  1295.       radians=rotation*radians_per_degree;
  1296.       cos_rotation=cos(radians);
  1297.       sin_rotation=sin(radians);
  1298.       z=fabs(f(x_min,y_min));
  1299.       x_rotated=x_min*cos_rotation+y_min*sin_rotation;
  1300.       *y_prime_min=-x_min*sin_rotation+y_min*cos_rotation;
  1301.       *z_prime_min=-x_rotated*sin_tilt+z*cos_tilt;
  1302.       *y_prime_max=*y_prime_min;
  1303.       *z_prime_max=*z_prime_min;
  1304.       *x_prime_max=x_rotated*cos_tilt+z*sin_tilt;
  1305.       x_delta=(double) (num_x_divisions-1);
  1306.       x_delta=(x_max-x_min)/x_delta;
  1307.       y_delta=(double) (num_y_divisions-1);
  1308.       y_delta=(y_max-y_min)/y_delta;
  1309.       x=x_min;
  1310.       prime_num=0l;
  1311.       for (x_division_num=0; x_division_num < num_x_divisions; x_division_num++)
  1312.         {
  1313.           titillate();
  1314.           y=y_min;
  1315.           for (y_division_num=0; y_division_num < num_y_divisions;
  1316.            y_division_num++)
  1317.             {
  1318.               z=f(x,y);
  1319.               if (z > 0.0)
  1320.                 base_z[prime_num]=(unsigned char) 1;
  1321.               else
  1322.                 if (z < 0.0)
  1323.                   base_z[prime_num]=(unsigned char) 2;
  1324.                 else
  1325.                   base_z[prime_num]=(unsigned char) 0;
  1326.               z=fabs(z);
  1327.               x_division_index[prime_num]=x_division_num;
  1328.               y_division_index[prime_num]=y_division_num;
  1329.               x_rotated=x*cos_rotation+y*sin_rotation;
  1330.               y_prime[prime_num]=(float) (-x*sin_rotation+y*cos_rotation);
  1331.               x_prime[prime_num]=(float) (x_rotated*cos_tilt+z*sin_tilt);
  1332.               z_prime[prime_num]=(float) (-x_rotated*sin_tilt+z*cos_tilt);
  1333.               if (((double) (x_prime[prime_num])) > *x_prime_max)
  1334.                 *x_prime_max=(double) (x_prime[prime_num]);
  1335.               if (((double) (y_prime[prime_num])) < *y_prime_min)
  1336.                 *y_prime_min=(double) (y_prime[prime_num]);
  1337.               if (((double) (y_prime[prime_num])) > *y_prime_max)
  1338.                 *y_prime_max=(double) (y_prime[prime_num]);
  1339.               if (((double) (z_prime[prime_num])) < *z_prime_min)
  1340.                 *z_prime_min=(double) (z_prime[prime_num]);
  1341.               if (((double) (z_prime[prime_num])) > *z_prime_max)
  1342.                 *z_prime_max=(double) (z_prime[prime_num]);
  1343.               y+=y_delta;
  1344.               prime_num++;
  1345.             }
  1346.           x+=x_delta;
  1347.         }
  1348.       magnitude=(*light).x*(*light).x;
  1349.       magnitude+=((*light).y*(*light).y);
  1350.       magnitude+=((*light).z*(*light).z);
  1351.       magnitude=sqrt(magnitude);
  1352.       (*light).x/=magnitude;
  1353.       (*light).y/=magnitude;
  1354.       (*light).z/=magnitude;
  1355.       return;
  1356.     }
  1357.  
  1358. static void shade(num_x_divisions,num_y_divisions,x_prime,y_prime,z_prime,color,
  1359.  light)
  1360.   int                num_x_divisions;
  1361.   int                num_y_divisions;
  1362.   float huge         *x_prime;
  1363.   float huge         *y_prime;
  1364.   float huge         *z_prime;
  1365.   unsigned char huge *color;
  1366.   vertex_rec         *light;
  1367.     {
  1368.       static   double     magnitude;
  1369.       static   vertex_rec normal;
  1370.       static   long       prime_num;
  1371.       static   vertex_rec vertex [4];
  1372.       register int        x_division_num;
  1373.       register int        y_division_num;
  1374.  
  1375.       prime_num=0l;
  1376.       for (x_division_num=0; x_division_num < num_x_divisions;
  1377.        x_division_num++)
  1378.         {
  1379.           titillate();
  1380.           for (y_division_num=0; y_division_num < num_y_divisions;
  1381.            y_division_num++)
  1382.             {
  1383.               vertex[0].x=(double) (x_prime[prime_num]);
  1384.               vertex[0].y=(double) (y_prime[prime_num]);
  1385.               vertex[0].z=(double) (z_prime[prime_num]);
  1386.               if (x_division_num < (num_x_divisions-1))
  1387.                 if (y_division_num < (num_y_divisions-1))
  1388.                   {
  1389.                     prime_num+=((long) num_y_divisions);
  1390.                     vertex[1].x=(double) (x_prime[prime_num]);
  1391.                     vertex[1].y=(double) (y_prime[prime_num]);
  1392.                     vertex[1].z=(double) (z_prime[prime_num]);
  1393.                     prime_num++;
  1394.                     vertex[2].x=(double) (x_prime[prime_num]);
  1395.                     vertex[2].y=(double) (y_prime[prime_num]);
  1396.                     vertex[2].z=(double) (z_prime[prime_num]);
  1397.                     prime_num-=((long) num_y_divisions);
  1398.                     vertex[3].x=(double) (x_prime[prime_num]);
  1399.                     vertex[3].y=(double) (y_prime[prime_num]);
  1400.                     vertex[3].z=(double) (z_prime[prime_num]);
  1401.                     prime_num--;
  1402.                   }
  1403.                 else
  1404.                   {
  1405.                     prime_num--;
  1406.                     vertex[1].x=(double) (x_prime[prime_num]);
  1407.                     vertex[1].y=(double) (y_prime[prime_num]);
  1408.                     vertex[1].z=(double) (z_prime[prime_num]);
  1409.                     prime_num+=((long) num_y_divisions);
  1410.                     vertex[2].x=(double) (x_prime[prime_num]);
  1411.                     vertex[2].y=(double) (y_prime[prime_num]);
  1412.                     vertex[2].z=(double) (z_prime[prime_num]);
  1413.                     prime_num++;
  1414.                     vertex[3].x=(double) (x_prime[prime_num]);
  1415.                     vertex[3].y=(double) (y_prime[prime_num]);
  1416.                     vertex[3].z=(double) (z_prime[prime_num]);
  1417.                     prime_num-=((long) num_y_divisions);
  1418.                   }
  1419.               else
  1420.                 if (y_division_num < (num_y_divisions-1))
  1421.                   {
  1422.                     prime_num++;
  1423.                     vertex[1].x=(double) (x_prime[prime_num]);
  1424.                     vertex[1].y=(double) (y_prime[prime_num]);
  1425.                     vertex[1].z=(double) (z_prime[prime_num]);
  1426.                     prime_num-=((long) num_y_divisions);
  1427.                     vertex[2].x=(double) (x_prime[prime_num]);
  1428.                     vertex[2].y=(double) (y_prime[prime_num]);
  1429.                     vertex[2].z=(double) (z_prime[prime_num]);
  1430.                     prime_num--;
  1431.                     vertex[3].x=(double) (x_prime[prime_num]);
  1432.                     vertex[3].y=(double) (y_prime[prime_num]);
  1433.                     vertex[3].z=(double) (z_prime[prime_num]);
  1434.                     prime_num+=((long) num_y_divisions);
  1435.                   }
  1436.                 else
  1437.                   {
  1438.                     prime_num-=((long) num_y_divisions);
  1439.                     vertex[1].x=(double) (x_prime[prime_num]);
  1440.                     vertex[1].y=(double) (y_prime[prime_num]);
  1441.                     vertex[1].z=(double) (z_prime[prime_num]);
  1442.                     prime_num--;
  1443.                     vertex[2].x=(double) (x_prime[prime_num]);
  1444.                     vertex[2].y=(double) (y_prime[prime_num]);
  1445.                     vertex[2].z=(double) (z_prime[prime_num]);
  1446.                     prime_num+=((long) num_y_divisions);
  1447.                     vertex[3].x=(double) (x_prime[prime_num]);
  1448.                     vertex[3].y=(double) (y_prime[prime_num]);
  1449.                     vertex[3].z=(double) (z_prime[prime_num]);
  1450.                     prime_num++;
  1451.                   }
  1452.               normal.x
  1453.                =(vertex[1].y-vertex[0].y)*(vertex[3].z-vertex[0].z)
  1454.                -(vertex[3].y-vertex[0].y)*(vertex[1].z-vertex[0].z)
  1455.                +(vertex[2].y-vertex[1].y)*(vertex[0].z-vertex[1].z)
  1456.                -(vertex[0].y-vertex[1].y)*(vertex[2].z-vertex[1].z)
  1457.                +(vertex[3].y-vertex[2].y)*(vertex[1].z-vertex[2].z)
  1458.                -(vertex[1].y-vertex[2].y)*(vertex[3].z-vertex[2].z)
  1459.                +(vertex[0].y-vertex[3].y)*(vertex[2].z-vertex[3].z)
  1460.                -(vertex[2].y-vertex[3].y)*(vertex[0].z-vertex[3].z);
  1461.               normal.y
  1462.                =(vertex[3].x-vertex[0].x)*(vertex[1].z-vertex[0].z)
  1463.                -(vertex[1].x-vertex[0].x)*(vertex[3].z-vertex[0].z)
  1464.                +(vertex[0].x-vertex[1].x)*(vertex[2].z-vertex[1].z)
  1465.                -(vertex[2].x-vertex[1].x)*(vertex[0].z-vertex[1].z)
  1466.                +(vertex[1].x-vertex[2].x)*(vertex[3].z-vertex[2].z)
  1467.                -(vertex[3].x-vertex[2].x)*(vertex[1].z-vertex[2].z)
  1468.                +(vertex[2].x-vertex[3].x)*(vertex[0].z-vertex[3].z)
  1469.                -(vertex[0].x-vertex[3].x)*(vertex[2].z-vertex[3].z);
  1470.               normal.z
  1471.                =(vertex[1].x-vertex[0].x)*(vertex[3].y-vertex[0].y)
  1472.                -(vertex[3].x-vertex[0].x)*(vertex[1].y-vertex[0].y)
  1473.                +(vertex[2].x-vertex[1].x)*(vertex[0].y-vertex[1].y)
  1474.                -(vertex[0].x-vertex[1].x)*(vertex[2].y-vertex[1].y)
  1475.                +(vertex[3].x-vertex[2].x)*(vertex[1].y-vertex[2].y)
  1476.                -(vertex[1].x-vertex[2].x)*(vertex[3].y-vertex[2].y)
  1477.                +(vertex[0].x-vertex[3].x)*(vertex[2].y-vertex[3].y)
  1478.                -(vertex[2].x-vertex[3].x)*(vertex[0].y-vertex[3].y);
  1479.               if (normal.x < 0.0)
  1480.                 color[prime_num]=NUM_COLORS;
  1481.               else
  1482.                 {
  1483.                   magnitude
  1484.                    =sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z);
  1485.                   if (magnitude == 0.0)
  1486.                     color[prime_num]=(unsigned char) 0;
  1487.                   else
  1488.                     {
  1489.                       color[prime_num]
  1490.                        =(unsigned char) ((((float) (NUM_COLORS-1))/2.0)*(1.0
  1491.                        +((*light).x*normal.x+(*light).y*normal.y
  1492.                        +(*light).z*normal.z)/magnitude));
  1493.                       if (color[prime_num] >= (unsigned char) (NUM_COLORS-1))
  1494.                         color[prime_num]=(unsigned char) (NUM_COLORS-2);
  1495.                     }
  1496.                 }
  1497.               prime_num++;
  1498.             }
  1499.         }
  1500.       return;
  1501.     }
  1502.  
  1503. static void adjust_perspective(num_x_divisions,num_y_divisions,x_prime,y_prime,
  1504.  z_prime,x_prime_max,y_prime_min,y_prime_max,z_prime_min,z_prime_max)
  1505.   int        num_x_divisions;
  1506.   int        num_y_divisions;
  1507.   float huge *x_prime;
  1508.   float huge *y_prime;
  1509.   float huge *z_prime;
  1510.   double     x_prime_max;
  1511.   double     y_prime_min;
  1512.   double     y_prime_max;
  1513.   double     z_prime_min;
  1514.   double     z_prime_max;  
  1515.     {
  1516.       static   long       prime_num;
  1517.       static   vertex_rec vertex [4];
  1518.       register int        x_division_num;
  1519.       static   double     x_eye;
  1520.       static   double     y_center;
  1521.       register int        y_division_num;
  1522.       static   double     z_center;
  1523.  
  1524.       if ((y_prime_max-y_prime_min) > (z_prime_max-z_prime_min))
  1525.         x_eye=1.1*(y_prime_max-y_prime_min)+x_prime_max;
  1526.       else
  1527.         x_eye=1.1*(z_prime_max-z_prime_min)+x_prime_max;
  1528.       if (((y_prime_max-y_prime_min) > (z_prime_max-z_prime_min))
  1529.       ||  (z_prime_max != z_prime_min))
  1530.         {
  1531.           y_center=(y_prime_max+y_prime_min)/2.0;
  1532.           z_center=(z_prime_max+z_prime_min)/2.0;
  1533.           prime_num=0l;
  1534.           for (x_division_num=0; x_division_num < num_x_divisions;
  1535.            x_division_num++)
  1536.             {
  1537.               titillate();
  1538.               for (y_division_num=0; y_division_num < num_y_divisions;
  1539.                y_division_num++)
  1540.                 {
  1541.                   vertex[0].x=(double) (x_prime[prime_num]);
  1542.                   vertex[0].y=(double) (y_prime[prime_num]);
  1543.                   vertex[0].z=(double) (z_prime[prime_num]);
  1544.                   if (x_division_num < (num_x_divisions-1))
  1545.                     if (y_division_num < (num_y_divisions-1))
  1546.                       {
  1547.                         prime_num+=((long) num_y_divisions);
  1548.                         vertex[1].x=(double) (x_prime[prime_num]);
  1549.                         vertex[1].y=(double) (y_prime[prime_num]);
  1550.                         vertex[1].z=(double) (z_prime[prime_num]);
  1551.                         prime_num++;
  1552.                         vertex[2].x=(double) (x_prime[prime_num]);
  1553.                         vertex[2].y=(double) (y_prime[prime_num]);
  1554.                         vertex[2].z=(double) (z_prime[prime_num]);
  1555.                         prime_num-=((long) num_y_divisions);
  1556.                         vertex[3].x=(double) (x_prime[prime_num]);
  1557.                         vertex[3].y=(double) (y_prime[prime_num]);
  1558.                         vertex[3].z=(double) (z_prime[prime_num]);
  1559.                         prime_num--;
  1560.                       }
  1561.                     else
  1562.                       {
  1563.                         prime_num--;
  1564.                         vertex[1].x=(double) (x_prime[prime_num]);
  1565.                         vertex[1].y=(double) (y_prime[prime_num]);
  1566.                         vertex[1].z=(double) (z_prime[prime_num]);
  1567.                         prime_num+=((long) num_y_divisions);
  1568.                         vertex[2].x=(double) (x_prime[prime_num]);
  1569.                         vertex[2].y=(double) (y_prime[prime_num]);
  1570.                         vertex[2].z=(double) (z_prime[prime_num]);
  1571.                         prime_num++;
  1572.                         vertex[3].x=(double) (x_prime[prime_num]);
  1573.                         vertex[3].y=(double) (y_prime[prime_num]);
  1574.                         vertex[3].z=(double) (z_prime[prime_num]);
  1575.                         prime_num-=((long) num_y_divisions);
  1576.                       }
  1577.                   else
  1578.                     if (y_division_num < (num_y_divisions-1))
  1579.                       {
  1580.                         prime_num++;
  1581.                         vertex[1].x=(double) (x_prime[prime_num]);
  1582.                         vertex[1].y=(double) (y_prime[prime_num]);
  1583.                         vertex[1].z=(double) (z_prime[prime_num]);
  1584.                         prime_num-=((long) num_y_divisions);
  1585.                         vertex[2].x=(double) (x_prime[prime_num]);
  1586.                         vertex[2].y=(double) (y_prime[prime_num]);
  1587.                         vertex[2].z=(double) (z_prime[prime_num]);
  1588.                         prime_num--;
  1589.                         vertex[3].x=(double) (x_prime[prime_num]);
  1590.                         vertex[3].y=(double) (y_prime[prime_num]);
  1591.                         vertex[3].z=(double) (z_prime[prime_num]);
  1592.                         prime_num+=((long) num_y_divisions);
  1593.                       }
  1594.                     else
  1595.                       {
  1596.                         prime_num-=((long) num_y_divisions);
  1597.                         vertex[1].x=(double) (x_prime[prime_num]);
  1598.                         vertex[1].y=(double) (y_prime[prime_num]);
  1599.                         vertex[1].z=(double) (z_prime[prime_num]);
  1600.                         prime_num--;
  1601.                         vertex[2].x=(double) (x_prime[prime_num]);
  1602.                         vertex[2].y=(double) (y_prime[prime_num]);
  1603.                         vertex[2].z=(double) (z_prime[prime_num]);
  1604.                         prime_num+=((long) num_y_divisions);
  1605.                         vertex[3].x=(double) (x_prime[prime_num]);
  1606.                         vertex[3].y=(double) (y_prime[prime_num]);
  1607.                         vertex[3].z=(double) (z_prime[prime_num]);
  1608.                         prime_num++;
  1609.                       }
  1610.                   y_prime[prime_num]=(float) y_center
  1611.                    +(vertex[0].y-y_center)*(x_eye-x_prime_max)
  1612.                    /(x_eye-vertex[0].x);
  1613.                   z_prime[prime_num]=(float) z_center
  1614.                    +(vertex[0].z-z_center)*(x_eye-x_prime_max)
  1615.                    /(x_eye-vertex[0].x);
  1616.                   x_prime[prime_num]=(float)
  1617.                    (-(vertex[0].x+vertex[1].x+vertex[2].x+vertex[3].x)/4.0);
  1618.                   prime_num++;
  1619.                 }
  1620.             }
  1621.          }
  1622.       return;
  1623.     }
  1624.  
  1625. static void sort_back_to_front(num_primes,x_prime,x_division_index,
  1626.  y_division_index)
  1627.   long       num_primes;
  1628.   float huge *x_prime;
  1629.   int huge   *x_division_index;
  1630.   int huge   *y_division_index;
  1631.     {
  1632.       static   int   finished;
  1633.       static   long  key_index_1;
  1634.       static   long  key_index_2;
  1635.       static   long  left;
  1636.       static   long  right;
  1637.       static   float t1;
  1638.       register int   t2;
  1639.       register int   t3;
  1640.  
  1641.       left=num_primes/((long) 2);
  1642.       right=num_primes-1l;
  1643.       t1=x_prime[0];
  1644.       t2=x_division_index[0];
  1645.       t3=y_division_index[0];
  1646.       while (right > 0l)
  1647.         {
  1648.           titillate();
  1649.           if (left > 0l)
  1650.             {
  1651.               left--;
  1652.               t1=x_prime[left];
  1653.               t2=x_division_index[left];
  1654.               t3=y_division_index[left];
  1655.             }
  1656.           else
  1657.             {
  1658.               t1=x_prime[right];
  1659.               t2=x_division_index[right];
  1660.               t3=y_division_index[right];
  1661.               x_prime[right]=x_prime[0];
  1662.               x_division_index[right]=x_division_index[0];
  1663.               y_division_index[right]=y_division_index[0];
  1664.               right--;
  1665.             }
  1666.           if (right > 0l)
  1667.             {
  1668.               finished=FALSE;
  1669.               key_index_2=left;
  1670.               while (! finished)
  1671.                 {
  1672.                   key_index_1=key_index_2;
  1673.                   key_index_2+=key_index_2;
  1674.                   key_index_2++;
  1675.                   if (key_index_2 > right)
  1676.                     finished=TRUE;
  1677.                   else
  1678.                     {
  1679.                       if (key_index_2 != right)
  1680.                         {
  1681.                           if (x_prime[key_index_2] > x_prime[key_index_2+1])
  1682.                             key_index_2++;
  1683.                         }
  1684.                       if (t1 <= x_prime[key_index_2])
  1685.                         finished=TRUE;
  1686.                       else
  1687.                         {
  1688.                           x_prime[key_index_1]=x_prime[key_index_2];
  1689.                           x_division_index[key_index_1]
  1690.                            =x_division_index[key_index_2];
  1691.                           y_division_index[key_index_1]
  1692.                            =y_division_index[key_index_2];
  1693.                         }
  1694.                     }
  1695.                 }
  1696.               x_prime[key_index_1]=t1;
  1697.               x_division_index[key_index_1]=t2;
  1698.               y_division_index[key_index_1]=t3;
  1699.             }
  1700.         }
  1701.       x_prime[0]=t1;
  1702.       x_division_index[0]=t2;
  1703.       y_division_index[0]=t3;
  1704.       return;
  1705.     }
  1706.  
  1707. static void plot(num_x_divisions,x_division_index,num_y_divisions,
  1708.  y_division_index,num_primes,y_prime,z_prime,y_prime_min,y_prime_max,z_prime_min,
  1709.  z_prime_max,color,base_z,solve,aspect_ratio)
  1710.   int                num_x_divisions;
  1711.   int huge           *x_division_index;
  1712.   int                num_y_divisions;
  1713.   int huge           *y_division_index;
  1714.   long               num_primes;
  1715.   float huge         *y_prime;
  1716.   float huge         *z_prime;
  1717.   double             y_prime_min;
  1718.   double             y_prime_max;
  1719.   double             z_prime_min;
  1720.   double             z_prime_max;
  1721.   unsigned char huge *color;
  1722.   unsigned char huge *base_z;
  1723.   int                solve;
  1724.   double             aspect_ratio;
  1725.     {  
  1726.       static   double        box_delta_x;
  1727.       static   double        box_delta_y;
  1728.       static   box_rec       box [4];
  1729.       static   int           box_num_1;
  1730.       static   int           box_num_2;
  1731.       static   double        box_x_intercept;
  1732.       static   int           box_x1;
  1733.       static   int           box_x2;
  1734.       static   int           box_y_max;
  1735.       static   int           box_y_min;
  1736.       static   double        box_y_offset;
  1737.       static   int           box_y1;
  1738.       static   short         color_num;
  1739.       static   int           intercept_count_mod_2;
  1740.       register int           line_x1;
  1741.       register int           line_x2;
  1742.       static   double        pixels_per_unit;
  1743.       static   long          prime_num;
  1744.       static   int           solution;
  1745.       static   vertex_rec    vertex [4];
  1746.       static   int           x_division_num;
  1747.       static   long          x_prime_num;
  1748.       static   int           y_division_num;
  1749.       static   double        y_offset;
  1750.       static   double        y_out_max;
  1751.       static   double        z_offset;
  1752.       static   double        z_out_max;
  1753.  
  1754.       aspect_ratio=(HEIGHT_OF_SCREEN/WIDTH_OF_SCREEN)
  1755.        /(((double) NUM_Y_PIXELS)/((double) NUM_X_PIXELS));
  1756.       y_out_max=(double) (NUM_X_PIXELS-1);
  1757.       z_out_max=(double) (NUM_Y_PIXELS-1);
  1758.       if (aspect_ratio*z_out_max*(y_prime_max-y_prime_min)
  1759.        > y_out_max*(z_prime_max-z_prime_min))
  1760.         {
  1761.           pixels_per_unit
  1762.            =y_out_max/(aspect_ratio*(y_prime_max-y_prime_min));
  1763.           y_offset=0.0;
  1764.           z_offset
  1765.            =-(z_out_max-pixels_per_unit*(z_prime_max-z_prime_min))/2.0;
  1766.         }
  1767.       else
  1768.         if (aspect_ratio*z_out_max*(y_prime_max-y_prime_min)
  1769.          < y_out_max*(z_prime_max-z_prime_min))
  1770.           {
  1771.             pixels_per_unit=z_out_max/(z_prime_max-z_prime_min);
  1772.             y_offset=(y_out_max
  1773.              -aspect_ratio*pixels_per_unit*(y_prime_max-y_prime_min))/2.0;
  1774.             z_offset=0.0;
  1775.           }
  1776.         else
  1777.           {
  1778.             pixels_per_unit=1.0;
  1779.             y_offset=y_out_max/2.0;
  1780.             z_offset=-z_out_max/2.0;
  1781.           };
  1782.       for (x_prime_num=0l; x_prime_num < num_primes; x_prime_num++)
  1783.         {
  1784.           x_division_num=x_division_index[x_prime_num];
  1785.           if (x_division_num < (num_x_divisions-1))
  1786.             {
  1787.               y_division_num=y_division_index[x_prime_num];
  1788.               if (y_division_num < (num_y_divisions-1))
  1789.                 {
  1790.                   prime_num
  1791.                    =((long) num_y_divisions)*((long) x_division_num)
  1792.                    +((long) y_division_num);
  1793.                   color_num=(short) (color[prime_num]);
  1794.                   if (color_num < NUM_COLORS)
  1795.                     {
  1796.                       vertex[0].y=(double) (y_prime[prime_num]);
  1797.                       vertex[0].z=(double) (z_prime[prime_num]);
  1798.                       solution=(base_z[prime_num] == (unsigned char) 2);
  1799.                       prime_num+=((long) num_y_divisions);
  1800.                       vertex[1].y=(double) (y_prime[prime_num]);
  1801.                       vertex[1].z=(double) (z_prime[prime_num]);
  1802.                       if (solution)
  1803.                         solution=(base_z[prime_num] == (unsigned char) 2);
  1804.                       prime_num++;
  1805.                       vertex[2].y=(double) (y_prime[prime_num]);
  1806.                       vertex[2].z=(double) (z_prime[prime_num]);
  1807.                       if (solution)
  1808.                         solution=(base_z[prime_num] == (unsigned char) 2);
  1809.                       prime_num-=((long) num_y_divisions);
  1810.                       vertex[3].y=(double) (y_prime[prime_num]);
  1811.                       vertex[3].z=(double) (z_prime[prime_num]);
  1812.                       if (solution)
  1813.                         solution=(base_z[prime_num] == (unsigned char) 2);
  1814.                       if ((! solve) || (solution))
  1815.                         {
  1816.                           if (solve)
  1817.                             color_num=(short) (NUM_COLORS-1);
  1818.                           for (box_num_1=0; box_num_1 < 4; box_num_1++)
  1819.                             {
  1820.                               box[box_num_1].x=(int) (y_offset
  1821.                                +pixels_per_unit*aspect_ratio
  1822.                                *(vertex[box_num_1].y-y_prime_min));
  1823.                               box[box_num_1].y=(int) (z_offset+z_out_max
  1824.                                -pixels_per_unit
  1825.                                *(vertex[box_num_1].z-z_prime_min));
  1826.                             }
  1827.                           box_y_min=box[0].y;
  1828.                           box_y_max=box_y_min;
  1829.                           for (box_num_1=1; box_num_1 < 4; box_num_1++)
  1830.                             {
  1831.                               if (box[box_num_1].y < box_y_min)
  1832.                                 box_y_min=box[box_num_1].y;
  1833.                               if (box[box_num_1].y > box_y_max)
  1834.                                 box_y_max=box[box_num_1].y;
  1835.                             }
  1836.                           for (box_y1=box_y_min; box_y1 <= box_y_max; ++box_y1)
  1837.                             {
  1838.                               intercept_count_mod_2=0;
  1839.                               box_num_2=1;
  1840.                               for (box_num_1=0; box_num_1 < 4; ++box_num_1)
  1841.                                 {
  1842.                                   if (box[box_num_1].y >= box_y1)
  1843.                                     {
  1844.                                       if (box_y1 > box[box_num_2].y)
  1845.                                         {
  1846.                                           box_delta_y=(double)
  1847.                                            (box[box_num_2].y-box[box_num_1].y);
  1848.                                           box_delta_x=(double)
  1849.                                            (box[box_num_2].x-box[box_num_1].x);
  1850.                                           box_y_offset=(double)
  1851.                                            (box_y1-box[box_num_1].y);
  1852.                                           box_x_intercept
  1853.                                            =(double) (box[box_num_1].x);
  1854.                                           box_x1
  1855.                                            =(int) ((box_delta_x*box_y_offset)
  1856.                                            /box_delta_y+box_x_intercept);
  1857.                                           if (intercept_count_mod_2 == 0)
  1858.                                             box_x2=box_x1;
  1859.                                           else
  1860.                                             {
  1861.                                               if (box_x1 < box_x2)
  1862.                                                 {
  1863.                                                   line_x1=box_x1;
  1864.                                                   line_x2=box_x2;
  1865.                                                 }
  1866.                                               else
  1867.                                                 {
  1868.                                                   line_x1=box_x2;
  1869.                                                   line_x2=box_x1;
  1870.                                                 }
  1871.                                               set_pixel(line_x1,box_y1,
  1872.                                                color_num);
  1873.                                               while (line_x1 < line_x2)
  1874.                                                 {
  1875.                                                   line_x1++;
  1876.                                                   set_pixel(line_x1,box_y1,
  1877.                                                    color_num);
  1878.                                                 }
  1879.                                             }
  1880.                                           intercept_count_mod_2
  1881.                                            =1-intercept_count_mod_2;
  1882.                                         }
  1883.                                     }
  1884.                                   else
  1885.                                     {
  1886.                                       if (box_y1 <= box[box_num_2].y)
  1887.                                         {
  1888.                                           box_delta_y=(double)
  1889.                                            (box[box_num_2].y-box[box_num_1].y);
  1890.                                           box_delta_x=(double)
  1891.                                            (box[box_num_2].x-box[box_num_1].x);
  1892.                                           box_y_offset=(double)
  1893.                                            (box_y1-box[box_num_1].y);
  1894.                                           box_x_intercept
  1895.                                            =(double) (box[box_num_1].x);
  1896.                                           box_x1
  1897.                                            =(int) ((box_delta_x*box_y_offset)
  1898.                                            /box_delta_y+box_x_intercept);
  1899.                                           if (intercept_count_mod_2 == 0)
  1900.                                             box_x2=box_x1;
  1901.                                           else
  1902.                                             {
  1903.                                               if (box_x1 < box_x2)
  1904.                                                 {
  1905.                                                   line_x1=box_x1;
  1906.                                                   line_x2=box_x2;
  1907.                                                 }
  1908.                                               else
  1909.                                                 {
  1910.                                                   line_x1=box_x2;
  1911.                                                   line_x2=box_x1;
  1912.                                                 }
  1913.                                               set_pixel(line_x1,box_y1,
  1914.                                                color_num);
  1915.                                               while (line_x1 < line_x2)
  1916.                                                 {
  1917.                                                   line_x1++;
  1918.                                                   set_pixel(line_x1,box_y1,
  1919.                                                    color_num);
  1920.                                                 }
  1921.                                             }
  1922.                                           intercept_count_mod_2
  1923.                                            =1-intercept_count_mod_2;
  1924.                                         }
  1925.                                     }
  1926.                                   box_num_2++;
  1927.                                   if (box_num_2 >= 4)
  1928.                                     box_num_2=0;
  1929.                                 }
  1930.                             }
  1931.                         }
  1932.                     }
  1933.                 }
  1934.             }
  1935.         }
  1936.       return;
  1937.     }
  1938.  
  1939. static double f(
  1940.   double x,
  1941.   double y)
  1942.     {
  1943.       static   int    base_x = 0;
  1944.       static   int    base_y = 0;
  1945.       static   int    solution = 0;
  1946.       register int    x_next = 0;
  1947.       static   int    x_offset = 0;
  1948.       static   int    x_out = 0;
  1949.       register int    y_next = 0;
  1950.       static   int    y_offset = 0;
  1951.       static   int    y_out = 0;
  1952.       static   double z = 0.0;
  1953.  
  1954.       y_out=(int) x;
  1955.       if (y_out < 0)
  1956.         z=0.0;
  1957.       else
  1958.         if (y_out > y_dot_max)
  1959.           z=0.0;
  1960.         else
  1961.           {
  1962.             x_out=(int) y;
  1963.             if (x_out < 0)
  1964.               z=0.0;
  1965.             else
  1966.               if (x_out > x_dot_max)
  1967.                 z=0.0;
  1968.               else
  1969.                 if (page[y_out][x_out] == 'W')
  1970.                   {
  1971.                     solution=FALSE;
  1972.                     base_x=x_out/RESOLUTION;
  1973.                     base_y=y_out/RESOLUTION;
  1974.                     for (y_offset=-4; ((! solution) && (y_offset <= 4));
  1975.                      y_offset++)
  1976.                       for (x_offset=-4; ((! solution) && (x_offset <= 4));
  1977.                        x_offset++)
  1978.                         if (abs(x_offset)+abs(y_offset) <= 4)
  1979.                           {
  1980.                             y_next=base_y+y_offset;
  1981.                             if ((y_next >= 0) && (y_next <= max_y))
  1982.                               {
  1983.                                 x_next=base_x+x_offset;
  1984.                                 if ((x_next >= 0) && (x_next <= max_x))
  1985.                                   {
  1986.                                      if (base_page[y_next][x_next] == 'S')
  1987.                                        solution=TRUE; 
  1988.                                   }
  1989.                               }
  1990.                           };
  1991.                     z=((double) (5*RESOLUTION));
  1992.                     if (solution)
  1993.                       z=-z;
  1994.                   }
  1995.                 else
  1996.                   z=0.0;
  1997.           }
  1998.       return(z);
  1999.     }
  2000.  
  2001. static void free_memory(x_prime,y_prime,z_prime,x_division_index,
  2002.  y_division_index,color,base_z,max_y_plus_1,base_page,num_y_dots,page,
  2003.  num_rooms_in_maze,stack)
  2004.   float huge         **x_prime;
  2005.   float huge         **y_prime;
  2006.   float huge         **z_prime;
  2007.   int   huge         **x_division_index;
  2008.   int   huge         **y_division_index;
  2009.   unsigned char huge **color;
  2010.   unsigned char huge **base_z;
  2011.   int                max_y_plus_1;
  2012.   char               ***base_page;
  2013.   int                num_y_dots;
  2014.   char               ***page;
  2015.   int                num_rooms_in_maze;
  2016.   stack_rec          **stack;
  2017.     {
  2018.       register int y;
  2019.  
  2020.       hfree((void huge *) *base_z);
  2021.       hfree((void huge *) *color);
  2022.       hfree((void huge *) *y_division_index);
  2023.       hfree((void huge *) *x_division_index);
  2024.       hfree((void huge *) *z_prime);
  2025.       hfree((void huge *) *y_prime);
  2026.       hfree((void huge *) *x_prime);
  2027.       for (y=0; y < num_y_dots; y++)
  2028.         free((void *) (*page)[y]);
  2029.       free((void *) (*page));
  2030.       for (y=0; y < max_y_plus_1; y++)
  2031.         free((void *) (*base_page)[y]);
  2032.       free((void *) (*base_page));
  2033.       free((void *) *stack);
  2034.       return;
  2035.     }
  2036.  
  2037. static int VGA_640_480_16()
  2038.   {
  2039.     static char          *buffer;
  2040.     static USHORT        cell_num;
  2041.     static int           color_num;
  2042.     static int           plane_num;
  2043.     static int           result;
  2044.     static unsigned char tint;
  2045.  
  2046.     /* Allocate memory to save screen when it's switched. */
  2047.     result=TRUE;
  2048.     for (plane_num=0; ((result) && (plane_num < 4)); plane_num++)
  2049.       result=((video_plane[plane_num]
  2050.        =(long huge *) halloc(NUM_CELLS,sizeof(char))) != NULL);
  2051.  
  2052.     if (result)
  2053.       {
  2054.         VioScrLock((USHORT) LOCKIO_WAIT,(PBYTE) &scr_lock,(HVIO) 0);
  2055.     
  2056.         /* Save current video mode. */
  2057.         default_video_mode.cb=sizeof(VIOMODEINFO);
  2058.         VioGetMode((PVIOMODEINFO) &default_video_mode,(HVIO) 0);
  2059.     
  2060.         /* Switch to 640 x 480 x 16 VGA mode. */
  2061.         memcpy((void *) &maze_video_mode,(const void *) &default_video_mode,
  2062.          sizeof(VIOMODEINFO));
  2063.         maze_video_mode.fbType=VGMT_GRAPHICS|VGMT_OTHER;
  2064.         maze_video_mode.color=COLORS_16;
  2065.         maze_video_mode.col=80;
  2066.          maze_video_mode.row=25;
  2067.         maze_video_mode.hres=NUM_X_PIXELS;
  2068.         maze_video_mode.vres=NUM_Y_PIXELS;
  2069.         if (result=(VioSetMode((PVIOMODEINFO) &maze_video_mode,(HVIO) 0)
  2070.          == (USHORT) 0))
  2071.           {
  2072.             /* Set up palette for invisible screen redraw. */
  2073.             invisible_palette=(PVIOPALSTATE) &invisible_palette_byte[0];
  2074.             invisible_palette->cb=(USHORT) sizeof(invisible_palette_byte);
  2075.             invisible_palette->type=(USHORT) 0;
  2076.             invisible_palette->iFirst=(USHORT) 0;
  2077.             for (color_num=0; color_num < NUM_COLORS; color_num++)
  2078.               invisible_palette->acolor[color_num]=(USHORT) 0;
  2079.     
  2080.             /* Set up shades of gray, etc. for drawing maze. */
  2081.             maze_palette=(PVIOPALSTATE) &maze_palette_byte[0];
  2082.             maze_palette->cb=(USHORT) sizeof(maze_palette_byte);
  2083.             maze_palette->type=(USHORT) 0;
  2084.             maze_palette->iFirst=(USHORT) 0;
  2085.             for (color_num=0; color_num < NUM_COLORS; color_num++)
  2086.               maze_palette->acolor[color_num]=(USHORT) color_num;
  2087.             VioSetState(maze_palette,(HVIO) 0);
  2088.             maze_color.cb=(USHORT) sizeof(maze_color);
  2089.             maze_color.type=(USHORT) 3;
  2090.             maze_color.firstcolorreg=(USHORT) 0;
  2091.             maze_color.numcolorregs=(USHORT) NUM_COLORS;
  2092.             maze_color.colorregaddr=(PCH) &maze_rgb[0];
  2093.             tint=(unsigned char) 0;
  2094.             for (color_num=0; color_num < (NUM_COLORS-1); color_num++)
  2095.               {
  2096.                 maze_rgb[color_num].red=tint;
  2097.                 maze_rgb[color_num].green=tint;
  2098.                 maze_rgb[color_num].blue=tint;
  2099.                 tint+=((unsigned char) RGB_INCREMENT);
  2100.               }
  2101.             maze_rgb[color_num].red=tint;
  2102.             maze_rgb[color_num].green=(unsigned char) 0;
  2103.             maze_rgb[color_num].blue=(unsigned char) 0;
  2104.             VioSetState(&maze_color,(HVIO) 0);
  2105.     
  2106.             /* Locate physical video buffer. */
  2107.             FP_SEG(phys_buf.pBuf)=0x000a;
  2108.             FP_OFF(phys_buf.pBuf)=0;
  2109.             phys_buf.cb=NUM_CELLS;
  2110.             VioGetPhysBuf((PVIOPHYSBUF) &phys_buf,(USHORT) 0);
  2111.             VGA_base_adr=phys_buf.asel[0];
  2112.     
  2113.             /* Clear screen. */
  2114.             FP_SEG(buffer)=phys_buf.asel[0];
  2115.             for (cell_num=(USHORT) 0; cell_num < (USHORT) NUM_CELLS; cell_num++)
  2116.               {
  2117.                 FP_OFF(buffer)=cell_num;
  2118.                 *buffer='\0';
  2119.               }
  2120.     
  2121.             /* Start thread to save/redraw screen when screen is switched. */
  2122.             DosCreateThread((PFNTHREAD) save_redraw_thread,
  2123.              (PTID) &save_redraw_id,(PBYTE) 
  2124.              (save_redraw_thread_stack+sizeof(save_redraw_thread_stack)));
  2125.     
  2126.             /* Start thread to keep screen in 640 x 480 x 16 VGA mode. */
  2127.             DosCreateThread((PFNTHREAD) mode_thread,
  2128.              (PTID) &mode_thread_stack,
  2129.              (PBYTE) (mode_thread_stack+sizeof(mode_thread_stack)));
  2130.           }
  2131.         VioScrUnLock((HVIO) 0);
  2132.       }
  2133.     return(result);
  2134.   }
  2135.  
  2136. static void set_initial_video_mode()
  2137.   {
  2138.     VioScrLock((USHORT) LOCKIO_WAIT,(PBYTE) &scr_lock,(HVIO) 0);
  2139.     VioSetMode((PVIOMODEINFO) &default_video_mode,(HVIO) 0);
  2140.     VioScrUnLock((HVIO) 0);
  2141.     hfree((void huge *) (video_plane[3]));
  2142.     hfree((void huge *) (video_plane[2]));
  2143.     hfree((void huge *) (video_plane[1]));
  2144.     hfree((void huge *) (video_plane[0]));
  2145.     return;
  2146.   }
  2147.  
  2148. static void set_pixel(x,y,color)
  2149.   int   x;
  2150.   int   y;
  2151.   short color;
  2152.     {
  2153.       int   bit_mask;
  2154.       char  *cell;
  2155.       int   dummy;
  2156.     
  2157.       VioScrLock((USHORT) LOCKIO_WAIT,(PBYTE) &scr_lock,(HVIO) 0);
  2158.       FP_SEG(cell)=VGA_base_adr;
  2159.       FP_OFF(cell)=y*80+x/8;
  2160.       bit_mask=0x80>>(x % 8);
  2161.       outp(VGA_control,VGA_bit_mask);
  2162.       outp(VGA_control_data,bit_mask);
  2163.       outp(VGA_control,VGA_mode);
  2164.       outp(VGA_control_data,2);
  2165.       dummy=*cell; 
  2166.       *cell=(char) color;
  2167.       outp(VGA_control,VGA_mode);
  2168.       outp(VGA_control_data,0);
  2169.       outp(VGA_control,VGA_bit_mask);
  2170.       outp(VGA_control_data,0xff);
  2171.       VioScrUnLock((HVIO) 0);
  2172.       return;
  2173.     }
  2174.  
  2175. static void save_redraw_thread()
  2176.   {
  2177.     long         *buffer;
  2178.     unsigned     count;
  2179.     long         dummy;
  2180.     VIOMODEINFO  mode_info; 
  2181.     int          plane_num;
  2182.     int          power_of_2;
  2183.     int          save_redraw_cmd;
  2184.  
  2185.     while (TRUE)
  2186.       {
  2187.         VioSavRedrawWait(VSRWI_SAVEANDREDRAW,&save_redraw_cmd,0);
  2188.         if (save_redraw_cmd == VSRWN_SAVE)
  2189.           {
  2190.             /* Save a copy of the screen mode. */
  2191.             mode_info.cb=sizeof(VIOMODEINFO);
  2192.             VioGetMode((PVIOMODEINFO) &mode_info,(HVIO) 0);
  2193.  
  2194.             /* Save the contents of the screen. */
  2195.             FP_SEG(buffer)=VGA_base_adr;
  2196.             for (plane_num=0; plane_num < 4; plane_num++)
  2197.               {
  2198.                 outp(VGA_control,VGA_read_map);
  2199.                 outp(VGA_control_data,plane_num);
  2200.                 for (count=0; count < NUM_CELLS; count+=4)
  2201.                   {
  2202.                     FP_OFF(buffer)=count;
  2203.                     (video_plane[plane_num])[count>>2]=*buffer;
  2204.                   }
  2205.               }
  2206.  
  2207.             outp(VGA_sequence,VGA_map_mask); 
  2208.             outp(VGA_sequence_data,0xff);
  2209.           }
  2210.         else
  2211.           {
  2212.             /* Restore the screen mode. */
  2213.             VioSetMode((PVIOMODEINFO) &mode_info,(HVIO) 0);
  2214.  
  2215.             /* Set the screen up for invisible restore. */
  2216.             VioSetState((PVOID) invisible_palette,(HVIO) 0);
  2217.  
  2218.             /* Reset the colors. */
  2219.             VioSetState((PVOID) &maze_color,(HVIO) 0);
  2220.  
  2221.             /* Restore the screen. */
  2222.             FP_SEG(buffer)=VGA_base_adr;
  2223.             power_of_2=1;
  2224.             for (plane_num=0; plane_num < 4; plane_num++)
  2225.               {
  2226.                 outp(VGA_sequence,VGA_map_mask);
  2227.                 outp(VGA_sequence_data,power_of_2);
  2228.                 for (count=0; count < NUM_CELLS; count+=4)
  2229.                   {
  2230.                     FP_OFF(buffer)=count;
  2231.                     dummy=*buffer;
  2232.                     *buffer=(video_plane[plane_num])[count>>2];
  2233.                   }
  2234.                 power_of_2*=2;
  2235.               }
  2236.  
  2237.             outp(VGA_sequence,VGA_map_mask);
  2238.             outp(VGA_sequence_data,0xff);
  2239.  
  2240.             /* Make the screen visible. */
  2241.             VioSetState((PVOID) maze_palette,(HVIO) 0);
  2242.           }
  2243.       }
  2244.     return;
  2245.   }
  2246.  
  2247. static void mode_thread()
  2248.   {
  2249.     USHORT mode_cmd;
  2250.  
  2251.     while (TRUE)
  2252.       {
  2253.         VioModeWait((USHORT) 0,(PUSHORT) &mode_cmd,(HVIO) 0);
  2254.         VioSetMode((PVIOMODEINFO) &maze_video_mode,(HVIO) 0);
  2255.       }
  2256.     return;
  2257.   }
  2258.