www.pudn.com > back.rar > cwayai.cpp


#include  
#include  
 
#include "base.h" 
#include "xblock_table.h" 
#include "skill.h" 
 
#include "../CUserInfo/userinfo.h" 
#include "npc.h" 
#include "xblock.h" 
#include "MAP.H" 
 
#include "Clock.H" 
#include "party.h" 
//#include "skill.h" 
#include "trade.h" 
#include "buy.h" 
#include "sell.h" 
#include "guild.h" 
#include "PrivateShop.h"	//ÀÓâ¿ø Ãß°¡. 
 
#include "server.h" 
#include "Main.H" 
#include "CWayAi.h" 
 
/**************************************************************************/ 
/*                            STACK FUNCTIONS                             */ 
/**************************************************************************/ 
void CWayAi::Push(NODE *Node)	{					// ... 
    AI_STATIC *tmp; 
 
    tmp=( AI_STATIC *)calloc(1,sizeof(AI_STATIC)); 
    tmp->NodePtr=Node; 
    tmp->NextStackPtr=Stack->NextStackPtr; 
    Stack->NextStackPtr=tmp; 
} 
NODE* CWayAi::Pop()	{								// ... 
    NODE *tmp; 
    AI_STATIC *tmpSTK; 
 
    tmpSTK=Stack->NextStackPtr; 
    tmp=tmpSTK->NodePtr; 
 
    Stack->NextStackPtr=tmpSTK->NextStackPtr; 
    free(tmpSTK); 
    return (tmp); 
} 
 
/**************************************************************************/ 
/***************************** A* Algorithm *******************************/ 
/**************************************************************************/ 
void CWayAi::PropagateDown(NODE *Old)	{			// °¡ÁöÀÇ ÀüÆÄ... 
    int c,g; 
    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 CWayAi::Insert(NODE *Successor)	{					// ...??? 
    NODE *tmp1,*tmp2; 
    int 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;  // ÀÚ½ÅÀº »çÀÌ¿¡ µé¾î°£´Ù. 
} 
 
 
// °¢°¢ÀÇ ³ëµå¿¡ ´ëÇÏ¿© ¿­¸° °ªÀÌÁö üũÇÑ´Ù.??? 
NODE* CWayAi::CheckOPEN(int tilenum)	{ 
    NODE *tmp; 
    tmp=OPEN->NextNode; 
    while (tmp != NULL) { 
        if (tmp->NodeNum == tilenum) 
            return (tmp); 
        else 
            tmp=tmp->NextNode; 
    } 
    return (NULL); 
} 
// °¢°¢ÀÇ ³ëµå¿¡ ´ëÇÏ¿© ´ÝÈù °ªÀÎÁö üũÇÑ´Ù.??? 
NODE* CWayAi::CheckCLOSED(int tilenum)	{ 
    NODE *tmp; 
    tmp=CLOSED->NextNode; 
    while (tmp != NULL) { 
        if (tmp->NodeNum == tilenum) 
            return (tmp); 
        else 
            tmp=tmp->NextNode; 
    } 
    return (NULL); 
} 
 
// °¢°¢ ŸÀÏÀÇ ±æÃ£±â test ¼º°ø... 
void CWayAi::GenerateSucc(NODE *BestNode, int x, int y, int dx, int dy)	{ 
    int g,TileNumS,c=0; 
    NODE *Old,*Successor; 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<" GenerateSucc ½ÃÀÛ \r\n"; 
#endif 
 
    g=BestNode->g+1;    // g(Successor)=g(BestNode)+cost of getting from BestNode to Successor 
    TileNumS=y*COLS+x;	// 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=(NODE *)calloc(1,sizeof( 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; 
 
    } 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<" GenerateSucc ³¡ \r\n"; 
#endif 
 
} 
 
 
bool CWayAi::isTile(int x, int y)  
{ 
	// 1 -> ¿ÀºêÁ§Æ®. 2 -> PC, 3 -> NPC 
	if( x < 0 || y < 0 ||  
		x >= Line[tmap->m_map_size] || y >= Line[tmap->m_map_size] ||  
//		tmap->m_use_path[ x ][ y ] == (char)OBJECT_TILE || tmap->m_use_path[ x ][ y ] == (char)PC_TILE || 
//		tmap->m_use_path[ x ][ y ] == (char)NPC_TILE ) 
		tmap->m_block_table[x][y].bBlocked || tmap->m_block_table[x][y].bNPC || tmap->m_block_table[x][y].bPC || // tmap->m_block_table[x][y].bITEM ||  
		tmap->m_block_table[x][y].bSNPC ) 
		return false; 
	return true; 
} 
 
