CDGPath *newPath() { CDGPath *path; path = (CDGPath *) malloc(sizeof(CDGPath)); assert(NULL != path); setPathNode(path, NULL); setNextPath(path, NULL); return path; }
void SC2Map::buildPathGraph( PathType t ) { // first create a node for every pathable cell // for the given pathing type for( int pci = 0; pci < cxDimPlayable; ++pci ) { for( int pcj = 0; pcj < cyDimPlayable; ++pcj ) { point c; c.pcSet( pci, pcj ); Node* u = NULL; if( getPathing( &c, t ) ) { u = new Node(); u->pathsFromThisSrcCalculated = false; u->loc.pcSet( pci, pcj ); for( int i = 0; i < NUM_NODE_NEIGHBORS; ++i ) { u->neighbors[i] = NULL; } u->id = this->nodes[t].size(); this->nodes[t].push_back( u ); } setPathNode( &c, t, u ); } } // all the nodes are created, now run a second pass // where we decide which of the possible 16 neighbor // edges to create based on what neighbors exist for( int pci = 0; pci < cxDimPlayable; ++pci ) { for( int pcj = 0; pcj < cyDimPlayable; ++pcj ) { // useful points for the following neighbor // calculations and tests--all in cell coordinates point c_p0_p0; c_p0_p0.pcSet( pci + 0, pcj + 0 ); point c_p0_p1; c_p0_p1.pcSet( pci + 0, pcj + 1 ); point c_p1_p2; c_p1_p2.pcSet( pci + 1, pcj + 2 ); point c_p1_p1; c_p1_p1.pcSet( pci + 1, pcj + 1 ); point c_p2_p1; c_p2_p1.pcSet( pci + 2, pcj + 1 ); point c_p1_p0; c_p1_p0.pcSet( pci + 1, pcj + 0 ); point c_p2_m1; c_p2_m1.pcSet( pci + 2, pcj - 1 ); point c_p1_m1; c_p1_m1.pcSet( pci + 1, pcj - 1 ); point c_p1_m2; c_p1_m2.pcSet( pci + 1, pcj - 2 ); point c_p0_m1; c_p0_m1.pcSet( pci + 0, pcj - 1 ); Node* u = getPathNode( &c_p0_p0, t ); if( u == NULL ) { continue; } // we only have to link to half of u's possible // neighbors because the the other half of the links // will be made by a node v who has u as its neighbor Node* v; // for adjacent cells, if it is there its connected v = getPathNode( &c_p0_p1, t ); if( v != NULL ) { u->neighbors[0] = v; v->neighbors[2] = u; } v = getPathNode( &c_p1_p0, t ); if( v != NULL ) { u->neighbors[1] = v; v->neighbors[3] = u; } // for diagonal cells, we say there is a path if one // of the two adjacent cells is pathable // THIS WOULD BE GREAT IF t3SyncInfoPathing WAS AVAILABLE // IN EVERY MAP. SINCE IT IS NOT, WE HAVE TO APPROXIMATE // PATHING AND IN SOME CASES A TRUE PATH IS ONLY CONNECTED // TO ANOTHER CELL BY A DIAGONAL NEIGHBOR, SO FOR NOW IT'S // IF DIAG NEIGHBOR EXISTS --> IT'S PATHABLE v = getPathNode( &c_p1_p1, t ); if( v != NULL ) { //if( getPathNode( &c_p0_p1, t ) != NULL || // getPathNode( &c_p1_p0, t ) != NULL // ) { u->neighbors[4] = v; v->neighbors[6] = u; //} } v = getPathNode( &c_p1_m1, t ); if( v != NULL ) { //if( getPathNode( &c_p0_m1, t ) != NULL || // getPathNode( &c_p1_p0, t ) != NULL // ) { u->neighbors[5] = v; v->neighbors[7] = u; //} } // for the knight's jump cells if BOTH the adjacent // cells in between are pathable, it suffices: // P v <-- if P cells are pathable, make // u P the link u<-->v v = getPathNode( &c_p1_p2, t ); if( v != NULL ) { if( getPathNode( &c_p0_p1, t ) != NULL && getPathNode( &c_p1_p1, t ) != NULL ) { u->neighbors[8] = v; v->neighbors[12] = u; } } v = getPathNode( &c_p2_p1, t ); if( v != NULL ) { if( getPathNode( &c_p1_p0, t ) != NULL && getPathNode( &c_p1_p1, t ) != NULL ) { u->neighbors[9] = v; v->neighbors[13] = u; } } v = getPathNode( &c_p2_m1, t ); if( v != NULL ) { if( getPathNode( &c_p1_p0, t ) != NULL && getPathNode( &c_p1_m1, t ) != NULL ) { u->neighbors[10] = v; v->neighbors[14] = u; } } v = getPathNode( &c_p1_m2, t ); if( v != NULL ) { if( getPathNode( &c_p0_m1, t ) != NULL && getPathNode( &c_p1_m1, t ) != NULL ) { u->neighbors[11] = v; v->neighbors[15] = u; } } } } }
CDGPath *getTopPaths(CDGContext * ctx, CDGNode * root, int numberOfPaths) { CDGPath *pathHead = NULL; CDGNode *path; CDGPath *currPath; CDGNode *node; int branch; Stack *changedNodes = stackNew(sizeof(CDGNode *)); Stack *changedBranches = stackNew(sizeof(int)); while (numberOfPaths--) { path = getTopPath(root, changedNodes, changedBranches); if (NULL == path) break; if (NULL == pathHead) { pathHead = setPathNode(newPath(), path); currPath = pathHead; } else { setNextPath(currPath, setPathNode(newPath(), path)); currPath = getNextPath(currPath); } updateCDG(root, 0); } while (!stackIsEmpty(changedNodes) && !stackIsEmpty(changedBranches)) { stackPop(changedNodes, &node); stackPop(changedBranches, &branch); if (isLeaf(node)) { setScore(node, 1); } else { if (branch) setBranchInfo(getID(node), 0, getBranchInfo(getID(node), 0)); else setBranchInfo(getID(node), getBranchInfo(getID(node), 1), 0); } } updateCDG(root, 0); stackFree(changedNodes); stackFree(changedBranches); /* Updating context */ (*ctx).topPaths = pathHead; /* Ensuring atleast one path was found */ if (NULL == pathHead) return NULL; /* Creating list of nodes from complicated path form */ CDGPath *outPathHead = NULL; currPath = NULL; path = NULL; while (NULL != pathHead) { path = getPathNode(pathHead); if (NULL == outPathHead) { outPathHead = setPathNode(newPath(), pathToList(path)); currPath = outPathHead; } else { setNextPath(currPath, setPathNode(newPath(), pathToList(path))); currPath = getNextPath(currPath); } pathHead = getNextPath(pathHead); } return outPathHead; }