home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************
- // Title: Astar.c
- //27jul92-bm
- // SOLVE 15-PUZZLE
- //
- // by: Bob McIsaac
- **************************************************************/
- #include <dos.h>
- #include <bios.h>
- #include <conio.h>
- #include <graph.h>
- #include <malloc.h>
- #include <memory.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include "astar.h"
-
- extern NPTR FreeHead; /* defined in linked.c */
-
- /* 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 Closed0; /* list of puzzles already tried S->G */
- NPTR Closed1; /* list of puzzles already tried G->S */
- NPTR CommonNode; /* needed for solution path; */
- NPTR Known0[HASH_SIZE];/* hashed list of known puzzles S->G */
- NPTR Known1[HASH_SIZE];/* hashed list of known puzzles G->S */
- NPTR Open0[FN_MAX]; /* heuristically open list S->G */
- NPTR Open1[FN_MAX]; /* heuristically open list G->S */
-
- 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;
- int (*Heuristic)(); /* pointer to function returning int */
- FILE *Fp;
-
- 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 */
- static int Astar( PUZZLE *Pz, NPTR *Open, NPTR *Known,NPTR Closed );
- static int BiAstar( void );
- static int CharPos( char *Px, int ch );
- static void ClearStates( int All );
- static int DrawSym( int Row, int Col, char *Pz );
- static NPTR DropPuzzles( NPTR Head );
- static void DropTable( NPTR *Table, int Size );
- static NPTR FindPuzLink( NPTR Pos, char *Px );
- static NPTR FromOpen( NPTR *Table );
- static int Generate( NPTR *OpenTable, NPTR *Known, NPTR Link );
- static NPTR HashPuzzle( NPTR *Table, PUZZLE *Pz );
- static int IfExistPuz( char *Pz, int TableNum );
- static void KeyWait( void );
- static void ListInFile( NPTR Head, int Level );
- static int MakeKey( char *Pz );
- static NPTR MakePuzNode( PUZZLE *Pz );
- static void MakeTextRoom( void );
- static int Manhattan( char *Px, char *Gx );
- static int MisMatch( char *Px, char *Gx );
- static void NoRoom( void );
- static NPTR PushToOpen( NPTR *Table, NPTR Link );
- static void ReleasePuzzles( void );
- static void SetPos( char Row, char Col );
- static void ShowHow( void );
- static void ShowList( NPTR Link );
- static int ShowMoves( void );
- static void ShowSuccess( int Success );
- static void ShowTable( NPTR *Table, int Size );
- static void ShowTableLists( NPTR *Table, int Size );
- static void Statistics( void );
- static int TestKey( void );
-
- /**************************************************************
- // *** MAIN ***
- //
- **************************************************************/
- void main( argc, argv ) 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();
- 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;
- Closed0 = Closed1 = NULL;
- NodeNum=0;
- FreePuzzles = FreeHead = NULL;
- Time1 = Time2 = 0;
- for( i=0; i<POLES; i++ )
- {
- Tries[i].Gn = Tries[i].Hn = INVALID ;
- }
- for( i=0; i<HASH_SIZE; i++ )
- {
- Known0[i] = NULL; /* forward */
- Known1[i] = NULL; /* reverse */
- }
-
- for( i=0; i<FN_MAX; i++ ) /* Fn range */
- {
- Open0[i] = NULL; /* forward */
- Open1[i] = NULL; /* reverse */
- }
-
- Heuristic = Manhattan;
- memset( Choice.Puz, HOLE, PSIZE );
- time( &Time1 ); /* start timer */
- ShowMoves();
-
- if( argc>2 )
- printf("\n%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.Tmp");
- 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 );
- CommonNode=NULL;
- ShowMoves();
- cputs("\n..busy..");
- Success = BiAstar();
- time( &Time2 );
- ShowMoves();
- MakeTextRoom();
- Statistics();
- ShowSuccess( Success );
- KeyWait();
-
- if( Fp != NULL )
- fprintf(Fp,"\n%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( Closed0 );
- fprintf(Fp,"\n..Final Open List..");
- ShowTableLists( Open0, FN_MAX );
- }
- ClearStates(1);
- ReleasePuzzles();
- if( Fp != NULL )
- { /* use external full screen viewer to scan solution */
- fclose( Fp );
- system("List BMresult.tmp");
- }
- exit(0);
- }
- /**************************************************************
- // Given a source puzzle, pointers to Open and Closed, perform
- // an A* search. Initially, Open and Closed are empty.
- // return success
- // GLOBALS: Choice,Gp,Depth
- **************************************************************/
- static int Astar( Pz, OpenTable, Known, Closed )
- PUZZLE *Pz; NPTR *OpenTable; NPTR *Known; NPTR Closed;
- {
- int i, j, Done;
- NPTR L1;
- Pz->Gn = 0;
- Pz->Hn = Manhattan( Pz->Puz , Gp );
- L1 = MakePuzNode( Pz );
- PushToOpen( OpenTable, L1 );
- HashPuzzle( Known, (PUZZLE*)L1->Dptr );
- Done = Success = NO;
- while( !Done )
- {
- PUZZLE *Py;
- if( Listing )
- {
- printf("\n&&&OPEN&&&");ShowTable(OpenTable, FN_MAX);
- KeyWait;
- printf("\n%%Known%%%");ShowTable( Known,HASH_SIZE);
- KeyWait();
- printf("\n@@Closed@@");ShowList( Closed );
- }
- L1 = FromOpen( OpenTable );
- Closed = PushLink( Closed, L1 );
- Py = (PUZZLE*)(Closed->Dptr);
- if( Direction == FORWARD )
- DownDepth = max( DownDepth, Py->Gn );
- else
- UpDepth = max( UpDepth, Py->Gn );
- Success=( strcmp( Gp, Py->Puz )==0 );
- if( !Success )
- {
- Generate( OpenTable, Known, Closed );
- }
- Done = ( Success || L1==NULL );
- }
- if( Direction == FORWARD )
- Closed0 = Closed;
- else
- Closed1 = Closed;
- return( Success );
- }
- /**************************************************************
- // Bidirectional A* search
- // return solution type: goal hit or common node w/ direction
- // GLOBALS: Success,Known[],Depth
- **************************************************************/
- static int BiAstar( void )
- {
- int Solution = NO;
- Depth = 1;
- Success=NO;
- ExpDown = ExpUp = 0L;
- DownDepth = UpDepth = 0;
- while( !Success && Depth>0 )
- {
- Direction = FORWARD;
- Gp = Goal.Puz;
- Solution = StoG;
- Success = Astar( &Source, Open0, Known0, Closed0 );
- Solution = Success;
- if( !Success )
- {
- /* SaveDownData(); */
- ClearStates(0);
- Gp = Source.Puz;
- Direction=REVERSE;
- UpDepth = Depth;
- Solution = GtoS;
- /* Success = Astar( &Goal );*/
- }
- }
- return(Solution);
- }
- /**************************************************************
- // CharPos()
- // Determine if 'ch' exists within puzzle string at Sptr.
- // Return integer offset from start of string to position.
- // Else trap system error.
- **************************************************************/
- static int CharPos( Sptr, ch ) char *Sptr; int ch;
- {
- static char *Lptr;
- Lptr = strchr( Sptr, ch );
- if ( *Lptr != (char)ch )
- {
- printf("\n** puzzle error ** %s",Sptr);
- exit(0);
- }
- return( Lptr-Sptr );
- }
- /**************************************************************
- // 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
- **************************************************************/
- static void ClearStates( All ) int All;
- {
- Closed0 = DropPuzzles( Closed0 );
- Closed1 = DropPuzzles( Closed1 );
- DropTable( Open0, FN_MAX );
- DropTable( Open1, FN_MAX );
- DropTable( Known0, HASH_SIZE );
- DropTable( Known1, HASH_SIZE );
- }
- /**************************************************************
- // DrawSym()
- // display a puzzle given it's string and a starting position
- **************************************************************/
- static int DrawSym( Row , Col, Sptr ) int Row; int Col; char *Sptr;
- {
- int i,j;
- for( j=0; j<PW; j++ )
- {
- SetPos( (char)Row, (char)Col );
- for( i=0; i<PW; i++ )
- {
- printf(" %c",*Sptr++ );
- }
- Row+=1;
- }
- return(0);
- }
- /**************************************************************
- // DropPUzzles()
- // 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
- **************************************************************/
- static NPTR DropPuzzles( Head ) NPTR Head;
- {
- NPTR L1;
- while( Head != NULL )
- {
- L1 = Head->Next;
- FreePuzzles = PushLink( FreePuzzles, Head );
- Head = L1;
- }
- return( Head );
- }
- /**************************************************************
- DropTable()
- // Free linked lists connected to a table of pointers
- **************************************************************/
- static void DropTable( Table, Size ) NPTR *Table; int Size;
- {
- int i;
- for( i=0; i<Size; i++ )
- {
- Table[i] = DropLinked( Table[i] );
- }
- }
- /**************************************************************
- FindPuzLink()
- // Return pointer to node in linked list of puzzles which
- // contains specified puzzle string.
- // GLOBALS:
- **************************************************************/
- static NPTR FindPuzLink( Pos, Sp ) NPTR Pos; char *Sp;
- {
- 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 );
- }
- /**************************************************************
- FromOpen()
- // Retrieve item of lowest fn from heuristic open table
- // The heuristic table is scanned in ascending order to find
- // first pointer. Then the head of list is removed.
- // return null if open empty
- **************************************************************/
- static NPTR FromOpen( Table ) NPTR *Table;
- {
- NPTR L1 = NULL;
- int i;
- for( i=0; i<FN_MAX && L1 == NULL; i++ )
- {
- if( Table[i] != NULL )
- {
- L1 = PopLink( &Table[i] );
- }
- }
- return( L1 );
- }
- /**************************************************************
- Generate()
- **************************************************************/
- static int Generate( OpenTable, Known, Link )
- NPTR *OpenTable; NPTR *Known; NPTR Link;
- {
- 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] ] = (char)ch;
- if( !IfExistPuz( Tries[i].Puz, Direction ) )
- { /* if not in hash table, put new kids on open list*/
- NPTR L1;
- if( Direction != FORWARD )
- ExpUp++;
- else
- ExpDown++;
- Tries[i].Dad = Link->Num; /* remember path*/
- Tries[i].Gn = Py->Gn + 1; /* increment Gn*/
- Tries[i].Hn = Manhattan( Tries[i].Puz, Gp );
- L1 = MakePuzNode( &Tries[i] );
- PushToOpen( OpenTable, L1 );
- HashPuzzle( Known, (PUZZLE*)L1->Dptr );
- }
- }
- else
- Tries[i].Gn = INVALID ;
- Mask=Mask<<1;
- }
- if( Puz_Show)
- {
- memcpy( &Choice, Py, sizeof( PUZZLE ) );
- ShowMoves(); /* optionally display children*/
- }
- return( 0 );
- }
- /**************************************************************
- HashPuzzle()
- // Store a pointer to a puzzle in a hashed table. Note that a
- // puzzle pointer should already exist on the open list and this
- // table indirectly points to puzzles on open & closed.
- // return puzzle node pointer
- // GLOBALS:
- **************************************************************/
- static NPTR HashPuzzle( Table, Pz ) NPTR *Table; PUZZLE *Pz;
- {
- NPTR L1 ; /* another link for collision chain*/
- int i;
- L1 = MakeLink( (char*)Pz, 0 );
- if( L1 == NULL )
- NoRoom();
- i = MakeKey( Pz->Puz );
- Table[i] = PushLink( Table[i], L1 );
- return( L1 );
- }
- /**************************************************************
- IfExistPuz()
- // Determine if a given puzzle already exists in the selected
- // forward or reverse hash table.
- // GLOBALS: Known[]
- **************************************************************/
- static int IfExistPuz( Pz, TableNum ) char *Pz; int TableNum;
- {
- int Ans = NO;
- NPTR Link;
- if( TableNum == FORWARD )
- Link = Known0[ MakeKey( Pz ) ];
- else
- Link = Known1[ MakeKey( Pz ) ];
- if( Link != NULL )
- {
- Link = FindPuzLink( Link, Pz );
- Ans=( Link!=NULL );
- }
- return(Ans);
- }
- /**************************************************************
- **************************************************************/
- static void KeyWait( void )
- {
- printf(" ..key?" );
- getch();
- }
- /**************************************************************
- **************************************************************/
- static int Manhattan( Px, Gx ) char *Px; char *Gx;
- {
- int xd, r1, r2, c1, c2, Dist;
- r1 = c1 = Dist = 0;
- while( *Px )
- {
- if ( *Px != HOLE )
- {
- xd = CharPos( Gx, *Px );
- r2 = xd/PW;
- c2 = xd % PW;
- Dist += ( abs( r2-r1 ) + abs( c2-c1 ) );
- }
- Px++;
- c1++;
- if( c1 >= PW )
- {
- c1=0;
- r1++;
- }
- }
- return( Dist );
- }
- /**************************************************************
- MakeKey()
- // 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
- // Letters: 1 2 3 4 5 6 7 8 9 A B C D E F -
- // Codes : 31 32 33 34 35 36 37 38 39 65 66 67 68 69 70 45
- **************************************************************/
- static int MakeKey( Sp ) char *Sp;
- {
- 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 */
- }
- /**************************************************************
- **************************************************************/
- static NPTR MakePuzNode( Px ) PUZZLE *Px;
- {
- 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 );
- }
- /**************************************************************
- MakeTextRoom()
- // erase expansion area of puzzle screen where child nodes
- // are optionally displayed.
- **************************************************************/
- static void MakeTextRoom( void )
- {
- int Row, Col;
- for( Row=8; Row<23; Row++ )
- {
- SetPos( (char)Row,0);
- for( Col=0; Col < 78; Col++)
- putch(' ');
- }
- SetPos(8,0);
- }
- /**************************************************************
- MisMatch()
- // Compare puzzle string to goal
- // return count of mismatches
- // GLOBALS:
- **************************************************************/
- static int MisMatch( Px, Gx ) char *Px; char *Gx;
- {
- int Mis = 0;
- /* while( *Px )
- { // this count includes the "blank"
- Mis += ( *Px++ != *Gx++ );
- } */
- while( *Px )
- { /* this one does not include the blank */
- Mis += ( *Px != *Gx && *Px != HOLE && *Gx != HOLE );
- Px++;
- Gx++;
- }
- return( Mis );
- }
- /**************************************************************
- **************************************************************/
- static void NoRoom( void )
- {
- time( &Time2 );
- MakeTextRoom();
- printf("\n*** no heap space ***\n");
- Statistics();
- ClearStates(1);
- KeyWait();
- exit(0);
- }
- /**************************************************************
- PushToOpen()
- // Add link to specified OPEN table in heuristic order
- // Use the Fn value as table index, then push the new
- // link on the list of equal values at that location
- // return addrs of puzzle link
- // GLOBALS: Gp
- **************************************************************/
- static NPTR PushToOpen( Table, Link ) NPTR *Table; NPTR Link;
- {
- PUZZLE *Px = (PUZZLE*)Link->Dptr;
- int Fn = Px->Hn + Px->Gn;
- if( Fn >= FN_MAX )
- {
- printf("\nProgram Error: Heuristic table too small");
- exit(0);
- }
- Table[Fn] = PushLink( Table[Fn], Link );
- return( Link );
- }
- /**************************************************************
- ReleasePuzzles()
- // Unallocate puzzles kept on spare list
- // GLOBALS: FreePuzzles, FreeHead
- **************************************************************/
- static void ReleasePuzzles( void )
- {
- NPTR Tmp = FreePuzzles;
- PUZZLE *Px;
- while( Tmp != NULL )
- {
- Px = (PUZZLE*)Tmp->Dptr;
- free( Px );
- FreeHead = PushLink( FreeHead, PopLink( &FreePuzzles ) );
- Tmp = FreePuzzles;
- }
- ReleaseNodes();
- }
- /**************************************************************
- //
- **************************************************************/
- static void SetPos( Row, Col )
- char Row; char Col;
- { _settextposition( Row, Col );
- }
- /**************************************************************
- ShowList()
- // Display a linked list of puzzles, if file is open, also
- // output to the text file.
- // GLOBALS: FILE *Fp
- **************************************************************/
- static void ShowList( Link ) NPTR Link;
- {
- 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();
- }
- /**************************************************************
- **************************************************************/
- static int ShowMoves( void )
- {
- int i;
- time_t Ticks;
- SetPos(0,4);
- printf("-Source-");
-
- DrawSym( 2,4,Source.Puz );
- SetPos(0,16);
- printf("-Choice-");
- 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 );
- printf("Clock: %f ",difftime( Ticks, Time1 ) );
- SetPos(3,50);
- printf("Depth: %ld",(long)Depth );
- SetPos(4,50);
- printf("Moves: %ld",(long)Moves );
- SetPos(8,12);printf("\nA-Star Algorithm -- by Bob McIsaac");
- for( i=0; i < POLES; i++ )
- if( Tries[i].Gn == INVALID )
- memset( Tries[i].Puz, HOLE, PSIZE );
- 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);
- }
- /**************************************************************
- **************************************************************/
- static void ShowTable( Table, Size ) NPTR *Table; int Size;
- {
- PUZZLE *Pz;
- NPTR Link;
- unsigned int i, Row=0;
- for( i=0; i<(UINT)Size; i++ )
- {
- Link = Table[i];
- Row=0;
- while( Link != NULL )
- {
- Pz = (PUZZLE*)Link->Dptr;
- printf("\n Table___: key %4d Gn %4d Hn %4d %s",
- i,Pz->Gn,Pz->Hn,Pz->Puz );
- Link = Link->Next;
- if( ++Row % 12 == 0 ) KeyWait();
- }
- }
- }
- /**************************************************************
- ShowTableLists()
- // This will show show all the linked list found in an array
- // of pointers. Handy for writing the open list to the
- // solution file
- **************************************************************/
- static void ShowTableLists( Table, Size ) NPTR *Table; int Size;
- {
- int i;
- for( i=0; i<Size; i++ )
- {
- NPTR Link = Table[i];
- if( Link != NULL )
- {
- ShowList( Link );
- }
- }
- }
- /**************************************************************
- **************************************************************/
- static void ShowHow(void)
- {
- int i;
- printf("\nUSAGE: Astar <puzzle string>");
- printf("\nEx:");
- printf("\n Astar 123456789ABCDEF-");
- printf("\n or use STARTEST.BAT");
- exit(0);
- }
- /**************************************************************
- **************************************************************/
- static void ShowSuccess( Success ) 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;
- }
- }
- /**************************************************************
- **************************************************************/
- static int TestKey()
- {
- int Ans = 0;
- if( Pausing )
- {
- printf("\n 1=more 0=quit >>" );
- Ans = ( getch()=='0');
- }
- return( Ans );
- }
- /**************************************************************
- **************************************************************/
- static void Statistics( void )
- {
- 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\nA-Star Algorithm --- by Bob McIsaac" );
- fprintf(Fp,"\nUsing Manhattan Heuristic" );
- 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 );
- }
- }
-
-