Exemple #1
0
Nested<const int> SegmentSoup::neighbors() const {
  if (nodes() && !neighbors_.size()) {
    Array<int> lengths(nodes());
    for(int s=0;s<elements.size();s++)
      for(int a=0;a<2;a++)
        lengths[elements[s][a]]++;
    neighbors_ = Nested<int>(lengths);
    for(int s=0;s<elements.size();s++) {
      int i,j;elements[s].get(i,j);
      neighbors_(i,neighbors_.size(i)-lengths[i]--) = j;
      neighbors_(j,neighbors_.size(j)-lengths[j]--) = i;
    }
    // Sort and remove duplicates if necessary
    bool need_copy = false;
    for(int i=0;i<nodes();i++) {
      RawArray<int> n = neighbors_[i];
      sort(n);
      int* last = std::unique(n.begin(),n.end());
      if(last!=n.end())
        need_copy = true;
      lengths[i] = int(last-n.begin());
    }
    if (need_copy) {
      Nested<int> copy(lengths);
      for(int i=0;i<nodes();i++)
        copy[i] = neighbors_[i].slice(0,lengths[i]);
      neighbors_ = copy;
    }
  }
  return neighbors_;
}
// Add an edge from this node to neighbor.
void
node_impl::add_edge (Supports_Test::Node * neighbor)
{
  degree_ (degree_ () + 1);
  neighbors_ ().length (neighbors_ ().length () + 1);
  neighbors_ ()[neighbors_ ().length () - 1] = neighbor;
  neighbor->_add_ref ();
  return;
}
void
node_impl::print (void)
{
  cout << "  Name: " << name_ () << endl;
  cout << "    Weight: " << weight_ () << endl;
  cout << "    Degree: " << degree_ () << endl;
  cout << "    Neighbors: " << endl;
  for (size_t i = 0; i < neighbors_ ().length (); i++)
    cout << "      " << neighbors_ ()[i]->name_ () << endl;
}
// Initialize state.
node_impl::node_impl (const char * name)
{
        name_ (name);
        weight_ (0);
        degree_ (0);
        neighbors_ ().length (0);
}
// Remove the edge from this node to neighbor.
void
node_impl::remove_edge (Supports_Test::Node * neighbor)
{
  for (unsigned int i = 0; i < neighbors_ ().length (); i++)
    if (neighbors_ ()[i] == neighbor)
      {
        neighbors_ ()[i] = neighbors_ ()[neighbors_ ().length () - 1];
        neighbors_ ().length (neighbors_ ().length () - 1);
        neighbor->_remove_ref ();
      }
}
Exemple #6
0
std::vector<int> Pathfinder::getReachableNodes(int start, int maxDist) const
{
    std::queue<BfsNode> nodeQ;
    std::vector<int> reachable;

    nodeQ.emplace(BfsNode{start, 0});

    while (!nodeQ.empty()) {
        const auto &node = nodeQ.front();
        if (binary_search(std::begin(reachable), std::end(reachable), node.id)) {
            nodeQ.pop();
            continue;
        }

        reachable.push_back(node.id);
        sort(std::begin(reachable), std::end(reachable));

        for (auto nbr : neighbors_(node.id)) {
            auto cost = node.costSoFar + stepCost_(node.id, nbr);
            if (cost <= maxDist) {
                nodeQ.emplace(BfsNode{nbr, cost});
            }
        }

        nodeQ.pop();
    }

    // AI players use this function when computing possible moves.  All else
    // equal, it looks better if the AI prefers to stand still and attack an
    // adjacent unit rather than move and attack.  Thus, we ensure the unit's
    // current hex is the first in the list of possible moves.
    auto iter = lower_bound(std::begin(reachable), std::end(reachable), start);
    rotate(std::begin(reachable), iter, std::end(reachable));

    return reachable;
}
Exemple #7
0
std::vector<int> Pathfinder::getPathFrom(int start) const
{
    if (goal_(start)) return {start};

    // Record shortest path costs for every node we examine.
    std::unordered_map<int, AstarNodePtr> nodes;
    // Maintain a heap of nodes to consider.
    std::vector<int> open;
    int goalLoc = -1;
    AstarNodePtr goalNode;

    // The heap functions confusingly use operator< to build a heap with the
    // *largest* element on top.  We want to get the node with the *least* cost,
    // so we have to order nodes in the opposite way.
    auto orderByCost = [&] (int lhs, int rhs)
    {
        return nodes[lhs]->estTotalCost > nodes[rhs]->estTotalCost;
    };

    nodes.emplace(start, make_astar_node(-1, 0, 0));
    open.push_back(start);

    // A* algorithm.  Decays to Dijkstra's if estimate function is always 0.
    while (!open.empty()) {
        auto loc = open.front();
        pop_heap(std::begin(open), std::end(open), orderByCost);
        open.pop_back();
        if (goal_(loc)) {
            goalLoc = loc;
            goalNode = nodes[loc];
            break;
        }

        auto &curNode = nodes[loc];
        curNode->visited = true;
        for (auto n : neighbors_(loc)) {
            auto nIter = nodes.find(n);
            auto step = stepCost_(loc, n);

            if (nIter != nodes.end()) {
                auto &nNode = nIter->second;
                if (nNode->visited) {
                    continue;
                }

                // Are we on a shorter path to the neighbor node than what
                // we've already seen?  If so, update the neighbor's node data.
                if (curNode->costSoFar + step < nNode->costSoFar) {
                    nNode->prev = loc;
                    nNode->costSoFar = curNode->costSoFar + step;
                    nNode->estTotalCost = nNode->costSoFar + estimate_(n);
                    make_heap(std::begin(open), std::end(open), orderByCost);
                }
            }
            else {
                // We haven't seen this node before.  Add it to the open list.
                nodes.emplace(n, make_astar_node(loc, curNode->costSoFar + step, 
                    curNode->costSoFar + step + estimate_(n)));
                open.push_back(n);
                push_heap(std::begin(open), std::end(open), orderByCost);
            }
        }
    }

    if (!goalNode) {
        return {};
    }

    // Build the path from the chain of nodes leading to the goal.
    std::vector<int> path = {goalLoc};
    auto n = goalNode;
    while (n->prev != -1) {
        path.push_back(n->prev);
        n = nodes[n->prev];
    }
    reverse(std::begin(path), std::end(path));
    assert(contains(path, start));
    return path;
}