// init level-info subsystem void LoadLevelsList(void) { CPrintF(TRANSV("Reading levels directory...\n")); // list the levels directory with subdirs CDynamicStackArray<CTFileName> afnmDir; MakeDirList(afnmDir, CTString("Levels\\"), CTString("*.wld"), DLI_RECURSIVE|DLI_SEARCHCD); // for each file in the directory for (INDEX i=0; i<afnmDir.Count(); i++) { CTFileName fnm = afnmDir[i]; CPrintF(TRANSV(" file '%s' : "), (const char *)fnm); // try to load its info, and if valid CLevelInfo li; if (GetLevelInfo(li, fnm)) { CPrintF(TRANSV("'%s' spawn=0x%08x\n"), (const char *) li.li_strName, li.li_ulSpawnFlags); // create new info for that file CLevelInfo *pliNew = new CLevelInfo; *pliNew = li; // add it to list of all levels _lhAllLevels.AddTail(pliNew->li_lnNode); } else { CPrintF(TRANSV("invalid level\n")); } } // sort the list _lhAllLevels.Sort(qsort_CompareLevels, _offsetof(CLevelInfo, li_lnNode)); }
/* * Move all elements of another list into this one. */ void CListHead::MoveList(CListHead &lhOther) { ASSERT(IsValid() && lhOther.IsValid()); // if the second list is empty if (lhOther.IsEmpty()) { // no moving return; } // get first element in other list CListNode &lnOtherFirst = *lhOther.lh_Head; // get last element in other list CListNode &lnOtherLast = *lhOther.lh_Tail; // get last element in this list CListNode &lnThisLast = *lh_Tail; // relink elements lnOtherLast.ln_Succ = lnThisLast.ln_Succ; lnThisLast.ln_Succ = &lnOtherFirst; lnOtherFirst.ln_Pred = &lnThisLast; lh_Tail = &lnOtherLast; // clear the other list lhOther.Clear(); }
void FillDirList_internal(const CTFileName &fnmBasePath, CDynamicStackArray<CTFileName> &afnm, const CTFileName &fnmDir, const CTString &strPattern, BOOL bRecursive, CDynamicStackArray<CTFileName> *pafnmInclude, CDynamicStackArray<CTFileName> *pafnmExclude) { // add the directory to list of directories to search CListHead lhDirs; CDirToRead *pdrFirst = new CDirToRead; pdrFirst->dr_strDir = fnmDir; lhDirs.AddTail(pdrFirst->dr_lnNode); // while the list of directories is not empty while (!lhDirs.IsEmpty()) { // take the first one CDirToRead *pdr = LIST_HEAD(lhDirs, CDirToRead, dr_lnNode); CTFileName fnmDir = pdr->dr_strDir; delete pdr; // if the dir is not allowed if (pafnmInclude!=NULL && (!FileMatchesList(*pafnmInclude, fnmDir) || FileMatchesList(*pafnmExclude, fnmDir)) ) { // skip it continue; } // start listing the directory struct _finddata_t c_file; long hFile; hFile = _findfirst( (const char *)(fnmBasePath+fnmDir+"*"), &c_file ); // for each file in the directory for ( BOOL bFileExists = hFile!=-1; bFileExists; bFileExists = _findnext( hFile, &c_file )==0) { // if dummy dir (this dir, parent dir, or any dir starting with '.') if (c_file.name[0]=='.') { // skip it continue; } // get the file's filepath CTFileName fnm = fnmDir+c_file.name; // if it is a directory if (c_file.attrib&_A_SUBDIR) { // if recursive reading if (bRecursive) { // add it to the list of directories to search CDirToRead *pdrNew = new CDirToRead; pdrNew->dr_strDir = fnm+"\\"; lhDirs.AddTail(pdrNew->dr_lnNode); } // if it matches the pattern } else if (strPattern=="" || fnm.Matches(strPattern)) { // add that file afnm.Push() = fnm; } } } }
/* * Enumerate all providers at startup (later enumeration just copies this list). */ void CMessageDispatcher::EnumNetworkProviders_startup(CListHead &lh) { // create local connection provider CNetworkProvider *pnpLocal = new CNetworkProvider; pnpLocal->np_Description = "Local"; lh.AddTail(pnpLocal->np_Node); // create TCP/IP connection provider CNetworkProvider *pnpTCP = new CNetworkProvider; pnpTCP->np_Description = "TCP/IP Server"; lh.AddTail(pnpTCP->np_Node); CNetworkProvider *pnpTCPCl = new CNetworkProvider; pnpTCPCl->np_Description = "TCP/IP Client"; lh.AddTail(pnpTCPCl->np_Node); }
/* Sort the list. */ void CListHead::Sort(int (*pCompare)(const void *p0, const void *p1), int iNodeOffset) { // get number of elements INDEX ctCount = Count(); // if none if (ctCount==0) { // do not sort } // create array of that much integers (the array will hold pointers to the list) ULONG *aulPointers = new ULONG[ctCount]; // fill it INDEX i=0; for ( CListIter<int, 0> iter(*this); !iter.IsPastEnd(); iter.MoveToNext() ) { aulPointers[i] = ((ULONG)&*iter)-iNodeOffset; i++; } // sort it qsort(aulPointers, ctCount, sizeof(SLONG), pCompare); // make temporary list CListHead lhTmp; // for each pointer {for(INDEX i=0; i<ctCount; i++) { ULONG ul = aulPointers[i]; // get the node CListNode *pln = (CListNode*)(ul+iNodeOffset); // remove it from original list pln->Remove(); // add it to the end of new list lhTmp.AddTail(*pln); }} // free the pointer array delete[] aulPointers; // move the sorted list here MoveList(lhTmp); }
// add given node to open list, sorting best first static void SortIntoOpenList(CPathNode *ppnLink) { // start at head of the open list LISTITER(CPathNode, pn_lnInOpen) itpn(_lhOpen); // while the given node is further than the one in list while(ppnLink->pn_fF>itpn->pn_fF && !itpn.IsPastEnd()) { // move to next node itpn.MoveToNext(); } // if past the end of list if (itpn.IsPastEnd()) { // add to the end of list _lhOpen.AddTail(ppnLink->pn_lnInOpen); // if not past end of list } else { // add before current node itpn.InsertBeforeCurrent(ppnLink->pn_lnInOpen); } }
// find shortest path from one marker to another static BOOL FindPath(CNavigationMarker *pnmSrc, CNavigationMarker *pnmDst) { ASSERT(pnmSrc!=pnmDst); CPathNode *ppnSrc = pnmSrc->GetPathNode(); CPathNode *ppnDst = pnmDst->GetPathNode(); PRINTOUT(CPrintF("--------------------\n")); PRINTOUT(CPrintF("FindPath(%s, %s)\n", ppnSrc->GetName(), ppnDst->GetName())); // start with empty open and closed lists ASSERT(_lhOpen.IsEmpty()); ASSERT(_lhClosed.IsEmpty()); // add the start node to open list ppnSrc->pn_fG = 0.0f; ppnSrc->pn_fH = NodeDistance(ppnSrc, ppnDst); ppnSrc->pn_fF = ppnSrc->pn_fG +ppnSrc->pn_fH; _lhOpen.AddTail(ppnSrc->pn_lnInOpen); PRINTOUT(CPrintF("StartState: %s\n", ppnSrc->GetName())); // while the open list is not empty while (!_lhOpen.IsEmpty()) { // get the first node from open list (that is, the one with lowest F) CPathNode *ppnNode = LIST_HEAD(_lhOpen, CPathNode, pn_lnInOpen); ppnNode->pn_lnInOpen.Remove(); _lhClosed.AddTail(ppnNode->pn_lnInClosed); PRINTOUT(CPrintF("Node: %s - moved from OPEN to CLOSED\n", ppnNode->GetName())); // if this is the goal if (ppnNode==ppnDst) { PRINTOUT(CPrintF("PATH FOUND!\n")); // the path is found return TRUE; } // for each link of current node CPathNode *ppnLink = NULL; for(INDEX i=0; (ppnLink=ppnNode->GetLink(i))!=NULL; i++) { PRINTOUT(CPrintF(" Link %d: %s\n", i, ppnLink->GetName())); // get cost to get to this node if coming from current node FLOAT fNewG = ppnLink->pn_fG+NodeDistance(ppnNode, ppnLink); // if a shorter path already exists if ((ppnLink->pn_lnInOpen.IsLinked() || ppnLink->pn_lnInClosed.IsLinked()) && fNewG>=ppnLink->pn_fG) { PRINTOUT(CPrintF(" shorter path exists through: %s\n", ppnLink->pn_ppnParent->GetName())); // skip this link continue; } // remember this path ppnLink->pn_ppnParent = ppnNode; ppnLink->pn_fG = fNewG; ppnLink->pn_fH = NodeDistance(ppnLink, ppnDst); ppnLink->pn_fF = ppnLink->pn_fG + ppnLink->pn_fH; // remove from closed list, if in it if (ppnLink->pn_lnInClosed.IsLinked()) { ppnLink->pn_lnInClosed.Remove(); PRINTOUT(CPrintF(" %s removed from CLOSED\n", ppnLink->GetName())); } // add to open if not in it if (!ppnLink->pn_lnInOpen.IsLinked()) { SortIntoOpenList(ppnLink); PRINTOUT(CPrintF(" %s added to OPEN\n", ppnLink->GetName())); } } } // if we get here, there is no path PRINTOUT(CPrintF("PATH NOT FOUND!\n")); return FALSE; }