void DestroyLinkedList(struct LinkedList* _List) { LnkLstClear(_List); free(_List); }
/* * Pathfind takes ownership of _Path and then releases ownership of _Path when it calls _Path's callback. */ int PathfindNext(struct PathData* _Path, void* _None) { const struct Tile* _StartTile = MapGetTile(g_GameWorld.MapRenderer, &_Path->Start); const struct Tile* _Goal = MapGetTile(g_GameWorld.MapRenderer, &_Path->End); struct Tile* _Neighbors[TILE_SIZE]; /* * TODO: Remove LinkedList from PathfindNext to remove malloc calls from PathfindNext. */ struct LinkedList _ClosedList = {0, NULL, NULL}; struct LnkLst_Node* _Itr = NULL; struct BinaryHeap _OpenList = {NULL, PATHFIND_OPENSIZE, 0, PathNodeScoreCmp}; struct PathNodeScore* _Current = NULL; _OpenList.Table = PathStackNext(); BinaryHeapInsert(&_OpenList, CreatePathNodeScore(_StartTile, 0, _Path->Heuristic(_StartTile, _Goal), TILE_SIZE, NULL)); while(_OpenList.Size > 0 && _OpenList.Size <= _OpenList.TblSz) { _Current = BinaryHeapTop(&_OpenList); LnkLstPushBack(&_ClosedList, BinaryHeapPop(&_OpenList)); if(_Current->Node->TilePos.x == _Goal->TilePos.x && _Current->Node->TilePos.y == _Goal->TilePos.y) break; /* * Fill the open list with _Tile's neighbors. */ TileGetAdjTiles(g_GameWorld.MapRenderer, _Current->Node, _Neighbors); for(int i = 0; i < TILE_SIZE; ++i) { if(_Neighbors[i] != NULL) { const struct LnkLst_Node* CloseItr = _ClosedList.Front; while(CloseItr != NULL) { const struct PathNodeScore* _Node = (struct PathNodeScore*)CloseItr->Data; if(_Node->Node == _Neighbors[i]) { goto loop_end; } CloseItr = CloseItr->Next; } /* * Check if neighbors are already in open list. */ for(int j = 0; j < _OpenList.Size; ++j) { struct PathNodeScore* _OpenTemp = (struct PathNodeScore*)_OpenList.Table[j]; if(_OpenTemp->Node == _Neighbors[i]) { int _gCost = _Current->g + _Path->Heuristic(_OpenTemp->Node, _Neighbors[i]); if(_gCost < _OpenTemp->g) { _OpenTemp->g = _gCost; BinaryHeapIncrease(&_OpenList, j); } goto loop_end; } } BinaryHeapInsert(&_OpenList, CreatePathNodeScore(_Neighbors[i], _Current->g + 1, _Path->Heuristic(_Neighbors[i], _Goal), i, _Current)); loop_end: continue; } } } while(_OpenList.Size > 0) { DestroyPathNodeScore((struct PathNodeScore*)BinaryHeapPop(&_OpenList)); } PathStackFree(_OpenList.Table); _Itr = _ClosedList.Front; //ListToPath(&_ClosedList, _Path->Path); const struct PathNodeScore* _Temp = _Current; struct LinkedList _TempList = {0, NULL, NULL}; while(_Temp != NULL) { LnkLstPushFront(&_TempList, (struct PathNodeScore*)_Temp); _Temp = _Temp->Parent; } ListToPath(&_TempList, _Path->Path); while(_Itr != NULL) { DestroyPathNodeScore((struct PathNodeScore*)_Itr->Data); _Itr = _Itr->Next; } LnkLstClear(&_ClosedList); _Path->Callback(_Path->Data, _Path->Path); MemPoolFree(g_PathDataPool, _Path); return 0; }