Category : Printer + Display Graphics
Archive   : MAZE1.ZIP
Filename : MAZE.C

 
Output of file : MAZE.C contained in archive : MAZE1.ZIP

/*==========================================================================*/
/* Maze generation program */
/* */
/* Thomas G. Ore */
/* 3615 Fawn Cove Lane, Apt #6 */
/* Portage, MI 49002 */
/* */
/* 1988 */
/*--------------------------------------------------------------------------*/
/* This program was developed using Turboc-1.5 on an IBM PS/2 Model 50 */
/*--------------------------------------------------------------------------*/
/* This maze program will generate random mazes either smaller than the */
/* screen, the full size of the screen, larger than the screen or a user */
/* specified size. The maze can be solved on screen or printed out. The */
/* printer codes used are for an Epson printer, however codes for another */
/* type of printer can easily be added. If the maze is solved on screen, */
/* the computer, the user, or both can be used to solve it. While the */
/* computer is working on a solution, it picks random directions to search. */
/* The only checks it does are not going down a known dead end path and not */
/* going backwards unless it reaches a dead end. */
/*==========================================================================*/
/* Modifications by J. L.Wargula 07-06-88 */
/* 760 Pilgrim Trail */
/* Sun Prairie, Wi 53590 */
/* using Turboc-1.5 on an CompuAdd Standard 286/10 */
/* Search comments for JLW to find modified sections. */
/* */
/* Modifications by Brian Alberts 01-18-89 */
/*BKA Added code to allow user to force screen mode of CGA (80x25) */
/*==========================================================================*/
#include "stdlib.h"
#include "conio.h"
#include "dos.h"
#include "stdio.h"
#include "time.h"

#define DEAD_END 177 /* Char. signaling a dead end */
#define FACE 1 /* The smiling face cursor */

int back(int); /* Ret. opp. direct. from input */
void build_maze(void); /* Convert the tree to a maze */
void build_tree(void); /* Build the tree structure */
void deltas(int num,int *xstp,int *ystp); /* Sets the move deltas */
void footer(int num); /* Prints the footer line */
void get_option(void); /* Get the maze size option */
void goto_xy(int x,int y); /* Move the cursor */
int inkey(int *scan); /* Get a keystroke */
void init(void); /* Initialize the maze */
void refresh(void); /* Draws the maze to the screen */
int solve_maze(void); /* Solve the maze */
void solv_time(unsigned long int init_time);/* Calc's maze solve time */
void split_screen(void); /* Sets 43 or 50 line mode */
void textmode(int mode_code); /* sets text mode */
void trace_path(void); /* Trace the tree */
int user_int(int num); /* User interface while solving */
int video_card(int *max_col,int *max_row); /* Goofy routine to get adapter */

/*............................ Global variables ............................*/

int *path,*trail,*maze; /* These are storage pointers */
int nrow,ncol; /* These are for *path & *trail */
int num_row,num_col; /* These are for *maze */
int wall_col=2,path_col=3,solv_col=15; /* Set the initial colors */
int curscol=15; /* The cursor color */
char solver='C'; /* 'C' or 'M' for solve type */
char PRINTER; /* 'E'pson 'P'ro etc... JLW */
int min_row,min_col; /* Maze uppr left display corner*/
int max_row,max_col; /* Screen lowr rgt display limit*/
int startup; /* For starting up */
int delr,delc; /* Centers the maze on screen */
FILE *outFile; /* For printing to printer */
int EGA=0, VGA=0, CGA=0; /* Adapter types JLW */

/*.............................. Main routine ..............................*/

