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;
}