// ¹æÇâ º°·Î ±æÀ» ã¾Æº»´Ù... 
void CWayAi::GenerateSuccessors(NODE *BestNode,int dx,int dy)	 
{ 
	int tx,ty; 
 #if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<" GenerateSuccessors½ÃÀÛ \r\n"; 
#endif 
 
	// Upper-Left...(´ë°¢¼± ÁÂÃøÀ¸·Î °¥¼ö ÀÖ´Ù¸é...) 
	tx = BestNode->x-1; 
	ty = BestNode->y-1; 
	if( isTile( tx, ty ) )	 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
    
	// Upper... 
	tx=BestNode->x; 
	ty=BestNode->y-1; 
    if (isTile( tx, ty ) )		 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
     
	// Upper-Right... 
	tx =BestNode->x+1; 
	ty = BestNode->y-1; 
	if( isTile( tx, ty ) ) 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
  
	// Right... 
	tx=BestNode->x+1; 
	ty=BestNode->y; 
    if (isTile( tx, ty ))		 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
   
	// Lower-Right... 
	tx=BestNode->x+1; 
	ty=BestNode->y+1; 
	if( isTile( tx, ty ) )	 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
    
	// Lower... 
	tx=BestNode->x; 
	ty=BestNode->y+1; 
    if ( isTile( tx, ty ) )		 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
  
	// Lower-Left... 
	tx=BestNode->x-1; 
	ty=BestNode->y+1; 
	if( isTile( tx, ty ) ) 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
   
	// Left... 
	tx=BestNode->x-1; 
	ty=BestNode->y; 
    if ( isTile( tx, ty ) )		 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<" GenerateSuccessors³¡ \r\n"; 
#endif 
 
} 
 
 
// ±æÃ£±â Áß¿¡¼­ ¸·´Ù¸¦ ±æÀ» ã¾Ò´Ù¸é, ÀÌÀü ±æÀ» ¼±ÅÃÇÑ´Ù... 
NODE* CWayAi::ReturnBestNode(void)	{ 
    NODE *tmp; 
////////////////////////////////////////////////////////////////////////////////////////////////////////// 
    if (OPEN->NextNode == NULL) {							// ±æÀ» ¸øÃ£À»¶§... 
//	    printf("ERROR: no more nodes on OPEN\n"); 
//	    exit(0); 
		return NULL; 
	} 
 
/* 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); 
} 
 
 
// ±æÃ£±â¸¦ ½ÃÀÛÇÑ´Ù. 
NODE* CWayAi::FindPath(int sx,int sy,int dx,int dy, NPC_STATUS status )	{ 
    NODE *Node, *BestNode; 
    int TileNumDest; 
	int Depth=0; 
 
    TileNumDest=dy*COLS+dx; 
 
    OPEN=(NODE *)calloc(1,sizeof( NODE )); 
    CLOSED=(NODE *)calloc(1,sizeof( NODE )); 
 
    Node=(NODE *)calloc(1,sizeof( 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=sy*COLS+sx; 
    Node->x=sx; 
    Node->y=sy; 
 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"±æÃ£±â ³ëµåÇÒ´ç ³¡, ·çÇÁ µ¹±â \r\n"; 
#endif 
    OPEN->NextNode=Node;						 /* make Open List point to first node */ 
    for (;;) { 
		BestNode=(NODE *)ReturnBestNode(); 
		// ³»°¡ 
		if( BestNode == NULL ) 
			return NULL; 
 
        if (BestNode->NodeNum == TileNumDest)    /* if we've found the end, break and finish */ 
            break; 
 
		else if( (abs( BestNode->x - dx ) <= 1 && abs( BestNode->y - dy ) <= 1) ) 
		{ 
//			if ( tmap->m_use_path[dx][dy] == (char)PC_TILE  
//				|| tmap->m_use_path[dx][dy] == (char)NPC_TILE  
//				|| tmap->m_use_path[dx][dy] == (char)OBJECT_TILE )	// ´ÙÀ½ À§Ä¡¿¡ ¸Õ°¡ ÀÖÀ¸¸é ¸ø°¡ ½ºÅé 
			if( tmap->m_block_table[dx][dy].bBlocked || tmap->m_block_table[dx][dy].bNPC || tmap->m_block_table[dx][dy].bPC || tmap->m_block_table[dx][dy].bSNPC )//tmap->m_block_table[x][y].bITEM ||  
				break; 
//			else continue;		// 0->ºó°÷À̸é Çѹø ´õ µ¹¾Æ¼­ ³¡±îÁö µµÂø 
		} 
 
		else GenerateSuccessors(BestNode,dx,dy); 
		/// ±íÀÌ ÇѰ踦 µÑ¶§.....................................................................		 
		if( DEPTH<++Depth )	{ 
			bWayPossibled = false; 
			break; 
		} 
    } 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"·çÇÁ µ¹±â ³¡\r\n"; 
#endif 
 
    return (BestNode); 
} 
 