int main(argc, argv) /* command-line opts by JLW */
int argc;
char *argv[];
{
unsigned long int init_time; /* Maze solve time */
int exit_key; /* The exit status flag */
int card_type; /* The video mode (card) */
char ch;
int force_CGA_mode = 0; /* force CGA switch BKA */

ch=*argv[1];
if (argc>1) switch(ch) { /* command-line options by JLW */
case 'H': /* help */
case 'h': /* help */
case '?': /* help */
printf("Usage is MAZE x \n");
printf(" where x = E for wide carriage LQ Epson\n");
printf(" e for narrow carriage LQ Epson\n");
printf(" P for wide carriage Draft IBM Proprinter\n");
printf(" p for narrow carriage Draft IBM Proprinter (the default)\n\n");
printf(" c for force normal CGA screen size (80x25 lines).\n");
return(0); /* out */
case 'E':
case 'e':
case 'P':
PRINTER=ch;
break;
case 'p':
default:
PRINTER='p';
break;
case 'c':
case 'C':
force_CGA_mode = 1 ;
break ;
}
else PRINTER='p';
srand(time(0)); /* Initialize the random # gen. */

total_restart:
startup=1; /* First time through */
nrow=5; ncol=8; /* Use this for startup only */

card_type=video_card(&max_col,&max_row); /* Get card type */
if(card_type>18) VGA=1; /* record it JLW */
else if(card_type>15) EGA=1; /* JLW */
else CGA=1; /* JLW */
/* BKA Patch by Brian Alberts to force CGA */
if ( force_CGA_mode ) {
card_type = 3 ;
textmode( card_type );
VGA = 0 ; EGA = 0 ; CGA = 1;
max_col = 80 ;
max_row = 25 - 3;
}


start_here: /* Go here to start after intro */
if(card_type!=0) textmode(3); /* Set normal mode */
else textmode(0); /* Use this if we have to */

if(max_row>25)split_screen(); /* Set to split screen mode */

if (max_col==80)
goto_xy((max_col-50)/2,1); /* added JLW */
else goto_xy(1,1);
printf("- Thomas G. Ore's SuperMaze 1988 Version 2.1 -");

if(solver=='M') footer(1); /* Print the footer line */
else if(startup==0) footer(2);
else footer(3);

resize_here: /* Go here to start new maze */
num_col=2*ncol+3; num_row=2*nrow+3; /* Set the maze dimensions */

/*........................... Allocate the memory ..........................*/
/* */
/* The entire maze is stored in dynamically allocated memory. Two bytes */
/* are needed at each position to store the character and the color. Thus */
/* the path, trail and maze are integer pointers. */
/* */
/*..........................................................................*/

path=(int *)calloc((nrow+1)*(ncol+1),sizeof(int));
trail=(int *)calloc((nrow+1)*(ncol+1),sizeof(int));
maze=(int *)calloc((num_row+1)*(num_col+1),sizeof(int));
if(path==NULL||trail==NULL||maze==NULL) { /* Check for NULL pointers */
/*** BKA clrscr(); ***/ textmode(0); /* Clear the screen */
goto_xy((max_col-26)/2,(max_row-2)/2); /* Write out a warning */
printf("Failed to allocate memory.");
goto_xy((max_col-26)/2,(max_row-2)/2+1);
printf("Restart with smaller maze.");
getch(); /* Wait for keyboard input */
goto total_restart; /* Do a total restart */
}

/*......... Start through the routines and keep solving the maze ..........*/

for(;;) {
init(); /* Initialize the arrays */
build_tree(); /* Build the tree */
trace_path(); /* Trace through the tree */
build_maze(); /* Build the maze */
init_time=time(0); /* Store the starting time */
exit_key=solve_maze(); /* Solve the maze */

if(!exit_key&&!startup)solv_time(init_time); /* Print the solution time */
else if(exit_key==1||exit_key==2) /* User said to exit */
goto exit_here;
else if(exit_key==3) { /* Pick new maze size */
startup=1;
goto exit_here;
}

do { /* Pick a new path color */
path_col=rand()/4096+9; /* */
} while(path_col>14); /* And don't go above 14 */
do { /* Pick a new wall color */
wall_col=rand()/4096+2; /* */
} while(wall_col>7); /* And don't go above 7 */
if(solver=='C'&&startup==0) { /* For computer solved */
exit_key=2;
goto exit_here;
}
} /* End of infinite loop */

/*............... Exit here when through solving the maze ..................*/

exit_here:
if(maze!=0)free(maze); /* Free the memory */
if(trail!=0)free(trail);
if(path!=0)free(path);

/*......................... If we are not leaving ..........................*/

if(exit_key!=1) { /* We are not quitting */
get_option(); /* Find out what to do next */
if(startup==1) { /* Do this first time through */
startup=0;
goto start_here;
}
else goto resize_here;
}
textmode(3); /* Set screen mode for exiting */
return(0);
} /* End of program */
/*--------------------------------------------------------------------------*/
/* Initialize the variables */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* The maze is constructed by using three dynamically allocated arrays. The*/
/* path and trail contain the tree which defines the maze. The path is the */
/* forward direction and the trail is the backward direction. The maze */
/* array is twice as large as the path and trail arrays because it must have*/
/* room the the maze path and the walls in between. The path and trail */
/* arrays are initialized to zero and the maze array is initialized to a */
/* checker board pattern with character 32 being the space and character 33 */
/* being the wall. */
/*--------------------------------------------------------------------------*/
void init()
{
register int i,j;

min_row=min_col=1; /* Set the minimum row and col */

if(num_row-1 delr=(max_row-num_row+2)/2.; /* if it is smaller than the */
else delr=0; /* display screen */
if(num_col-1 delc=(max_col-num_col+2)/2.;
else delc=0;

for(i=0;i for(j=0;j *(path+i*ncol+j)=*(trail+i*ncol+j)=0;
}

for(i=1;i for(j=1;j *(maze+i*num_col+j)=33;
*(maze+i*num_col)=32; /* Blank out the outer edges */
*(maze+(i+1)*num_col-1)=32;
}
for(j=0;j<=num_col;j++) { /* Blank out the top & bottom */
*(maze+j)=32;
*(maze+(num_row-1)*num_col+j)=32;
}
for(i=2;i for(j=2;j *(maze+i*num_col+j)=32;
}
}
/*--------------------------------------------------------------------------*/
/* The first step is to create a tree structure defining the path */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* The tree structure ensures that the maze is completely filled and that */
/* there is alwalys one and only one solution through the maze. The tree */
/* is started int the lower right corner and wanders aimlessly around. The */
/* path is not allowed to cross over itself, go outside the confines of the */
/* rectangle or go backwards down it's own path. When it reaches a dead */
/* end (no valid moves), it backtracks until a valid move is available. */
/* The tree is built by continuing to wander and backtrack until it returns */
/* to the starting point. When this occurs the maze is completely defined. */
/*--------------------------------------------------------------------------*/
void build_tree()
{
int x,y,xstp,ystp; /* These define current position*/
int num,num_old=0; /* This is the move direction */
int i,j; /* These define new position */
int bkwd=0; /* This is the backtracking flag*/
static int ntry[5]={0,0,0,0,0}; /* This tracks invalid moves */

x=nrow-1; y=ncol-1; /* Set the initial position */

for(;;) { /* Enter an infinite loop */
if(bkwd==0)*(trail+x*ncol+y)=num_old; /* Keep track of our path */
do { /* Get number between 1 and 4 */
num=rand()/8192+1;
} while(num==num_old); /* Don't go backwards */

deltas(num,&xstp,&ystp); /* Get the deltas */
i=x+xstp; j=y+ystp; /* Set the new position */

/*......... Don't move outside limits, or cross over our path ..............*/

if(i<0||i>=nrow||j<0||j>=ncol||*(path+i*ncol+j)>0) {
ntry[num]=1; /* Keep track of bad direction */
if((ntry[1]+ntry[2]+ntry[3]+ntry[4])==4) {/* We are at a dead end */
for(i=1;i<=4;i++)ntry[i]=0; /* Reset check */
if(bkwd==0)*(path+x*ncol+y)=5; /* Set mark at dead end */
bkwd=1; /* Set backtracking flag */
num=*(trail+x*ncol+y); /* This is backward direction */
if(num==0)return; /* We are finished with the maze*/

deltas(num,&xstp,&ystp); /* Get the deltas */
x+=xstp; y+=ystp; /* Set the new position */

num_old=back(num); /* Set the old direction */
ntry[num_old]=1; /* Can't go back., so set flag */
}
}

/*............................ Was a valid move ............................*/

else {
*(path+x*ncol+y)=num; /* Set the path direction */
bkwd=0; /* Reset the backtracking flag */
num_old=back(num); /* num_old is opposite num */
y=j; x=i; /* Set the new position */
for(i=1;i<=4;i++)ntry[i]=0; /* Reset check */
ntry[num_old]=1; /* Can't go back., so set flag */
}
}
}
/*--------------------------------------------------------------------------*/
/* The second step is to trace path through the maze array */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* The walls of the maze are constructed by tracing every dead end (a 5) */
/* all the wall to the begining of the maze (a 0). The maze is formed by */
/* punching through the checker board pattern where there should be a path. */
/*--------------------------------------------------------------------------*/
void trace_path()
{
register int i,j;
int x,y,xstp,ystp;

for(i=0;i for(j=0;j if(*(path+i*ncol+j)==5) { /* Found a dead end */
x=i; y=j; /* Set the position */
do { /* Trace backwards through loop */
deltas(*(trail+x*ncol+y),&xstp,&ystp); /* Get the deltas */
*(trail+x*ncol+y)=0; /* Set trail to zero */
*(maze+(2*(x+1)+xstp)*num_col+2*(y+1)+ystp)=32;/* Set maze to zero*/
x+=xstp; y+=ystp; /* Set the position */
} while(*(trail+x*ncol+y)>0); /* Stop when no more trail */
}
}
}
*(maze+1*num_col+2)=32; /* This is the start */
*(maze+(num_row-2)*num_col+(num_col-3))=32; /* This is the end */
}
/*--------------------------------------------------------------------------*/
/* The third step is to convert the maze to maze characters */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* The maze is converted into a printable pattern by stopping at each wall */
/* character (>32) and checking the four adjacent wall characters. The */
/* wall character being defined is determined by looking up the character in*/
/* the walls array. */
/*--------------------------------------------------------------------------*/
void build_maze()
{
register int i,j;
static int walls[]={32,198,208,200,181,205,188,202,210,201,186,204,187,203,185,206};
int sum;

for(i=1;i for(j=1;j sum=0;
if(*(maze+i*num_col+j)>32) { /* We are on a part of the wall */
if(*(maze+i*num_col+j+1)>32)sum+=1;
if(*(maze+(i-1)*num_col+j)>32)sum+=2;
if(*(maze+i*num_col+j-1)>32)sum+=4;
if(*(maze+(i+1)*num_col+j)>32)sum+=8;
}
*(maze+i*num_col+j)=walls[sum]; /* Set the wall character */
}
}

for(i=1;i<=num_row;i++) /* Go through entire array */
for(j=1;j<=num_col;j++) *(maze+i*num_col+j)+=(wall_col<<8);

for(i=0;i<=num_row;i++) *(maze+i*num_col)=DEAD_END+(solv_col<<8);
for(i=0;i<=num_row;i++) *(maze+(i+1)*num_col-1)=DEAD_END+(solv_col<<8);
for(i=0;i<=num_col;i++) *(maze+i)=DEAD_END+(solv_col<<8);
for(i=0;i<=num_col;i++) *(maze+num_row*num_col+i)=DEAD_END+(solv_col<<8);
}
/*--------------------------------------------------------------------------*/
/* The final step is to solve the maze */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* The maze is solved by starting at the begining and randomly searching */
/* until it finds the exit. The computer will search unless any key is */
/* hit. When this happens, a menu is popped up to allow the user to make */
/* some choices. While the computer is searching, it keeps track of dead */
/* ends and doesn't backtrack unless it reaches a dead end. */
/*--------------------------------------------------------------------------*/
int solve_maze()
{
int far *ptr=(int far *) 0xB8000000; /* For direct video writing */
int x,y,xstp,ystp;
int i_was_here;
int num_old,num,sum=0;
int test_val,col;

i_was_here=DEAD_END+(solv_col<<8);
x=1; y=2; /* Start at upper left opening */
num_old=0; /* Set the old direction */
refresh(); /* Draw the maze */

for(;;) { /* Start an infinite loop */

if(kbhit()) { /* If any key hit */
getch(); /* Get the key with no echo */
solver='M'; /* Return to manual solve */
if(startup!=1)footer(1);
else return(2); /* Jump out if this is startup */
}

*(maze+x*num_col+y)=FACE+(curscol<<8); /* Place the cursor */
*(ptr+(x-min_row+1+delr)*max_col+(y-min_col+delc))=FACE+(curscol<<8);

do {
num=rand()/8192+1; /* Pick a random number (1 to 4)*/
} while(num==num_old); /* Don't go backwards */

if(solver=='M'&&(i_was_here&255)<=32&&(sum>2||(sum==2&&num_old==0))) {
num=user_int(num);
while(min_row>x)min_row--; /* May have to reset screen */
while(min_row+max_row-1 while(min_col>y)min_col--;
while(min_col+max_col-1 refresh();
}

if(num==0)return(1); /* User said to exit */
if(num==-1)return(3); /* User said to resize */

deltas(num,&xstp,&ystp); /* Get the deltas */
test_val=*(maze+(x+xstp)*num_col+(y+ystp));

/*. . . . . . . . . . . . . The new space is okay. . . . . . . . . . . . . .*/

if((test_val&255)<=32) {
*(maze+x*num_col+y)=i_was_here; /* Update the array */
*(ptr+(x-min_row+1+delr)*max_col+(y-min_col+delc))=i_was_here;

num_old=back(num); /* Keep track of our move */
x+=xstp; y+=ystp;

if(x==min_row&&min_row>0)min_row--; /* Set the minimums */
else if(x>min_row+max_row-2)min_row++;
else if(y==min_col&&min_col>0)min_col--;
else if(y>min_col+78)min_col++;
else goto jump;
refresh(); /* Only refresh for min change */

jump:
sum=0; /* Find number of valid moves */
if((*(maze+x*num_col+y+1)&255)<=32)sum+=1;
if((*(maze+(x-1)*num_col+y)&255)<=32)sum+=1;
if((*(maze+x*num_col+y-1)&255)<=32)sum+=1;
if((*(maze+(x+1)*num_col+y)&255)<=32)sum+=1;

if(sum>1) { /* We have more than one choice */
if((i_was_here&255)==DEAD_END)num_old=0;
i_was_here=num+23+(path_col<<8);
if((*(maze+(x-xstp)*num_col+y-ystp)&255)!=DEAD_END) {
*(maze+(x-xstp)*num_col+y-ystp)=i_was_here;
*(ptr+(x-xstp-min_row+1+delr)*max_col+(y-ystp-min_col+delc))=
i_was_here;
}
}
else if(sum==1){ /* There is just one move */
if((*(maze+x*num_col+y+1)>>8)==solv_col)col=solv_col;
else if((*(maze+(x-1)*num_col+y)>>8)==solv_col)col=solv_col;
else if((*(maze+x*num_col+y-1)>>8)==solv_col)col=solv_col;
else if((*(maze+(x+1)*num_col+y)>>8)==solv_col)col=solv_col;
else col=path_col;
i_was_here=DEAD_END+(col<<8);
num_old=0;
}

if(x==num_row-2&&y==num_col-3)return(0); /* FOUND OUR WAY OUT!!! */
} /* End of if-else */
} /* End of infinite loop */
}
/*--------------------------------------------------------------------------*/
/* This routine puts the maze into screen memory */
/*--------------------------------------------------------------------------*/
void refresh()
{
int far *ptr=(int far *) 0xB8000000;
register int i,j,index,index1;
int row_end,col_end;

if(num_row-1 else row_end=max_row;
if(num_col-1 else col_end=max_col;

for(i=0;i index=(i+1+delr)*max_col+delc;
index1=(i+min_row)*num_col+min_col;
for(j=0;j *(ptr+index)=*(maze+index1);
}
}
/*--------------------------------------------------------------------------*/
/* This function returns the backward direction */
/*--------------------------------------------------------------------------*/
int back(num)
int num;
{
if(num==1||num==3)return(num+1);
else return(num-1);
}
/*--------------------------------------------------------------------------*/
/* This function returns the x and y deltas */
/*--------------------------------------------------------------------------*/
void deltas(num,xstp,ystp)
int num;
int *xstp,*ystp;
{
switch (num) { /* Set deltas for direction num */
case 1: *xstp=-1; *ystp= 0; break; /* Up */
case 2: *xstp= 1; *ystp= 0; break; /* Down */
case 3: *xstp= 0; *ystp= 1; break; /* Right */
case 4: *xstp= 0; *ystp=-1; break; /* Left */
}
}
/*--------------------------------------------------------------------------*/
/* This routine does the user interface while solving */
/*--------------------------------------------------------------------------*/
int user_int(int num)
{
int keycode,scan;
int i,j,c;

top:
keycode=inkey(&scan); /* Get the key with no echo */
if(!keycode) switch (scan) {
case 75: num=4; break; /* left */
case 77: num=3; break; /* right */
case 72: num=1; break; /* up */
case 80: num=2; break; /* down */
case 59: /* F1 - Switch to computer solve*/
solver='C';
footer(2);
break;
case 60: /* F2 - Shift the screen */
footer(4);
for(;;) {
keycode=inkey(&scan);
if(!keycode) switch (scan) {
case 75: if(min_col case 77: if(min_col>1)min_col--; refresh(); break;
case 72: if(min_row case 80: if(min_row>1)min_row--; refresh(); break;
}
else {
footer(1);
goto top;
}
}
case 61: return(-1); /* F3 - Exit to resize */
case 62: /* F4 - Print the maze */
outFile=fopen("PRN","wt");
biosprint(1, 0, 0); /* Initialize the printer JLW */

if (PRINTER=='E') /* Epson wide carriage */
{ /* original code for Epson */
fprintf(outFile,"%c%c",27,64); /* Initialize the printer */
fprintf(outFile,"%c%c%c",27,120,1); /* Select LQ mode */
fprintf(outFile,"%c%c%c",27,107,0); /* Select Typestyle */
fprintf(outFile,"%c%c%c",27,116,1); /* Select graphics characters */
if(num_col> 156)
fprintf(outFile,"%c%c",27,103); /* Select 15 cpi */
else if(num_col> 132)
fprintf(outFile,"%c%c",27,77); /* Select 12 cpi */
else if(num_col<= 132)
fprintf(outFile,"%c%c",27,80); /* Select 10 cpi */
else {
fclose(outFile);
break;
}
}
if (PRINTER=='e') /* Epson narrow carriage JLW */
{ /* added code for Epson: JLW */
fprintf(outFile,"%c%c",27,64); /* Initialize the printer */
fprintf(outFile,"%c%c%c",27,120,1); /* Select LQ mode */
fprintf(outFile,"%c%c%c",27,107,0); /* Select Typestyle */
fprintf(outFile,"%c%c%c",27,116,1); /* Select graphics characters */
if(num_col> 96)
fprintf(outFile,"%c%c",27,103); /* Select 15 cpi */
else if(num_col> 80)
fprintf(outFile,"%c%c",27,77); /* Select 12 cpi */
else if(num_col<= 80)
fprintf(outFile,"%c%c",27,80); /* Select 10 cpi */
else {
fclose(outFile);
break;
}
}
if (PRINTER=='P') /* IBMproprinter wide carriage */
{ /* added printer JLW draft */
if(num_col> 156)
fprintf(outFile,"%c",15); /* Select 17 cpi */
else if(num_col> 132)
fprintf(outFile,"%c%c",27,58); /* Select 12 cpi */
else if(num_col<= 132)
fprintf(outFile,"%c",18); /* Select 10 cpi */
else {
fclose(outFile);
break;
}
fprintf(outFile,"%c%c",27,48); /* Select 8-lines/inch */
}
if (PRINTER=='p') /* IBMproprinter narrow carriage*/
{ /* added printer JLW draft */
if(num_col> 96)
fprintf(outFile,"%c",15); /* Select 17 cpi */
else if(num_col> 80)
fprintf(outFile,"%c%c",27,58); /* Select 12 cpi */
else if(num_col<= 80)
fprintf(outFile,"%c",18); /* Select 10 cpi */
else {
fclose(outFile);
break;
}
fprintf(outFile,"%c%c",27,48); /* Select 8-lines/inch */
}
for(i=0;i for(j=0;j c=(*(maze+i*num_col+j)&255);
if(c>32&&c!=DEAD_END) fprintf(outFile,"%c",c);
else fprintf(outFile,"%c",32);
}
fprintf(outFile,"\n");
}
fclose(outFile);
break;
case 63: return(0); /* Exit to quit to DOS */
}
return(num);
}
/*--------------------------------------------------------------------------*/
/* This function prints the maze solve times */
/*--------------------------------------------------------------------------*/
void solv_time(unsigned long int init_time)
{
int this_time;
static unsigned int min_time=999,max_time=0,avg_time=0,counter=0;

this_time=(int)(time(0)-init_time); /* Calculate the solve time */

if(this_time if(this_time>max_time)max_time=this_time;
avg_time+=this_time; /* Calculate the avgerage time */
counter+=1;
goto_xy(1,max_row+3);
printf("TIME%5d AVG%5d MIN%5d MAX%5d", /* Print the times */
this_time,avg_time/counter,min_time,max_time);
if(num_col>40)printf(" NUMBER%5d",counter);
}
/*--------------------------------------------------------------------------*/
/* This function prints the footers */
/*--------------------------------------------------------------------------*/
void footer(int num)
{
goto_xy(1,max_row+2);
switch (num) {
case 1:
cprintf("F1-Auto F2-Shift F3-New F4-Print F5-End");
break;
case 2:
cprintf("Hit any key to return to manual solve...");
break;
case 3:
goto_xy((max_col-23)/2,max_row+2);
cprintf("Hit any key to start...");
goto_xy((max_col-49)/2,max_row-1); /* added JLW */
cprintf("2.1 Version updates by J.L.Wargula and B. Alberts"); /* added JLW */
goto_xy((max_col-36)/2,max_row); /* added JLW */
cprintf("Enter Maze H to list printer options"); /* added JLW */
break;
case 4:
cprintf("Use arrows to shift, then hit space bar ");
break;
}
goto_xy(1,1);
}
/*--------------------------------------------------------------------------*/
/* Set to split screen - mode 43 or 50 lines */
/*--------------------------------------------------------------------------*/
void split_screen()
{
union REGS r;

r.x.ax=0x1112;
r.h.bl=0;
int86(0x10,&r,&r);
}
/*--------------------------------------------------------------------------*/
/* Set the video mode */
/*--------------------------------------------------------------------------*/
void textmode(int mode_code)
{
union REGS r;

r.h.ah=0;
r.h.al=mode_code;
int86(0x10, &r, &r);
}
/*--------------------------------------------------------------------------*/
/* From 'C - The Complete Reference', by Herbert Schildt */
/*--------------------------------------------------------------------------*/
void goto_xy(int x,int y)
{
union REGS r;

r.h.ah=2;
r.h.dl=x-1; /* Subtract one to allow Turbo C*/
r.h.dh=y-1; /* addressing. The Turbo C 1.5 */
r.h.bh=0; /* gotoxy routine apparently */
int86(0x10, &r, &r); /* doesn't allow 43 or 50 lines */
}
/*--------------------------------------------------------------------------*/
/* Read the scan code */
/*--------------------------------------------------------------------------*/
int inkey(int *scan)
{
union REGS r;

r.h.ah=0;
int86(0x16, &r, &r);
if(!r.h.al) {
*scan=r.h.ah;
return(0);
}
else {
*scan=r.h.al;
return(1);
}
}
/*--------------------------------------------------------------------------*/
/* Get the video card type */
/*--------------------------------------------------------------------------*/
int video_card(int *max_col,int *max_row)
{
union REGS r;

textmode(0);
textmode(3);
textmode(16);
textmode(18);

r.h.ah=15; /* Get the mode set */
r.h.al=50;
int86(0x10, &r, &r);

*max_col=r.h.ah; /* This is number of columns */

if(r.h.al>18) *max_row=46; /* VGA */
else if(r.h.al>=16) *max_row=40; /* EGA */
else *max_row=22; /* CGA -code by JLW */


return(r.h.al); /* Return the mode */
}
/*--------------------------------------------------------------------------*/
/* Get the maze option */
/*--------------------------------------------------------------------------*/
void get_option(void)
{
int divisor;
int keycode,scan; /* Used for when reading a key */
static int maze_size; /* Flag to indicated maze size */

if(startup==1) {
goto_xy((max_col-28)/2,(max_row-7)/2);
printf(" ");
goto_xy((max_col-28)/2,(max_row-7)/2+1);
printf(" 1 - Variable small mazes ");
goto_xy((max_col-28)/2,(max_row-7)/2+2);
printf(" 2 - Full screen maze ");
goto_xy((max_col-28)/2,(max_row-7)/2+3);
printf(" 3 - Variable large mazes ");
goto_xy((max_col-28)/2,(max_row-7)/2+4);
printf(" 4 - User specified mazes ");
goto_xy((max_col-28)/2,(max_row-7)/2+5);
printf(" 5 - Exit to DOS ");
goto_xy((max_col-28)/2,(max_row-7)/2+6);
printf(" ");
do { /* Get the maze size code */
keycode=inkey(&scan);
} while(keycode==0||scan<49||scan>53); /* Don't use bad keys */
maze_size=scan-48; /* Make it 1 to 4 */
}
switch(maze_size) {
case 1: /* Variable small maze */
nrow=rand()/2000+5;
ncol=rand()/1200+8;
break;
case 2: /* Full maze */
if (VGA) nrow=21; /* if logic added by JLW VGA */
else if (EGA) nrow=19; /* added by JLW EGA */
else nrow=10; /* added by JLW CGA */
ncol=38;
break;
case 3: /* Variable large */
divisor=rand()/16383+1; /* Weight to get more small ones*/
nrow=rand()/512/divisor+10;
ncol=rand()/256/divisor+10;
break;
case 4: /* Size is read from user */
goto_xy(1,2);
printf("Enter maze size (rows cols): "); /* remove comma JLW */
scanf("%d %d",&num_row,&num_col);
nrow=(num_row-3)/2; /* Edit the # of rows */
if(nrow<5)nrow=5;
ncol=(num_col-3)/2; /* Edit the # of cols */
if(ncol<5)ncol=5;
break;
default: /* Exit */
textmode(3);
exit(0);
}
}