home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////
- // Title: Dfid.c 25jun91/bm //
- // by: Bob McIsaac //
- ///////////////////////////////////////////////////////////////
- //
- #include <bios.h>
- #include <conio.h>
- //nclude <fcntl.h>
- #include <graph.h>
- //nclude <io.h>
- #include <malloc.h>
- #include <memory.h>
- #include <process.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- //nclude <sys\types.h>
- //nclude <sys\stat.h>
- #include <time.h>
- #define HASH_SIZE 161 // primary hash table size
- #define YES 1
- #define NO 0
- #define INVALID -1
- #define PW 4 // puzzle width
- #define PSIZE PW * PW // puzzle size
- #define POLES 4 // North,South,East,West
- #define HOLE '-' // place to move into
- #define FORWARD 0
- #define REVERSE1 1
- #define REVERSE2 2
- // solution types
- #define StoG 1 // if goal on down search
- #define GtoS 2 // if goal on 1st up search
- #define GtoS_COM 3 // if common node on up search
- #define GtoS_K1 4 // if goal on 2nd up search
- #define GtoS_K1_COM 5 // if common node on 2nd up search
-
- #define SetPos(Row,Col) _asm \
- { _asm mov ah,02h _asm mov bh,00h \
- _asm mov dh,Row _asm mov dl,Col _asm int 10h \
- }
-
- typedef struct lnode *NPTR; // node pointer
- struct lnode
- { NPTR Next; // pointer to next node
- int Num; // node number
- char *Dptr; // pointer to data store
- } ; // : use cast if not char
-
- typedef struct
- { unsigned int
- Gn, // cost from source to n
- Hn, // estimated cost to goal
- Dad; // nodenum of parent node
- char Puz[PSIZE+1]; // string representation of puzzle
- } PUZZLE ;
- //
- // global variables
- PUZZLE Goal; // the ultimate Target
- PUZZLE Source; // the input pattern
- PUZZLE Choice; // the best one to reach goal
- PUZZLE Tries[POLES]; // temporary expansions
- NPTR FreePuzzles; // list of spare puzzle nodes
- NPTR Closed; // list of puzzles already tried
- NPTR Open; // list of puzzles to be evaluated
- NPTR DownData; // puzzles saved from kth level S->G
- NPTR CommonNode; // needed for solution path;
- NPTR Known[HASH_SIZE]; // hashed list of known puzzles
- NPTR D_Dat[HASH_SIZE]; // hashed list of level k S->G
- char *Gp; // the current goal
- time_t Time1, Time2; // timer variables
- unsigned long
- ExpDown, // count of nodes expanded S to G
- ExpUp, // count of nodes expanded G go S
- Moves; // count of expansions attempted
- unsigned int
- Depth, // maximum depth of current search
- Level, // current position in a Dfs
- DownDepth, // how far from S->G
- UpDepth, // how far from G->S
- NodeNum; // count of linked nodes in use
- int Success; // set if goal with solution type
- int Direction; // move from goal to source if != 0
- int Pausing; // pause and test for quit
- int Listing; // show open & closed lists
- int Puz_Show; // show puzzles
- int ResultInFile; // save closed in file
- FILE *Fp; // data file pointer
- int JmpDistance[] = { -PW, // offset to North
- +PW, // offset to South
- +1, // offset to East
- -1 }; // offset to West
- int ValidJmps[] = { 0x6,0xE,0xE,0xA, // direction masks
- 0x7,0xF,0xF,0xB, // for move rules
- 0x7,0xF,0xF,0xB,
- 0x5,0xD,0xD,0x9 };
- //
- // function prototypes
- int BiDfid ( void );
- int CharPos ( char *Px, int ch );
- void ClearStates ( int All );
- int Dfs ( PUZZLE *Px );
- NPTR DfsOpen ( PUZZLE *Pz );
- int DrawSym ( int Row, int Col, char *Pz );
- NPTR DropPuzzles ( NPTR Head );
- void DropTable ( NPTR *Table, int Size );
- NPTR FindPuzLink ( NPTR Pos, char *Px );
- int Generate ( NPTR Link );
- int IfExistPuz ( char *Pz );
- void KeyWait ( void );
- void ListInFile ( NPTR Head, int Level );
- int MakeKey ( char *Pz );
- NPTR MakePuzNode ( PUZZLE *Pz );
- void MakeTextRoom ( void );
- int MatchBottom ( void );
- void NoRoom ( void );
- void ReleasePuzzles ( void );
- void SaveDownData ( void );
- void ShowHow ( void );
- void ShowList ( NPTR Link );
- void ShowListStep ( void );
- int ShowMoves ( void );
- void ShowTable ( NPTR *Table, int Size );
- void ShowSuccess ( int Success );
- void Statistics ( void );
- int TestKey ( void );
- #include "Linked.c" //
- ///////////////////////////////////////////////////////////////
- // *** MAIN ***
- //
- void main( int argc, char *argv[] )
- {
- char *Sptr, *Lptr;
- int i, bpos, Done, ch;
- NPTR L1, L2;
- PUZZLE *Px, *Py;
- _clearscreen(0);
- if( strlen(argv[1]) != PSIZE )
- ShowHow(); // trap puzzle error
- memcpy( Source.Puz, argv[1], PSIZE );
- Source.Puz[PSIZE]=0;
- strcpy( Source.Puz, strupr( Source.Puz ) );
- strcpy( Goal.Puz, "123456789ABCDEF-" );
- Goal.Gn = Goal.Hn = Source.Gn = Source.Hn = 0;
- NodeNum=0;
- FreePuzzles = FreeHead = NULL;
- Fp = NULL; // data file
- DownData = Open = Closed = NULL;
- Time1 = Time2 = 0;
- for( i=0; i<POLES; i++ )
- {
- Tries[i].Gn = Tries[i].Hn = INVALID ;
- }
- for( i=0; i<HASH_SIZE; i++ )
- {
- Known[i] = NULL; // puzzles on open & closed
- D_Dat[i] = NULL; // puzzles at depth bound only
- }
- memset( Choice.Puz, HOLE, PSIZE );
- time( &Time1 ); // start timer
- ShowMoves();
- // MakeTextRoom();
- printf("\nSource= %s ** %s **",argv[1],argv[2]);
- printf("\n Solve this puzzle <*/N>");
- if( toupper(getch()) =='N' ) exit(0);
- //
- Pausing=NO;
- printf("\n1. Display Puzzles");
- printf("\n2. Display Lists");
- printf("\n3. Save Result in file..BmResult");
- printf("\n0. Display Nothing");
- ch = getch();
- Puz_Show = ( ch=='1');
- Listing = ( ch=='2');
- ResultInFile = ( ch=='3');
- if( ResultInFile )
- {
- if(( Fp = fopen( "BMresult.tmp","w" )) == NULL )
- {
- printf(" ** file open error ** ");
- KeyWait();
- exit(0);
- }
- else
- printf("\nSolution File BMresult.tmp is open..");
- }
- if( !ResultInFile && Listing||Puz_Show )
- {
- printf("\nPause while displaying 1=yes 0=no");
- Pausing = ( getch()=='1' );
- }
- _clearscreen(0);
- Choice = Source;
- memset( Choice.Puz, HOLE, PSIZE );
- time( &Time1 ); // start timer
- CommonNode=NULL;
- ShowMoves();
- cputs("\n..busy..");
- Success = BiDfid(); // ...search...
- time( &Time2 ); // completion time
- //
- ShowMoves();
- MakeTextRoom();
- Statistics();
- ShowSuccess( Success );
- KeyWait();
- //
- if( Fp != NULL )
- fprintf(Fp,"\nSource= %s ** %s **",argv[1],argv[2]);
- i = ( Success == StoG || Success == GtoS || Success == GtoS_K1 );
- if( Fp != NULL && i )
- {
- fprintf(Fp,"\n..Final Closed List..");
- fprintf(Fp,"\n..Trace solution path backwards to source..");
- ShowList( Closed );
- }
- i = ( Success == GtoS_COM || Success == GtoS_K1_COM );
- if( Fp != NULL && i && CommonNode != NULL )
- {
- PUZZLE *Px = (PUZZLE*)CommonNode->Dptr;
- NPTR Link = FindPuzLink( DownData, Px->Puz );
- if( Link != NULL )
- {
- fprintf(Fp,"\n..Final Closed List..");
- fprintf(Fp,"\n..Trace path backwards to source.. %s",Source.Puz);
- fprintf(Fp,"\n..from common node %d %s",Link->Num,Px->Puz );
- ShowList( DownData );
- Link = FindPuzLink( Closed, Px->Puz );
- fprintf(Fp,"\n..Trace path backwards to goal.. %s",Goal.Puz);
- fprintf(Fp,"\n..from common node %d %s",Link->Num,Px->Puz );
- ShowList( Closed );
- }
- }
- ClearStates(1);
- ReleasePuzzles(); // make room for shell to dos
- if( Fp != NULL )
- { // use external full screen viewer to scan solution
- fclose( Fp );
- system("List BMresult.tmp");
- }
- exit(0);
- }//
- ///////////////////////////////////////////////////////////////
- int BiDfid( void )
- // Bidirectional depth first search with iterative deepening
- // return solution type: goal hit or common node w/ direction
- // GLOBALS: Known[],Depth,Success
- {
-
- int Solution = NO;
- Depth = 1;
- Success=NO;
- ExpDown = ExpUp = 0L; // no expansions yet
- while( !Success && Depth>0 )
- {
- Direction = FORWARD;
- DownDepth=Depth;
- Gp = Goal.Puz; // goal = actual goal
- Solution = StoG; // source to goal ?
- Success = Dfs( &Source );
- if( !Success )
- {
- SaveDownData(); // keep S->G bottom level
- ClearStates(0); // clear states except boundary
- Gp = Source.Puz; // goal is actual source
- Direction=REVERSE1;
- UpDepth = Depth; // span from goal to source
- Solution = GtoS; // goal to source ?
- Success = Dfs( &Goal ); // search reverse to level k
- if( !Success )
- {
- Solution = GtoS_COM; // look for common node
- Success = MatchBottom();
- if( !Success )
- { // search reverse to level k+1
- ClearStates(0); // clear reverse search
- Direction = REVERSE2;
- UpDepth=++Depth;
- Solution = GtoS_K1; // try K+1 iterations
- Success = Dfs( &Goal );
- if( !Success );
- {
- Solution = GtoS_K1_COM;
- Success = MatchBottom();
- if( !Success )
- {
- Solution=NO;
- ClearStates(1); //clear all search info
- }
- }
- }
- }
- }
- }
- return(Solution);
- }//
- ///////////////////////////////////////////////////////////////
- int CharPos( char *Sptr, int ch )
- // Determine if 'ch' exists within puzzle string at Sptr.
- // Return integer offset from start of string to position.
- // Else trap system error.
- {
-
- static char *Lptr;
- Lptr = strchr( Sptr, ch );
- if ( *Lptr != ch )
- {
- printf("\n** puzzle error ** %s",Sptr);
- exit(0);
- }
- return( Lptr-Sptr );
- }
- ///////////////////////////////////////////////////////////////
- void ClearStates( int All )
- // BiDirectional DFID requires clearing of the state space at
- // the end of each iteration. That is, except for the nodes of
- // the state space at the depth bound. These must be preserved
- // before calling this function.
- // Note: Single step mode may be exception
- {
- Open = DropPuzzles( Open );
- Closed = DropPuzzles( Closed );
- DropTable( Known, HASH_SIZE );
- if( All > 0 )
- {
- DownData = DropPuzzles( DownData );
- DropTable( D_Dat, HASH_SIZE );
- }
- }
- //
- ///////////////////////////////////////////////////////////////
- int Dfs( PUZZLE *Pz )
- // Depth first search with a depth bound
- // return success
- // GLOBALS: Choice,Puz_Show,Open,Closed,Gp,Depth,Level
- {
- int i, j, Done;
- PUZZLE *Py;
- Level=0;
- DfsOpen( Pz ); // source on open list
- Done = Success = NO;
- while( !Done )
- {
- if( Listing )
- {
- printf("\n---Open List---"); KeyWait();
- ShowList(Open);
- printf("\n---Closed List---"); KeyWait();
- ShowList(Closed);
- }
- Closed = PushLink( Closed, PopLink( &Open ) );
- Py = (PUZZLE*)(Closed->Dptr);
- Level = Py->Gn;
- Success=( strcmp( Gp, Py->Puz )==0 ); //?goal
- if( !Success )
- {
- if( Level < Depth ) // if expandable
- {
- Level++;
- Generate( Closed ); // process successors
- }
- }
- Done = ( Success || Open==NULL );
- }
- return( Success );
- }//
- ///////////////////////////////////////////////////////////////
- NPTR DfsOpen( PUZZLE *Pz )
- // put a puzzle in the LIFO ordered open list and also in the
- // the hashed list of generated puzzle strings
- // return puzzle node pointer
- // GLOBALS: Open, Known[], Level
- {
- NPTR L1, L2;
- int i;
- Pz->Gn = Level;
- L1 = MakePuzNode( Pz );
- Open = PushLink( Open, L1 ); // make open like a stack
- L2 = MakeLink( L1->Dptr, 0 );
- if( L2 == NULL )
- NoRoom();
- i = MakeKey( Pz->Puz ); // hash puzzle string
- Known[i] = PushLink( Known[i], L2 );
- return( L1 );
- }
- ///////////////////////////////////////////////////////////////
- int DrawSym( int Row, int Col, char *Sptr )
- // display a puzzle given it's string and a starting position
- //
- {
- int i,j;
- for( j=0; j<PW; j++ )
- {
- SetPos( Row, Col );
- for( i=0; i<PW; i++ )
- {
- printf(" %c",*Sptr++ );
- }
- Row+=1;
- }
- }//
- ///////////////////////////////////////////////////////////////
- NPTR DropPuzzles( NPTR Head )
- // Reuse space already allocated for a Linked list of puzzles
- // Put these puzzle nodes on a linked list of free puzzles.
- // and return NULL to mark empty list;
- // See also SaveDownDat()
- // GLOBALS: FreePuzzles
- {
- NPTR L1;
- while( Head != NULL )
- {
- L1 = Head->Next;
- FreePuzzles = PushLink( FreePuzzles, Head );
- Head = L1;
- }
- return( Head );
- }
- ///////////////////////////////////////////////////////////////
- void DropTable( NPTR *Table, int Size )
- // Free linked lists connected to a table of pointers
- {
- int i;
- for( i=0; i<Size; i++ )
- {
- Table[i] = DropLinked( Table[i] );
- }
- }
- ///////////////////////////////////////////////////////////////
- NPTR FindPuzLink( NPTR Pos, char *Sp )
- // Return pointer to node in linked list of puzzles which
- // contains specified puzzle string.
- // GLOBALS:
- {
- int Found = NO;
- while( Pos != NULL && !Found )
- {
- PUZZLE *Tmp = (PUZZLE*)Pos->Dptr;
- Found = ( strcmp( Tmp->Puz, Sp )==0 );
- if( !Found )
- Pos = Pos->Next;
- }
- return( Pos );
- }//
- ///////////////////////////////////////////////////////////////
- int Generate( NPTR Link )
- // Given a puzzle string, create upto 4 variants as permitted
- // by move rules. Note that for DFID, no expansion occurs for
- // states whose level is at the current Depth bound.
- // return nothing
- {
- PUZZLE *Py = (PUZZLE*)Link->Dptr;
- int i, bpos, ch, xd, Mask=1;
- bpos = CharPos( Py->Puz, HOLE ); // find open square
- xd = ValidJmps[bpos];
- for( i=0; i<POLES; i++ ) // upto 4 moves possible
- { // if move is possible copy puzzle and switch 2 squares
- if( xd & Mask )
- {
- Moves++; // total # moves considered
- strcpy( Tries[i].Puz, Py->Puz );
- ch = Tries[i].Puz[bpos]; // get the HOLE
- Tries[i].Puz[bpos] = Tries[i].Puz[ bpos+JmpDistance[i] ];
- Tries[i].Puz[ bpos+JmpDistance[i] ] = ch;
- if( !IfExistPuz( Tries[i].Puz ) )
- { // put new children on open list
- if( Direction != FORWARD )
- ExpUp++; // count reverse
- else
- ExpDown++; // count forward
- Tries[i].Dad = Link->Num; // remember path
- DfsOpen( &Tries[i] );
- }
- }
- else
- {
- Tries[i].Gn = INVALID ;
- }
- Mask=Mask<<1;
- }
- if( Puz_Show ) // optionally display moves
- {
- memcpy( &Choice, Py, sizeof(PUZZLE) );
- ShowMoves();
- }
- return( 0 );
- }//
- ///////////////////////////////////////////////////////////////
- int IfExistPuz( char *Pz )
- // Determine if a given puzzle was already generated. Search
- // the hashed puzzle string table for a match
- // GLOBALS: Known[]
- {
- int Ans = NO;
- NPTR Link = Known[ MakeKey( Pz ) ];
- if( Link != NULL )
- {
- Link = FindPuzLink( Link, Pz );
- Ans=( Link!=NULL );
- }
- return(Ans);
- }
- ///////////////////////////////////////////////////////////////
- void KeyWait( void )
- {
- printf(" ..key?" );
- getch();
- }//
- ///////////////////////////////////////////////////////////////
- void ListInFile( NPTR Head, int Level )
- // create test data by writing to a file all the nodes from
- // the closed list at a specified level.
- // Note: Copy Puzzles.dat to a batch file between runs
- {
- FILE *fp;
- PUZZLE *Px;
- char Sp[] = "Puzzles.dat";
- if(( fp = fopen( Sp,"w" )) == NULL )
- {
- printf(" ** file open error ** ");
- KeyWait();
- exit(0);
- }
- printf("Filing %s",Sp);
- while( Head != NULL )
- {
- Px = (PUZZLE*)Head->Dptr;
- Head = Head->Next;
- if( Px->Gn == Level )
- fprintf( fp, "\ndfid %s Level_%d",Px->Puz,Level );
- }
- fclose( fp );
- KeyWait();
- }
- ///////////////////////////////////////////////////////////////
- int MakeKey( char *Sp )
- // Given a 16-char puzzle string, pick every 4th char and
- // produce a long integer K by multiplication. Then return a
- // 16-bit integer result produced by K mod Tp where Tp is
- // a prime number table size.
- // GLOBALS: Tp
- {
- ldiv_t Result;
- long K1 ;
- K1 = 1000L * *(Sp+15) + 100L * *(Sp+11) +
- 10L * *(Sp+ 7) + *Sp;
- Result = ldiv( K1, (long)HASH_SIZE );
- return( (int)Result.rem ); // quotient not needed
- }//
- ///////////////////////////////////////////////////////////////
- NPTR MakePuzNode( PUZZLE *Px )
- // Get a puzzle node from the free list or
- // allocate space for a puzzle node, copy temporary values
- // to it, then return pointer to allocated space.
- // If no memory, abort gracefully
- // GLOBALS: FreePuzzles, NodeNum
- {
- NPTR Link = PopLink( &FreePuzzles ); // recycle an old puzzle
- if( Link == NULL )
- {
- PUZZLE *Puz = (PUZZLE*)malloc( sizeof(PUZZLE) );
- if( Puz != NULL )
- Link = MakeLink( (char*)Puz, 0 );
- if( Puz == NULL || Link == NULL )
- {
- NoRoom();
- }
- }
- memcpy( (PUZZLE*)Link->Dptr, Px, sizeof(PUZZLE) );
- Link->Num = ++NodeNum; // count puzzles created
- return( Link );
- }//
- ///////////////////////////////////////////////////////////////
- void MakeTextRoom( void )
- // erase expansion area of puzzle screen
- {
- int Row, Col;
- for( Row=8; Row<23; Row++ )
- {
- SetPos(Row,0);
- for( Col=0; Col < 78; Col++)
- putch(' ');
- }
- SetPos(8,0);
- }
- ///////////////////////////////////////////////////////////////
- int MatchBottom( void )
- // scan closed list from reverse search selecting those nodes
- // where Gn = Depth. Look for match in table saved by forward
- // search. Remember common node for solution display
- // GLOBALS: CommonNode, Success, Depth, D_Dat[]
- {
- NPTR Head = Closed; // the reverse list
- PUZZLE *Px;
- CommonNode = NULL ;
- Success = NO;
- while( Head != NULL && CommonNode == NULL )
- {
- Px = (PUZZLE*)Head->Dptr;
- if( Px->Gn == Depth )
- { // hash to the forward list
- CommonNode = D_Dat[ MakeKey( Px->Puz ) ];
- if( CommonNode != NULL )
- {
- CommonNode = FindPuzLink( CommonNode, Px->Puz );
- }
- Success = ( CommonNode != NULL );
- }
- Head = Head->Next;
- }
- return( Success );
- }//
- ///////////////////////////////////////////////////////////////
- void NoRoom( void )
- {
- time( &Time2 ); // mark the run time
- MakeTextRoom();
- printf("\n*** no heap space ***\n");
- Statistics();
- ClearStates(1); // clear the state space
- KeyWait();
- exit(0);
- }
- ///////////////////////////////////////////////////////////////
- void ReleasePuzzles( void )
- // Unallocate puzzles kept on spare list
- // GLOBALS: FreePuzzles, FreeHead
- {
- NPTR Tmp = FreePuzzles;
- PUZZLE *Px;
- while( Tmp != NULL )
- {
- Px = (PUZZLE*)Tmp->Dptr;
- free( Px );
- FreeHead = PushLink( FreeHead, PopLink( &FreePuzzles ) );
- Tmp = FreePuzzles;
- }
- ReleaseNodes();
- }
- ///////////////////////////////////////////////////////////////
- void SaveDownData( void )
- // Upon completion of search from source to goal for some depth
- // Kn, if the goal was not found, save puzzles from closed list
- // which have Gn = Kn, in hashed table. Do this before clearing
- // the state space before reverse search.
- // Note: all nodes are saved if ResultInFile is TRUE
- // GLOBALS: D_DAT[], Depth, Closed, DownData
- {
- PUZZLE *Px;
- int x;
- NPTR L1, L2;
- while( Closed != NULL )
- {
- L1 = PopLink( &Closed ); // eat the closed list
- Px = (PUZZLE*)L1->Dptr;
- if( ( Px->Gn == Depth )||(ResultInFile) )
- {
- DownData = PushLink( DownData, L1 );
- x = MakeKey( Px->Puz ); // use hashing
- L2 = MakeLink( L1->Dptr, 0 );
- if( L2 == NULL )
- NoRoom();
- D_Dat[x] = PushLink( D_Dat[x], L2 );
- }
- else // recycle if not needed
- FreePuzzles = PushLink( FreePuzzles, L1 );
- }
- //ShowTable( D_Dat, HASH_SIZE );
- return;
- }//
- ///////////////////////////////////////////////////////////////
- void ShowList( NPTR Link )
- // Display a linked list of puzzles, if file is open, also
- // output to the text file.
- // GLOBALS: FILE *Fp
- {
- PUZZLE *Pz;
- unsigned int Row=0;
- if( Link== NULL ) printf("\nNULL list..");
- while( Link != NULL )
- {
- Pz = (PUZZLE*)Link->Dptr;
- if( Fp != NULL )
- { // if result file open
- fprintf(Fp,"\n NodeNum: %5d Gn: %4d Hn: %3d Dad %5d %s",
- Link->Num, Pz->Gn, Pz->Hn,Pz->Dad, Pz->Puz );
- }
- else
- {
- printf("\n NodeNum: %5d Gn: %4d Hn: %3d Dad %5d %s",
- Link->Num, Pz->Gn, Pz->Hn,Pz->Dad, Pz->Puz );
- }
- Link = Link->Next;
- if( ++Row % 12 == 0 && Fp==NULL )
- {
- KeyWait();
- }
- }
- if( Fp==NULL) KeyWait();
- } //
- ///////////////////////////////////////////////////////////////
- int ShowMoves( void )
- {
- int i;
- time_t Ticks;
- SetPos(0,4);
- printf("-Source-");
- DrawSym( 2,4,Source.Puz );
- SetPos(0,16);
- printf("-Parent-");
- DrawSym( 2,16,Choice.Puz );
- SetPos( 0,28 );
- printf("-Goal---");
- DrawSym( 2,28,Goal.Puz );
- SetPos(0,50);
- if( Direction != FORWARD )
- printf("G-->S: %ld",ExpUp);
- else
- printf("S-->G: %ld",ExpDown);
- SetPos(1,50);
- printf("Tries: %ld",ExpDown+ExpUp);
- SetPos(2,50);
- time( &Ticks ); // current time
- printf("Clock: %f ",difftime( Ticks, Time1 ) );
- SetPos(3,50);
- printf("Depth: %ld",(long)Depth );
- SetPos(4,50);
- printf("Moves: %ld",(long)Moves );
- for( i=0; i < POLES; i++ )
- if( Tries[i].Gn == INVALID )
- memset( Tries[i].Puz, HOLE, PSIZE );
- SetPos( 8, 4); printf("BiDirectional DFID -- Bob McIsaac");
- SetPos(12, 4); printf("%5d",Tries[0].Gn );
- SetPos(12,16); printf("%5d",Tries[1].Gn );
- SetPos(12,28); printf("%5d",Tries[2].Gn );
- SetPos(12,40); printf("%5d",Tries[3].Gn );
- printf(" . . . Gn");
- DrawSym(14, 4,Tries[0].Puz );
- DrawSym(14,16,Tries[1].Puz );
- DrawSym(14,28,Tries[2].Puz );
- DrawSym(14,40,Tries[3].Puz );
- putchar('\n');
- if( TestKey() ) exit(0);
- return(0);
- }//
- ///////////////////////////////////////////////////////////////
- void ShowTable( NPTR *Table, int Size )
- {
- PUZZLE *Pz;
- NPTR Link;
- unsigned int i, Row=0;
- for( i=0; i<Size; i++ )
- {
- Link = Table[i];
- Row=0;
- while( Link != NULL )
- {
- Pz = (PUZZLE*)Link->Dptr;
- printf("\n Table___: key %4d Gn %4d %s",i,Pz->Gn,Pz->Puz );
- Link = Link->Next;
- if( ++Row % 12 == 0 ) KeyWait();
- }
- }
- }//
- ///////////////////////////////////////////////////////////////
- void ShowSuccess( int Success )
- {
- printf("\n $$$ success $$$ %d",Success );
- switch( Success )
- {
- case StoG:
- printf("\nGoal found on S->G search (step K)");
- break;
- case GtoS:
- printf("\nSource found on G->S search (step K)");
- break;
- case GtoS_COM:
- printf("\nCommon found on G->S search (step K)");
- break;
- case GtoS_K1:
- printf("\nSource found on G->S search (K+1)");
- break;
- case GtoS_K1_COM:
- printf("\nCommon found on G->S search (K+1)");
- break;
- default: break;
- }
- }
- //
- ///////////////////////////////////////////////////////////////
- // Show correct format for command line.
- void ShowHow(void)
- {
- int i;
- printf("\nUSAGE: dfid <puzzle string>");
- printf("\nEx:");
- printf("\n DFID 123456789ABCDEF-");
- printf("\n or use DfidTest.Bat");
- exit(0);
- }
- //
- ///////////////////////////////////////////////////////////////
- void Statistics( void )
- // GLOBALS: all variables
- {
- if( Fp == NULL )
- {
- printf("\nClock: %6.2f Seconds",difftime( Time2, Time1 ) );
- printf("\nNodes Expanded: S->G %6ld Depth %d",
- ExpDown,DownDepth );
- printf("\nNodes Expanded: G->S %6ld Depth %d",
- ExpUp,UpDepth);
- printf("\nMoves Considered: %6ld", Moves);
- printf("\nPuzzles generated: %6ld",(long)NodeNum );
- }
- else // write to BmResult.Tmp
- {
- fprintf(Fp,"\n\nBiDirectional DFID --- by Bob McIsaac" );
- fprintf(Fp,"\nClock: %6.1f Seconds",difftime( Time2, Time1 ) );
- fprintf(Fp,"\nNodes Expanded: S->G %6ld Depth %d",
- ExpDown,DownDepth );
- fprintf(Fp,"\nNodes Expanded: G->S %6ld Depth %d",
- ExpUp,UpDepth);
- fprintf(Fp,"\nMoves Considered: %6ld", Moves);
- fprintf(Fp,"\nPuzzles generated: %6ld",(long)NodeNum );
- }
- }
- ///////////////////////////////////////////////////////////////
- int TestKey()
- {
- int Ans = 0;
- if( Pausing )
- {
- printf("\n 1=more 0=quit >>" );
- Ans = ( getch()=='0');
- }
- return( Ans );
- }
- //