// ±æÃ£±â ±¸Á¶Ã¼ ¼³Á¤... 
NODE* CWayAi::SearchWay( int x, int y, int dx, int dy, NPC_STATUS status )		{ 
	NODE *path; 
	bWayPossibled = true; 
	Stack=( AI_STATIC *)calloc(1,sizeof(AI_STATIC));  // setup the Stack. 
	path=FindPath(x,y,dx,dy, status ); 
	Exe = true; 
 
	if( bWayPossibled ) 
		return (path); 
	else  
	{ 
		path = NULL; 
		return (path); 
	} 
 
	return (path); 
 
} 
 
// 3-21 ¿ø°Å¸®°ø°Ý ¸¶¹ýµî 
DWORD	CWayAi::Return_Distance( int x, int y, int dx, int dy ) 
{ 
	bWayPossibled = true; 
	Stack=( AI_STATIC *)calloc(1,sizeof(AI_STATIC));  // setup the Stack. 
//	path=FindPath(dx,dy,x,y);	// ¸ñÇ¥Á¡, ½ÃÀÛÁ¡. 
	DWORD dist=FindPath_Distance(x,y,dx,dy); 
 
	return dist; 
} 
 
DWORD CWayAi::FindPath_Distance( int sx, int sy, int dx, int dy ) 
{ 
	int count=0; 
    NODE *Node, *BestNode; 
    int TileNumDest; 
	int Depth=0; 
 
    TileNumDest=dy*COLS+dx; 
 
    OPEN=(NODE *)calloc(1,sizeof( NODE )); 
    CLOSED=(NODE *)calloc(1,sizeof( NODE )); 
 
    Node=(NODE *)calloc(1,sizeof( 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=sy*COLS+sx; 
    Node->x=sx; 
    Node->y=sy; 
 
    OPEN->NextNode=Node;						 /* make Open List point to first node */ 
    for (;;) { 
		BestNode=(NODE *)ReturnBestNode(); 
		// ³»°¡ 
		if( BestNode == NULL ) 
			return 0; 
 
        if (BestNode->NodeNum == TileNumDest)    /* if we've found the end, break and finish */ 
            break; 
 
//		else if( (abs( BestNode->x - dx ) <= 1 && abs( BestNode->y - dy ) <= 1) ) 
//		{ 
//			if ( tmap->m_use_path[dx][dy] == (char)OBJECT_TILE )	// object 
			if( tmap->m_block_table[dx][dy].bBlocked ) 
			{ 
				count = dx + dy*COLS; 
				break; 
			} 
//		} 
 
		else GenerateSuccMy(BestNode,dx,dy); 
		count++; 
 		/// ±íÀÌ ÇѰ踦 µÑ¶§.....................................................................		 
		if( DEPTH<++Depth )	{ 
			bWayPossibled = false; 
			break; 
		} 
   } 
    return count; 
 
} 
 
void CWayAi::GenerateSuccMy(NODE *BestNode,int dx,int dy) 
{ 
	int tx,ty; 
  
	// Upper-Left...(´ë°¢¼± ÁÂÃøÀ¸·Î °¥¼ö ÀÖ´Ù¸é...) 
	tx = BestNode->x-1; 
	ty = BestNode->y-1; 
	if( isTileMy( tx, ty ) )	 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
    
	// Upper... 
	tx=BestNode->x; 
	ty=BestNode->y-1; 
    if (isTileMy( tx, ty ) )		 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
     
	// Upper-Right... 
	tx =BestNode->x+1; 
	ty = BestNode->y-1; 
	if( isTileMy( tx, ty ) ) 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
  
	// Right... 
	tx=BestNode->x+1; 
	ty=BestNode->y; 
    if (isTileMy( tx, ty ))		 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
   
	// Lower-Right... 
	tx=BestNode->x+1; 
	ty=BestNode->y+1; 
	if( isTileMy( tx, ty ) )	 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
    
	// Lower... 
	tx=BestNode->x; 
	ty=BestNode->y+1; 
    if ( isTileMy( tx, ty ) )		 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
  
	// Lower-Left... 
	tx=BestNode->x-1; 
	ty=BestNode->y+1; 
	if( isTileMy( tx, ty ) ) 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
   
	// Left... 
	tx=BestNode->x-1; 
	ty=BestNode->y; 
    if ( isTileMy( tx, ty ) )		 
		GenerateSucc(BestNode,tx,ty,dx,dy); 
 
} 
 
bool CWayAi::isTileMy( int x, int y ) 
{ 
	if( x < 0 || y < 0 ||  
		x >= Line[tmap->m_map_size] || y >= Line[tmap->m_map_size] ||  
//		tmap->m_use_path[ x ][ y ] == (char)OBJECT_TILE ) 
		tmap->m_block_table[x][y].bBlocked ) 
		return false; 
	return true; 
 
} 
 
/////////////////////////////////////////////////////////////////////////////////// 
 
 
 
 
 
// ±æÃ£±â ±¸Á¶Ã¼¸¦ Áö¿î´Ù... 
void CWayAi::DeleteWay( void )	{ 
    NODE *path, *Node; 
 
    // Free Nodes up 
    Node=OPEN;//->NextNode;??? 
    while (Node != NULL) { 
		path=Node; 
        Node=Node->NextNode; 
		free(path); 
		path = NULL; 
    } 
    Node=CLOSED;//->NextNode;??? 
    while (Node != NULL) { 
		path=Node; 
        Node=Node->NextNode; 
		free(path); 
		path = NULL; 
    } 
/* 
	if( Stack != NULL ) 
	{ 
		free( Stack ); 
		Stack = NULL; 
	} 
*/ 
	free( Stack ); 
	Stack = NULL; 
	Exe = false; 
} 
 
// ±æÃ£±â °¡´É Áö¿ªÀΰ¡ ÆÇÁ¤... 
bool CWayAi::CheckPossablePoint( int dx, int dy )	{ 
	// °¥¼ö ¾ø´Â Áö¿ªÀ̸é, °Ë»ö Ãë¼Ò... 
//	if( tmap->m_use_path[dx][dy*COLS] == (char)OBJECT_TILE )	return false;	 
	if( tmap->m_block_table[dx][dy].bBlocked ) return false; 
	return true; 
} 
 
// Å«¸÷ ±æÃ£±â 
// ±æÃ£±â ±¸Á¶Ã¼ ¼³Á¤... 
NODE* CWayAi::BigSearchWay( int x, int y, int dx, int dy, NPC_SIZE size, int nPos, bool bSummon ) 
{ 
	NODE *path; 
	bWayPossibled = true; 
	Stack=( AI_STATIC *)calloc(1,sizeof(AI_STATIC));  // setup the Stack. 
	path=BigFindPath(x,y,dx,dy, size, nPos, bSummon ); 
	Exe = true; 
 
	if( bWayPossibled ) 
		return (path); 
	else  
	{ 
		path = NULL; 
		return (path); 
	} 
 
	return (path); 
} 
 
NODE* CWayAi::BigFindPath( int sx, int sy, int dx, int dy, NPC_SIZE size, int nPos, bool bSummon ) 
{ 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"Bigfindpath ½ÃÀÛ \r\n"; 
#endif 
    NODE *Node, *BestNode; 
    int TileNumDest; 
	int Depth=0; 
 
    TileNumDest=dy*COLS+dx; 
 
    OPEN=(NODE *)calloc(1,sizeof( NODE )); 
	CLOSED=(NODE *)calloc(1,sizeof( NODE )); 
 
    Node=(NODE *)calloc(1,sizeof( 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=sy*COLS+sx; 
    Node->x=sx; 
    Node->y=sy; 
 
    OPEN->NextNode=Node;						 /* make Open List point to first node */ 
    for (;;) { 
		BestNode=(NODE *)ReturnBestNode(); 
		if( BestNode == NULL ) 
			return NULL; 
 
        if (BestNode->NodeNum == TileNumDest)    /* if we've found the end, break and finish */ 
            break; 
 
//		else if( (abs( BestNode->x - dx ) <= 1 && abs( BestNode->y - dy ) <= 1) ) 
		else if( ((abs( BestNode->x - dx ) <= 1 && abs( BestNode->y - dy ) <= 1)) ||  
			((abs( BestNode->x - dx ) <= 1 && abs( BestNode->y - dy ) == 0)) ||  
			((abs( BestNode->x - dx ) == 0 && abs( BestNode->y - dy ) <= 1)) ) 
		{ 
//			if ( tmap->m_use_path[dx][dy] == (char)PC_TILE  
//				|| tmap->m_use_path[dx][dy] == (char)NPC_TILE 
//				|| tmap->m_use_path[dx][dy] == (char)OBJECT_TILE )	// ´ÙÀ½ À§Ä¡¿¡ ¸Õ°¡ ÀÖÀ¸¸é ¸ø°¡ ½ºÅé 
			if( tmap->m_block_table[dx][dy].bBlocked || //tmap->m_block_table[dx][dy].bITEM || 
				tmap->m_block_table[dx][dy].bNPC || tmap->m_block_table[dx][dy].bPC || tmap->m_block_table[dx][dy].bSNPC ) 
				break; 
//			else continue;		// 0->ºó°÷À̸é Çѹø ´õ µ¹¾Æ¼­ ³¡±îÁö µµÂø 
		} 
		else BigGenerateSuccessors( BestNode, dx, dy, size, nPos, bSummon ); 
		/// ±íÀÌ ÇѰ踦 µÑ¶§.....................................................................		 
		if( DEPTH<++Depth )	{ 
			bWayPossibled = false; 
			break; 
		} 
    } 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"Bigfindpath end \r\n"; 
#endif 
 
    return (BestNode); 
} 
 
 
bool CWayAi::BigisTile(int x, int y, NPC_SIZE size, int nPos, bool bSummon )  
{ 
	if( x == Line[tmap->m_map_size]-1 || y == Line[tmap->m_map_size]-1 || 
		x == Line[tmap->m_map_size] || y == Line[tmap->m_map_size] || 
		x <= 0 || y <= 0  
		) 
		return false; 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"BigisTile start \r\n"; 
#endif 
	if( bSummon ) 
	{ 
		if( tmap->m_block_table[x][y].bBlocked == true ||  
//			tmap->m_block_table[x][y].bITEM == true || 
			tmap->m_block_table[x][y].bPC == true || 
			tmap->m_block_table[x][y].bNPC == true || 
			( tmap->m_block_table[x][y].bSNPC == true && tmap->m_block_table[x][y].nArrayNo != nPos && tmap->m_block_table[x][y].nArrayNo != -1 ) 
			) 
			return false; 
		if( tmap->m_block_table[x+1][y].bBlocked == true ||  
//			tmap->m_block_table[x+1][y].bITEM == true || 
			tmap->m_block_table[x+1][y].bPC == true || 
			tmap->m_block_table[x+1][y].bNPC == true || 
			( tmap->m_block_table[x+1][y].bSNPC == true && tmap->m_block_table[x+1][y].nArrayNo != nPos && tmap->m_block_table[x+1][y].nArrayNo != -1 ) 
			) 
			return false; 
		if( tmap->m_block_table[x][y+1].bBlocked == true ||  
//			tmap->m_block_table[x][y+1].bITEM == true || 
			tmap->m_block_table[x][y+1].bPC == true || 
			tmap->m_block_table[x][y+1].bNPC == true || 
			( tmap->m_block_table[x][y+1].bSNPC == true && tmap->m_block_table[x][y+1].nArrayNo != nPos && tmap->m_block_table[x][y+1].nArrayNo != -1 ) 
			) 
			return false; 
		if( tmap->m_block_table[x+1][y+1].bBlocked == true ||  
//			tmap->m_block_table[x+1][y+1].bITEM == true || 
			tmap->m_block_table[x+1][y+1].bPC == true || 
			tmap->m_block_table[x+1][y+1].bNPC == true || 
			( tmap->m_block_table[x+1][y+1].bSNPC == true && tmap->m_block_table[x+1][y+1].nArrayNo != nPos && tmap->m_block_table[x+1][y+1].nArrayNo != -1 ) 
			) 
			return false; 
	} 
	else 
	{ 
		if( tmap->m_block_table[x][y].bBlocked == true ||  
//			tmap->m_block_table[x][y].bITEM == true || 
			tmap->m_block_table[x][y].bPC == true || 
			tmap->m_block_table[x][y].bSNPC == true || 
			( tmap->m_block_table[x][y].bNPC == true && tmap->m_block_table[x][y].nArrayNo != nPos && tmap->m_block_table[x][y].nArrayNo != -1 ) 
			) 
			return false; 
		if( tmap->m_block_table[x+1][y].bBlocked == true ||  
//			tmap->m_block_table[x+1][y].bITEM == true || 
			tmap->m_block_table[x+1][y].bPC == true || 
			tmap->m_block_table[x+1][y].bSNPC == true || 
			( tmap->m_block_table[x+1][y].bNPC == true && tmap->m_block_table[x+1][y].nArrayNo != nPos && tmap->m_block_table[x+1][y].nArrayNo != -1 ) 
			) 
			return false; 
		if( tmap->m_block_table[x][y+1].bBlocked == true ||  
//			tmap->m_block_table[x][y+1].bITEM == true || 
			tmap->m_block_table[x][y+1].bPC == true || 
			tmap->m_block_table[x][y+1].bSNPC == true || 
			( tmap->m_block_table[x][y+1].bNPC == true && tmap->m_block_table[x][y+1].nArrayNo != nPos && tmap->m_block_table[x][y+1].nArrayNo != -1 ) 
			) 
			return false; 
		if( tmap->m_block_table[x+1][y+1].bBlocked == true ||  
//			tmap->m_block_table[x+1][y+1].bITEM == true || 
			tmap->m_block_table[x+1][y+1].bPC == true || 
			tmap->m_block_table[x+1][y+1].bSNPC == true || 
			( tmap->m_block_table[x+1][y+1].bNPC == true && tmap->m_block_table[x+1][y+1].nArrayNo != nPos && tmap->m_block_table[x+1][y+1].nArrayNo != -1 ) 
			) 
			return false; 
	} 
	return true; 
} 
 
// ¹æÇâ º°·Î ±æÀ» ã¾Æº»´Ù... 
void CWayAi::BigGenerateSuccessors(NODE *BestNode,int dx,int dy, NPC_SIZE size, int nPos, bool bSummon ) 
{ 
	int tx,ty; 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"BigGenerateSuccessors½ÃÀÛ \r\n"; 
#endif 
 
	// Upper-Left...(´ë°¢¼± ÁÂÃøÀ¸·Î °¥¼ö ÀÖ´Ù¸é...) 
	tx = BestNode->x-1; 
	ty = BestNode->y-1; 
	if( BigisTile( tx, ty, size, nPos, bSummon ) )	 
		BigGenerateSucc(BestNode,tx,ty,dx,dy,size,nPos,bSummon); 
    
	// Upper... 
	tx=BestNode->x; 
	ty=BestNode->y-1; 
	if( BigisTile( tx, ty, size, nPos, bSummon ) )	 
		BigGenerateSucc(BestNode,tx,ty,dx,dy,size,nPos,bSummon); 
     
	// Upper-Right... 
	tx =BestNode->x+1; 
	ty = BestNode->y-1; 
	if( BigisTile( tx, ty, size, nPos, bSummon ) )	 
		BigGenerateSucc(BestNode,tx,ty,dx,dy,size,nPos,bSummon); 
  
	// Right... 
	tx=BestNode->x+1; 
	ty=BestNode->y; 
	if( BigisTile( tx, ty, size, nPos, bSummon ) )	 
		BigGenerateSucc(BestNode,tx,ty,dx,dy,size,nPos,bSummon); 
   
	// Lower-Right... 
	tx=BestNode->x+1; 
	ty=BestNode->y+1; 
	if( BigisTile( tx, ty, size, nPos, bSummon ) )	 
		BigGenerateSucc(BestNode,tx,ty,dx,dy,size,nPos,bSummon); 
    
	// Lower... 
	tx=BestNode->x; 
	ty=BestNode->y+1; 
	if( BigisTile( tx, ty, size, nPos, bSummon ) )	 
		BigGenerateSucc(BestNode,tx,ty,dx,dy,size,nPos,bSummon); 
  
	// Lower-Left... 
	tx=BestNode->x-1; 
	ty=BestNode->y+1; 
	if( BigisTile( tx, ty, size, nPos, bSummon ) )	 
		BigGenerateSucc(BestNode,tx,ty,dx,dy,size,nPos,bSummon); 
   
	// Left... 
	tx=BestNode->x-1; 
	ty=BestNode->y; 
	if( BigisTile( tx, ty, size, nPos, bSummon ) )	 
		BigGenerateSucc(BestNode,tx,ty,dx,dy,size,nPos,bSummon); 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"Biggeneratesuccessor end  \r\n"; 
#endif 
} 
 
// °¢°¢ ŸÀÏÀÇ ±æÃ£±â test ¼º°ø... 
void CWayAi::BigGenerateSucc(NODE *BestNode, int x, int y, int dx, int dy, NPC_SIZE size, int nPos, bool bSummon )	 
{ 
    int g,TileNumS,c=0; 
    NODE *Old,*Successor; 
 
    g=BestNode->g+1;    // g(Successor)=g(BestNode)+cost of getting from BestNode to Successor 
    TileNumS=y*COLS+x;	// 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=(NODE *)calloc(1,sizeof( 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; 
    } 
 
} 
 
 
//________________________________________________________________________________ 
// 
// waypoint ±æÃ£±â 
//________________________________________________________________________________ 
// 
NODE* CWayAi::WPSearchWay( int x, int y, int dx, int dy ) 
{ 
	NODE *path; 
	bWayPossibled = true; 
	Stack=( AI_STATIC *)calloc(1,sizeof(AI_STATIC));  // setup the Stack. 
	path=WPFindPath(x,y,dx,dy); 
	Exe = true; 
 
	if( bWayPossibled ) 
		return (path); 
	else  
	{ 
		path = NULL; 
		return (path); 
	} 
 
	return (path); 
} 
 
NODE* CWayAi::WPFindPath( int sx, int sy, int dx, int dy ) 
{ 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"WPfindpath start \r\n"; 
#endif 
    NODE *Node, *BestNode; 
    int TileNumDest; 
	int Depth=0; 
 
    TileNumDest=dy*COLS+dx; 
 
    OPEN=(NODE *)calloc(1,sizeof( NODE )); 
	CLOSED=(NODE *)calloc(1,sizeof( NODE )); 
 
    Node=(NODE *)calloc(1,sizeof( 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=sy*COLS+sx; 
    Node->x=sx; 
    Node->y=sy; 
 
    OPEN->NextNode=Node;						 /* make Open List point to first node */ 
    for (;;) { 
		BestNode=(NODE *)ReturnBestNode(); 
		if( BestNode == NULL ) 
			return NULL; 
 
        if (BestNode->NodeNum == TileNumDest)    /* if we've found the end, break and finish */ 
            break; 
		else WPGenerateSuccessors( BestNode, dx, dy); 
		/// ±íÀÌ ÇѰ踦 µÑ¶§.....................................................................		 
		if( DEPTH<++Depth )	{ 
			bWayPossibled = false; 
			break; 
		} 
    } 
 
    return (BestNode); 
} 
 
 
bool CWayAi::WPisTile(int x, int y ) 
{ 
	if( x < 0 || y < 0 || x >= (COLS/WAYPOINT) || y >= (ROWS/WAYPOINT) )  
		return false; 
	if( tmap->m_WayPoint[x][y] == 0 ) 
		return false; 
 
	return true; 
} 
 
// ¹æÇâ º°·Î ±æÀ» ã¾Æº»´Ù... 
void CWayAi::WPGenerateSuccessors(NODE *BestNode,int dx,int dy ) 
{ 
#if defined ( GENERATE_LOG_PATH_FIND ) 
	g_GameServer.m_output<<"WPgeneratesuccessors start \r\n"; 
#endif 
	int tx,ty; 
	// Upper-Left...(´ë°¢¼± ÁÂÃøÀ¸·Î °¥¼ö ÀÖ´Ù¸é...) 
	tx = BestNode->x-1; 
	ty = BestNode->y-1; 
	if( WPisTile( tx, ty) ) 
		WPGenerateSucc(BestNode,tx,ty,dx,dy); 
    
	// Upper... 
	tx=BestNode->x; 
	ty=BestNode->y-1; 
	if( WPisTile( tx, ty )) 
		WPGenerateSucc(BestNode,tx,ty,dx,dy); 
     
	// Upper-Right... 
	tx =BestNode->x+1; 
	ty = BestNode->y-1; 
	if( WPisTile( tx, ty)) 
		WPGenerateSucc(BestNode,tx,ty,dx,dy); 
  
	// Right... 
	tx=BestNode->x+1; 
	ty=BestNode->y; 
	if( WPisTile( tx, ty)) 
		WPGenerateSucc(BestNode,tx,ty,dx,dy); 
   
	// Lower-Right... 
	tx=BestNode->x+1; 
	ty=BestNode->y+1; 
	if( WPisTile( tx, ty)) 
		WPGenerateSucc(BestNode,tx,ty,dx,dy); 
    
	// Lower... 
	tx=BestNode->x; 
	ty=BestNode->y+1; 
	if( WPisTile( tx, ty)) 
		WPGenerateSucc(BestNode,tx,ty,dx,dy); 
  
	// Lower-Left... 
	tx=BestNode->x-1; 
	ty=BestNode->y+1; 
	if( WPisTile( tx, ty)) 
		WPGenerateSucc(BestNode,tx,ty,dx,dy); 
   
	// Left... 
	tx=BestNode->x-1; 
	ty=BestNode->y; 
	if( WPisTile( tx, ty)) 
		WPGenerateSucc(BestNode,tx,ty,dx,dy); 
} 
 
// °¢°¢ ŸÀÏÀÇ ±æÃ£±â test ¼º°ø... 
void CWayAi::WPGenerateSucc(NODE *BestNode, int x, int y, int dx, int dy ) 
{ 
    int g,TileNumS,c=0; 
    NODE *Old,*Successor; 
 
    g=BestNode->g+1;    // g(Successor)=g(BestNode)+cost of getting from BestNode to Successor 
    TileNumS=y*COLS+x;	// 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=(NODE *)calloc(1,sizeof( 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; 
    } 
 
} 
 
//________________________________________________________________________________ 
// 
// waypoint ±æÃ£±â ³¡ 
//________________________________________________________________________________ 
//