Newsgroups: comp.os.msdos.djgpp From: Matt Reiferson Subject: A* Algorithm Problems SIGSEGV Content-Type: multipart/alternative; boundary="------------46003C0AF10F5A060574AABD" Reply-To: MReiferson AT aol DOT com Organization: DeltaSoft Message-ID: Mime-Version: 1.0 Date: Wed, 9 Jul 1997 17:02:14 GMT Lines: 1085 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk --------------46003C0AF10F5A060574AABD Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit This A* Pathfinding algorithm I am planning to use in a Warcraft II type game, the problem is, it doesn't work.......Sometimes I will be able to find the paths but sometimes it gives me SIGSEGV crash messages.....NOTE, this program that follows is just a program that allows you to place blockades, a start and an end position to find the fastest route from one point to another around those obstacles, it uses allegro for the graphics, and a specialized version of MikMod, because of this you will be unable to recompile the code without removing the #include .....The line that is faulty (claimed by symify is highlighted RED) Here is the symify output: Shutting down Allegro Exiting due to signal SIGSEGV General Protection Fault at eip=000019d0 eax=fffe6485 ebx=00000000 ecx=00000003 edx=000000b7 esi=00000009 edi=00000001 ebp=001297df esp=001297df program=C:\DJGPP\SOURCE\PROJECTS\ASTAR\ASTAR.EXE cs: sel=00af base=82e15000 limit=0015ffff ds: sel=00b7 base=82e15000 limit=0015ffff es: sel=00b7 base=82e15000 limit=0015ffff fs: sel=00c7 base=00000000 limit=ffffffff gs: sel=00c7 base=00000000 limit=ffffffff ss: sel=00b7 base=82e15000 limit=0015ffff Call frame traceback EIPs: 0x000019d0 _CheckCLOSED+16, line 302 of mypath.c 0x00001900 _GenerateSucc+104, line 240 of mypath.c 0x00001791 _GenerateSuccessors+49, line 163 of mypath.c 0x0000171f _FindPath+151, line 121 of mypath.c 0x00001fd9 _main+997, line 437 of mypath.c 0x00013b72 ___crt1_startup+138 And here is the source code: #include #include #include #include #include #include #include #include #include #include #include #include #define COLS 20 #define ROWS 15 #define TOTAL_TILES ROWS*COLS #define TILESIZE 1 int TileMap[TOTAL_TILES]; int FINISHED=0; typedef int boolean; struct NODE { long f,h; int g,tmpg; int x,y; int NodeNum; struct NODE *Parent; struct NODE *Child[8]; /* a node may have upto 8+(NULL) children. */ struct NODE *NextNode; /* for filing purposes */ }; struct NODE *OPEN; struct NODE *CLOSED; struct STACK { struct NODE *NodePtr; struct STACK *NextStackPtr; }; struct STACK *Stack; unsigned _stklen = 1048567; boolean FreeTile(int x, int y); int TileNum(int x, int y); struct NODE *FindPath(long sx,long sy,long dx,long dy); struct NODE *ReturnBestNode(void); void GenerateSuccessors(struct NODE *BestNode,long dx,long dy); void GenerateSucc(struct NODE *BestNode,long x, long y, long dx, long dy); struct NODE *CheckOPEN(int tilenum); struct NODE *CheckCLOSED(int tilenum); void Insert(struct NODE *Successor); void PropagateDown(struct NODE *Old); void Push(struct NODE *Node); struct NODE *Pop(void); int TileNum(int x, int y) { return ((y*20)+x); } boolean FreeTile(int x, int y) { // returns 1 if tile is free(nothing on it). // Note: if TileMap[equation]==0 it means free so just !(not) it. return (!TileMap[(y*20)+x]); } void DisplayPath(int x1, int y1, int x2, int y2) { struct NODE *path, *Node; int lx=x2,ly=y2; path=(struct NODE *)FindPath((long)x1,(long)y1,(long)x2,(long)y2); while (path->Parent != NULL) { path=path->Parent; line(screen,lx*32+16,ly*32+16,path->x*32+16,path->y*32+16,44); lx=path->x; ly=path->y; } line(screen,lx*32+16,ly*32+16,path->x*32+16,path->y*32+16,44); // Free Nodes up Node=OPEN->NextNode; while (Node != NULL) { free(Node); Node=Node->NextNode; } Node=CLOSED->NextNode; while (Node != NULL) { free(Node); Node=Node->NextNode; } } struct NODE *FindPath(long sx,long sy,long dx,long dy) { struct NODE *Node, *BestNode; int TileNumDest; TileNumDest=TileNum((int)dx,(int)dy); OPEN=(struct NODE *)malloc(sizeof( struct NODE )); CLOSED=(struct NODE *)malloc(sizeof( struct NODE )); Node=(struct NODE *)malloc(sizeof( struct NODE )); Node->g=0; Node->h=(sx-dx)*(sx-dx)+(sy-dy)*(sy-dy); // should really use sqrt(). Node->f=Node->g+Node->h; Node->NodeNum=TileNum((int)sx,(int)sy); Node->x=sx; Node->y=sy; Node->NextNode=NULL; OPEN->NextNode=Node; /* make Open List point to first node */ for (;;) { BestNode=(struct NODE *)ReturnBestNode(); if (BestNode->NodeNum == TileNumDest) /* if we've found the end, break and finish */ break; GenerateSuccessors(BestNode,dx,dy); } return (BestNode); } struct NODE *ReturnBestNode(void) { struct NODE *tmp; if (OPEN->NextNode == NULL) { exit(0); } /* Pick Node with lowest f, in this case it's the first node in list because we sort the OPEN list wrt lowest f. Call it BESTNODE. */ tmp=OPEN->NextNode; // point to first node on OPEN OPEN->NextNode=tmp->NextNode; // Make OPEN point to nextnode or NULL. /* Next take BESTNODE (or temp in this case) and put it on CLOSED */ tmp->NextNode=CLOSED->NextNode; CLOSED->NextNode=tmp; return(tmp); } void GenerateSuccessors(struct NODE *BestNode,long dx,long dy) { long x,y; /* Upper-Left */ x=(long)BestNode->x-TILESIZE; y=(long)BestNode->y-TILESIZE; if(x>0 && x0 && yx; y=(long)BestNode->y-TILESIZE; if(x>0 && x0 && yx+TILESIZE; y=(long)BestNode->y-TILESIZE; if(x>0 && x0 && yx+TILESIZE; y=(long)BestNode->y; if(x>0 && x0 && yx+TILESIZE; y=(long)BestNode->y+TILESIZE; if(x>0 && x0 && yx; y=(long)BestNode->y+TILESIZE; if(x>0 && x0 && yx-TILESIZE; y=(long)BestNode->y+TILESIZE; if(x>0 && x0 && yx-TILESIZE; y=(long)BestNode->y; if(x>0 && x0 && yg+1; /* g(Successor)=g(BestNode)+cost of getting from BestNode to Successor */ TileNumS=TileNum((int)x,(int)y); /* identification purposes */ if ((Old=CheckOPEN(TileNumS)) != NULL) /* if equal to NULL then not in OPEN list, else it returns the Node in Old */ { for(c=0;c<8;c++) if(BestNode->Child[c] == NULL) /* Add Old to the list of BestNode's Children (or Successors). */ break; BestNode->Child[c]=Old; if (g < Old->g) /* if our new g value is < Old's then reset Old's parent to point to BestNode */ { Old->Parent=BestNode; Old->g=g; Old->f=g+Old->h; } } else if ((Old=CheckCLOSED(TileNumS)) != NULL) /* if equal to NULL then not in OPEN list, else it returns the Node in Old */ { for(c=0;c<8;c++) if (BestNode->Child[c] == NULL) /* Add Old to the list of BestNode's Children (or Successors). */ break; BestNode->Child[c]=Old; if (g < Old->g) /* if our new g value is < Old's then reset Old's parent to point to BestNode */ { Old->Parent=BestNode; Old->g=g; Old->f=g+Old->h; PropagateDown(Old); /* Since we changed the g value of Old, we need to propagate this new value downwards, i.e. do a Depth-First traversal of the tree! */ } } else { Successor=(struct NODE *)malloc(sizeof( struct NODE )); Successor->Parent=BestNode; Successor->g=g; Successor->h=(x-dx)*(x-dx)+(y-dy)*(y-dy); // should do sqrt(), but since we don't really Successor->f=g+Successor->h; // care about the distance but just which branch looks Successor->x=x; // better this should suffice. Anyayz it's faster. Successor->y=y; Successor->NodeNum=TileNumS; Insert(Successor); /* Insert Successor on OPEN list wrt f */ for(c=0;c<8;c++) if (BestNode->Child[c] == NULL) /* Add Old to the list of BestNode's Children (or Successors). */ break; BestNode->Child[c]=Successor; } } struct NODE *CheckOPEN(int tilenum) { struct NODE *tmp; tmp=OPEN->NextNode; while (tmp != NULL) { if (tmp->NodeNum == tilenum) return (tmp); else tmp=tmp->NextNode; } return (NULL); } struct NODE *CheckCLOSED(int tilenum) { struct NODE *tmp; tmp=CLOSED->NextNode; while (tmp != NULL) { if (tmp->NodeNum == tilenum) return (tmp); else tmp=tmp->NextNode; } return (NULL); } void Insert(struct NODE *Successor) { struct NODE *tmp1,*tmp2; long f; if (OPEN->NextNode == NULL) { OPEN->NextNode=Successor; return; } /* insert into OPEN successor wrt f */ f=Successor->f; tmp1=OPEN; tmp2=OPEN->NextNode; while ((tmp2 != NULL) && (tmp2->f < f)) { tmp1=tmp2; tmp2=tmp2->NextNode; } Successor->NextNode=tmp2; tmp1->NextNode=Successor; } void PropagateDown(struct NODE *Old) { int c,g; struct NODE *Child, *Father; g=Old->g; // alias. for(c=0;c<8;c++) { if ((Child=Old->Child[c])==NULL) // create alias for faster access. break; if (g+1 < Child->g) { Child->g=g+1; Child->f=Child->g+Child->h; Child->Parent=Old; // reset parent to new path. Push(Child); // Now the Child's branch need to be } // checked out. Remember the new cost must be propagated down. } while (Stack->NextStackPtr != NULL) { Father=Pop(); for(c=0;c<8;c++) { if ((Child=Father->Child[c])==NULL) /* we may stop the propagation 2 ways: either */ break; if (Father->g+1 < Child->g) /* there are no children, or that the g value of */ { /* the child is equal or better than the cost we're propagating */ Child->g=Father->g+1; Child->f=Child->g+Child->h; Child->Parent=Father; Push(Child); } } } } void Push(struct NODE *Node) { struct STACK *tmp; tmp=(struct STACK *)malloc(sizeof(struct STACK)); tmp->NodePtr=Node; tmp->NextStackPtr=Stack->NextStackPtr; Stack->NextStackPtr=tmp; } struct NODE *Pop() { struct NODE *tmp; struct STACK *tmpSTK; tmpSTK=Stack->NextStackPtr; tmp=tmpSTK->NodePtr; Stack->NextStackPtr=tmpSTK->NextStackPtr; free(tmpSTK); return (tmp); } void main() { int x,y,x1,y1,x2,y2,x3,y3,count=0; allegro_init(); install_keyboard(); install_mouse(); install_timer(); set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0); for(x3=0;x3<=640;x3+=32) line(screen,x3,0,x3,480,55); for(y3=0;y3<=480;y3+=32) line(screen,0,y3,640,y3,55); for(y3=0;y3 This A* Pathfinding algorithm I am planning to use in a Warcraft II type game, the problem is, it doesn't work.......Sometimes I will be able to find the paths but sometimes it gives me SIGSEGV crash messages.....NOTE, this program that follows is just a program that allows you to place blockades, a start and an end position to find the fastest route from one point to another around those obstacles, it uses allegro for the graphics, and a specialized version of MikMod, because of this you will be unable to recompile the code without removing the #include <mikmod.h>.....The line that is faulty (claimed by symify is highlighted RED) Here is the symify output:

Shutting down Allegro
Exiting due to signal SIGSEGV
General Protection Fault at eip=000019d0
eax=fffe6485 ebx=00000000 ecx=00000003 edx=000000b7 esi=00000009 edi=00000001
ebp=001297df esp=001297df program=C:\DJGPP\SOURCE\PROJECTS\ASTAR\ASTAR.EXE
cs: sel=00af  base=82e15000  limit=0015ffff
ds: sel=00b7  base=82e15000  limit=0015ffff
es: sel=00b7  base=82e15000  limit=0015ffff
fs: sel=00c7  base=00000000  limit=ffffffff
gs: sel=00c7  base=00000000  limit=ffffffff
ss: sel=00b7  base=82e15000  limit=0015ffff
 
Call frame traceback EIPs:
  0x000019d0   _CheckCLOSED+16, line 302 of mypath.c
  0x00001900   _GenerateSucc+104, line 240 of mypath.c
  0x00001791   _GenerateSuccessors+49, line 163 of mypath.c
  0x0000171f   _FindPath+151, line 121 of mypath.c
  0x00001fd9   _main+997, line 437 of mypath.c
  0x00013b72   ___crt1_startup+138
 
And here is the source code:

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <math.h>
#include <string.h>
#include <sys/farptr.h>
#include <sys/segments.h>
#include <sys/movedata.h>
#include <mikmod.h>
#include <allegro.h>
#include <time.h>

#define COLS 20
#define ROWS 15
#define TOTAL_TILES ROWS*COLS
#define TILESIZE 1

int TileMap[TOTAL_TILES];
int FINISHED=0;

typedef int boolean;

struct NODE {
    long f,h;
    int g,tmpg;
    int x,y;
    int NodeNum;
    struct NODE *Parent;
    struct NODE *Child[8];       /* a node may have upto 8+(NULL) children. */
    struct NODE *NextNode;       /* for filing purposes */
};

struct NODE *OPEN;
struct NODE *CLOSED;

struct STACK {
    struct NODE *NodePtr;
    struct STACK *NextStackPtr;
};

struct STACK *Stack;

unsigned _stklen = 1048567;

boolean FreeTile(int x, int y);
int TileNum(int x, int y);
struct NODE *FindPath(long sx,long sy,long dx,long dy);
struct NODE *ReturnBestNode(void);
void GenerateSuccessors(struct NODE *BestNode,long dx,long dy);
void GenerateSucc(struct NODE *BestNode,long x, long y, long dx, long dy);
struct NODE *CheckOPEN(int tilenum);
struct NODE *CheckCLOSED(int tilenum);
void Insert(struct NODE *Successor);
void PropagateDown(struct NODE *Old);
void Push(struct NODE *Node);
struct NODE *Pop(void);

int TileNum(int x, int y)
{
  return ((y*20)+x);
}

boolean FreeTile(int x, int y)
{             //  returns 1 if tile is free(nothing on it).
       //  Note: if TileMap[equation]==0 it means free so just !(not) it.
  return (!TileMap[(y*20)+x]);
}

void DisplayPath(int x1, int y1, int x2, int y2)
{
  struct NODE *path, *Node;
  int lx=x2,ly=y2;

  path=(struct NODE *)FindPath((long)x1,(long)y1,(long)x2,(long)y2);

  while (path->Parent != NULL)
  {
     path=path->Parent;
     line(screen,lx*32+16,ly*32+16,path->x*32+16,path->y*32+16,44);
     lx=path->x;
     ly=path->y;
  }
  line(screen,lx*32+16,ly*32+16,path->x*32+16,path->y*32+16,44);

  // Free Nodes up
  Node=OPEN->NextNode;
  while (Node != NULL)
  {
     free(Node);
     Node=Node->NextNode;
  }
  Node=CLOSED->NextNode;
  while (Node != NULL)
  {
     free(Node);
     Node=Node->NextNode;
  }
}

struct NODE *FindPath(long sx,long sy,long dx,long dy)
{
    struct NODE *Node, *BestNode;
    int TileNumDest;

    TileNumDest=TileNum((int)dx,(int)dy);

    OPEN=(struct NODE *)malloc(sizeof( struct NODE ));
    CLOSED=(struct NODE *)malloc(sizeof( struct NODE ));

    Node=(struct NODE *)malloc(sizeof( struct NODE ));
    Node->g=0;
    Node->h=(sx-dx)*(sx-dx)+(sy-dy)*(sy-dy);  // should really use sqrt().
    Node->f=Node->g+Node->h;
    Node->NodeNum=TileNum((int)sx,(int)sy);
    Node->x=sx;
    Node->y=sy;
    Node->NextNode=NULL;

    OPEN->NextNode=Node;        /* make Open List point to first node */
    for (;;)
    {
  BestNode=(struct NODE *)ReturnBestNode();
    if (BestNode->NodeNum == TileNumDest)    /* if we've found the end, break and finish */
       break;
  GenerateSuccessors(BestNode,dx,dy);
    }
    return (BestNode);
}

struct NODE *ReturnBestNode(void)
{
    struct NODE *tmp;

    if (OPEN->NextNode == NULL)
  {
     exit(0);
  }

    /* Pick Node with lowest f, in this case it's the first node in list
    because we sort the OPEN list wrt lowest f. Call it BESTNODE. */

    tmp=OPEN->NextNode;   // point to first node on OPEN
    OPEN->NextNode=tmp->NextNode;    // Make OPEN point to nextnode or NULL.

    /* Next take BESTNODE (or temp in this case) and put it on CLOSED */

    tmp->NextNode=CLOSED->NextNode;
    CLOSED->NextNode=tmp;

    return(tmp);
}

void GenerateSuccessors(struct NODE *BestNode,long dx,long dy)
{
    long x,y;

      /* Upper-Left  */
    x=(long)BestNode->x-TILESIZE;
    y=(long)BestNode->y-TILESIZE;
    if(x>0 && x<COLS && y>0 && y<ROWS)
       if (FreeTile(x,y))
          GenerateSucc(BestNode,x,y,dx,dy);

      /* Upper       */
    x=(long)BestNode->x;
    y=(long)BestNode->y-TILESIZE;
    if(x>0 && x<COLS && y>0 && y<ROWS)
       if (FreeTile(x,y))
          GenerateSucc(BestNode,x,y,dx,dy);

      /* Upper-Right */
    x=(long)BestNode->x+TILESIZE;
    y=(long)BestNode->y-TILESIZE;
    if(x>0 && x<COLS && y>0 && y<ROWS)
       if (FreeTile(x,y))
          GenerateSucc(BestNode,x,y,dx,dy);

      /* Right       */
    x=(long)BestNode->x+TILESIZE;
    y=(long)BestNode->y;
    if(x>0 && x<COLS && y>0 && y<ROWS)
       if (FreeTile(x,y))
          GenerateSucc(BestNode,x,y,dx,dy);

      /* Lower-Right */
    x=(long)BestNode->x+TILESIZE;
    y=(long)BestNode->y+TILESIZE;
    if(x>0 && x<COLS && y>0 && y<ROWS)
       if (FreeTile(x,y))
          GenerateSucc(BestNode,x,y,dx,dy);

      /* Lower       */
    x=(long)BestNode->x;
    y=(long)BestNode->y+TILESIZE;
    if(x>0 && x<COLS && y>0 && y<ROWS)
       if (FreeTile(x,y))
          GenerateSucc(BestNode,x,y,dx,dy);

      /* Lower-Left  */
    x=(long)BestNode->x-TILESIZE;
    y=(long)BestNode->y+TILESIZE;
    if(x>0 && x<COLS && y>0 && y<ROWS)
       if (FreeTile(x,y))
          GenerateSucc(BestNode,x,y,dx,dy);

      /* Left        */
    x=(long)BestNode->x-TILESIZE;
    y=(long)BestNode->y;
    if(x>0 && x<COLS && y>0 && y<ROWS)
       if (FreeTile(x,y))
          GenerateSucc(BestNode,x,y,dx,dy);
}

void GenerateSucc(struct NODE *BestNode,long x, long y, long dx, long dy)
{
    int g,TileNumS,c=0;
    struct NODE *Old,*Successor;

    g=BestNode->g+1;     /* g(Successor)=g(BestNode)+cost of getting from BestNode to Successor */
    TileNumS=TileNum((int)x,(int)y);  /* identification purposes */

    if ((Old=CheckOPEN(TileNumS)) != NULL) /* if equal to NULL then not in OPEN list, else it returns the Node in Old */
    {
       for(c=0;c<8;c++)
        if(BestNode->Child[c] == NULL) /* Add Old to the list of BestNode's Children (or Successors). */
           break;
     BestNode->Child[c]=Old;
 

     if (g < Old->g)  /* if our new g value is < Old's then reset Old's parent to point to BestNode */
     {
        Old->Parent=BestNode;
        Old->g=g;
        Old->f=g+Old->h;
     }
    }
    else if ((Old=CheckCLOSED(TileNumS)) != NULL) /* if equal to NULL then not in OPEN list, else it returns the Node in Old */
    {
       for(c=0;c<8;c++)
        if (BestNode->Child[c] == NULL) /* Add Old to the list of BestNode's Children (or Successors). */
           break;
       BestNode->Child[c]=Old;

     if (g < Old->g)  /* if our new g value is < Old's then reset Old's parent to point to BestNode */
       {
        Old->Parent=BestNode;
        Old->g=g;
        Old->f=g+Old->h;
        PropagateDown(Old);       /* Since we changed the g value of Old, we need
      to propagate this new value downwards, i.e.
      do a Depth-First traversal of the tree! */
      }
    }
    else
    {
     Successor=(struct NODE *)malloc(sizeof( struct NODE ));
     Successor->Parent=BestNode;
     Successor->g=g;
     Successor->h=(x-dx)*(x-dx)+(y-dy)*(y-dy);  // should do sqrt(), but since we don't really
     Successor->f=g+Successor->h;     // care about the distance but just which branch looks
     Successor->x=x;                  // better this should suffice. Anyayz it's faster.
     Successor->y=y;
     Successor->NodeNum=TileNumS;
     Insert(Successor);     /* Insert Successor on OPEN list wrt f */
     for(c=0;c<8;c++)
        if (BestNode->Child[c] == NULL) /* Add Old to the list of BestNode's Children (or Successors). */
           break;
     BestNode->Child[c]=Successor;
    }
}

struct NODE *CheckOPEN(int tilenum)
{
    struct NODE *tmp;

    tmp=OPEN->NextNode;
    while (tmp != NULL)
    {
     if (tmp->NodeNum == tilenum)
        return (tmp);
     else
        tmp=tmp->NextNode;
    }
    return (NULL);
}

struct NODE *CheckCLOSED(int tilenum)
{
    struct NODE *tmp;

    tmp=CLOSED->NextNode;

    while (tmp != NULL)
    {
      if (tmp->NodeNum == tilenum)
        return (tmp);
     else
        tmp=tmp->NextNode;
    }
    return (NULL);
}

void Insert(struct NODE *Successor)
{
    struct NODE *tmp1,*tmp2;
    long f;

    if (OPEN->NextNode == NULL)
    {
       OPEN->NextNode=Successor;
       return;
    }

       /* insert into OPEN successor wrt f */

    f=Successor->f;
    tmp1=OPEN;
    tmp2=OPEN->NextNode;

    while ((tmp2 != NULL) && (tmp2->f < f))
    {
       tmp1=tmp2;
       tmp2=tmp2->NextNode;
    }
  Successor->NextNode=tmp2;
  tmp1->NextNode=Successor;
}

void PropagateDown(struct NODE *Old)
{
    int c,g;
    struct NODE *Child, *Father;

    g=Old->g;            // alias.
    for(c=0;c<8;c++)
    {
       if ((Child=Old->Child[c])==NULL)   // create alias for faster access.
          break;
     if (g+1 < Child->g)
     {
        Child->g=g+1;
        Child->f=Child->g+Child->h;
        Child->Parent=Old;           // reset parent to new path.
        Push(Child);                 // Now the Child's branch need to be
       }     // checked out. Remember the new cost must be propagated down.
    }

    while (Stack->NextStackPtr != NULL)
    {
     Father=Pop();
     for(c=0;c<8;c++)
     {
        if ((Child=Father->Child[c])==NULL)       /* we may stop the propagation 2 ways: either */
           break;
        if (Father->g+1 < Child->g) /* there are no children, or that the g value of */
        {                           /* the child is equal or better than the cost we're propagating */
           Child->g=Father->g+1;
           Child->f=Child->g+Child->h;
           Child->Parent=Father;
           Push(Child);
        }
       }
    }
}

void Push(struct NODE *Node)
{
    struct STACK *tmp;

    tmp=(struct STACK *)malloc(sizeof(struct STACK));
    tmp->NodePtr=Node;
    tmp->NextStackPtr=Stack->NextStackPtr;
    Stack->NextStackPtr=tmp;
}

struct NODE *Pop()
{
    struct NODE *tmp;
    struct STACK *tmpSTK;

    tmpSTK=Stack->NextStackPtr;
    tmp=tmpSTK->NodePtr;

    Stack->NextStackPtr=tmpSTK->NextStackPtr;
    free(tmpSTK);
    return (tmp);
}

void main()
{
   int x,y,x1,y1,x2,y2,x3,y3,count=0;
   allegro_init();
   install_keyboard();
   install_mouse();
   install_timer();
   set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0);

   for(x3=0;x3<=640;x3+=32)
      line(screen,x3,0,x3,480,55);
   for(y3=0;y3<=480;y3+=32)
      line(screen,0,y3,640,y3,55);

   for(y3=0;y3<ROWS;y3++)
      for(x3=0;x3<COLS;x3++)
         TileMap[(y3*20)+x3] = 0;

   while(!FINISHED)       // loop until ESC key hit
   {
      show_mouse(NULL);
      if(mouse_b & 1)
         {
         TileMap[((mouse_y/32)*20)+(mouse_x/32)]=1;
         rectfill(screen, (mouse_x/32)*32,(mouse_y/32)*32,(mouse_x/32)*32+32,(mouse_y/32)*32+32,55);
         }
    if(key[KEY_X])
       {
         circlefill(screen,((mouse_x/32)*32)+16,((mouse_y/32)*32)+16,16,32);

         if(count==0)
       {
            x=(mouse_x/32);
            y=(mouse_y/32);
            count++;
         }
         else if(count==1)
         {
            x1=(mouse_x/32);
            y1=(mouse_y/32);
            count=0;
          DisplayPath(x,y,x1,y1);
         }
       }

    if(key[KEY_ESC])
       FINISHED=1;

      show_mouse(screen);
      rest(300);
   }

   exit(0);
}

---------------------
Matt Reiferson
MReiferson AT aol DOT com
RingMaster: Game Programmers Guild
URL: http://gpg.home.ml.org
WebMaster: The Game Programming MegaSite
URL: http://gpmega.home.ml.org
---------------------
"See You On The Other Side........"
  -Ozzy
  --------------46003C0AF10F5A060574AABD--